FooGallery – Image Gallery WordPress Plugin - Version 1.4.30

Version Description

  • Fix : Album 404 issues when used on homepage
  • Fix : Dimension attributes missing for upscaling small images
  • Fix : Issue when galleries cannot be added to an album
  • Fix : Lightbox caption mismatch
  • New : Setting for legacy thumb cropping in Simple Portfolio gallery
  • Update : FooGallery client side 1.0.26
Download this release

Release Info

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

Code changes from version 1.4.29 to 1.4.30

Files changed (73) hide show
  1. README.txt +9 -0
  2. extensions/albums/js/admin-foogallery-album.js +1 -0
  3. extensions/albums/public/class-rewrite-rules.php +31 -1
  4. extensions/default-templates/justified/class-justified-gallery-template.php +2 -1
  5. extensions/default-templates/shared/css/foogallery.css +2 -0
  6. extensions/default-templates/shared/css/foogallery.min.css +1 -1
  7. extensions/default-templates/shared/js/foogallery.js +169 -118
  8. extensions/default-templates/shared/js/foogallery.min.js +3 -2
  9. extensions/default-templates/simple-portfolio/class-simple-portfolio-gallery-template.php +18 -3
  10. foogallery.php +2 -2
  11. freemius/.codeclimate.yml +19 -19
  12. freemius/.github/ISSUE_TEMPLATE.md +29 -29
  13. freemius/.travis.yml +11 -11
  14. freemius/assets/css/admin/account.css +1 -1
  15. freemius/assets/css/admin/affiliation.css +1 -1
  16. freemius/assets/css/admin/connect.css +1 -1
  17. freemius/assets/css/admin/dialog-boxes.css +2 -2
  18. freemius/assets/css/admin/index.php +2 -2
  19. freemius/assets/css/index.php +2 -2
  20. freemius/assets/img/index.php +2 -2
  21. freemius/assets/js/index.php +2 -2
  22. freemius/assets/scss/_colors.scss +65 -65
  23. freemius/assets/scss/admin/_license-activation.scss +6 -6
  24. freemius/assets/scss/admin/_modal-common.scss +185 -185
  25. freemius/assets/scss/admin/account.scss +255 -255
  26. freemius/assets/scss/admin/dialog-boxes.scss +6 -6
  27. freemius/assets/scss/admin/index.php +2 -2
  28. freemius/assets/scss/index.php +2 -2
  29. freemius/gulpfile.js +166 -166
  30. freemius/includes/class-fs-logger.php +687 -687
  31. freemius/includes/customizer/class-fs-customizer-support-section.php +101 -101
  32. freemius/includes/customizer/class-fs-customizer-upsell-control.php +156 -156
  33. freemius/includes/customizer/index.php +2 -2
  34. freemius/includes/debug/class-fs-debug-bar-panel.php +64 -64
  35. freemius/includes/debug/debug-bar-start.php +51 -51
  36. freemius/includes/entities/class-fs-plugin-license.php +224 -224
  37. freemius/includes/entities/class-fs-plugin-tag.php +23 -23
  38. freemius/includes/entities/class-fs-plugin.php +116 -116
  39. freemius/includes/entities/class-fs-site.php +147 -147
  40. freemius/includes/l10n.php +48 -48
  41. freemius/includes/managers/class-fs-admin-menu-manager.php +849 -849
  42. freemius/includes/managers/class-fs-cache-manager.php +280 -280
  43. freemius/includes/managers/class-fs-key-value-storage.php +327 -327
  44. freemius/includes/managers/class-fs-option-manager.php +352 -352
  45. freemius/includes/managers/class-fs-plugin-manager.php +219 -219
  46. freemius/includes/supplements/fs-essential-functions-1.1.7.1.php +47 -47
  47. freemius/package.json +27 -27
  48. freemius/require.php +44 -44
  49. freemius/templates/account/billing.php +430 -430
  50. freemius/templates/account/payments.php +58 -58
  51. freemius/templates/add-ons.php +192 -192
  52. freemius/templates/admin-notice.php +48 -48
  53. freemius/templates/all-admin-notice.php +38 -38
  54. freemius/templates/checkout-legacy.php +242 -242
  55. freemius/templates/debug/api-calls.php +154 -154
  56. freemius/templates/debug/logger.php +65 -65
  57. freemius/templates/forms/deactivation/contact.php +23 -23
  58. freemius/templates/forms/deactivation/form.php +409 -409
  59. freemius/templates/forms/deactivation/retry-skip.php +23 -23
  60. freemius/templates/forms/optout.php +267 -267
  61. freemius/templates/forms/resend-key.php +247 -247
  62. freemius/templates/forms/trial-start.php +181 -181
  63. freemius/templates/js/style-premium-theme.php +44 -44
  64. freemius/templates/plugin-icon.php +129 -129
  65. freemius/templates/plugin-info/description.php +77 -77
  66. freemius/templates/plugin-info/features.php +113 -113
  67. freemius/templates/plugin-info/screenshots.php +34 -34
  68. freemius/templates/secure-https-header.php +38 -38
  69. includes/admin/class-settings.php +8 -0
  70. includes/class-thumbnail-dimensions.php +54 -3
  71. includes/class-thumbnails.php +21 -4
  72. includes/functions.php +8 -2
  73. js/foogallery.admin.min.js +1 -1
README.txt CHANGED
@@ -150,6 +150,15 @@ Update now to get all the latest features, bug fixes and improvements!
150
 
151
  == Changelog ==
152
 
 
 
 
 
 
 
 
 
 
153
  = 1.4.29 =
154
 
155
  * New : Added an album setting to set the gallery title size (h2,h3,h4,h5,h6)
150
 
151
  == Changelog ==
152
 
153
+ = 1.4.30 =
154
+
155
+ * Fix : Album 404 issues when used on homepage
156
+ * Fix : Dimension attributes missing for upscaling small images
157
+ * Fix : Issue when galleries cannot be added to an album
158
+ * Fix : Lightbox caption mismatch
159
+ * New : Setting for legacy thumb cropping in Simple Portfolio gallery
160
+ * Update : FooGallery client side 1.0.26
161
+
162
  = 1.4.29 =
163
 
164
  * New : Added an album setting to set the gallery title size (h2,h3,h4,h5,h6)
extensions/albums/js/admin-foogallery-album.js CHANGED
@@ -3,6 +3,7 @@
3
  FOOGALLERYALBUM.bindElements = function() {
4
  $('.foogallery-album-gallery-list')
5
  .on('click', '.foogallery-gallery-select', function(e) {
 
6
  $(this).toggleClass('selected');
7
  FOOGALLERYALBUM.changeSelection();
8
  })
3
  FOOGALLERYALBUM.bindElements = function() {
4
  $('.foogallery-album-gallery-list')
5
  .on('click', '.foogallery-gallery-select', function(e) {
6
+ e.stopPropagation();
7
  $(this).toggleClass('selected');
8
  FOOGALLERYALBUM.changeSelection();
9
  })
extensions/albums/public/class-rewrite-rules.php CHANGED
@@ -8,10 +8,40 @@ if (!class_exists('FooGallery_Album_Rewrite_Rules')) {
8
 
9
  function __construct() {
10
  add_action( 'init', array( $this, 'add_gallery_endpoint' ) );
 
 
11
  }
12
 
13
  function add_gallery_endpoint() {
14
- add_rewrite_endpoint( foogallery_album_gallery_url_slug(), EP_ALL );
 
 
 
 
 
 
 
 
 
 
 
15
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  }
17
  }
8
 
9
  function __construct() {
10
  add_action( 'init', array( $this, 'add_gallery_endpoint' ) );
11
+ add_filter( 'redirect_canonical', array( $this, 'disable_canonical_redirect_for_front_page' ), 10, 2 );
12
+ add_action( 'update_option_page_on_front', array( $this, 'flush_rules' ) );
13
  }
14
 
15
  function add_gallery_endpoint() {
16
+ $gallery_slug = foogallery_album_gallery_url_slug();
17
+
18
+ // Ensures the $query_vars['item'] is available
19
+ add_rewrite_tag( "%{$gallery_slug}%", '([^&]+)' );
20
+
21
+ // Requires flushing endpoints whenever the front page is switched to a different page
22
+ $page_on_front = get_option( 'page_on_front' );
23
+
24
+ // Match the front page and pass item value as a query var.
25
+ add_rewrite_rule( "^{$gallery_slug}/([^/]*)/?", 'index.php?page_id='.$page_on_front.'&'.$gallery_slug.'=$matches[1]', 'top' );
26
+ // Match non-front page pages.
27
+ add_rewrite_rule( "^(.*)/{$gallery_slug}/([^/]*)/?", 'index.php?pagename=$matches[1]&static=true&'.$gallery_slug.'=$matches[2]', 'top' );
28
  }
29
+
30
+ // http://wordpress.stackexchange.com/a/220484/52463
31
+ // In order to keep WordPress from forcing a redirect to the canonical
32
+ // home page, the redirect needs to be disabled.
33
+ function disable_canonical_redirect_for_front_page( $redirect_url, $requested_url ) {
34
+ if ( is_page() && $front_page = get_option( 'page_on_front' ) ) {
35
+ if ( is_page( $front_page ) ) {
36
+ $redirect_url = false;
37
+ }
38
+ }
39
+
40
+ return $redirect_url;
41
+ }
42
+
43
+ function flush_rules() {
44
+ flush_rewrite_rules();
45
+ }
46
  }
47
  }
extensions/default-templates/justified/class-justified-gallery-template.php CHANGED
@@ -262,7 +262,8 @@ if ( !class_exists( 'FooGallery_Justified_Gallery_Template' ) ) {
262
  $height = foogallery_gallery_template_setting( 'thumb_height', '250' );
263
  $args = array(
264
  'height' => $height,
265
- 'link' => foogallery_gallery_template_setting( 'thumbnail_link', 'image' )
 
266
  );
267
 
268
  return $args;
262
  $height = foogallery_gallery_template_setting( 'thumb_height', '250' );
263
  $args = array(
264
  'height' => $height,
265
+ 'link' => foogallery_gallery_template_setting( 'thumbnail_link', 'image' ),
266
+ 'crop' => false
267
  );
268
 
269
  return $args;
extensions/default-templates/shared/css/foogallery.css CHANGED
@@ -1748,6 +1748,8 @@ only screen and (min-resolution: 2.25dppx) {
1748
  width: 100%;
1749
  height: auto;
1750
  min-height: 100%;
 
 
1751
  }
1752
  /* Base Styles */
1753
  .fg-simple_portfolio {
1748
  width: 100%;
1749
  height: auto;
1750
  min-height: 100%;
1751
+ top: 50%;
1752
+ transform: translateY(-50%);
1753
  }
1754
  /* Base Styles */
1755
  .fg-simple_portfolio {
extensions/default-templates/shared/css/foogallery.min.css CHANGED
@@ -1 +1 @@
1
- .foogallery,.foogallery *{box-sizing:border-box}.foogallery{display:block;z-index:1;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;position:relative;line-height:0;font-size:0;width:100%;max-width:100%}.foogallery .fg-item{display:inline-block;position:relative;background-color:transparent;z-index:2;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.foogallery .fg-item-inner{display:block;position:relative;visibility:hidden;overflow:hidden;opacity:0;z-index:3;margin:0;border:solid 0 transparent}.foogallery .fg-item.fg-error,.foogallery .fg-item.fg-loading{background:no-repeat center}.foogallery .fg-item.fg-error{background-image:url(../img/image.png)}@media only screen and (-o-min-device-pixel-ratio:5/4),only screen and (-webkit-min-device-pixel-ratio:1.25),only screen and (min-device-pixel-ratio:1.25),only screen and (min-resolution:1.25dppx){.foogallery .fg-item.fg-error{background-image:url(../img/image@2x.png)}}@media only screen and (-o-min-device-pixel-ratio:9/4),only screen and (-webkit-min-device-pixel-ratio:2.25),only screen and (min-device-pixel-ratio:2.25),only screen and (min-resolution:2.25dppx){.foogallery .fg-item.fg-error{background-image:url(../img/image@3x.png)}}.foogallery .fg-item.fg-loaded{z-index:4}.foogallery .fg-loaded .fg-item-inner{visibility:visible;opacity:1;z-index:5}.foogallery .fg-error .fg-item-inner{pointer-events:none;cursor:default}.foogallery .fg-thumb{display:block;position:relative;border:none;outline:0;text-decoration:none;z-index:4}.foogallery .fg-image{display:block;position:relative;border:none;outline:0;text-decoration:none;z-index:5;max-width:none;height:auto;margin:0}.foogallery .fg-loaded .fg-thumb{z-index:6}.foogallery .fg-loaded .fg-image{z-index:7}.foogallery.fg-light .fg-item-inner{background-color:#fff;color:#333;border-color:#fff}.foogallery.fg-dark .fg-item-inner{background-color:#333;color:#fff;border-color:#333}.foogallery.fg-light .fg-item.fg-error,.foogallery.fg-light .fg-item.fg-idle,.foogallery.fg-light .fg-item.fg-loading{background-color:#eee;box-shadow:inset 0 0 0 1px #ddd}.foogallery.fg-dark .fg-item.fg-error,.foogallery.fg-dark .fg-item.fg-idle,.foogallery.fg-dark .fg-item.fg-loading{background-color:#444;box-shadow:inset 0 0 0 1px #333}.foogallery.fg-border-thin .fg-item-inner{border-width:4px}.foogallery.fg-border-medium .fg-item-inner{border-width:10px}.foogallery.fg-border-thick .fg-item-inner{border-width:16px}.foogallery.fg-light.fg-shadow-outline .fg-item-inner{box-shadow:0 0 0 1px #ddd}.foogallery.fg-dark.fg-shadow-outline .fg-item-inner{box-shadow:0 0 0 1px #222}.foogallery.fg-dark.fg-shadow-small .fg-item-inner,.foogallery.fg-light.fg-shadow-small .fg-item-inner{box-shadow:0 1px 4px 0 rgba(0,0,0,.5)}.foogallery.fg-dark.fg-shadow-medium .fg-item-inner,.foogallery.fg-light.fg-shadow-medium .fg-item-inner{box-shadow:0 1px 10px 0 rgba(0,0,0,.5)}.foogallery.fg-dark.fg-shadow-large .fg-item-inner,.foogallery.fg-light.fg-shadow-large .fg-item-inner{box-shadow:0 1px 16px 0 rgba(0,0,0,.5)}.foogallery.fg-shadow-inset-large .fg-thumb:after,.foogallery.fg-shadow-inset-medium .fg-thumb:after,.foogallery.fg-shadow-inset-small .fg-thumb:after{display:block;content:"";position:absolute;top:0;left:0;right:0;bottom:0;z-index:7}.foogallery.fg-dark.fg-shadow-inset-small .fg-thumb:after,.foogallery.fg-light.fg-shadow-inset-small .fg-thumb:after{box-shadow:inset 0 1px 4px 0 rgba(0,0,0,.3)}.foogallery.fg-dark.fg-shadow-inset-medium .fg-thumb:after,.foogallery.fg-light.fg-shadow-inset-medium .fg-thumb:after{box-shadow:inset 0 1px 10px 0 rgba(0,0,0,.3)}.foogallery.fg-dark.fg-shadow-inset-large .fg-thumb:after,.foogallery.fg-light.fg-shadow-inset-large .fg-thumb:after{box-shadow:inset 0 1px 16px 0 rgba(0,0,0,.3)}.foogallery.fg-round-full.fg-shadow-inset-large .fg-thumb:after,.foogallery.fg-round-full.fg-shadow-inset-medium .fg-thumb:after,.foogallery.fg-round-full.fg-shadow-inset-small .fg-thumb:after{border-radius:50%}.foogallery.fg-round-small .fg-item,.foogallery.fg-round-small .fg-item-inner{border-radius:5px}.foogallery.fg-round-medium .fg-item,.foogallery.fg-round-medium .fg-item-inner{border-radius:10px}.foogallery.fg-round-large .fg-item,.foogallery.fg-round-large .fg-item-inner{border-radius:15px}.foogallery.fg-round-full .fg-item,.foogallery.fg-round-full .fg-item-inner{border-radius:50%}.foogallery .fg-loader{position:absolute;top:50%;left:50%;transform:translateX(-50%) translateY(-50%);width:1em;height:1em;font-size:5px;visibility:hidden;opacity:0}.foogallery .fg-loading .fg-loader{visibility:visible;opacity:1}.fg-loading-default .fg-loader{border-radius:50%;text-indent:-9999em;-webkit-animation:loading-default 1.1s infinite ease;animation:loading-default 1.1s infinite ease}@-webkit-keyframes loading-default{0%,100%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,1),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.5),-1.8em -1.8em 0 0 rgba(130,130,130,.7)}12.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.7),1.8em -1.8em 0 0 rgba(130,130,130,1),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.5)}25%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.5),1.8em -1.8em 0 0 rgba(130,130,130,.7),2.5em 0 0 0 rgba(130,130,130,1),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}37.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.5),2.5em 0 0 0 rgba(130,130,130,.7),1.75em 1.75em 0 0 rgba(130,130,130,1),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}50%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.5),1.75em 1.75em 0 0 rgba(130,130,130,.7),0 2.5em 0 0 rgba(130,130,130,1),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}62.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.5),0 2.5em 0 0 rgba(130,130,130,.7),-1.8em 1.8em 0 0 rgba(130,130,130,1),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}75%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.5),-1.8em 1.8em 0 0 rgba(130,130,130,.7),-2.6em 0 0 0 rgba(130,130,130,1),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}87.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.5),-2.6em 0 0 0 rgba(130,130,130,.7),-1.8em -1.8em 0 0 rgba(130,130,130,1)}}@keyframes loading-default{0%,100%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,1),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.5),-1.8em -1.8em 0 0 rgba(130,130,130,.7)}12.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.7),1.8em -1.8em 0 0 rgba(130,130,130,1),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.5)}25%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.5),1.8em -1.8em 0 0 rgba(130,130,130,.7),2.5em 0 0 0 rgba(130,130,130,1),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}37.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.5),2.5em 0 0 0 rgba(130,130,130,.7),1.75em 1.75em 0 0 rgba(130,130,130,1),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}50%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.5),1.75em 1.75em 0 0 rgba(130,130,130,.7),0 2.5em 0 0 rgba(130,130,130,1),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}62.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.5),0 2.5em 0 0 rgba(130,130,130,.7),-1.8em 1.8em 0 0 rgba(130,130,130,1),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}75%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.5),-1.8em 1.8em 0 0 rgba(130,130,130,.7),-2.6em 0 0 0 rgba(130,130,130,1),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}87.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.5),-2.6em 0 0 0 rgba(130,130,130,.7),-1.8em -1.8em 0 0 rgba(130,130,130,1)}}.fg-loading-bars .fg-loader,.fg-loading-bars .fg-loader:after,.fg-loading-bars .fg-loader:before{background:rgba(130,130,130,1);-webkit-animation:loading-bars 1s infinite ease-in-out;animation:loading-bars 1s infinite ease-in-out;width:1em;height:4em}.fg-loading-bars .fg-loader{color:rgba(130,130,130,1);text-indent:-9999em;font-size:4px;-webkit-animation-delay:-.16s;animation-delay:-.16s}.fg-loading-bars .fg-loader:after,.fg-loading-bars .fg-loader:before{position:absolute;top:0;content:''}.fg-loading-bars .fg-loader:before{left:-1.5em;-webkit-animation-delay:-.32s;animation-delay:-.32s}.fg-loading-bars .fg-loader:after{left:1.5em}@-webkit-keyframes loading-bars{0%,100%,80%{box-shadow:0 0;height:4em}40%{box-shadow:0 -2em;height:5em}}@keyframes loading-bars{0%,100%,80%{box-shadow:0 0;height:4em}40%{box-shadow:0 -2em;height:5em}}.fg-loading-trail .fg-loader{color:#828282;font-size:20px;text-indent:-9999em;overflow:hidden;border-radius:50%;-webkit-animation:loading-trail-1 1.7s infinite ease,loading-trail-2 1.7s infinite ease;animation:loading-trail-1 1.7s infinite ease,loading-trail-2 1.7s infinite ease}@-webkit-keyframes loading-trail-1{0%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}5%,95%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}10%,59%{box-shadow:0 -.83em 0 -.4em,-.087em -.825em 0 -.42em,-.173em -.812em 0 -.44em,-.256em -.789em 0 -.46em,-.297em -.775em 0 -.477em}20%{box-shadow:0 -.83em 0 -.4em,-.338em -.758em 0 -.42em,-.555em -.617em 0 -.44em,-.671em -.488em 0 -.46em,-.749em -.34em 0 -.477em}38%{box-shadow:0 -.83em 0 -.4em,-.377em -.74em 0 -.42em,-.645em -.522em 0 -.44em,-.775em -.297em 0 -.46em,-.82em -.09em 0 -.477em}100%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}}@keyframes loading-trail-1{0%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}5%,95%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}10%,59%{box-shadow:0 -.83em 0 -.4em,-.087em -.825em 0 -.42em,-.173em -.812em 0 -.44em,-.256em -.789em 0 -.46em,-.297em -.775em 0 -.477em}20%{box-shadow:0 -.83em 0 -.4em,-.338em -.758em 0 -.42em,-.555em -.617em 0 -.44em,-.671em -.488em 0 -.46em,-.749em -.34em 0 -.477em}38%{box-shadow:0 -.83em 0 -.4em,-.377em -.74em 0 -.42em,-.645em -.522em 0 -.44em,-.775em -.297em 0 -.46em,-.82em -.09em 0 -.477em}100%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}}@-webkit-keyframes loading-trail-2{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}@keyframes loading-trail-2{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}.fg-loading-pulse .fg-loader,.fg-loading-pulse .fg-loader:after,.fg-loading-pulse .fg-loader:before{border-radius:50%;width:2.5em;height:2.5em;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation:loading-pulse 1.8s infinite ease-in-out;animation:loading-pulse 1.8s infinite ease-in-out}.fg-loading-pulse .fg-loader{color:#828282;font-size:4px;text-indent:-9999em;transform:translateX(-50%) translateY(-150%);-webkit-animation-delay:-.16s;animation-delay:-.16s}.fg-loading-pulse .fg-loader:after,.fg-loading-pulse .fg-loader:before{content:'';position:absolute;top:0}.fg-loading-pulse .fg-loader:before{left:-3.5em;-webkit-animation-delay:-.32s;animation-delay:-.32s}.fg-loading-pulse .fg-loader:after{left:3.5em}@-webkit-keyframes loading-pulse{0%,100%,80%{box-shadow:0 2.5em 0 -1.3em}40%{box-shadow:0 2.5em 0 0}}@keyframes loading-pulse{0%,100%,80%{box-shadow:0 2.5em 0 -1.3em}40%{box-shadow:0 2.5em 0 0}}.fg-loading-dots .fg-loader{color:#828282;font-size:5px;border-radius:50%;text-indent:-9999em;-webkit-animation:loading-dots 1.3s infinite linear;animation:loading-dots 1.3s infinite linear}@-webkit-keyframes loading-dots{0%,100%{box-shadow:0 -3em 0 .2em,2em -2em 0 0,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 0}12.5%{box-shadow:0 -3em 0 0,2em -2em 0 .2em,3em 0 0 0,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}25%{box-shadow:0 -3em 0 -.5em,2em -2em 0 0,3em 0 0 .2em,2em 2em 0 0,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}37.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 0,2em 2em 0 .2em,0 3em 0 0,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}50%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 0,0 3em 0 .2em,-2em 2em 0 0,-3em 0 0 -1em,-2em -2em 0 -1em}62.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 0,-2em 2em 0 .2em,-3em 0 0 0,-2em -2em 0 -1em}75%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 .2em,-2em -2em 0 0}87.5%{box-shadow:0 -3em 0 0,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 0,-2em -2em 0 .2em}}@keyframes loading-dots{0%,100%{box-shadow:0 -3em 0 .2em,2em -2em 0 0,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 0}12.5%{box-shadow:0 -3em 0 0,2em -2em 0 .2em,3em 0 0 0,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}25%{box-shadow:0 -3em 0 -.5em,2em -2em 0 0,3em 0 0 .2em,2em 2em 0 0,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}37.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 0,2em 2em 0 .2em,0 3em 0 0,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}50%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 0,0 3em 0 .2em,-2em 2em 0 0,-3em 0 0 -1em,-2em -2em 0 -1em}62.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 0,-2em 2em 0 .2em,-3em 0 0 0,-2em -2em 0 -1em}75%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 .2em,-2em -2em 0 0}87.5%{box-shadow:0 -3em 0 0,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 0,-2em -2em 0 .2em}}.fg-loading-partial .fg-loader,.fg-loading-partial .fg-loader:after{border-radius:50%;width:10em;height:10em}.fg-loading-partial .fg-loader{font-size:4px;text-indent:-9999em;border-top:1.1em solid rgba(130,130,130,.2);border-right:1.1em solid rgba(130,130,130,.2);border-bottom:1.1em solid rgba(130,130,130,.2);border-left:1.1em solid #828282;-webkit-animation:loading-partial 1.1s infinite linear;animation:loading-partial 1.1s infinite linear}@-webkit-keyframes loading-partial{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}@keyframes loading-partial{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}.foogallery.fg-loaded-drop .fg-item,.foogallery.fg-loaded-fade-in .fg-item,.foogallery.fg-loaded-flip .fg-item,.foogallery.fg-loaded-fly .fg-item,.foogallery.fg-loaded-scale-up .fg-item,.foogallery.fg-loaded-slide-down .fg-item,.foogallery.fg-loaded-slide-left .fg-item,.foogallery.fg-loaded-slide-right .fg-item,.foogallery.fg-loaded-slide-up .fg-item,.foogallery.fg-loaded-swing-down .fg-item{transition-timing-function:ease;transition-duration:650ms;transition-property:background-color,transform}.foogallery.fg-loaded-drop .fg-item-inner,.foogallery.fg-loaded-fade-in .fg-item-inner,.foogallery.fg-loaded-flip .fg-item-inner,.foogallery.fg-loaded-fly .fg-item-inner,.foogallery.fg-loaded-scale-up .fg-item-inner,.foogallery.fg-loaded-slide-down .fg-item-inner,.foogallery.fg-loaded-slide-left .fg-item-inner,.foogallery.fg-loaded-slide-right .fg-item-inner,.foogallery.fg-loaded-slide-up .fg-item-inner,.foogallery.fg-loaded-swing-down .fg-item-inner{transition-timing-function:ease;transition-duration:650ms}.foogallery.fg-loaded-drop .fg-item.fg-loaded,.foogallery.fg-loaded-flip .fg-item.fg-loaded,.foogallery.fg-loaded-fly .fg-item.fg-loaded,.foogallery.fg-loaded-swing-down .fg-item.fg-loaded{perspective:1300px}.foogallery.fg-loaded-fade-in .fg-item-inner{transition-property:visibility,opacity}.foogallery .fg-caption{visibility:hidden;opacity:0;background-color:rgba(0,0,0,.6);color:#fff;position:absolute;z-index:8;width:100%;max-height:100%;overflow:hidden;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:13px;font-weight:400;line-height:1.3;border:none;text-align:center;cursor:pointer}.foogallery .fg-caption a{text-decoration:none;color:#fff;border-bottom:1px solid #fff}.foogallery .fg-caption a:hover{border-bottom:none}.foogallery .fg-caption-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:16px;font-weight:400;padding:5px}.foogallery .fg-caption-desc{padding:5px}.foogallery .fg-caption-title+.fg-caption-desc{padding-top:0}.foogallery.fg-caption-always .fg-caption .fg-caption-inner:before{display:none}.foogallery.fg-caption-always .fg-item.fg-loaded .fg-caption{left:0;bottom:0;transition-timing-function:ease;transition-duration:.3s;transition-property:visibility,opacity;visibility:visible;opacity:1;text-align:left}.foogallery.fg-caption-hover .fg-caption .fg-caption-inner{width:100%;max-height:100%;position:absolute;top:50%;left:0;transform:translateY(-50%)}.foogallery.fg-caption-hover .fg-item.fg-loaded .fg-thumb:before{display:none}.foogallery.fg-hover-circle-plus .fg-thumb:before,.foogallery.fg-hover-external .fg-thumb:before,.foogallery.fg-hover-eye .fg-thumb:before,.foogallery.fg-hover-plus .fg-thumb:before,.foogallery.fg-hover-tint .fg-thumb:before,.foogallery.fg-hover-zoom .fg-thumb:before,.foogallery.fg-hover-zoom2 .fg-thumb:before,.foogallery.fg-hover-zoom3 .fg-thumb:before{content:"";display:block;position:absolute;visibility:hidden;opacity:0;top:0;bottom:0;left:0;right:0;z-index:8;background:rgba(0,0,0,.5) no-repeat center center;background-size:32px 32px}.foogallery.fg-hover-circle-plus .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-circle-plus .fg-thumb:focus:before,.foogallery.fg-hover-external .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-external .fg-thumb:focus:before,.foogallery.fg-hover-eye .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-eye .fg-thumb:focus:before,.foogallery.fg-hover-plus .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-plus .fg-thumb:focus:before,.foogallery.fg-hover-tint .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-tint .fg-thumb:focus:before,.foogallery.fg-hover-zoom .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-zoom .fg-thumb:focus:before,.foogallery.fg-hover-zoom2 .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-zoom2 .fg-thumb:focus:before,.foogallery.fg-hover-zoom3 .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-zoom3 .fg-thumb:focus:before{visibility:visible;opacity:1}.foogallery.fg-hover-circle-plus .fg-caption-inner:before,.foogallery.fg-hover-external .fg-caption-inner:before,.foogallery.fg-hover-eye .fg-caption-inner:before,.foogallery.fg-hover-plus .fg-caption-inner:before,.foogallery.fg-hover-tint .fg-caption-inner:before,.foogallery.fg-hover-zoom .fg-caption-inner:before,.foogallery.fg-hover-zoom2 .fg-caption-inner:before,.foogallery.fg-hover-zoom3 .fg-caption-inner:before{content:"";display:inline-block;position:relative;width:32px;height:32px;margin:10px 0 5px 0;background:transparent no-repeat center center;background-size:32px 32px;vertical-align:middle}.foogallery.fg-hover-zoom .fg-caption-inner:before,.foogallery.fg-hover-zoom .fg-thumb:before{background-image:url(../img/zoom.png)}.foogallery.fg-hover-zoom2 .fg-caption-inner:before,.foogallery.fg-hover-zoom2 .fg-thumb:before{background-image:url(../img/zoom2.png)}.foogallery.fg-hover-zoom3 .fg-caption-inner:before,.foogallery.fg-hover-zoom3 .fg-thumb:before{background-image:url(../img/zoom3.png)}.foogallery.fg-hover-plus .fg-caption-inner:before,.foogallery.fg-hover-plus .fg-thumb:before{background-image:url(../img/plus.png)}.foogallery.fg-hover-circle-plus .fg-caption-inner:before,.foogallery.fg-hover-circle-plus .fg-thumb:before{background-image:url(../img/circle-plus.png)}.foogallery.fg-hover-eye .fg-caption-inner:before,.foogallery.fg-hover-eye .fg-thumb:before{background-image:url(../img/eye.png)}.foogallery.fg-hover-external .fg-caption-inner:before,.foogallery.fg-hover-external .fg-thumb:before{background-image:url(../img/external.png)}@media only screen and (-o-min-device-pixel-ratio:5/4),only screen and (-webkit-min-device-pixel-ratio:1.25),only screen and (min-device-pixel-ratio:1.25),only screen and (min-resolution:1.25dppx){.foogallery.fg-hover-zoom .fg-caption-inner:before,.foogallery.fg-hover-zoom .fg-thumb:before{background-image:url(../img/zoom@2x.png)}.foogallery.fg-hover-zoom2 .fg-caption-inner:before,.foogallery.fg-hover-zoom2 .fg-thumb:before{background-image:url(../img/zoom2@2x.png)}.foogallery.fg-hover-zoom3 .fg-caption-inner:before,.foogallery.fg-hover-zoom3 .fg-thumb:before{background-image:url(../img/zoom3@2x.png)}.foogallery.fg-hover-plus .fg-caption-inner:before,.foogallery.fg-hover-plus .fg-thumb:before{background-image:url(../img/plus@2x.png)}.foogallery.fg-hover-circle-plus .fg-caption-inner:before,.foogallery.fg-hover-circle-plus .fg-thumb:before{background-image:url(../img/circle-plus@2x.png)}.foogallery.fg-hover-eye .fg-caption-inner:before,.foogallery.fg-hover-eye .fg-thumb:before{background-image:url(../img/eye@2x.png)}.foogallery.fg-hover-external .fg-caption-inner:before,.foogallery.fg-hover-external .fg-thumb:before{background-image:url(../img/external@2x.png)}}@media only screen and (-o-min-device-pixel-ratio:9/4),only screen and (-webkit-min-device-pixel-ratio:2.25),only screen and (min-device-pixel-ratio:2.25),only screen and (min-resolution:2.25dppx){.foogallery.fg-hover-zoom .fg-caption-inner:before,.foogallery.fg-hover-zoom .fg-thumb:before{background-image:url(../img/zoom@3x.png)}.foogallery.fg-hover-zoom2 .fg-caption-inner:before,.foogallery.fg-hover-zoom2 .fg-thumb:before{background-image:url(../img/zoom2@3x.png)}.foogallery.fg-hover-zoom3 .fg-caption-inner:before,.foogallery.fg-hover-zoom3 .fg-thumb:before{background-image:url(../img/zoom3@3x.png)}.foogallery.fg-hover-plus .fg-caption-inner:before,.foogallery.fg-hover-plus .fg-thumb:before{background-image:url(../img/plus@3x.png)}.foogallery.fg-hover-circle-plus .fg-caption-inner:before,.foogallery.fg-hover-circle-plus .fg-thumb:before{background-image:url(../img/circle-plus@3x.png)}.foogallery.fg-hover-eye .fg-caption-inner:before,.foogallery.fg-hover-eye .fg-thumb:before{background-image:url(../img/eye@3x.png)}.foogallery.fg-hover-external .fg-caption-inner:before,.foogallery.fg-hover-external .fg-thumb:before{background-image:url(../img/external@3x.png)}}.foogallery.fg-caption-hover.fg-hover-colorize .fg-caption,.foogallery.fg-caption-hover.fg-hover-fade .fg-caption,.foogallery.fg-caption-hover.fg-hover-grayscale .fg-caption,.foogallery.fg-caption-hover.fg-hover-instant .fg-caption,.foogallery.fg-caption-hover.fg-hover-push .fg-caption,.foogallery.fg-caption-hover.fg-hover-scale .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-down .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-left .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-right .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-up .fg-caption,.foogallery.fg-hover-colorize .fg-image,.foogallery.fg-hover-colorize .fg-thumb:before,.foogallery.fg-hover-fade .fg-thumb:before,.foogallery.fg-hover-grayscale .fg-image,.foogallery.fg-hover-grayscale .fg-thumb:before,.foogallery.fg-hover-instant .fg-thumb:before,.foogallery.fg-hover-push .fg-thumb,.foogallery.fg-hover-scale .fg-item,.foogallery.fg-hover-scale .fg-thumb:before,.foogallery.fg-hover-slide-down .fg-thumb:before,.foogallery.fg-hover-slide-left .fg-thumb:before,.foogallery.fg-hover-slide-right .fg-thumb:before,.foogallery.fg-hover-slide-up .fg-thumb:before{transition-timing-function:ease;transition-duration:.3s}.foogallery.fg-hover-colorize .fg-image{filter:url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'saturate\' values=\'0\'/></filter></svg>#grayscale");filter:gray;-webkit-filter:grayscale(100%);-webkit-transition-property:-webkit-filter;transition-property:filter}.foogallery.fg-hover-colorize .fg-item-inner:hover .fg-image{-webkit-filter:none;filter:none}.foogallery.fg-caption-hover.fg-hover-colorize .fg-caption,.foogallery.fg-hover-colorize .fg-thumb:before{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity}.foogallery.fg-caption-hover.fg-hover-colorize .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-colorize .fg-item-inner:hover .fg-thumb:before{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-fade .fg-loaded .fg-caption,.foogallery.fg-hover-fade .fg-loaded .fg-thumb:before{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity}.foogallery.fg-caption-hover.fg-hover-fade .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-fade .fg-loaded .fg-item-inner:hover .fg-thumb:before{visibility:visible;opacity:1}.foogallery.fg-hover-grayscale .fg-image{-webkit-filter:none;filter:none;-webkit-transition-property:-webkit-filter;transition-property:filter}.foogallery.fg-hover-grayscale .fg-item-inner:hover .fg-image{-webkit-filter:grayscale(1);-webkit-filter:grayscale(100%);filter:grayscale(100%);filter:gray;opacity:1}.foogallery.fg-caption-hover.fg-hover-grayscale .fg-caption,.foogallery.fg-hover-grayscale .fg-thumb:before{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity}.foogallery.fg-caption-hover.fg-hover-grayscale .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-grayscale .fg-item-inner:hover .fg-thumb:before{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-instant .fg-loaded .fg-caption,.foogallery.fg-hover-instant .fg-loaded .fg-thumb:before{display:block;left:0;top:0;bottom:0;transition-property:none}.foogallery.fg-caption-hover.fg-hover-instant .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-instant .fg-loaded .fg-item-inner:hover .fg-thumb:before{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-caption,.foogallery.fg-hover-push .fg-loaded .fg-thumb:before{display:block;left:0;top:0;bottom:0;transform:translateX(100%);visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-caption,.foogallery.fg-hover-push .fg-loaded .fg-thumb{transition-property:transform}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-item-inner:hover .fg-caption{transform:translateY(0)}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-item-inner:hover .fg-thumb,.foogallery.fg-hover-push .fg-loaded .fg-item-inner:hover .fg-thumb{transform:translateX(-100%)}.foogallery.fg-hover-scale .fg-item{transition-property:transform;z-index:4}.foogallery.fg-hover-scale .fg-item:hover{transform:scale(1.048);z-index:10}.foogallery.fg-caption-hover.fg-hover-scale .fg-caption,.foogallery.fg-hover-scale .fg-thumb:before{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity}.foogallery.fg-caption-hover.fg-hover-scale .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-scale .fg-item-inner:hover .fg-thumb:before{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-slide-down .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-left .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-right .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-up .fg-loaded .fg-caption,.foogallery.fg-hover-slide-down .fg-loaded .fg-thumb:before,.foogallery.fg-hover-slide-left .fg-loaded .fg-thumb:before,.foogallery.fg-hover-slide-right .fg-loaded .fg-thumb:before,.foogallery.fg-hover-slide-up .fg-loaded .fg-thumb:before{display:block;left:0;top:0;bottom:0;transition-property:transform;visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-slide-down .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-left .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-right .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-up .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-slide-down .fg-loaded .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-slide-left .fg-loaded .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-slide-right .fg-loaded .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-slide-up .fg-loaded .fg-item-inner:hover .fg-thumb:before{transform:translateY(0) translateX(0)}.foogallery.fg-caption-hover.fg-hover-slide-up .fg-loaded .fg-caption,.foogallery.fg-hover-slide-up .fg-loaded .fg-thumb:before{transform:translateY(100%)}.foogallery.fg-caption-hover.fg-hover-slide-down .fg-loaded .fg-caption,.foogallery.fg-hover-slide-down .fg-loaded .fg-thumb:before{transform:translateY(-100%)}.foogallery.fg-caption-hover.fg-hover-slide-left .fg-loaded .fg-caption,.foogallery.fg-hover-slide-left .fg-loaded .fg-thumb:before{transform:translateX(100%)}.foogallery.fg-caption-hover.fg-hover-slide-right .fg-loaded .fg-caption,.foogallery.fg-hover-slide-right .fg-loaded .fg-thumb:before{transform:translateX(-100%)}.fg-paging-container,.fg-paging-container *,.fg-paging-container :after,.fg-paging-container :before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fg-paging-container{display:block;padding:15px;text-align:center;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fg-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.fg-paging-container .fg-dot-item,.fg-paging-container .fg-dots{display:inline-block;margin:0;padding:0;outline:0;list-style:none}.fg-paging-container .fg-dot-item .fg-dot-link{display:inline-block;margin:3px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;user-select:none;background-image:none;text-decoration:none;border:1px solid transparent;position:relative;border-radius:50%;padding:0;font-size:0;outline:0;color:transparent;box-shadow:none}.fg-paging-container .fg-dot-item .fg-dot-link:before{content:"";background-color:transparent;border:1px solid transparent;display:block;border-radius:50%;width:9px;height:9px;padding:0;margin:2px}.fg-paging-container .fg-dot-item .fg-dot-link:active,.fg-paging-container .fg-dot-item .fg-dot-link:focus,.fg-paging-container .fg-dot-item .fg-dot-link:hover{text-decoration:none;box-shadow:none;outline:0}.fg-paging-container .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container .fg-dot-item.fg-selected .fg-dot-link{cursor:not-allowed;pointer-events:none}.fg-paging-container .fg-dot-item.fg-disabled .fg-dot-link{cursor:not-allowed;pointer-events:none;outline:0}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link,.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:before{transition-timing-function:ease-out;transition-duration:.3s;transition-property:color,border-color,background-color}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link{background-color:#eee;border-color:#9e9e9e}.fg-paging-container.fg-light .fg-dot-item.fg-selected .fg-dot-link{border-color:#8a8a8a}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:focus:before,.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:hover:before,.fg-paging-container.fg-light .fg-dot-item.fg-selected .fg-dot-link:before{background-color:#666;border-color:#8a8a8a}.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link:focus,.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link:hover{background-color:#eee;border-color:#9e9e9e;opacity:.5}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link,.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:before{transition-timing-function:ease-out;transition-duration:.3s;transition-property:color,border-color,background-color}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link{background-color:#666;border-color:#333}.fg-paging-container.fg-dark .fg-dot-item.fg-selected .fg-dot-link{border-color:#444}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:focus:before,.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:hover:before,.fg-paging-container.fg-dark .fg-dot-item.fg-selected .fg-dot-link:before{background-color:#333;border-color:#444}.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link:focus,.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link:hover{background-color:#666;border-color:#333;opacity:.5}.fg-default:after{content:'';display:block;clear:both}.fg-default .fg-item,.fg-default .fg-item-inner,.fg-default .fg-thumb{display:inline-block;vertical-align:top;max-width:100%}.fg-default .fg-image{border-radius:0;display:block;max-width:100%;height:auto;margin:0;padding:0}.fg-default .fg-image{vertical-align:top}.fg-default.fg-left{text-align:left}.fg-default.fg-center{text-align:center}.fg-default.fg-right{text-align:right}.fg-default.fg-gutter-5{padding-left:5px;margin-bottom:-5px}.fg-default.fg-gutter-5 .fg-item{margin-right:5px;margin-bottom:5px}.fg-default.fg-gutter-10{padding-left:10px;margin-bottom:-10px}.fg-default.fg-gutter-10 .fg-item{margin-right:10px;margin-bottom:10px}.fg-default.fg-gutter-15{padding-left:15px;margin-bottom:-15px}.fg-default.fg-gutter-15 .fg-item{margin-right:15px;margin-bottom:15px}.fg-default.fg-gutter-20{padding-left:20px;margin-bottom:-20px}.fg-default.fg-gutter-20 .fg-item{margin-right:20px;margin-bottom:20px}.fg-default.fg-gutter-25{padding-left:25px;margin-bottom:-25px}.fg-default.fg-gutter-25 .fg-item{margin-right:25px;margin-bottom:25px}.fg-masonry *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.foogallery.fg-masonry.fg-center{margin:0 auto}.fg-masonry .fg-thumb{display:block}.fg-masonry.fg-masonry-fixed .fg-thumb{display:inline-block}.fg-masonry.fg-masonry-fixed .fg-image{max-width:100%}.fg-masonry .fg-column-width{display:inline-block;visibility:hidden;height:0;border:solid 0 transparent}.fg-masonry.fg-masonry-2col .fg-image,.fg-masonry.fg-masonry-3col .fg-image,.fg-masonry.fg-masonry-4col .fg-image,.fg-masonry.fg-masonry-5col .fg-image{width:100%;height:auto;max-width:100%}.fg-masonry .fg-item{line-height:0;font-size:0}.fg-masonry.fg-masonry-2col .fg-item{margin-bottom:1%;width:49%}.fg-masonry.fg-masonry-2col .fg-column-width{width:49%}.fg-masonry.fg-masonry-2col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-item{margin-bottom:0;width:50%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-column-width{width:50%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-item{margin-bottom:3%;width:47%}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-column-width{width:47%}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-gutter-width{width:3%}.fg-masonry.fg-masonry-3col .fg-item{margin-bottom:1%;width:32%}.fg-masonry.fg-masonry-3col .fg-column-width{width:32%}.fg-masonry.fg-masonry-3col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-item{margin-bottom:0;width:33%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-column-width{width:33%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-item{margin-bottom:3%;width:30%}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-column-width{width:30%}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-gutter-width{width:3%}.fg-masonry.fg-masonry-4col .fg-item{margin-bottom:1%;width:24%}.fg-masonry.fg-masonry-4col .fg-column-width{width:24%}.fg-masonry.fg-masonry-4col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item{margin-bottom:0;width:25%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width{width:25%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item{margin-bottom:3%;width:22%}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width{width:22%}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width{width:3%}.fg-masonry.fg-masonry-5col .fg-item{margin-bottom:1%;width:19%}.fg-masonry.fg-masonry-5col .fg-column-width{width:19%}.fg-masonry.fg-masonry-5col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item{margin-bottom:0;width:20%}.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width{width:20%}.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item{margin-bottom:3%;width:17%}.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width{width:17%}.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width{width:3%}@media screen and (max-width:720px){.fg-masonry.fg-masonry-4col .fg-item,.fg-masonry.fg-masonry-5col .fg-item{margin-bottom:1%;width:32%}.fg-masonry.fg-masonry-4col .fg-column-width,.fg-masonry.fg-masonry-5col .fg-column-width{width:32%}.fg-masonry.fg-masonry-4col .fg-gutter-width,.fg-masonry.fg-masonry-5col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item{margin-bottom:0;width:33%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width{width:33%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item{margin-bottom:3%;width:30%}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width{width:30%}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width{width:3%}}@media screen and (max-width:480px){.fg-masonry.fg-masonry-3col .fg-item,.fg-masonry.fg-masonry-4col .fg-item,.fg-masonry.fg-masonry-5col .fg-item{margin-bottom:1%;width:49%}.fg-masonry.fg-masonry-3col .fg-column-width,.fg-masonry.fg-masonry-4col .fg-column-width,.fg-masonry.fg-masonry-5col .fg-column-width{width:49%}.fg-masonry.fg-masonry-3col .fg-gutter-width,.fg-masonry.fg-masonry-4col .fg-gutter-width,.fg-masonry.fg-masonry-5col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item{margin-bottom:0;width:50%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width{width:50%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item{margin-bottom:3%;width:47%}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width{width:47%}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width{width:3%}}@media screen and (max-width:320px){.fg-masonry.fg-masonry-2col .fg-item,.fg-masonry.fg-masonry-3col .fg-item,.fg-masonry.fg-masonry-4col .fg-item,.fg-masonry.fg-masonry-5col .fg-item{margin-bottom:1%;width:100%}.fg-masonry.fg-masonry-2col .fg-column-width,.fg-masonry.fg-masonry-3col .fg-column-width,.fg-masonry.fg-masonry-4col .fg-column-width,.fg-masonry.fg-masonry-5col .fg-column-width{width:100%}.fg-masonry.fg-masonry-2col .fg-gutter-width,.fg-masonry.fg-masonry-3col .fg-gutter-width,.fg-masonry.fg-masonry-4col .fg-gutter-width,.fg-masonry.fg-masonry-5col .fg-gutter-width{width:0}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item{margin-bottom:0;width:100%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width{width:100%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item{margin-bottom:3%;width:100%}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width{width:100%}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width{width:0}}.foogallery.fg-border-thin .fg-column-width{border-width:5px}.foogallery.fg-border-medium .fg-column-width{border-width:10px}.foogallery.fg-border-thick .fg-column-width{border-width:15px}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner .fg-caption{visibility:visible;opacity:1;font-size:13px;position:relative;display:block;top:auto;bottom:auto;left:auto;right:auto;width:auto;height:auto;text-transform:none;transform:none;transition:none;background-color:transparent;border-style:solid;border-color:transparent}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner:hover .fg-caption{transform:none;transition:none}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner .fg-caption-inner{display:block;position:relative;max-height:none;top:auto;bottom:auto;left:auto;right:auto;width:auto;height:auto;border:none;transform:none;transition:none}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner .fg-caption-inner:before{display:none}.foogallery.fg-masonry.fg-captions-bottom.fg-caption-hover .fg-item-inner .fg-thumb:before{display:block}.foogallery.fg-masonry.fg-captions-bottom.fg-caption-always .fg-item-inner:hover .fg-caption{visibility:visible;opacity:1}.fg-masonry.fg-captions-bottom .fg-caption-desc,.fg-masonry.fg-captions-bottom .fg-caption-title{text-align:left}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption,.fg-masonry.fg-captions-bottom.fg-light .fg-caption{color:#828282}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption a,.fg-masonry.fg-captions-bottom.fg-light .fg-caption a{color:#828282;border-bottom:1px solid #828282}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption a:hover,.fg-masonry.fg-captions-bottom.fg-light .fg-caption a:hover{border-bottom:none}.fg-masonry.fg-captions-bottom.fg-light .fg-caption-title,.fg-masonry.fg-captions-bottom.fg-light .fg-caption-title a{color:#222}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption-title,.fg-masonry.fg-captions-bottom.fg-dark .fg-caption-title a{color:#fff}.fg-masonry.fg-captions-bottom.fg-light .fg-caption-title a{border-bottom:1px solid #222}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption-title a{border-bottom:1px solid #fff}.fg-masonry.fg-captions-bottom .fg-caption{border-width:10px}.fg-masonry.fg-captions-bottom .fg-caption-title+.fg-caption-desc{margin-top:5px}.fg-masonry.fg-captions-bottom.fg-border-thin .fg-caption{border-width:10px 5px 5px 5px}.fg-masonry.fg-captions-bottom.fg-border-medium .fg-caption{border-width:10px 0 0 0}.fg-masonry.fg-captions-bottom.fg-border-thick .fg-caption{border-width:15px 0 0 0}.fg-masonry.fg-captions-bottom.fg-border-thick .fg-caption-title+.fg-caption-desc{margin-top:10px}.fg-justified{box-sizing:border-box;position:relative}.foogallery.fg-justified .fg-image,.foogallery.fg-justified .fg-item,.foogallery.fg-justified .fg-item-inner,.foogallery.fg-justified .fg-thumb{box-sizing:border-box;display:block;margin:0;padding:0}.fg-justified .fg-item{visibility:visible;position:absolute}.fg-justified .fg-item-inner{position:relative;width:100%;height:100%}.fg-justified .fg-thumb{position:relative;overflow:hidden}.fg-justified .fg-image{z-index:1}.fg-justified .fg-item.fg-positioned .fg-thumb{width:100%;height:100%}.fg-justified .fg-item.fg-positioned .fg-image{width:100%;height:auto;min-height:100%}.fg-simple_portfolio{box-sizing:border-box;position:relative;font-size:16px;margin:0 auto;padding:0;width:100%}.fg-simple_portfolio .fg-item{position:absolute;display:inline-block;margin:0;padding:0;outline:0}.fg-simple_portfolio .fg-image,.fg-simple_portfolio .fg-item-inner,.fg-simple_portfolio .fg-thumb{display:block;margin:0;padding:0;outline:0}.fg-simple_portfolio .fg-item-inner{position:relative;width:100%;height:100%}.fg-simple_portfolio .fg-thumb{box-sizing:border-box;display:block;margin:0;padding:0;border:none;outline:0;position:relative;overflow:hidden}.fg-simple_portfolio .fg-item.fg-positioned .fg-image{width:100%;height:auto}.fg-simple_portfolio .fg-image{z-index:1}.foogallery.fg-simple_portfolio .fg-item-inner .fg-caption{visibility:visible;opacity:1;font-size:13px;position:relative;display:block;top:auto;bottom:auto;left:auto;right:auto;width:auto;height:auto;text-transform:none;transform:none;transition:none;background-color:transparent;border-style:solid;border-color:transparent}.foogallery.fg-simple_portfolio .fg-item-inner:hover .fg-caption{transform:none;transition:none}.foogallery.fg-simple_portfolio .fg-item-inner .fg-caption-inner{display:block;top:auto;bottom:auto;left:auto;right:auto;width:auto;height:auto;border:none;transform:none;transition:none}.foogallery.fg-simple_portfolio .fg-item-inner .fg-caption-inner:before{display:none}.foogallery.fg-simple_portfolio.fg-caption-hover .fg-item-inner .fg-thumb:before{display:block}.foogallery.fg-simple_portfolio.fg-caption-always .fg-item-inner:hover .fg-caption{visibility:visible;opacity:1}.fg-simple_portfolio .fg-caption-title{text-align:left}.fg-simple_portfolio .fg-caption-desc{text-align:left}.fg-simple_portfolio.fg-dark .fg-caption,.fg-simple_portfolio.fg-light .fg-caption{color:#828282}.fg-simple_portfolio.fg-dark .fg-caption a,.fg-simple_portfolio.fg-light .fg-caption a{color:#828282;border-bottom:1px solid #828282}.fg-simple_portfolio.fg-dark .fg-caption a:hover,.fg-simple_portfolio.fg-light .fg-caption a:hover{border-bottom:none}.fg-simple_portfolio.fg-light .fg-caption-title,.fg-simple_portfolio.fg-light .fg-caption-title a{color:#222}.fg-simple_portfolio.fg-dark .fg-caption-title,.fg-simple_portfolio.fg-dark .fg-caption-title a{color:#fff}.fg-simple_portfolio.fg-light .fg-caption-title a{border-bottom:1px solid #222}.fg-simple_portfolio.fg-dark .fg-caption-title a{border-bottom:1px solid #fff}.fg-simple_portfolio.fg-captions-top .fg-item.fg-positioned .fg-thumb{position:absolute;bottom:0;left:0}.fg-simple_portfolio .fg-caption{border-width:0}.fg-simple_portfolio .fg-caption-title+.fg-caption-desc{margin-top:5px}.fg-simple_portfolio.fg-border-thin .fg-caption{border-width:10px 5px 5px 5px}.fg-simple_portfolio.fg-captions-top.fg-border-thin .fg-caption{border-width:5px 5px 10px 5px}.fg-simple_portfolio.fg-border-medium .fg-caption{border-width:10px 0 0 0}.fg-simple_portfolio.fg-captions-top.fg-border-medium .fg-caption{border-width:0 0 10px 0}.fg-simple_portfolio.fg-border-thick .fg-caption{border-width:15px 0 0 0}.fg-simple_portfolio.fg-captions-top.fg-border-thick .fg-caption{border-width:0 0 15px 0}.fg-simple_portfolio.fg-border-thick .fg-caption-title+.fg-caption-desc{margin-top:10px}.foogallery.fg-preset.fg-polaroid .fg-item{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transition:-webkit-transform .35s,background-color .65s;transition:transform .35s,background-color .65s}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(2n+1){-webkit-transform:rotate(3deg);transform:rotate(3deg)}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(2n){-webkit-transform:rotate(-3deg);transform:rotate(-3deg)}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(3n){-webkit-transform:rotate(1deg);transform:rotate(1deg)}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(5n){-webkit-transform:rotate(-2deg);transform:rotate(-2deg)}.foogallery.fg-preset.fg-polaroid .fg-item:hover{-webkit-transform:rotate(0);transform:rotate(0)}.foogallery.fg-preset.fg-polaroid .fg-caption{position:relative;width:auto;font-family:"Segoe Print Regular",-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif}.foogallery.fg-preset.fg-polaroid .fg-caption-inner,.foogallery.fg-preset.fg-polaroid .fg-caption-title{position:relative;width:auto}.foogallery.fg-preset.fg-polaroid .fg-caption-title{text-align:center}.foogallery.fg-preset.fg-polaroid .fg-caption-desc{display:none}.foogallery.fg-light.fg-preset.fg-polaroid .fg-caption-title,.foogallery.fg-preset.fg-polaroid .fg-caption-title{color:#333}.foogallery.fg-dark.fg-preset.fg-polaroid .fg-caption-title{color:#fff}.foogallery.fg-preset.fg-polaroid .fg-caption{border-style:solid;border-color:transparent;border-width:10px}.foogallery.fg-preset.fg-polaroid .fg-caption-title+.fg-caption-desc{margin-top:5px}.foogallery.fg-preset.fg-polaroid.fg-border-thin .fg-caption{border-width:10px 5px 5px 5px}.foogallery.fg-preset.fg-polaroid.fg-captions-top.fg-border-thin .fg-caption{border-width:5px 5px 10px 5px}.foogallery.fg-preset.fg-polaroid.fg-border-medium .fg-caption{border-width:10px 0 0 0}.foogallery.fg-preset.fg-polaroid.fg-captions-top.fg-border-medium .fg-caption{border-width:0 0 10px 0}.foogallery.fg-preset.fg-polaroid.fg-border-thick .fg-caption{border-width:15px 0 0 0}.foogallery.fg-preset.fg-polaroid.fg-captions-top.fg-border-thick .fg-caption{border-width:0 0 15px 0}.foogallery.fg-preset.fg-polaroid.fg-border-thick .fg-caption-title+.fg-caption-desc{margin-top:10px}.fg-image-viewer{display:block;font-family:'Open Sans','Helvetica Neue',Arial,sans-serif}.fg-image-viewer.fg-left{text-align:left}.fg-image-viewer.fg-center{text-align:center}.fg-image-viewer.fg-right{text-align:right}.fiv-inner{position:relative;display:inline-block;max-width:100%;overflow:hidden;z-index:6}.fiv-inner .fiv-inner-container{position:relative;overflow:hidden;max-width:100%;border-style:solid;border-width:0;border-bottom-width:4px;z-index:5}.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb,.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb:active,.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb:hover,.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb:visited{position:relative;display:block;border:none;outline:0;text-decoration:none;box-shadow:none;max-width:100%}.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item{position:relative;visibility:visible;opacity:1;border:none;outline:0;text-decoration:none;box-shadow:none;max-width:100%}.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb img{display:block;max-width:100%;height:auto;border:none;outline:0;text-decoration:none}.fg-image-viewer .fiv-inner .fiv-ctrls{display:block;text-align:center;font-size:14px;border-style:solid;line-height:34px}.fg-image-viewer .fiv-inner .fiv-ctrls:after{content:'';display:block;clear:both}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-count{display:inline-block;font-weight:400;margin:0}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:none;min-width:80px;position:relative;overflow:hidden;transition:background-color .3s}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:before,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:before{display:block;position:absolute;font-size:24px;line-height:30px;top:0;left:0;width:100%;transform:translateY(0);transition:transform .3s}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:hover:before,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:hover:before{transform:translateY(-100%)}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next span,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev span{display:block;width:100%;transform:translateY(100%);transition:transform .3s}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:hover span,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:hover span{transform:translateY(0)}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev{float:left}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:before{content:'\2190'}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next{float:right}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:before{content:'\2192'}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-count span{margin:0 4px}/*!* Theme - Default (Light) *!*//*!* Theme - Dark *!*/.foogallery.fg-image-viewer.fg-caption-always .fg-item-inner .fg-caption{padding:0;border:none;background:#000;background:-moz-linear-gradient(left,rgba(0,0,0,.8) 0,rgba(0,0,0,.8) 60%,rgba(0,0,0,0) 100%);background:-webkit-linear-gradient(left,rgba(0,0,0,.8) 0,rgba(0,0,0,.8) 60%,rgba(0,0,0,0) 100%);background:linear-gradient(to right,rgba(0,0,0,.8) 0,rgba(0,0,0,.8) 60%,rgba(0,0,0,0) 100%)}.foogallery.fg-image-viewer.fg-caption-always .fg-caption-title{padding:10px 10px 10px 10px}.foogallery.fg-image-viewer.fg-caption-always .fg-caption-desc{padding:10px 10px 10px 10px}.foogallery.fg-image-viewer.fg-caption-always .fg-caption-title+.fg-caption-desc{padding:0 10px 10px 10px}.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-count,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-next,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-prev,.fg-image-viewer.fg-light .fiv-inner .fiv-inner-container{background-color:#fff;color:#333;border-color:#fff}.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-next:hover,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-prev:hover{background-color:#f2f2f2}.fg-image-viewer.fg-light .fiv-next,.fg-image-viewer.fg-light .fiv-prev{box-shadow:inset 0 0 0 1px #ddd}.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-count,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-next,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-prev,.fg-image-viewer.fg-dark .fiv-inner .fiv-inner-container{background-color:#333;color:#fff;border-color:#333}.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-next:hover,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-prev:hover{background-color:#444}.fg-image-viewer.fg-dark .fiv-next,.fg-image-viewer.fg-dark .fiv-prev{box-shadow:inset 0 0 0 1px #222}.foogallery.fg-image-viewer.fg-border-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin .fg-item-inner{border-width:0}.foogallery.fg-image-viewer .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thin .fiv-inner-container{border-width:4px}.foogallery.fg-image-viewer.fg-border-medium .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-medium .fiv-inner-container{border-width:10px}.foogallery.fg-image-viewer.fg-border-thick .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thick .fiv-inner-container{border-width:16px}.foogallery.fg-image-viewer .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-medium .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thick .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thin .fiv-ctrls{border-top-width:1px}.foogallery.fg-image-viewer.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-round-small .fiv-inner{border-radius:5px}.foogallery.fg-image-viewer.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-round-small .fg-item-inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.foogallery.fg-image-viewer.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-round-small .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fiv-prev,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fiv-prev,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-round-medium .fiv-inner{border-radius:10px}.foogallery.fg-image-viewer.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-round-medium .fg-item-inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.foogallery.fg-image-viewer.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-round-medium .fiv-prev{border-radius:5px}.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fiv-prev{border-radius:5px}.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fiv-prev,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-round-large .fiv-inner{border-radius:15px}.foogallery.fg-image-viewer.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-round-large .fg-item-inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.foogallery.fg-image-viewer.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-round-large .fiv-prev{border-radius:11px}.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fiv-prev{border-radius:11px}.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fiv-prev{border-radius:5px}.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-round-full .fiv-inner,.foogallery.fg-image-viewer.fg-round-full .fiv-next,.foogallery.fg-image-viewer.fg-round-full .fiv-prev{border-radius:50%}.foogallery.fg-image-viewer.fg-dark.fg-shadow-large .fg-item-inner,.foogallery.fg-image-viewer.fg-dark.fg-shadow-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-dark.fg-shadow-outline .fg-item-inner,.foogallery.fg-image-viewer.fg-dark.fg-shadow-small .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-large .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-outline .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-small .fg-item-inner{box-shadow:none}.foogallery.fg-image-viewer.fg-light.fg-shadow-outline .fiv-inner{box-shadow:0 0 0 1px #ddd}.foogallery.fg-image-viewer.fg-dark.fg-shadow-outline .fiv-inner{box-shadow:0 0 0 1px #222}.foogallery.fg-image-viewer.fg-dark.fg-shadow-small .fiv-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-small .fiv-inner{box-shadow:0 1px 4px 0 rgba(0,0,0,.5)}.foogallery.fg-image-viewer.fg-dark.fg-shadow-medium .fiv-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-medium .fiv-inner{box-shadow:0 1px 10px 0 rgba(0,0,0,.5)}.foogallery.fg-image-viewer.fg-dark.fg-shadow-large .fiv-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-large .fiv-inner{box-shadow:0 1px 16px 0 rgba(0,0,0,.5)}.foogallery.fg-thumbnail,.foogallery.fg-thumbnail.fg-center{text-align:center}.foogallery.fg-thumbnail.fg-left{text-align:left}.foogallery.fg-thumbnail.fg-right{text-align:right}.foogallery.fg-thumbnail.fg-float-left{float:left;width:auto}.foogallery.fg-thumbnail.fg-float-right{float:right;width:auto}.foogallery.fg-thumbnail .fg-item{display:inline-block;vertical-align:top;max-width:100%}.foogallery.fg-thumbnail .fg-image{max-width:100%}.foogallery.fg-thumbnail .fg-st-hidden{display:none}
1
+ .foogallery,.foogallery *{box-sizing:border-box}.foogallery{display:block;z-index:1;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;position:relative;line-height:0;font-size:0;width:100%;max-width:100%}.foogallery .fg-item{display:inline-block;position:relative;background-color:transparent;z-index:2;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.foogallery .fg-item-inner{display:block;position:relative;visibility:hidden;overflow:hidden;opacity:0;z-index:3;margin:0;border:solid 0 transparent}.foogallery .fg-item.fg-error,.foogallery .fg-item.fg-loading{background:no-repeat center}.foogallery .fg-item.fg-error{background-image:url(../img/image.png)}@media only screen and (-o-min-device-pixel-ratio:5/4),only screen and (-webkit-min-device-pixel-ratio:1.25),only screen and (min-device-pixel-ratio:1.25),only screen and (min-resolution:1.25dppx){.foogallery .fg-item.fg-error{background-image:url(../img/image@2x.png)}}@media only screen and (-o-min-device-pixel-ratio:9/4),only screen and (-webkit-min-device-pixel-ratio:2.25),only screen and (min-device-pixel-ratio:2.25),only screen and (min-resolution:2.25dppx){.foogallery .fg-item.fg-error{background-image:url(../img/image@3x.png)}}.foogallery .fg-item.fg-loaded{z-index:4}.foogallery .fg-loaded .fg-item-inner{visibility:visible;opacity:1;z-index:5}.foogallery .fg-error .fg-item-inner{pointer-events:none;cursor:default}.foogallery .fg-thumb{display:block;position:relative;border:none;outline:0;text-decoration:none;z-index:4}.foogallery .fg-image{display:block;position:relative;border:none;outline:0;text-decoration:none;z-index:5;max-width:none;height:auto;margin:0}.foogallery .fg-loaded .fg-thumb{z-index:6}.foogallery .fg-loaded .fg-image{z-index:7}.foogallery.fg-light .fg-item-inner{background-color:#fff;color:#333;border-color:#fff}.foogallery.fg-dark .fg-item-inner{background-color:#333;color:#fff;border-color:#333}.foogallery.fg-light .fg-item.fg-error,.foogallery.fg-light .fg-item.fg-idle,.foogallery.fg-light .fg-item.fg-loading{background-color:#eee;box-shadow:inset 0 0 0 1px #ddd}.foogallery.fg-dark .fg-item.fg-error,.foogallery.fg-dark .fg-item.fg-idle,.foogallery.fg-dark .fg-item.fg-loading{background-color:#444;box-shadow:inset 0 0 0 1px #333}.foogallery.fg-border-thin .fg-item-inner{border-width:4px}.foogallery.fg-border-medium .fg-item-inner{border-width:10px}.foogallery.fg-border-thick .fg-item-inner{border-width:16px}.foogallery.fg-light.fg-shadow-outline .fg-item-inner{box-shadow:0 0 0 1px #ddd}.foogallery.fg-dark.fg-shadow-outline .fg-item-inner{box-shadow:0 0 0 1px #222}.foogallery.fg-dark.fg-shadow-small .fg-item-inner,.foogallery.fg-light.fg-shadow-small .fg-item-inner{box-shadow:0 1px 4px 0 rgba(0,0,0,.5)}.foogallery.fg-dark.fg-shadow-medium .fg-item-inner,.foogallery.fg-light.fg-shadow-medium .fg-item-inner{box-shadow:0 1px 10px 0 rgba(0,0,0,.5)}.foogallery.fg-dark.fg-shadow-large .fg-item-inner,.foogallery.fg-light.fg-shadow-large .fg-item-inner{box-shadow:0 1px 16px 0 rgba(0,0,0,.5)}.foogallery.fg-shadow-inset-large .fg-thumb:after,.foogallery.fg-shadow-inset-medium .fg-thumb:after,.foogallery.fg-shadow-inset-small .fg-thumb:after{display:block;content:"";position:absolute;top:0;left:0;right:0;bottom:0;z-index:7}.foogallery.fg-dark.fg-shadow-inset-small .fg-thumb:after,.foogallery.fg-light.fg-shadow-inset-small .fg-thumb:after{box-shadow:inset 0 1px 4px 0 rgba(0,0,0,.3)}.foogallery.fg-dark.fg-shadow-inset-medium .fg-thumb:after,.foogallery.fg-light.fg-shadow-inset-medium .fg-thumb:after{box-shadow:inset 0 1px 10px 0 rgba(0,0,0,.3)}.foogallery.fg-dark.fg-shadow-inset-large .fg-thumb:after,.foogallery.fg-light.fg-shadow-inset-large .fg-thumb:after{box-shadow:inset 0 1px 16px 0 rgba(0,0,0,.3)}.foogallery.fg-round-full.fg-shadow-inset-large .fg-thumb:after,.foogallery.fg-round-full.fg-shadow-inset-medium .fg-thumb:after,.foogallery.fg-round-full.fg-shadow-inset-small .fg-thumb:after{border-radius:50%}.foogallery.fg-round-small .fg-item,.foogallery.fg-round-small .fg-item-inner{border-radius:5px}.foogallery.fg-round-medium .fg-item,.foogallery.fg-round-medium .fg-item-inner{border-radius:10px}.foogallery.fg-round-large .fg-item,.foogallery.fg-round-large .fg-item-inner{border-radius:15px}.foogallery.fg-round-full .fg-item,.foogallery.fg-round-full .fg-item-inner{border-radius:50%}.foogallery .fg-loader{position:absolute;top:50%;left:50%;transform:translateX(-50%) translateY(-50%);width:1em;height:1em;font-size:5px;visibility:hidden;opacity:0}.foogallery .fg-loading .fg-loader{visibility:visible;opacity:1}.fg-loading-default .fg-loader{border-radius:50%;text-indent:-9999em;-webkit-animation:loading-default 1.1s infinite ease;animation:loading-default 1.1s infinite ease}@-webkit-keyframes loading-default{0%,100%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,1),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.5),-1.8em -1.8em 0 0 rgba(130,130,130,.7)}12.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.7),1.8em -1.8em 0 0 rgba(130,130,130,1),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.5)}25%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.5),1.8em -1.8em 0 0 rgba(130,130,130,.7),2.5em 0 0 0 rgba(130,130,130,1),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}37.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.5),2.5em 0 0 0 rgba(130,130,130,.7),1.75em 1.75em 0 0 rgba(130,130,130,1),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}50%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.5),1.75em 1.75em 0 0 rgba(130,130,130,.7),0 2.5em 0 0 rgba(130,130,130,1),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}62.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.5),0 2.5em 0 0 rgba(130,130,130,.7),-1.8em 1.8em 0 0 rgba(130,130,130,1),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}75%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.5),-1.8em 1.8em 0 0 rgba(130,130,130,.7),-2.6em 0 0 0 rgba(130,130,130,1),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}87.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.5),-2.6em 0 0 0 rgba(130,130,130,.7),-1.8em -1.8em 0 0 rgba(130,130,130,1)}}@keyframes loading-default{0%,100%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,1),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.5),-1.8em -1.8em 0 0 rgba(130,130,130,.7)}12.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.7),1.8em -1.8em 0 0 rgba(130,130,130,1),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.5)}25%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.5),1.8em -1.8em 0 0 rgba(130,130,130,.7),2.5em 0 0 0 rgba(130,130,130,1),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}37.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.5),2.5em 0 0 0 rgba(130,130,130,.7),1.75em 1.75em 0 0 rgba(130,130,130,1),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}50%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.5),1.75em 1.75em 0 0 rgba(130,130,130,.7),0 2.5em 0 0 rgba(130,130,130,1),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}62.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.5),0 2.5em 0 0 rgba(130,130,130,.7),-1.8em 1.8em 0 0 rgba(130,130,130,1),-2.6em 0 0 0 rgba(130,130,130,.2),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}75%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.5),-1.8em 1.8em 0 0 rgba(130,130,130,.7),-2.6em 0 0 0 rgba(130,130,130,1),-1.8em -1.8em 0 0 rgba(130,130,130,.2)}87.5%{box-shadow:0 -2.6em 0 0 rgba(130,130,130,.2),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.5),-2.6em 0 0 0 rgba(130,130,130,.7),-1.8em -1.8em 0 0 rgba(130,130,130,1)}}.fg-loading-bars .fg-loader,.fg-loading-bars .fg-loader:after,.fg-loading-bars .fg-loader:before{background:rgba(130,130,130,1);-webkit-animation:loading-bars 1s infinite ease-in-out;animation:loading-bars 1s infinite ease-in-out;width:1em;height:4em}.fg-loading-bars .fg-loader{color:rgba(130,130,130,1);text-indent:-9999em;font-size:4px;-webkit-animation-delay:-.16s;animation-delay:-.16s}.fg-loading-bars .fg-loader:after,.fg-loading-bars .fg-loader:before{position:absolute;top:0;content:''}.fg-loading-bars .fg-loader:before{left:-1.5em;-webkit-animation-delay:-.32s;animation-delay:-.32s}.fg-loading-bars .fg-loader:after{left:1.5em}@-webkit-keyframes loading-bars{0%,100%,80%{box-shadow:0 0;height:4em}40%{box-shadow:0 -2em;height:5em}}@keyframes loading-bars{0%,100%,80%{box-shadow:0 0;height:4em}40%{box-shadow:0 -2em;height:5em}}.fg-loading-trail .fg-loader{color:#828282;font-size:20px;text-indent:-9999em;overflow:hidden;border-radius:50%;-webkit-animation:loading-trail-1 1.7s infinite ease,loading-trail-2 1.7s infinite ease;animation:loading-trail-1 1.7s infinite ease,loading-trail-2 1.7s infinite ease}@-webkit-keyframes loading-trail-1{0%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}5%,95%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}10%,59%{box-shadow:0 -.83em 0 -.4em,-.087em -.825em 0 -.42em,-.173em -.812em 0 -.44em,-.256em -.789em 0 -.46em,-.297em -.775em 0 -.477em}20%{box-shadow:0 -.83em 0 -.4em,-.338em -.758em 0 -.42em,-.555em -.617em 0 -.44em,-.671em -.488em 0 -.46em,-.749em -.34em 0 -.477em}38%{box-shadow:0 -.83em 0 -.4em,-.377em -.74em 0 -.42em,-.645em -.522em 0 -.44em,-.775em -.297em 0 -.46em,-.82em -.09em 0 -.477em}100%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}}@keyframes loading-trail-1{0%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}5%,95%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}10%,59%{box-shadow:0 -.83em 0 -.4em,-.087em -.825em 0 -.42em,-.173em -.812em 0 -.44em,-.256em -.789em 0 -.46em,-.297em -.775em 0 -.477em}20%{box-shadow:0 -.83em 0 -.4em,-.338em -.758em 0 -.42em,-.555em -.617em 0 -.44em,-.671em -.488em 0 -.46em,-.749em -.34em 0 -.477em}38%{box-shadow:0 -.83em 0 -.4em,-.377em -.74em 0 -.42em,-.645em -.522em 0 -.44em,-.775em -.297em 0 -.46em,-.82em -.09em 0 -.477em}100%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}}@-webkit-keyframes loading-trail-2{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}@keyframes loading-trail-2{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}.fg-loading-pulse .fg-loader,.fg-loading-pulse .fg-loader:after,.fg-loading-pulse .fg-loader:before{border-radius:50%;width:2.5em;height:2.5em;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation:loading-pulse 1.8s infinite ease-in-out;animation:loading-pulse 1.8s infinite ease-in-out}.fg-loading-pulse .fg-loader{color:#828282;font-size:4px;text-indent:-9999em;transform:translateX(-50%) translateY(-150%);-webkit-animation-delay:-.16s;animation-delay:-.16s}.fg-loading-pulse .fg-loader:after,.fg-loading-pulse .fg-loader:before{content:'';position:absolute;top:0}.fg-loading-pulse .fg-loader:before{left:-3.5em;-webkit-animation-delay:-.32s;animation-delay:-.32s}.fg-loading-pulse .fg-loader:after{left:3.5em}@-webkit-keyframes loading-pulse{0%,100%,80%{box-shadow:0 2.5em 0 -1.3em}40%{box-shadow:0 2.5em 0 0}}@keyframes loading-pulse{0%,100%,80%{box-shadow:0 2.5em 0 -1.3em}40%{box-shadow:0 2.5em 0 0}}.fg-loading-dots .fg-loader{color:#828282;font-size:5px;border-radius:50%;text-indent:-9999em;-webkit-animation:loading-dots 1.3s infinite linear;animation:loading-dots 1.3s infinite linear}@-webkit-keyframes loading-dots{0%,100%{box-shadow:0 -3em 0 .2em,2em -2em 0 0,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 0}12.5%{box-shadow:0 -3em 0 0,2em -2em 0 .2em,3em 0 0 0,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}25%{box-shadow:0 -3em 0 -.5em,2em -2em 0 0,3em 0 0 .2em,2em 2em 0 0,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}37.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 0,2em 2em 0 .2em,0 3em 0 0,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}50%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 0,0 3em 0 .2em,-2em 2em 0 0,-3em 0 0 -1em,-2em -2em 0 -1em}62.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 0,-2em 2em 0 .2em,-3em 0 0 0,-2em -2em 0 -1em}75%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 .2em,-2em -2em 0 0}87.5%{box-shadow:0 -3em 0 0,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 0,-2em -2em 0 .2em}}@keyframes loading-dots{0%,100%{box-shadow:0 -3em 0 .2em,2em -2em 0 0,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 0}12.5%{box-shadow:0 -3em 0 0,2em -2em 0 .2em,3em 0 0 0,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}25%{box-shadow:0 -3em 0 -.5em,2em -2em 0 0,3em 0 0 .2em,2em 2em 0 0,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}37.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 0,2em 2em 0 .2em,0 3em 0 0,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}50%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 0,0 3em 0 .2em,-2em 2em 0 0,-3em 0 0 -1em,-2em -2em 0 -1em}62.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 0,-2em 2em 0 .2em,-3em 0 0 0,-2em -2em 0 -1em}75%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 .2em,-2em -2em 0 0}87.5%{box-shadow:0 -3em 0 0,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 0,-2em -2em 0 .2em}}.fg-loading-partial .fg-loader,.fg-loading-partial .fg-loader:after{border-radius:50%;width:10em;height:10em}.fg-loading-partial .fg-loader{font-size:4px;text-indent:-9999em;border-top:1.1em solid rgba(130,130,130,.2);border-right:1.1em solid rgba(130,130,130,.2);border-bottom:1.1em solid rgba(130,130,130,.2);border-left:1.1em solid #828282;-webkit-animation:loading-partial 1.1s infinite linear;animation:loading-partial 1.1s infinite linear}@-webkit-keyframes loading-partial{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}@keyframes loading-partial{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}.foogallery.fg-loaded-drop .fg-item,.foogallery.fg-loaded-fade-in .fg-item,.foogallery.fg-loaded-flip .fg-item,.foogallery.fg-loaded-fly .fg-item,.foogallery.fg-loaded-scale-up .fg-item,.foogallery.fg-loaded-slide-down .fg-item,.foogallery.fg-loaded-slide-left .fg-item,.foogallery.fg-loaded-slide-right .fg-item,.foogallery.fg-loaded-slide-up .fg-item,.foogallery.fg-loaded-swing-down .fg-item{transition-timing-function:ease;transition-duration:650ms;transition-property:background-color,transform}.foogallery.fg-loaded-drop .fg-item-inner,.foogallery.fg-loaded-fade-in .fg-item-inner,.foogallery.fg-loaded-flip .fg-item-inner,.foogallery.fg-loaded-fly .fg-item-inner,.foogallery.fg-loaded-scale-up .fg-item-inner,.foogallery.fg-loaded-slide-down .fg-item-inner,.foogallery.fg-loaded-slide-left .fg-item-inner,.foogallery.fg-loaded-slide-right .fg-item-inner,.foogallery.fg-loaded-slide-up .fg-item-inner,.foogallery.fg-loaded-swing-down .fg-item-inner{transition-timing-function:ease;transition-duration:650ms}.foogallery.fg-loaded-drop .fg-item.fg-loaded,.foogallery.fg-loaded-flip .fg-item.fg-loaded,.foogallery.fg-loaded-fly .fg-item.fg-loaded,.foogallery.fg-loaded-swing-down .fg-item.fg-loaded{perspective:1300px}.foogallery.fg-loaded-fade-in .fg-item-inner{transition-property:visibility,opacity}.foogallery .fg-caption{visibility:hidden;opacity:0;background-color:rgba(0,0,0,.6);color:#fff;position:absolute;z-index:8;width:100%;max-height:100%;overflow:hidden;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:13px;font-weight:400;line-height:1.3;border:none;text-align:center;cursor:pointer}.foogallery .fg-caption a{text-decoration:none;color:#fff;border-bottom:1px solid #fff}.foogallery .fg-caption a:hover{border-bottom:none}.foogallery .fg-caption-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:16px;font-weight:400;padding:5px}.foogallery .fg-caption-desc{padding:5px}.foogallery .fg-caption-title+.fg-caption-desc{padding-top:0}.foogallery.fg-caption-always .fg-caption .fg-caption-inner:before{display:none}.foogallery.fg-caption-always .fg-item.fg-loaded .fg-caption{left:0;bottom:0;transition-timing-function:ease;transition-duration:.3s;transition-property:visibility,opacity;visibility:visible;opacity:1;text-align:left}.foogallery.fg-caption-hover .fg-caption .fg-caption-inner{width:100%;max-height:100%;position:absolute;top:50%;left:0;transform:translateY(-50%)}.foogallery.fg-caption-hover .fg-item.fg-loaded .fg-thumb:before{display:none}.foogallery.fg-hover-circle-plus .fg-thumb:before,.foogallery.fg-hover-external .fg-thumb:before,.foogallery.fg-hover-eye .fg-thumb:before,.foogallery.fg-hover-plus .fg-thumb:before,.foogallery.fg-hover-tint .fg-thumb:before,.foogallery.fg-hover-zoom .fg-thumb:before,.foogallery.fg-hover-zoom2 .fg-thumb:before,.foogallery.fg-hover-zoom3 .fg-thumb:before{content:"";display:block;position:absolute;visibility:hidden;opacity:0;top:0;bottom:0;left:0;right:0;z-index:8;background:rgba(0,0,0,.5) no-repeat center center;background-size:32px 32px}.foogallery.fg-hover-circle-plus .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-circle-plus .fg-thumb:focus:before,.foogallery.fg-hover-external .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-external .fg-thumb:focus:before,.foogallery.fg-hover-eye .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-eye .fg-thumb:focus:before,.foogallery.fg-hover-plus .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-plus .fg-thumb:focus:before,.foogallery.fg-hover-tint .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-tint .fg-thumb:focus:before,.foogallery.fg-hover-zoom .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-zoom .fg-thumb:focus:before,.foogallery.fg-hover-zoom2 .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-zoom2 .fg-thumb:focus:before,.foogallery.fg-hover-zoom3 .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-zoom3 .fg-thumb:focus:before{visibility:visible;opacity:1}.foogallery.fg-hover-circle-plus .fg-caption-inner:before,.foogallery.fg-hover-external .fg-caption-inner:before,.foogallery.fg-hover-eye .fg-caption-inner:before,.foogallery.fg-hover-plus .fg-caption-inner:before,.foogallery.fg-hover-tint .fg-caption-inner:before,.foogallery.fg-hover-zoom .fg-caption-inner:before,.foogallery.fg-hover-zoom2 .fg-caption-inner:before,.foogallery.fg-hover-zoom3 .fg-caption-inner:before{content:"";display:inline-block;position:relative;width:32px;height:32px;margin:10px 0 5px 0;background:transparent no-repeat center center;background-size:32px 32px;vertical-align:middle}.foogallery.fg-hover-zoom .fg-caption-inner:before,.foogallery.fg-hover-zoom .fg-thumb:before{background-image:url(../img/zoom.png)}.foogallery.fg-hover-zoom2 .fg-caption-inner:before,.foogallery.fg-hover-zoom2 .fg-thumb:before{background-image:url(../img/zoom2.png)}.foogallery.fg-hover-zoom3 .fg-caption-inner:before,.foogallery.fg-hover-zoom3 .fg-thumb:before{background-image:url(../img/zoom3.png)}.foogallery.fg-hover-plus .fg-caption-inner:before,.foogallery.fg-hover-plus .fg-thumb:before{background-image:url(../img/plus.png)}.foogallery.fg-hover-circle-plus .fg-caption-inner:before,.foogallery.fg-hover-circle-plus .fg-thumb:before{background-image:url(../img/circle-plus.png)}.foogallery.fg-hover-eye .fg-caption-inner:before,.foogallery.fg-hover-eye .fg-thumb:before{background-image:url(../img/eye.png)}.foogallery.fg-hover-external .fg-caption-inner:before,.foogallery.fg-hover-external .fg-thumb:before{background-image:url(../img/external.png)}@media only screen and (-o-min-device-pixel-ratio:5/4),only screen and (-webkit-min-device-pixel-ratio:1.25),only screen and (min-device-pixel-ratio:1.25),only screen and (min-resolution:1.25dppx){.foogallery.fg-hover-zoom .fg-caption-inner:before,.foogallery.fg-hover-zoom .fg-thumb:before{background-image:url(../img/zoom@2x.png)}.foogallery.fg-hover-zoom2 .fg-caption-inner:before,.foogallery.fg-hover-zoom2 .fg-thumb:before{background-image:url(../img/zoom2@2x.png)}.foogallery.fg-hover-zoom3 .fg-caption-inner:before,.foogallery.fg-hover-zoom3 .fg-thumb:before{background-image:url(../img/zoom3@2x.png)}.foogallery.fg-hover-plus .fg-caption-inner:before,.foogallery.fg-hover-plus .fg-thumb:before{background-image:url(../img/plus@2x.png)}.foogallery.fg-hover-circle-plus .fg-caption-inner:before,.foogallery.fg-hover-circle-plus .fg-thumb:before{background-image:url(../img/circle-plus@2x.png)}.foogallery.fg-hover-eye .fg-caption-inner:before,.foogallery.fg-hover-eye .fg-thumb:before{background-image:url(../img/eye@2x.png)}.foogallery.fg-hover-external .fg-caption-inner:before,.foogallery.fg-hover-external .fg-thumb:before{background-image:url(../img/external@2x.png)}}@media only screen and (-o-min-device-pixel-ratio:9/4),only screen and (-webkit-min-device-pixel-ratio:2.25),only screen and (min-device-pixel-ratio:2.25),only screen and (min-resolution:2.25dppx){.foogallery.fg-hover-zoom .fg-caption-inner:before,.foogallery.fg-hover-zoom .fg-thumb:before{background-image:url(../img/zoom@3x.png)}.foogallery.fg-hover-zoom2 .fg-caption-inner:before,.foogallery.fg-hover-zoom2 .fg-thumb:before{background-image:url(../img/zoom2@3x.png)}.foogallery.fg-hover-zoom3 .fg-caption-inner:before,.foogallery.fg-hover-zoom3 .fg-thumb:before{background-image:url(../img/zoom3@3x.png)}.foogallery.fg-hover-plus .fg-caption-inner:before,.foogallery.fg-hover-plus .fg-thumb:before{background-image:url(../img/plus@3x.png)}.foogallery.fg-hover-circle-plus .fg-caption-inner:before,.foogallery.fg-hover-circle-plus .fg-thumb:before{background-image:url(../img/circle-plus@3x.png)}.foogallery.fg-hover-eye .fg-caption-inner:before,.foogallery.fg-hover-eye .fg-thumb:before{background-image:url(../img/eye@3x.png)}.foogallery.fg-hover-external .fg-caption-inner:before,.foogallery.fg-hover-external .fg-thumb:before{background-image:url(../img/external@3x.png)}}.foogallery.fg-caption-hover.fg-hover-colorize .fg-caption,.foogallery.fg-caption-hover.fg-hover-fade .fg-caption,.foogallery.fg-caption-hover.fg-hover-grayscale .fg-caption,.foogallery.fg-caption-hover.fg-hover-instant .fg-caption,.foogallery.fg-caption-hover.fg-hover-push .fg-caption,.foogallery.fg-caption-hover.fg-hover-scale .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-down .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-left .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-right .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-up .fg-caption,.foogallery.fg-hover-colorize .fg-image,.foogallery.fg-hover-colorize .fg-thumb:before,.foogallery.fg-hover-fade .fg-thumb:before,.foogallery.fg-hover-grayscale .fg-image,.foogallery.fg-hover-grayscale .fg-thumb:before,.foogallery.fg-hover-instant .fg-thumb:before,.foogallery.fg-hover-push .fg-thumb,.foogallery.fg-hover-scale .fg-item,.foogallery.fg-hover-scale .fg-thumb:before,.foogallery.fg-hover-slide-down .fg-thumb:before,.foogallery.fg-hover-slide-left .fg-thumb:before,.foogallery.fg-hover-slide-right .fg-thumb:before,.foogallery.fg-hover-slide-up .fg-thumb:before{transition-timing-function:ease;transition-duration:.3s}.foogallery.fg-hover-colorize .fg-image{filter:url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'saturate\' values=\'0\'/></filter></svg>#grayscale");filter:gray;-webkit-filter:grayscale(100%);-webkit-transition-property:-webkit-filter;transition-property:filter}.foogallery.fg-hover-colorize .fg-item-inner:hover .fg-image{-webkit-filter:none;filter:none}.foogallery.fg-caption-hover.fg-hover-colorize .fg-caption,.foogallery.fg-hover-colorize .fg-thumb:before{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity}.foogallery.fg-caption-hover.fg-hover-colorize .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-colorize .fg-item-inner:hover .fg-thumb:before{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-fade .fg-loaded .fg-caption,.foogallery.fg-hover-fade .fg-loaded .fg-thumb:before{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity}.foogallery.fg-caption-hover.fg-hover-fade .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-fade .fg-loaded .fg-item-inner:hover .fg-thumb:before{visibility:visible;opacity:1}.foogallery.fg-hover-grayscale .fg-image{-webkit-filter:none;filter:none;-webkit-transition-property:-webkit-filter;transition-property:filter}.foogallery.fg-hover-grayscale .fg-item-inner:hover .fg-image{-webkit-filter:grayscale(1);-webkit-filter:grayscale(100%);filter:grayscale(100%);filter:gray;opacity:1}.foogallery.fg-caption-hover.fg-hover-grayscale .fg-caption,.foogallery.fg-hover-grayscale .fg-thumb:before{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity}.foogallery.fg-caption-hover.fg-hover-grayscale .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-grayscale .fg-item-inner:hover .fg-thumb:before{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-instant .fg-loaded .fg-caption,.foogallery.fg-hover-instant .fg-loaded .fg-thumb:before{display:block;left:0;top:0;bottom:0;transition-property:none}.foogallery.fg-caption-hover.fg-hover-instant .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-instant .fg-loaded .fg-item-inner:hover .fg-thumb:before{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-caption,.foogallery.fg-hover-push .fg-loaded .fg-thumb:before{display:block;left:0;top:0;bottom:0;transform:translateX(100%);visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-caption,.foogallery.fg-hover-push .fg-loaded .fg-thumb{transition-property:transform}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-item-inner:hover .fg-caption{transform:translateY(0)}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-item-inner:hover .fg-thumb,.foogallery.fg-hover-push .fg-loaded .fg-item-inner:hover .fg-thumb{transform:translateX(-100%)}.foogallery.fg-hover-scale .fg-item{transition-property:transform;z-index:4}.foogallery.fg-hover-scale .fg-item:hover{transform:scale(1.048);z-index:10}.foogallery.fg-caption-hover.fg-hover-scale .fg-caption,.foogallery.fg-hover-scale .fg-thumb:before{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity}.foogallery.fg-caption-hover.fg-hover-scale .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-scale .fg-item-inner:hover .fg-thumb:before{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-slide-down .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-left .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-right .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-up .fg-loaded .fg-caption,.foogallery.fg-hover-slide-down .fg-loaded .fg-thumb:before,.foogallery.fg-hover-slide-left .fg-loaded .fg-thumb:before,.foogallery.fg-hover-slide-right .fg-loaded .fg-thumb:before,.foogallery.fg-hover-slide-up .fg-loaded .fg-thumb:before{display:block;left:0;top:0;bottom:0;transition-property:transform;visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-slide-down .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-left .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-right .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-up .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-slide-down .fg-loaded .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-slide-left .fg-loaded .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-slide-right .fg-loaded .fg-item-inner:hover .fg-thumb:before,.foogallery.fg-hover-slide-up .fg-loaded .fg-item-inner:hover .fg-thumb:before{transform:translateY(0) translateX(0)}.foogallery.fg-caption-hover.fg-hover-slide-up .fg-loaded .fg-caption,.foogallery.fg-hover-slide-up .fg-loaded .fg-thumb:before{transform:translateY(100%)}.foogallery.fg-caption-hover.fg-hover-slide-down .fg-loaded .fg-caption,.foogallery.fg-hover-slide-down .fg-loaded .fg-thumb:before{transform:translateY(-100%)}.foogallery.fg-caption-hover.fg-hover-slide-left .fg-loaded .fg-caption,.foogallery.fg-hover-slide-left .fg-loaded .fg-thumb:before{transform:translateX(100%)}.foogallery.fg-caption-hover.fg-hover-slide-right .fg-loaded .fg-caption,.foogallery.fg-hover-slide-right .fg-loaded .fg-thumb:before{transform:translateX(-100%)}.fg-paging-container,.fg-paging-container *,.fg-paging-container :after,.fg-paging-container :before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fg-paging-container{display:block;padding:15px;text-align:center;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fg-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.fg-paging-container .fg-dot-item,.fg-paging-container .fg-dots{display:inline-block;margin:0;padding:0;outline:0;list-style:none}.fg-paging-container .fg-dot-item .fg-dot-link{display:inline-block;margin:3px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;user-select:none;background-image:none;text-decoration:none;border:1px solid transparent;position:relative;border-radius:50%;padding:0;font-size:0;outline:0;color:transparent;box-shadow:none}.fg-paging-container .fg-dot-item .fg-dot-link:before{content:"";background-color:transparent;border:1px solid transparent;display:block;border-radius:50%;width:9px;height:9px;padding:0;margin:2px}.fg-paging-container .fg-dot-item .fg-dot-link:active,.fg-paging-container .fg-dot-item .fg-dot-link:focus,.fg-paging-container .fg-dot-item .fg-dot-link:hover{text-decoration:none;box-shadow:none;outline:0}.fg-paging-container .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container .fg-dot-item.fg-selected .fg-dot-link{cursor:not-allowed;pointer-events:none}.fg-paging-container .fg-dot-item.fg-disabled .fg-dot-link{cursor:not-allowed;pointer-events:none;outline:0}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link,.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:before{transition-timing-function:ease-out;transition-duration:.3s;transition-property:color,border-color,background-color}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link{background-color:#eee;border-color:#9e9e9e}.fg-paging-container.fg-light .fg-dot-item.fg-selected .fg-dot-link{border-color:#8a8a8a}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:focus:before,.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:hover:before,.fg-paging-container.fg-light .fg-dot-item.fg-selected .fg-dot-link:before{background-color:#666;border-color:#8a8a8a}.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link:focus,.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link:hover{background-color:#eee;border-color:#9e9e9e;opacity:.5}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link,.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:before{transition-timing-function:ease-out;transition-duration:.3s;transition-property:color,border-color,background-color}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link{background-color:#666;border-color:#333}.fg-paging-container.fg-dark .fg-dot-item.fg-selected .fg-dot-link{border-color:#444}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:focus:before,.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:hover:before,.fg-paging-container.fg-dark .fg-dot-item.fg-selected .fg-dot-link:before{background-color:#333;border-color:#444}.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link:focus,.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link:hover{background-color:#666;border-color:#333;opacity:.5}.fg-default:after{content:'';display:block;clear:both}.fg-default .fg-item,.fg-default .fg-item-inner,.fg-default .fg-thumb{display:inline-block;vertical-align:top;max-width:100%}.fg-default .fg-image{border-radius:0;display:block;max-width:100%;height:auto;margin:0;padding:0}.fg-default .fg-image{vertical-align:top}.fg-default.fg-left{text-align:left}.fg-default.fg-center{text-align:center}.fg-default.fg-right{text-align:right}.fg-default.fg-gutter-5{padding-left:5px;margin-bottom:-5px}.fg-default.fg-gutter-5 .fg-item{margin-right:5px;margin-bottom:5px}.fg-default.fg-gutter-10{padding-left:10px;margin-bottom:-10px}.fg-default.fg-gutter-10 .fg-item{margin-right:10px;margin-bottom:10px}.fg-default.fg-gutter-15{padding-left:15px;margin-bottom:-15px}.fg-default.fg-gutter-15 .fg-item{margin-right:15px;margin-bottom:15px}.fg-default.fg-gutter-20{padding-left:20px;margin-bottom:-20px}.fg-default.fg-gutter-20 .fg-item{margin-right:20px;margin-bottom:20px}.fg-default.fg-gutter-25{padding-left:25px;margin-bottom:-25px}.fg-default.fg-gutter-25 .fg-item{margin-right:25px;margin-bottom:25px}.fg-masonry *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.foogallery.fg-masonry.fg-center{margin:0 auto}.fg-masonry .fg-thumb{display:block}.fg-masonry.fg-masonry-fixed .fg-thumb{display:inline-block}.fg-masonry.fg-masonry-fixed .fg-image{max-width:100%}.fg-masonry .fg-column-width{display:inline-block;visibility:hidden;height:0;border:solid 0 transparent}.fg-masonry.fg-masonry-2col .fg-image,.fg-masonry.fg-masonry-3col .fg-image,.fg-masonry.fg-masonry-4col .fg-image,.fg-masonry.fg-masonry-5col .fg-image{width:100%;height:auto;max-width:100%}.fg-masonry .fg-item{line-height:0;font-size:0}.fg-masonry.fg-masonry-2col .fg-item{margin-bottom:1%;width:49%}.fg-masonry.fg-masonry-2col .fg-column-width{width:49%}.fg-masonry.fg-masonry-2col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-item{margin-bottom:0;width:50%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-column-width{width:50%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-item{margin-bottom:3%;width:47%}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-column-width{width:47%}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-gutter-width{width:3%}.fg-masonry.fg-masonry-3col .fg-item{margin-bottom:1%;width:32%}.fg-masonry.fg-masonry-3col .fg-column-width{width:32%}.fg-masonry.fg-masonry-3col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-item{margin-bottom:0;width:33%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-column-width{width:33%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-item{margin-bottom:3%;width:30%}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-column-width{width:30%}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-gutter-width{width:3%}.fg-masonry.fg-masonry-4col .fg-item{margin-bottom:1%;width:24%}.fg-masonry.fg-masonry-4col .fg-column-width{width:24%}.fg-masonry.fg-masonry-4col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item{margin-bottom:0;width:25%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width{width:25%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item{margin-bottom:3%;width:22%}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width{width:22%}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width{width:3%}.fg-masonry.fg-masonry-5col .fg-item{margin-bottom:1%;width:19%}.fg-masonry.fg-masonry-5col .fg-column-width{width:19%}.fg-masonry.fg-masonry-5col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item{margin-bottom:0;width:20%}.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width{width:20%}.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item{margin-bottom:3%;width:17%}.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width{width:17%}.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width{width:3%}@media screen and (max-width:720px){.fg-masonry.fg-masonry-4col .fg-item,.fg-masonry.fg-masonry-5col .fg-item{margin-bottom:1%;width:32%}.fg-masonry.fg-masonry-4col .fg-column-width,.fg-masonry.fg-masonry-5col .fg-column-width{width:32%}.fg-masonry.fg-masonry-4col .fg-gutter-width,.fg-masonry.fg-masonry-5col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item{margin-bottom:0;width:33%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width{width:33%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item{margin-bottom:3%;width:30%}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width{width:30%}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width{width:3%}}@media screen and (max-width:480px){.fg-masonry.fg-masonry-3col .fg-item,.fg-masonry.fg-masonry-4col .fg-item,.fg-masonry.fg-masonry-5col .fg-item{margin-bottom:1%;width:49%}.fg-masonry.fg-masonry-3col .fg-column-width,.fg-masonry.fg-masonry-4col .fg-column-width,.fg-masonry.fg-masonry-5col .fg-column-width{width:49%}.fg-masonry.fg-masonry-3col .fg-gutter-width,.fg-masonry.fg-masonry-4col .fg-gutter-width,.fg-masonry.fg-masonry-5col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item{margin-bottom:0;width:50%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width{width:50%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item{margin-bottom:3%;width:47%}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width{width:47%}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width{width:3%}}@media screen and (max-width:320px){.fg-masonry.fg-masonry-2col .fg-item,.fg-masonry.fg-masonry-3col .fg-item,.fg-masonry.fg-masonry-4col .fg-item,.fg-masonry.fg-masonry-5col .fg-item{margin-bottom:1%;width:100%}.fg-masonry.fg-masonry-2col .fg-column-width,.fg-masonry.fg-masonry-3col .fg-column-width,.fg-masonry.fg-masonry-4col .fg-column-width,.fg-masonry.fg-masonry-5col .fg-column-width{width:100%}.fg-masonry.fg-masonry-2col .fg-gutter-width,.fg-masonry.fg-masonry-3col .fg-gutter-width,.fg-masonry.fg-masonry-4col .fg-gutter-width,.fg-masonry.fg-masonry-5col .fg-gutter-width{width:0}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item{margin-bottom:0;width:100%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width{width:100%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item{margin-bottom:3%;width:100%}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width{width:100%}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width{width:0}}.foogallery.fg-border-thin .fg-column-width{border-width:5px}.foogallery.fg-border-medium .fg-column-width{border-width:10px}.foogallery.fg-border-thick .fg-column-width{border-width:15px}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner .fg-caption{visibility:visible;opacity:1;font-size:13px;position:relative;display:block;top:auto;bottom:auto;left:auto;right:auto;width:auto;height:auto;text-transform:none;transform:none;transition:none;background-color:transparent;border-style:solid;border-color:transparent}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner:hover .fg-caption{transform:none;transition:none}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner .fg-caption-inner{display:block;position:relative;max-height:none;top:auto;bottom:auto;left:auto;right:auto;width:auto;height:auto;border:none;transform:none;transition:none}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner .fg-caption-inner:before{display:none}.foogallery.fg-masonry.fg-captions-bottom.fg-caption-hover .fg-item-inner .fg-thumb:before{display:block}.foogallery.fg-masonry.fg-captions-bottom.fg-caption-always .fg-item-inner:hover .fg-caption{visibility:visible;opacity:1}.fg-masonry.fg-captions-bottom .fg-caption-desc,.fg-masonry.fg-captions-bottom .fg-caption-title{text-align:left}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption,.fg-masonry.fg-captions-bottom.fg-light .fg-caption{color:#828282}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption a,.fg-masonry.fg-captions-bottom.fg-light .fg-caption a{color:#828282;border-bottom:1px solid #828282}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption a:hover,.fg-masonry.fg-captions-bottom.fg-light .fg-caption a:hover{border-bottom:none}.fg-masonry.fg-captions-bottom.fg-light .fg-caption-title,.fg-masonry.fg-captions-bottom.fg-light .fg-caption-title a{color:#222}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption-title,.fg-masonry.fg-captions-bottom.fg-dark .fg-caption-title a{color:#fff}.fg-masonry.fg-captions-bottom.fg-light .fg-caption-title a{border-bottom:1px solid #222}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption-title a{border-bottom:1px solid #fff}.fg-masonry.fg-captions-bottom .fg-caption{border-width:10px}.fg-masonry.fg-captions-bottom .fg-caption-title+.fg-caption-desc{margin-top:5px}.fg-masonry.fg-captions-bottom.fg-border-thin .fg-caption{border-width:10px 5px 5px 5px}.fg-masonry.fg-captions-bottom.fg-border-medium .fg-caption{border-width:10px 0 0 0}.fg-masonry.fg-captions-bottom.fg-border-thick .fg-caption{border-width:15px 0 0 0}.fg-masonry.fg-captions-bottom.fg-border-thick .fg-caption-title+.fg-caption-desc{margin-top:10px}.fg-justified{box-sizing:border-box;position:relative}.foogallery.fg-justified .fg-image,.foogallery.fg-justified .fg-item,.foogallery.fg-justified .fg-item-inner,.foogallery.fg-justified .fg-thumb{box-sizing:border-box;display:block;margin:0;padding:0}.fg-justified .fg-item{visibility:visible;position:absolute}.fg-justified .fg-item-inner{position:relative;width:100%;height:100%}.fg-justified .fg-thumb{position:relative;overflow:hidden}.fg-justified .fg-image{z-index:1}.fg-justified .fg-item.fg-positioned .fg-thumb{width:100%;height:100%}.fg-justified .fg-item.fg-positioned .fg-image{width:100%;height:auto;min-height:100%;top:50%;transform:translateY(-50%)}.fg-simple_portfolio{box-sizing:border-box;position:relative;font-size:16px;margin:0 auto;padding:0;width:100%}.fg-simple_portfolio .fg-item{position:absolute;display:inline-block;margin:0;padding:0;outline:0}.fg-simple_portfolio .fg-image,.fg-simple_portfolio .fg-item-inner,.fg-simple_portfolio .fg-thumb{display:block;margin:0;padding:0;outline:0}.fg-simple_portfolio .fg-item-inner{position:relative;width:100%;height:100%}.fg-simple_portfolio .fg-thumb{box-sizing:border-box;display:block;margin:0;padding:0;border:none;outline:0;position:relative;overflow:hidden}.fg-simple_portfolio .fg-item.fg-positioned .fg-image{width:100%;height:auto}.fg-simple_portfolio .fg-image{z-index:1}.foogallery.fg-simple_portfolio .fg-item-inner .fg-caption{visibility:visible;opacity:1;font-size:13px;position:relative;display:block;top:auto;bottom:auto;left:auto;right:auto;width:auto;height:auto;text-transform:none;transform:none;transition:none;background-color:transparent;border-style:solid;border-color:transparent}.foogallery.fg-simple_portfolio .fg-item-inner:hover .fg-caption{transform:none;transition:none}.foogallery.fg-simple_portfolio .fg-item-inner .fg-caption-inner{display:block;top:auto;bottom:auto;left:auto;right:auto;width:auto;height:auto;border:none;transform:none;transition:none}.foogallery.fg-simple_portfolio .fg-item-inner .fg-caption-inner:before{display:none}.foogallery.fg-simple_portfolio.fg-caption-hover .fg-item-inner .fg-thumb:before{display:block}.foogallery.fg-simple_portfolio.fg-caption-always .fg-item-inner:hover .fg-caption{visibility:visible;opacity:1}.fg-simple_portfolio .fg-caption-title{text-align:left}.fg-simple_portfolio .fg-caption-desc{text-align:left}.fg-simple_portfolio.fg-dark .fg-caption,.fg-simple_portfolio.fg-light .fg-caption{color:#828282}.fg-simple_portfolio.fg-dark .fg-caption a,.fg-simple_portfolio.fg-light .fg-caption a{color:#828282;border-bottom:1px solid #828282}.fg-simple_portfolio.fg-dark .fg-caption a:hover,.fg-simple_portfolio.fg-light .fg-caption a:hover{border-bottom:none}.fg-simple_portfolio.fg-light .fg-caption-title,.fg-simple_portfolio.fg-light .fg-caption-title a{color:#222}.fg-simple_portfolio.fg-dark .fg-caption-title,.fg-simple_portfolio.fg-dark .fg-caption-title a{color:#fff}.fg-simple_portfolio.fg-light .fg-caption-title a{border-bottom:1px solid #222}.fg-simple_portfolio.fg-dark .fg-caption-title a{border-bottom:1px solid #fff}.fg-simple_portfolio.fg-captions-top .fg-item.fg-positioned .fg-thumb{position:absolute;bottom:0;left:0}.fg-simple_portfolio .fg-caption{border-width:0}.fg-simple_portfolio .fg-caption-title+.fg-caption-desc{margin-top:5px}.fg-simple_portfolio.fg-border-thin .fg-caption{border-width:10px 5px 5px 5px}.fg-simple_portfolio.fg-captions-top.fg-border-thin .fg-caption{border-width:5px 5px 10px 5px}.fg-simple_portfolio.fg-border-medium .fg-caption{border-width:10px 0 0 0}.fg-simple_portfolio.fg-captions-top.fg-border-medium .fg-caption{border-width:0 0 10px 0}.fg-simple_portfolio.fg-border-thick .fg-caption{border-width:15px 0 0 0}.fg-simple_portfolio.fg-captions-top.fg-border-thick .fg-caption{border-width:0 0 15px 0}.fg-simple_portfolio.fg-border-thick .fg-caption-title+.fg-caption-desc{margin-top:10px}.foogallery.fg-preset.fg-polaroid .fg-item{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transition:-webkit-transform .35s,background-color .65s;transition:transform .35s,background-color .65s}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(2n+1){-webkit-transform:rotate(3deg);transform:rotate(3deg)}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(2n){-webkit-transform:rotate(-3deg);transform:rotate(-3deg)}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(3n){-webkit-transform:rotate(1deg);transform:rotate(1deg)}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(5n){-webkit-transform:rotate(-2deg);transform:rotate(-2deg)}.foogallery.fg-preset.fg-polaroid .fg-item:hover{-webkit-transform:rotate(0);transform:rotate(0)}.foogallery.fg-preset.fg-polaroid .fg-caption{position:relative;width:auto;font-family:"Segoe Print Regular",-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif}.foogallery.fg-preset.fg-polaroid .fg-caption-inner,.foogallery.fg-preset.fg-polaroid .fg-caption-title{position:relative;width:auto}.foogallery.fg-preset.fg-polaroid .fg-caption-title{text-align:center}.foogallery.fg-preset.fg-polaroid .fg-caption-desc{display:none}.foogallery.fg-light.fg-preset.fg-polaroid .fg-caption-title,.foogallery.fg-preset.fg-polaroid .fg-caption-title{color:#333}.foogallery.fg-dark.fg-preset.fg-polaroid .fg-caption-title{color:#fff}.foogallery.fg-preset.fg-polaroid .fg-caption{border-style:solid;border-color:transparent;border-width:10px}.foogallery.fg-preset.fg-polaroid .fg-caption-title+.fg-caption-desc{margin-top:5px}.foogallery.fg-preset.fg-polaroid.fg-border-thin .fg-caption{border-width:10px 5px 5px 5px}.foogallery.fg-preset.fg-polaroid.fg-captions-top.fg-border-thin .fg-caption{border-width:5px 5px 10px 5px}.foogallery.fg-preset.fg-polaroid.fg-border-medium .fg-caption{border-width:10px 0 0 0}.foogallery.fg-preset.fg-polaroid.fg-captions-top.fg-border-medium .fg-caption{border-width:0 0 10px 0}.foogallery.fg-preset.fg-polaroid.fg-border-thick .fg-caption{border-width:15px 0 0 0}.foogallery.fg-preset.fg-polaroid.fg-captions-top.fg-border-thick .fg-caption{border-width:0 0 15px 0}.foogallery.fg-preset.fg-polaroid.fg-border-thick .fg-caption-title+.fg-caption-desc{margin-top:10px}.fg-image-viewer{display:block;font-family:'Open Sans','Helvetica Neue',Arial,sans-serif}.fg-image-viewer.fg-left{text-align:left}.fg-image-viewer.fg-center{text-align:center}.fg-image-viewer.fg-right{text-align:right}.fiv-inner{position:relative;display:inline-block;max-width:100%;overflow:hidden;z-index:6}.fiv-inner .fiv-inner-container{position:relative;overflow:hidden;max-width:100%;border-style:solid;border-width:0;border-bottom-width:4px;z-index:5}.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb,.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb:active,.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb:hover,.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb:visited{position:relative;display:block;border:none;outline:0;text-decoration:none;box-shadow:none;max-width:100%}.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item{position:relative;visibility:visible;opacity:1;border:none;outline:0;text-decoration:none;box-shadow:none;max-width:100%}.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb img{display:block;max-width:100%;height:auto;border:none;outline:0;text-decoration:none}.fg-image-viewer .fiv-inner .fiv-ctrls{display:block;text-align:center;font-size:14px;border-style:solid;line-height:34px}.fg-image-viewer .fiv-inner .fiv-ctrls:after{content:'';display:block;clear:both}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-count{display:inline-block;font-weight:400;margin:0}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:none;min-width:80px;position:relative;overflow:hidden;transition:background-color .3s}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:before,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:before{display:block;position:absolute;font-size:24px;line-height:30px;top:0;left:0;width:100%;transform:translateY(0);transition:transform .3s}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:hover:before,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:hover:before{transform:translateY(-100%)}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next span,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev span{display:block;width:100%;transform:translateY(100%);transition:transform .3s}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:hover span,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:hover span{transform:translateY(0)}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev{float:left}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:before{content:'\2190'}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next{float:right}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:before{content:'\2192'}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-count span{margin:0 4px}/*!* Theme - Default (Light) *!*//*!* Theme - Dark *!*/.foogallery.fg-image-viewer.fg-caption-always .fg-item-inner .fg-caption{padding:0;border:none;background:#000;background:-moz-linear-gradient(left,rgba(0,0,0,.8) 0,rgba(0,0,0,.8) 60%,rgba(0,0,0,0) 100%);background:-webkit-linear-gradient(left,rgba(0,0,0,.8) 0,rgba(0,0,0,.8) 60%,rgba(0,0,0,0) 100%);background:linear-gradient(to right,rgba(0,0,0,.8) 0,rgba(0,0,0,.8) 60%,rgba(0,0,0,0) 100%)}.foogallery.fg-image-viewer.fg-caption-always .fg-caption-title{padding:10px 10px 10px 10px}.foogallery.fg-image-viewer.fg-caption-always .fg-caption-desc{padding:10px 10px 10px 10px}.foogallery.fg-image-viewer.fg-caption-always .fg-caption-title+.fg-caption-desc{padding:0 10px 10px 10px}.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-count,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-next,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-prev,.fg-image-viewer.fg-light .fiv-inner .fiv-inner-container{background-color:#fff;color:#333;border-color:#fff}.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-next:hover,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-prev:hover{background-color:#f2f2f2}.fg-image-viewer.fg-light .fiv-next,.fg-image-viewer.fg-light .fiv-prev{box-shadow:inset 0 0 0 1px #ddd}.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-count,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-next,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-prev,.fg-image-viewer.fg-dark .fiv-inner .fiv-inner-container{background-color:#333;color:#fff;border-color:#333}.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-next:hover,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-prev:hover{background-color:#444}.fg-image-viewer.fg-dark .fiv-next,.fg-image-viewer.fg-dark .fiv-prev{box-shadow:inset 0 0 0 1px #222}.foogallery.fg-image-viewer.fg-border-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin .fg-item-inner{border-width:0}.foogallery.fg-image-viewer .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thin .fiv-inner-container{border-width:4px}.foogallery.fg-image-viewer.fg-border-medium .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-medium .fiv-inner-container{border-width:10px}.foogallery.fg-image-viewer.fg-border-thick .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thick .fiv-inner-container{border-width:16px}.foogallery.fg-image-viewer .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-medium .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thick .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thin .fiv-ctrls{border-top-width:1px}.foogallery.fg-image-viewer.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-round-small .fiv-inner{border-radius:5px}.foogallery.fg-image-viewer.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-round-small .fg-item-inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.foogallery.fg-image-viewer.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-round-small .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fiv-prev,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fiv-prev,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-round-medium .fiv-inner{border-radius:10px}.foogallery.fg-image-viewer.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-round-medium .fg-item-inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.foogallery.fg-image-viewer.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-round-medium .fiv-prev{border-radius:5px}.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fiv-prev{border-radius:5px}.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fiv-prev,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-round-large .fiv-inner{border-radius:15px}.foogallery.fg-image-viewer.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-round-large .fg-item-inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.foogallery.fg-image-viewer.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-round-large .fiv-prev{border-radius:11px}.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fiv-prev{border-radius:11px}.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fiv-prev{border-radius:5px}.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-round-full .fiv-inner,.foogallery.fg-image-viewer.fg-round-full .fiv-next,.foogallery.fg-image-viewer.fg-round-full .fiv-prev{border-radius:50%}.foogallery.fg-image-viewer.fg-dark.fg-shadow-large .fg-item-inner,.foogallery.fg-image-viewer.fg-dark.fg-shadow-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-dark.fg-shadow-outline .fg-item-inner,.foogallery.fg-image-viewer.fg-dark.fg-shadow-small .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-large .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-outline .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-small .fg-item-inner{box-shadow:none}.foogallery.fg-image-viewer.fg-light.fg-shadow-outline .fiv-inner{box-shadow:0 0 0 1px #ddd}.foogallery.fg-image-viewer.fg-dark.fg-shadow-outline .fiv-inner{box-shadow:0 0 0 1px #222}.foogallery.fg-image-viewer.fg-dark.fg-shadow-small .fiv-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-small .fiv-inner{box-shadow:0 1px 4px 0 rgba(0,0,0,.5)}.foogallery.fg-image-viewer.fg-dark.fg-shadow-medium .fiv-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-medium .fiv-inner{box-shadow:0 1px 10px 0 rgba(0,0,0,.5)}.foogallery.fg-image-viewer.fg-dark.fg-shadow-large .fiv-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-large .fiv-inner{box-shadow:0 1px 16px 0 rgba(0,0,0,.5)}.foogallery.fg-thumbnail,.foogallery.fg-thumbnail.fg-center{text-align:center}.foogallery.fg-thumbnail.fg-left{text-align:left}.foogallery.fg-thumbnail.fg-right{text-align:right}.foogallery.fg-thumbnail.fg-float-left{float:left;width:auto}.foogallery.fg-thumbnail.fg-float-right{float:right;width:auto}.foogallery.fg-thumbnail .fg-item{display:inline-block;vertical-align:top;max-width:100%}.foogallery.fg-thumbnail .fg-image{max-width:100%}.foogallery.fg-thumbnail .fg-st-hidden{display:none}
extensions/default-templates/shared/js/foogallery.js CHANGED
@@ -6963,6 +6963,8 @@
6963
  this.$el = $(element);
6964
  this.options = $.extend(true, {}, _.Justified.defaults, options);
6965
  this._items = [];
 
 
6966
  },
6967
  init: function(){
6968
  var self = this;
@@ -6974,11 +6976,22 @@
6974
  }
6975
  }
6976
  $(window).on("resize.justified", {self: self}, self.onWindowResize);
 
 
 
6977
  },
6978
  destroy: function(){
 
6979
  $(window).off("resize.justified");
6980
  this.$el.removeAttr("style");
6981
  },
 
 
 
 
 
 
 
6982
  parse: function(){
6983
  var self = this, visible = self.$el.is(':visible'),
6984
  $test = $('<div/>', {'class': self.$el.attr('class')}).css({
@@ -6989,7 +7002,7 @@
6989
  maxWidth: self.getContainerWidth()
6990
  }).appendTo('body');
6991
  self._items = self.$el.find(self.options.itemSelector).removeAttr("style").removeClass("fg-positioned").map(function(i, el){
6992
- var $item = $(el), width = 0, height = 0, ratio;
6993
  if (!visible){
6994
  var $clone = $item.clone();
6995
  $clone.appendTo($test);
@@ -6999,12 +7012,11 @@
6999
  width = $item.outerWidth();
7000
  height = $item.outerHeight();
7001
  }
7002
- ratio = self.options.rowHeight / height;
7003
 
7004
  return {
7005
  index: i,
7006
- width: width * ratio,
7007
- height: self.options.rowHeight,
7008
  top: 0,
7009
  left: 0,
7010
  $item: $item
@@ -7013,9 +7025,16 @@
7013
  $test.remove();
7014
  return self._items;
7015
  },
7016
- round: function(value){
7017
- return Math.round(value);
7018
- //return Math.round(value*2) / 2;
 
 
 
 
 
 
 
7019
  },
7020
  getContainerWidth: function(){
7021
  var self = this, visible = self.$el.is(':visible');
@@ -7033,23 +7052,21 @@
7033
  }
7034
 
7035
  var self = this,
7036
- containerWidth = self.getContainerWidth(),
7037
- rows = self.rows(containerWidth),
7038
- offsetTop = 0;
7039
-
7040
- for (var i = 0, l = rows.length, row; i < l; i++){
7041
- row = rows[i];
7042
- if (i === l - 1){
7043
- offsetTop = self.lastRow(row, containerWidth, offsetTop);
7044
- } else {
7045
- offsetTop = self.justify(row, containerWidth, offsetTop);
7046
- }
7047
  self.render(row);
7048
- }
7049
- self.$el.height(offsetTop);
7050
  // if our layout caused the container width to get smaller
7051
  // i.e. makes a scrollbar appear then layout again to account for it
7052
- if (autoCorrect && self.getContainerWidth() < containerWidth){
7053
  self.layout(false, false);
7054
  }
7055
  },
@@ -7070,69 +7087,107 @@
7070
  }
7071
  }
7072
  },
7073
- lastRow: function(row, containerWidth, offsetTop){
7074
- var self = this;
7075
- switch(self.options.lastRow){
7076
- case "hide":
7077
- row.visible = false;
7078
- break;
7079
- case "justify":
7080
- offsetTop = self.justify(row, containerWidth, offsetTop);
7081
- break;
7082
- case "nojustify":
7083
- if (row.width / containerWidth > self.options.justifyThreshold){
7084
- offsetTop = self.justify(row, containerWidth, offsetTop);
7085
- } else {
7086
- offsetTop = self.position(row, containerWidth, offsetTop, "left");
7087
- }
7088
- break;
7089
- case "right":
7090
- case "center":
7091
- case "left":
7092
- offsetTop = self.position(row, containerWidth, offsetTop, self.options.lastRow);
7093
- break;
7094
- default:
7095
- offsetTop = self.position(row, containerWidth, offsetTop, "left");
7096
- break;
7097
- }
7098
- return offsetTop;
7099
- },
7100
- justify: function(row, containerWidth, offsetTop){
7101
  var self = this,
7102
- left = 0,
7103
  margins = self.options.margins * (row.items.length - 1),
7104
- ratio = (containerWidth - margins) / row.width;
7105
 
7106
- if (row.index > 0) offsetTop += self.options.margins;
7107
- row.top = offsetTop;
7108
- row.width = self.round(row.width * ratio);
7109
- row.height = self.round(row.height * ratio);
7110
 
7111
- for (var j = 0, jl = row.items.length, item; j < jl; j++){
7112
- item = row.items[j];
7113
- item.width = self.round(item.width * ratio);
7114
- item.height = self.round(item.height * ratio);
7115
- item.top = offsetTop;
7116
- if (j > 0) left += self.options.margins;
 
 
 
 
 
 
 
 
 
7117
  item.left = left;
 
 
 
 
 
 
7118
  left += item.width;
7119
  }
7120
- return offsetTop + (row.height > self.options.maxRowHeight ? self.options.maxRowHeight : row.height);
 
7121
  },
7122
- position: function(row, containerWidth, offsetTop, alignment){
7123
- var self = this, lastItem = row.items[row.items.length - 1], diff = containerWidth - (lastItem.left + lastItem.width);
7124
- if (row.index > 0) offsetTop += self.options.margins;
7125
- row.top = offsetTop;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7126
  for (var i = 0, l = row.items.length, item; i < l; i++){
 
7127
  item = row.items[i];
7128
- item.top = offsetTop;
7129
- if (alignment === "center"){
7130
- item.left += diff / 2;
7131
- } else if (alignment === "right"){
7132
- item.left += diff;
7133
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7134
  }
7135
- return offsetTop + row.height;
7136
  },
7137
  items: function(){
7138
  return $.map(this._items, function(item){
@@ -7146,57 +7201,52 @@
7146
  };
7147
  });
7148
  },
7149
- rows: function(containerWidth){
7150
  var self = this,
7151
  items = self.items(),
7152
  rows = [],
7153
- process = items.length > 0,
7154
- index = -1, offsetTop = 0;
7155
 
7156
- while (process){
7157
- index += 1;
7158
- if (index > 0) offsetTop += self.options.margins;
7159
  var row = {
7160
- index: index,
7161
  visible: true,
7162
- top: offsetTop,
7163
  width: 0,
7164
  height: self.options.rowHeight,
 
 
7165
  items: []
7166
- }, remove = [], left = 0, tmp;
 
 
 
 
7167
 
7168
- for (var i = 0, il = items.length, item, ratio; i < il; i++){
7169
- item = items[i];
7170
- tmp = row.width + item.width;
7171
- if (tmp > containerWidth && i > 0){
7172
- break;
7173
- } else if (tmp > containerWidth && i == 0){
7174
- tmp = containerWidth;
7175
- ratio = containerWidth / item.width;
7176
- item.width = self.round(item.width * ratio);
7177
- item.height = self.round(item.height * ratio);
7178
- row.height = item.height;
7179
- }
7180
- item.top = row.top;
7181
- if (i > 0) left += self.options.margins;
7182
- item.left = left;
7183
- left += item.width;
7184
- row.width = tmp;
7185
- row.items.push(item);
7186
- remove.push(i);
7187
  }
7188
- // make sure we don't get stuck in a loop, there should always be items to be removed
7189
- if (remove.length === 0){
7190
- process = false;
7191
- break;
7192
- }
7193
- remove.sort(function(a, b){ return b - a; });
7194
- for (var j = 0, jl = remove.length; j < jl; j++){
7195
- items.splice(remove[j], 1);
7196
  }
7197
- rows.push(row);
7198
- process = items.length > 0;
 
 
 
7199
  }
 
 
7200
  return rows;
7201
  },
7202
  onWindowResize: function(e){
@@ -7210,7 +7260,8 @@
7210
  maxRowHeight: "200%",
7211
  margins: 0,
7212
  lastRow: "center",
7213
- justifyThreshold: 0.5
 
7214
  };
7215
 
7216
  })(
@@ -7241,13 +7292,13 @@
7241
  self.justified.layout( true );
7242
  },
7243
  onParsedItems: function(event, self, items){
7244
- self.justified.layout( true );
7245
  },
7246
  onAppendedItems: function(event, self, items){
7247
- self.justified.layout( true );
7248
  },
7249
  onDetachedItems: function(event, self, items){
7250
- self.justified.layout( true );
7251
  }
7252
  });
7253
 
@@ -7496,13 +7547,13 @@
7496
  self.portfolio.layout( true );
7497
  },
7498
  onParsedItems: function(event, self, items){
7499
- self.portfolio.layout( true );
7500
  },
7501
  onAppendedItems: function(event, self, items){
7502
- self.portfolio.layout( true );
7503
  },
7504
  onDetachedItems: function(event, self, items){
7505
- self.portfolio.layout( true );
7506
  }
7507
  });
7508
 
6963
  this.$el = $(element);
6964
  this.options = $.extend(true, {}, _.Justified.defaults, options);
6965
  this._items = [];
6966
+ this._lastRefresh = 0;
6967
+ this._refresh = null;
6968
  },
6969
  init: function(){
6970
  var self = this;
6976
  }
6977
  }
6978
  $(window).on("resize.justified", {self: self}, self.onWindowResize);
6979
+ this._refresh = setInterval(function(){
6980
+ self.refresh();
6981
+ }, self.options.refreshInterval);
6982
  },
6983
  destroy: function(){
6984
+ if (this._refresh) clearInterval(this._refresh);
6985
  $(window).off("resize.justified");
6986
  this.$el.removeAttr("style");
6987
  },
6988
+ refresh: function(){
6989
+ var maxWidth = this.getContainerWidth();
6990
+ if (maxWidth != this._lastRefresh){
6991
+ this.layout();
6992
+ this._lastRefresh = maxWidth;
6993
+ }
6994
+ },
6995
  parse: function(){
6996
  var self = this, visible = self.$el.is(':visible'),
6997
  $test = $('<div/>', {'class': self.$el.attr('class')}).css({
7002
  maxWidth: self.getContainerWidth()
7003
  }).appendTo('body');
7004
  self._items = self.$el.find(self.options.itemSelector).removeAttr("style").removeClass("fg-positioned").map(function(i, el){
7005
+ var $item = $(el), width = 0, height = 0;
7006
  if (!visible){
7007
  var $clone = $item.clone();
7008
  $clone.appendTo($test);
7012
  width = $item.outerWidth();
7013
  height = $item.outerHeight();
7014
  }
 
7015
 
7016
  return {
7017
  index: i,
7018
+ width: width,
7019
+ height: height,
7020
  top: 0,
7021
  left: 0,
7022
  $item: $item
7025
  $test.remove();
7026
  return self._items;
7027
  },
7028
+ getMaxRowHeight: function() {
7029
+ var self = this;
7030
+ if (_is.string(self.options.maxRowHeight)){
7031
+ if (self.options.maxRowHeight.indexOf('%')){
7032
+ self.options.maxRowHeight = self.options.rowHeight * (parseInt(self.options.maxRowHeight) / 100);
7033
+ } else {
7034
+ self.options.maxRowHeight = parseInt(self.options.maxRowHeight);
7035
+ }
7036
+ }
7037
+ return _is.number(self.options.maxRowHeight) ? self.options.maxRowHeight : self.options.rowHeight;
7038
  },
7039
  getContainerWidth: function(){
7040
  var self = this, visible = self.$el.is(':visible');
7052
  }
7053
 
7054
  var self = this,
7055
+ height = 0,
7056
+ maxWidth = self.getContainerWidth(),
7057
+ maxHeight = self.getMaxRowHeight(),
7058
+ rows = self.rows(maxWidth, maxHeight);
7059
+
7060
+ $.each(rows, function(ri, row){
7061
+ if (!row.visible) return;
7062
+ if (ri > 0) height += self.options.margins;
7063
+ height += row.height;
 
 
7064
  self.render(row);
7065
+ });
7066
+ self.$el.height(height);
7067
  // if our layout caused the container width to get smaller
7068
  // i.e. makes a scrollbar appear then layout again to account for it
7069
+ if (autoCorrect && self.getContainerWidth() < maxWidth){
7070
  self.layout(false, false);
7071
  }
7072
  },
7087
  }
7088
  }
7089
  },
7090
+ justify: function(row, top, maxWidth, maxHeight){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7091
  var self = this,
 
7092
  margins = self.options.margins * (row.items.length - 1),
7093
+ max = maxWidth - margins;
7094
 
7095
+ var w_ratio = max / row.width;
7096
+ row.width = row.width * w_ratio;
7097
+ row.height = row.height * w_ratio;
7098
+ row.top = top;
7099
 
7100
+ if (row.height > maxHeight){
7101
+ row.height = maxHeight;
7102
+ }
7103
+
7104
+ row.left = 0;
7105
+ if (row.width < max){
7106
+ // here I'm not sure if I should center, left or right align a row that cannot be displayed at 100% width
7107
+ row.left = (max - row.width) / 2;
7108
+ }
7109
+ row.width += margins;
7110
+
7111
+ var left = row.left;
7112
+ for (var i = 0, l = row.items.length, item; i < l; i++){
7113
+ if (i > 0) left += self.options.margins;
7114
+ item = row.items[i];
7115
  item.left = left;
7116
+ item.top = top;
7117
+ item.width = item.width * w_ratio;
7118
+ item.height = item.height * w_ratio;
7119
+ if (item.height > maxHeight){
7120
+ item.height = maxHeight;
7121
+ }
7122
  left += item.width;
7123
  }
7124
+
7125
+ return row.height;
7126
  },
7127
+ position: function(row, top, maxWidth, align){
7128
+ var self = this,
7129
+ margins = self.options.margins * (row.items.length - 1),
7130
+ max = maxWidth - margins;
7131
+
7132
+ row.top = top;
7133
+ row.left = 0;
7134
+ if (row.width < max){
7135
+ switch (align){
7136
+ case "center":
7137
+ row.left = (max - row.width) / 2;
7138
+ break;
7139
+ case "right":
7140
+ row.left = max - row.width;
7141
+ break;
7142
+ }
7143
+ }
7144
+ row.width += margins;
7145
+
7146
+ var left = row.left;
7147
  for (var i = 0, l = row.items.length, item; i < l; i++){
7148
+ if (i > 0) left += self.options.margins;
7149
  item = row.items[i];
7150
+ item.left = left;
7151
+ item.top = top;
7152
+ left += item.width;
7153
+ }
7154
+
7155
+ return row.height;
7156
+ },
7157
+ lastRow: function(row, top, maxWidth, maxHeight){
7158
+ var self = this,
7159
+ margins = self.options.margins * (row.items.length - 1),
7160
+ max = maxWidth - margins,
7161
+ threshold = row.width / max > self.options.justifyThreshold;
7162
+
7163
+ switch (self.options.lastRow){
7164
+ case "hide":
7165
+ if (threshold){
7166
+ self.justify(row, top, maxWidth, maxHeight);
7167
+ } else {
7168
+ row.visible = false;
7169
+ }
7170
+ break;
7171
+ case "justify":
7172
+ self.justify(row, top, maxWidth, maxHeight);
7173
+ break;
7174
+ case "nojustify":
7175
+ if (threshold){
7176
+ self.justify(row, top, maxWidth, maxHeight);
7177
+ } else {
7178
+ self.position(row, top, maxWidth, "left");
7179
+ }
7180
+ break;
7181
+ case "left":
7182
+ case "center":
7183
+ case "right":
7184
+ if (threshold){
7185
+ self.justify(row, top, maxWidth, maxHeight);
7186
+ } else {
7187
+ self.position(row, top, maxWidth, self.options.lastRow);
7188
+ }
7189
+ break;
7190
  }
 
7191
  },
7192
  items: function(){
7193
  return $.map(this._items, function(item){
7201
  };
7202
  });
7203
  },
7204
+ rows: function(maxWidth, maxHeight){
7205
  var self = this,
7206
  items = self.items(),
7207
  rows = [],
7208
+ index = -1;
 
7209
 
7210
+ function create(){
 
 
7211
  var row = {
7212
+ index: ++index,
7213
  visible: true,
 
7214
  width: 0,
7215
  height: self.options.rowHeight,
7216
+ top: 0,
7217
+ left: 0,
7218
  items: []
7219
+ };
7220
+ // push the row into the result collection now
7221
+ rows.push(row);
7222
+ return row;
7223
+ }
7224
 
7225
+ var row = create(), top = 0, tmp = 0;
7226
+ for (var i = 0, il = items.length, item; i < il; i++){
7227
+ item = items[i];
7228
+ // first make all the items match the row height
7229
+ if (item.height != self.options.rowHeight){
7230
+ var ratio = self.options.rowHeight / item.height;
7231
+ item.height = item.height * ratio;
7232
+ item.width = item.width * ratio;
 
 
 
 
 
 
 
 
 
 
 
7233
  }
7234
+
7235
+ if (tmp + item.width > maxWidth && i > 0){
7236
+ // adding this item to the row would exceed the max width
7237
+ if (rows.length > 1) top += self.options.margins;
7238
+ top += self.justify(row, top, maxWidth, maxHeight); // first justify the current row
7239
+ row = create(); // then make the new one
7240
+ tmp = 0;
 
7241
  }
7242
+
7243
+ if (row.items.length > 0) tmp += self.options.margins;
7244
+ tmp += item.width;
7245
+ row.width += item.width;
7246
+ row.items.push(item);
7247
  }
7248
+ if (rows.length > 1) top += self.options.margins;
7249
+ self.lastRow(row, top, maxWidth, maxHeight);
7250
  return rows;
7251
  },
7252
  onWindowResize: function(e){
7260
  maxRowHeight: "200%",
7261
  margins: 0,
7262
  lastRow: "center",
7263
+ justifyThreshold: 0.5,
7264
+ refreshInterval: 250
7265
  };
7266
 
7267
  })(
7292
  self.justified.layout( true );
7293
  },
7294
  onParsedItems: function(event, self, items){
7295
+ if (self.initialized) self.justified.layout( true );
7296
  },
7297
  onAppendedItems: function(event, self, items){
7298
+ if (self.initialized) self.justified.layout( true );
7299
  },
7300
  onDetachedItems: function(event, self, items){
7301
+ if (self.initialized) self.justified.layout( true );
7302
  }
7303
  });
7304
 
7547
  self.portfolio.layout( true );
7548
  },
7549
  onParsedItems: function(event, self, items){
7550
+ if (self.initialized) self.portfolio.layout( true );
7551
  },
7552
  onAppendedItems: function(event, self, items){
7553
+ if (self.initialized) self.portfolio.layout( true );
7554
  },
7555
  onDetachedItems: function(event, self, items){
7556
+ if (self.initialized) self.portfolio.layout( true );
7557
  }
7558
  });
7559
 
extensions/default-templates/shared/js/foogallery.min.js CHANGED
@@ -1,10 +1,11 @@
1
  /*
2
  * FooGallery - The Most Intuitive and Extensible Gallery Creation and Management Tool Ever Created for WordPress
3
- * @version 1.0.25
4
  * @link
5
  * @copyright Steven Usher & Brad Vincent 2015
6
  * @license Released under the GPLv3 license.
7
  */
8
 
9
  !function(a,b){b.$=a}(jQuery,window.FooGallery=window.FooGallery||{}),function(a){if(!a)return void console.warn("jQuery must be included in the page prior to the FooGallery.utils library.");var b={$:a,version:"0.0.8"};b.versionCompare=function(a,b){function c(a){for(var b=a.split("."),c=0,d=b.length;c<d;c++)b[c]=parseInt(b[c]),isNaN(b[c])&&(b[c]=0);return b}if(!/[\d.]/.test(a)||!/[\d.]/.test(b))return NaN;for(var d=c(a),e=c(b);d.length<e.length;)d.push(0);for(;e.length<d.length;)e.push(0);for(var f=0;f<d.length;++f){if(e.length==f)return 1;if(d[f]!=e[f])return d[f]>e[f]?1:-1}return d.length!=e.length?-1:0},!function(){try{return!!window.FooGallery.utils}catch(a){return!1}}()?window.FooGallery.utils=b:b.versionCompare(b.version,window.FooGallery.utils.version)>0?(console.warn("An older version of FooGallery.utils ("+window.FooGallery.utils.version+") already exists in the page, version "+b.version+" will override it."),window.FooGallery.utils=b):console.warn("A newer version of FooGallery.utils ("+window.FooGallery.utils.version+") already exists in the page, version "+b.version+" will not register itself.")}(jQuery),function(a,b){"0.0.8"===b.version&&(b.is={},b.is.array=function(a){return"[object Array]"===Object.prototype.toString.call(a)},b.is.boolean=function(a){return"[object Boolean]"===Object.prototype.toString.call(a)},b.is.element=function(a){return"object"==typeof HTMLElement?a instanceof HTMLElement:!!a&&"object"==typeof a&&null!==a&&1===a.nodeType&&"string"==typeof a.nodeName},b.is.empty=function(a){if(b.is.undef(a)||null===a)return!0;if(b.is.number(a)&&0==a)return!0;if(b.is.boolean(a)&&!1===a)return!0;if(b.is.string(a)&&0===a.length)return!0;if(b.is.array(a)&&0===a.length)return!0;if(b.is.jq(a)&&0===a.length)return!0;if(b.is.hash(a)){for(var c in a)if(a.hasOwnProperty(c))return!1;return!0}return!1},b.is.error=function(a){return"[object Error]"===Object.prototype.toString.call(a)},b.is.fn=function(a){return a===window.alert||"[object Function]"===Object.prototype.toString.call(a)},b.is.hash=function(a){return b.is.object(a)&&a.constructor===Object&&!a.nodeType&&!a.setInterval},b.is.jq=function(c){return!b.is.undef(a)&&c instanceof a},b.is.number=function(a){return"[object Number]"===Object.prototype.toString.call(a)&&!isNaN(a)},b.is.object=function(a){return"[object Object]"===Object.prototype.toString.call(a)&&!b.is.undef(a)&&null!==a},b.is.promise=function(a){return b.is.object(a)&&b.is.fn(a.then)&&b.is.fn(a.promise)},b.is.size=function(a){return!!(b.is.string(a)&&!b.is.empty(a)||b.is.number(a))&&/^(auto|none|(?:[\d\.]*)+?(?:%|px|mm|q|cm|in|pt|pc|em|ex|ch|rem|vh|vw|vmin|vmax)?)$/.test(a)},b.is.string=function(a){return"[object String]"===Object.prototype.toString.call(a)},b.is.undef=function(a){return void 0===a})}(FooGallery.utils.$,FooGallery.utils),function(a,b,c){if("0.0.8"===b.version){b.fn={};var d=Function.prototype.toString;b.fn.CONTAINS_SUPER=/xyz/.test(d.call(function(){xyz}))?/\b_super\b/:/.*/,b.fn.addOrOverride=function(a,e,f){if(c.object(a)&&c.string(e)&&!c.empty(e)&&c.fn(f)){var g=a[e],h=c.fn(g)&&b.fn.CONTAINS_SUPER.test(d.call(f));a[e]=h?function(a,b){return function(){var c=this._super;this._super=a;var d=b.apply(this,arguments);return this._super=c,d}}(g,f):f}},b.fn.apply=function(a,b){function d(){return a.apply(this,b)}return b=c.array(b)?b:[],d.prototype=a.prototype,new d},b.fn.arg2arr=function(a){return Array.prototype.slice.call(a)},b.fn.check=function(d,e,f,g){function h(a){return function(){return a.apply(d,arguments)}}return f=c.fn(f)?f:a.noop,d=c.object(d)?d:window,e=c.string(e)?b.fn.fetch(e,g):e,h(c.fn(e)?e:f)},b.fn.fetch=function(b,d){return!c.string(b)||c.empty(b)?null:(d=c.object(d)?d:window,a.each(b.split("."),function(a,b){if(!d[b])return!1;d=d[b]}),c.fn(d)?d:null)},b.fn.enqueue=function(d,e,f,g){function h(a,b){try{return n.push(a),b.apply(a,i)}catch(a){return j.reject(a,n),j}}var i=b.fn.arg2arr(arguments),j=a.Deferred(),k=a.Deferred(),l=k.promise(),m=[],n=[],o=!0;return d=i.shift(),e=i.shift(),a.each(d,function(a,d){c.fn(d[e])&&(l=l.then(function(){if(!o){var a=b.fn.arg2arr(arguments);m.push(a)}return o=!1,h(d,d[e])}))}),l.then(function(){if(!o){var a=b.fn.arg2arr(arguments);m.push(a)}o=!1,j.resolve(m)}),l.fail(function(){var a=b.fn.arg2arr(arguments);a.push(n),j.reject.apply(j,a)}),k.resolve(),j.promise()},b.fn.when=function(b){if(!c.array(b)||c.empty(b))return a.when();for(var d=a.Deferred(),e=[],f=b.length,g=0;g<b.length;g++)b[g].then(function(a){e.push(a)}).always(function(){--f||d.resolve(e)});return d.promise()},b.fn.rejectWith=function(c,d){var e=a.Deferred(),f=b.fn.arg2arr(arguments);return e.reject.apply(e,f).promise()},b.fn.resolveWith=function(c,d){var e=a.Deferred(),f=b.fn.arg2arr(arguments);return e.resolve.apply(e,f).promise()},b.fn.resolved=a.Deferred().resolve().promise(),b.fn.rejected=a.Deferred().reject().promise()}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b){if("0.0.8"===a.version){a.url={};var c=document.createElement("a");a.url.parts=function(a){return c.href=a,{hash:c.hash,host:c.host,hostname:c.hostname,href:c.href,origin:c.origin,pathname:c.pathname,port:c.port,protocol:c.protocol,search:c.search}},a.url.full=function(a){return!b.string(a)||b.empty(a)?null:(c.href=a,c.href)},a.url.param=function(a,c,d){if(!b.string(a)||!b.string(c)||b.empty(c))return a;var e,f,g,h;return b.undef(d)?(e=new RegExp("[?|&]"+c+"=([^&;]+?)(&|#|;|$)"),f=e.exec(a)||[,""],g=f[1].replace(/\+/g,"%20"),b.string(g)&&!b.empty(g)?decodeURIComponent(g):null):(""===d||null===d?(e=new RegExp("^([^#]*?)(([^#]*)&)?"+c+"(=[^&#]*)?(&|#|$)"),g=a.replace(e,"$1$3$5").replace(/^([^#]*)((\?)&|\?(#|$))/,"$1$3$4")):(e=new RegExp("([?&])"+c+"[^&]*"),h=c+"="+encodeURIComponent(d),(g=a.replace(e,"$1"+h))!==a||e.test(g)||(g+=(-1!==g.indexOf("?")?"&":"?")+h)),g)}}}(FooGallery.utils,FooGallery.utils.is),function(a,b,c){"0.0.8"===a.version&&(a.str={},a.str.camel=function(a){return b.empty(a)?a:a.toUpperCase()===a?a.toLowerCase():a.replace(/^([A-Z])|[-\s_]+(\w)/g,function(a,c,d){return b.string(d)?d.toUpperCase():c.toLowerCase()})},a.str.contains=function(a,c,d){return!(!b.string(a)||b.empty(a)||!b.string(c)||b.empty(c))&&(c.length<=a.length&&-1!==(d?a.toUpperCase().indexOf(c.toUpperCase()):a.indexOf(c)))},a.str.containsWord=function(a,c,d){if(!b.string(a)||b.empty(a)||!b.string(c)||b.empty(c)||a.length<c.length)return!1;for(var e=a.split(/\W/),f=0,g=e.length;f<g;f++)if(d?e[f].toUpperCase()==c.toUpperCase():e[f]==c)return!0;return!1},a.str.endsWith=function(a,c){return!b.string(a)||b.empty(a)||!b.string(c)||b.empty(c)?a==c:a.slice(a.length-c.length)==c},a.str.escapeRegExp=function(a){return b.empty(a)?a:a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},a.str.fnv1a=function(a){if(!b.string(a)||b.empty(a))return null;var c,d,e=2166136261;for(c=0,d=a.length;c<d;c++)e^=a.charCodeAt(c),e+=(e<<1)+(e<<4)+(e<<7)+(e<<8)+(e<<24);return e>>>0},a.str.from=function(c,d){return!b.string(c)||b.empty(c)||!b.string(d)||b.empty(d)?null:a.str.contains(c,d)?c.substring(c.indexOf(d)+d.length):null},a.str.join=function(d,e,f){if(!b.string(d)||!b.string(e))return null;var g=c.arg2arr(arguments);d=g.shift();var h,i,j=g.shift();for(h=0,i=g.length;h<i;h++)e=g[h],b.empty(e)||(a.str.endsWith(j,d)&&(j=j.slice(0,j.length-d.length)),a.str.startsWith(e,d)&&(e=e.slice(d.length)),j+=d+e);return j},a.str.startsWith=function(a,c){return!b.empty(a)&&!b.empty(c)&&a.slice(0,c.length)==c},a.str.until=function(c,d){return b.empty(c)||b.empty(d)?c:a.str.contains(c,d)?c.substring(0,c.indexOf(d)):c},a.str.format=function(a,d,e){var f=c.arg2arr(arguments);if(a=f.shift(),b.empty(a)||b.empty(f))return a;1===f.length&&(b.array(f[0])||b.object(f[0]))&&(f=f[0]);for(var g in f)a=a.replace(new RegExp("\\{"+g+"\\}","gi"),f[g]);return a})}(FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn),function(a,b,c,d,e){if("0.0.8"===b.version){b.obj={};var f=function(){};b.obj.create=function(a){if(!c.object(a))throw TypeError("Argument must be an object");f.prototype=a;var b=new f;return f.prototype=null,b},b.obj.extend=function(e,f,g){e=c.object(e)?e:{};var h=d.arg2arr(arguments);return h.shift(),a.each(h,function(a,c){b.obj.merge(e,c)}),e},b.obj.merge=function(a,d){a=c.hash(a)?a:{},d=c.hash(d)?d:{};for(var e in d)d.hasOwnProperty(e)&&(c.hash(d[e])?(a[e]=c.hash(a[e])?a[e]:{},b.obj.merge(a[e],d[e])):c.array(d[e])?a[e]=d[e].slice():a[e]=d[e]);return a},b.obj.mergeValid=function(d,e,f,g){if(!c.hash(f)||!c.hash(e))return d;e=c.hash(e)?e:{},g=c.hash(g)?g:{};var h,i,j;for(h in e)e.hasOwnProperty(h)&&c.fn(e[h])&&(i=c.array(g[h])?g[h]:c.string(g[h])?[g[h]]:[h],a.each(i,function(a,g){if(j=b.obj.prop(f,g),!c.undef(j))return e[h](j)?(b.obj.prop(d,h,j),!1):void 0}));return d},b.obj.prop=function(b,d,f){if(c.object(b)&&!c.empty(d)){var g,h;if(c.undef(f))return e.contains(d,".")?(g=d.split("."),h=g.length-1,a.each(g,function(a,d){if(a===h)f=b[d];else{if(!c.hash(b[d]))return!1;b=b[d]}})):c.undef(b[d])||(f=b[d]),f;e.contains(d,".")?(g=d.split("."),h=g.length-1,a.each(g,function(a,d){a===h?b[d]=f:b=c.hash(b[d])?b[d]:b[d]={}})):c.undef(b[d])||(b[d]=f)}}}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.str),function(a,b,c){if("0.0.8"===b.version){b.ready=function(a){function c(){try{a.call(window,b.$)}catch(a){console.error(a)}}(Function("/*@cc_on return true@*/")()?"complete"===document.readyState:"loading"!==document.readyState)?c():document.addEventListener("DOMContentLoaded",c,!1)};var d=0;b.uniqueId=function(a,b){var e=a.attr("id");return c.empty(e)&&(b=c.string(b)&&!c.empty(b)?b:"uid-",e=b+ ++d,a.attr("id",e).data("__uniqueId__",!0)),e},b.removeUniqueId=function(a){a.data("__uniqueId__")&&a.removeAttr("id").removeData("__uniqueId__")}}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b,c){if("0.0.8"===b.version){b.transition={};var d=document.createElement("div");b.transition.supported=function(a){var b=a.style;return c.string(b.transition)||c.string(b.WebkitTransition)||c.string(b.MozTransition)||c.string(b.msTransition)||c.string(b.OTransition)}(d),b.transition.end=function(a){var b=a.style;return c.string(b.transition)?"transitionend":c.string(b.WebkitTransition)?"webkitTransitionEnd":c.string(b.MozTransition)?"transitionend":c.string(b.msTransition)?"msTransitionEnd":c.string(b.OTransition)?"oTransitionEnd":null}(d),b.transition.duration=function(a,b){if(b=c.number(b)?b:0,!c.jq(a))return b;var d=a.css("transition-duration");if(/^([\d\.]*)+?(ms|s)$/i.test(d)){var e=d.match(/^([\d\.]*)+?(ms|s)$/i),f=parseFloat(e[1]);return"s"===e[2].toLowerCase()&&(f*=1e3),f}return b},b.transition.start=function(d,e,f,g){var h=a.Deferred();if(d=d.first(),b.transition.supported){var i=d.data("transition_safety");c.hash(i)&&c.number(i.timer)&&(clearTimeout(i.timer),d.removeData("transition_safety").off(b.transition.end+".utils"),i.deferred.reject()),g=c.number(g)?g:b.transition.duration(d)+50,i={deferred:h,timer:setTimeout(function(){d.removeData("transition_safety").off(b.transition.end+".utils"),h.resolve()},g)},d.data("transition_safety",i),d.on(b.transition.end+".utils",function(a){d.is(a.target)&&(clearTimeout(i.timer),d.removeData("transition_safety").off(b.transition.end+".utils"),h.resolve())})}return setTimeout(function(){c.fn(e)?e.apply(d.get(0),[d]):d.toggleClass(e,f),b.transition.supported||h.resolve()},20),h.promise()}}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d,e){"0.0.8"===b.version&&(b.Class=function(){},b.Class.extend=function(a){function f(){if(!c.fn(this.construct))throw new SyntaxError('FooGallery.utils.Class objects must be constructed with the "new" keyword.');this.construct.apply(this,arguments)}a=c.hash(a)?a:{};var g=d.create(this.prototype);for(var h in a)a.hasOwnProperty(h)&&e.addOrOverride(g,h,a[h]);return g.construct=c.fn(g.construct)?g.construct:function(){},f.prototype=g,f.prototype.constructor=c.fn(g.__ctor__)?g.__ctor__:f,f.extend=b.Class.extend,f.override=b.Class.override,f},b.Class.override=function(a,b){e.addOrOverride(this.prototype,a,b)})}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj,FooGallery.utils.fn),function(a,b,c){if("0.0.8"===b.version){b.Bounds=b.Class.extend({construct:function(){var a=this;a.top=0,a.right=0,a.bottom=0,a.left=0,a.width=0,a.height=0},inflate:function(a){var b=this;return c.number(a)&&(b.top-=a,b.right+=a,b.bottom+=a,b.left-=a,b.width+=2*a,b.height+=2*a),b},intersects:function(a){var b=this;return b.left<=a.right&&a.left<=b.right&&b.top<=a.bottom&&a.top<=b.bottom}});var d;b.getViewportBounds=function(c){d||(d=a(window));var e=new b.Bounds;return e.top=d.scrollTop(),e.left=d.scrollLeft(),e.width=d.width(),e.height=d.height(),e.right=e.left+e.width,e.bottom=e.top+e.height,e.inflate(c),e},b.getElementBounds=function(d){c.jq(d)||(d=a(d));var e=new b.Bounds;if(0!==d.length){var f=d.offset();e.top=f.top,e.left=f.left,e.width=d.width(),e.height=d.height()}return e.right=e.left+e.width,e.bottom=e.top+e.height,e}}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d){"0.0.8"===b.version&&(b.Factory=b.Class.extend({construct:function(){this.registered={}},contains:function(a){return!c.undef(this.registered[a])},load:function(b,e,f){var g,h,i=this,j=d.arg2arr(arguments),k=[],l=[];b=j.shift()||{};for(g in i.registered)if(i.registered.hasOwnProperty(g)){var m=i.registered[g];b.hasOwnProperty(g)&&(h=b[g],c.string(h)&&(h=d.fetch(b[g])),c.fn(h)&&(m={name:g,klass:h,priority:i.registered[g].priority})),k.push(m)}for(g in b)b.hasOwnProperty(g)&&!i.registered.hasOwnProperty(g)&&(h=b[g],c.string(h)&&(h=d.fetch(b[g])),c.fn(h)&&k.push({name:g,klass:h,priority:0}));return k.sort(function(a,b){return b.priority-a.priority}),a.each(k,function(a,b){c.fn(b.klass)&&l.push(d.apply(b.klass,j))}),l},make:function(a,b,e){var f,g=this,h=d.arg2arr(arguments);return a=h.shift(),f=g.registered[a],c.hash(f)&&c.fn(f.klass)?d.apply(f.klass,h):null},names:function(b){b=!!c.boolean(b)&&b;var d,e=[];if(b){var f=[];for(d in this.registered)this.registered.hasOwnProperty(d)&&f.push(this.registered[d]);f.sort(function(a,b){return b.priority-a.priority}),a.each(f,function(a,b){e.push(b.name)})}else for(d in this.registered)this.registered.hasOwnProperty(d)&&e.push(d);return e},register:function(a,b,d){if(!c.string(a)||c.empty(a)||!c.fn(b))return!1;d=c.number(d)?d:0;var e=this.registered[a];return this.registered[a]={name:a,klass:b,priority:c.undef(e)?d:e.priority},!0}}))}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn),function(a,b,c){if("0.0.8"===a.version){var d=!1;try{d=!!window.localStorage}catch(a){d=!1}a.Debugger=a.Class.extend({construct:function(a){this.key=a,this.enabled=!!d&&!!localStorage.getItem(this.key)},enable:function(){d&&(this.enabled=!0,localStorage.setItem(this.key,this.enabled))},disable:function(){d&&(this.enabled=!1,localStorage.removeItem(this.key))},log:function(a,c){this.enabled&&console.log.apply(console,b.arg2arr(arguments))},logf:function(a,d,e){if(this.enabled){var f=b.arg2arr(arguments);a=f.shift(),d=f.shift(),f.unshift(c.format(a,d)),this.log.apply(this,f)}}})}}(FooGallery.utils,FooGallery.utils.fn,FooGallery.utils.str),function(a,b,c){"0.0.8"===b.version&&(b.Throttle=b.Class.extend({construct:function(a){this.id=null,this.active=!1,this.idle=c.number(a)?a:0},limit:function(a){if(c.fn(a)){this.clear();var b=this;this.active=!0,this.id=setTimeout(function(){b.active=!1,b.id=null,a()},this.idle)}},clear:function(){c.number(this.id)&&(clearTimeout(this.id),this.active=!1,this.id=null)}}))}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d,e){b.debug=new c.Debugger("__FooGallery__"),c.selectify=function(b){if(d.empty(b))return null;if(d.hash(b)){var e,f={};for(var g in b)b.hasOwnProperty(g)&&(e=c.selectify(b[g]))&&(f[g]=e);return f}return d.string(b)||d.array(b)?(d.string(b)&&(b=[b]),a.map(b,function(a){return d.string(a)?"."+a.split(/\s/g).join("."):null}).join(",")):null},b.emptyImage="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",b.dataTemplate="__FooGallery__",b.dataItem="__FooGalleryItem__",b.init=function(a,c){return b.template.make(a,c).initialize()},b.initAll=function(c){return e.when(a(".foogallery").map(function(a,d){return b.init(c,d)}).get())},b.parseSrc=function(b,c,e,f,g,h){if(!d.string(b))return null;if(!d.string(f))return b;var i=a.map(f.replace(/(\s[\d.]+[whx]),/g,"$1 @,@ ").split(" @,@ "),function(a){return{url:/^\s*(\S*)/.exec(a)[1],w:parseFloat((/\S\s+(\d+)w/.exec(a)||[0,1/0])[1]),h:parseFloat((/\S\s+(\d+)h/.exec(a)||[0,1/0])[1]),x:parseFloat((/\S\s+([\d.]+)x/.exec(a)||[0,1])[1])}});if(!i.length)return b;i.unshift({url:b,w:i[0].w!==1/0&&i[0].h===1/0?c:1/0,h:i[0].h!==1/0&&i[0].w===1/0?e:1/0,x:1});var j,k=window.devicePixelRatio||1,l={w:g*k,h:h*k,x:k};for(j in l)l.hasOwnProperty(j)&&(i=a.grep(i,function(a,b){return function(c){return c[a]>=l[a]||c[a]===b}}(j,Math.max.apply(null,a.map(i,function(a){return a[j]})))));for(j in l)l.hasOwnProperty(j)&&(i=a.grep(i,function(a,b){return function(c){return c[a]===b}}(j,Math.min.apply(null,a.map(i,function(a){return a[j]})))));return i[0].url},a.fn.foogallery=function(c,e){return this.each(function(f,g){if(d.string(c)){var h=a.data(g,b.dataTemplate);if(h instanceof b.Template)switch(c){case"layout":return void h.layout();case"destroy":return void h.destroy()}}else b.template.make(c,g).initialize().then(function(a){d.fn(e)&&e(a)})})}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn),function(a,b,c,d,e,f){b.TemplateFactory=c.Factory.extend({construct:function(){this.registered={}},register:function(a,b,c,e,f,g){var h=this,i=h._super(a,b,g);if(i){var j=h.registered;j[a].opt=d.hash(c)?c:{},j[a].cls=d.hash(e)?e:{},j[a].il8n=d.hash(f)?f:{}}return i},make:function(b,c){c=d.jq(c)?c:a(c),b=f.extend({},b,c.data("foogallery"));var e=this,g=e.type(b,c);return e.contains(g)?(b=e.options(g,b),e._super(g,b,c)):null},type:function(b,e){e=d.jq(e)?e:a(e);var f=this,g=d.hash(b)&&d.hash(b)&&d.string(b.type)&&f.contains(b.type)?b.type:"core";if("core"===g&&e.length>0)for(var h=f.registered,i=f.names(!0),j=0,k=i.length;j<k;j++)if(h.hasOwnProperty(i[j])){var l=i[j],m=h[l].cls;if(d.string(m.container)){var n=c.selectify(m.container);if(e.is(n)){g=i[j];break}}}return g},configure:function(a,b,c,d){var e=this;if(e.contains(a)){var g=e.registered;f.extend(g[a].opt,b),f.extend(g[a].cls,c),f.extend(g[a].il8n,d)}},options:function(a,c){c=f.extend({type:a},c);var e=this,g=e.registered,h=g.core.opt,i=g.core.cls,j=g.core.il8n;return d.hash(c.cls)||(c.cls={}),d.hash(c.il8n)||(c.il8n={}),d.undef(b.filtering)||(c=b.filtering.merge(c)),d.undef(b.paging)||(c=b.paging.merge(c)),"core"!==a&&e.contains(a)?(c=f.extend({},h,g[a].opt,c),c.cls=f.extend({},i,g[a].cls,c.cls),c.il8n=f.extend({},j,g[a].il8n,c.il8n)):(c=f.extend({},h,c),c.cls=f.extend({},i,c.cls),c.il8n=f.extend({},j,c.il8n)),c}}),b.template=new b.TemplateFactory}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d,e){a.PagingFactory=b.Factory.extend({construct:function(){this.registered={}},register:function(a,b,d,e,f,g,h){var i=this,j=i._super(a,b,h);if(j){var k=i.registered;k[a].ctrl=c.fn(d)?d:null,k[a].opt=c.hash(e)?e:{},k[a].cls=c.hash(f)?f:{},k[a].il8n=c.hash(g)?g:{}}return j},type:function(a){var b,d=this;return c.hash(a)&&c.hash(b=a.paging)&&c.string(b.type)&&d.contains(b.type)?b.type:null},merge:function(a){a=e.extend({},a);var b=this,d=b.type(a),f=b.registered,g=f.default.opt,h=f.default.cls,i=f.default.il8n,j=c.hash(a.paging)?a.paging:{},k=c.hash(a.cls)&&c.hash(a.cls.paging)?e.extend({},a.cls.paging):{},l=c.hash(a.il8n)&&c.hash(a.il8n.paging)?e.extend({},a.il8n.paging):{};return c.hash(a.cls)||(a.cls={}),c.hash(a.il8n)||(a.il8n={}),"default"!==d&&b.contains(d)?(a.paging=e.extend({},g,f[d].opt,j,{type:d}),a.cls=e.extend(a.cls,{paging:h},{paging:f[d].cls},{paging:k}),a.il8n=e.extend(a.il8n,{paging:i},{paging:f[d].il8n},{paging:l})):(a.paging=e.extend({},g,j,{type:d}),a.cls=e.extend(a.cls,{paging:h},{paging:k}),a.il8n=e.extend(a.il8n,{paging:i},{paging:l})),a},configure:function(a,b,c,d){var f=this;if(f.contains(a)){var g=f.registered;e.extend(g[a].opt,b),e.extend(g[a].cls,c),e.extend(g[a].il8n,d)}},hasCtrl:function(a){var b=this,d=b.registered[a];return c.hash(d)&&c.fn(d.ctrl)},makeCtrl:function(a,b,d,e){var f=this,g=f.registered[a];return c.hash(g)&&c.fn(g.ctrl)?new g.ctrl(b,d,e):null}}),a.paging=new a.PagingFactory}(FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d,e,f){var g=0;b.Template=c.Class.extend({construct:function(e,f){var h=this;h.namespace=".foogallery-"+ ++g,h.$el=d.jq(f)?f:a(f),h.opt=e,h.template=e.template,h.id=h.$el.prop("id")||e.id,h.cls=e.cls,h.il8n=e.il8n,h.sel=c.selectify(h.cls),h.items=b.components.make("items",h),h.pages=d.undef(b.paging)?null:b.paging.make(e.paging.type,h),h.filter=d.undef(b.filtering)?null:b.filtering.make(e.filtering.type,h),h.state=b.components.make("state",h),h._initialize=null,h.initializing=!1,h.initialized=!1,h.destroying=!1,h.destroyed=!1,h._undo={classes:"",style:"",create:!1,children:!1}},initialize:function(f){var g=this;return d.promise(g._initialize)?g._initialize:(f=d.jq(f)?f:a(f),g._initialize=a.Deferred(function(h){if(g.initializing=!0,0===f.length&&0===g.$el.parent().length)return void h.reject("A parent element is required.");0===g.$el.length&&(g.$el=g.create(),g._undo.create=!0),f.length>0&&g.$el.appendTo(f);var i,j=a.Deferred(),k=j.promise();g.$el.length>0&&(i=g.$el.data(b.dataTemplate))instanceof b.Template?k=k.then(function(){return i.destroy().then(function(){g.$el.data(b.dataTemplate,g)})}):g.$el.data(b.dataTemplate,g),k.then(function(){if(g.destroying)return e.rejectWith("destroy in progress");d.empty(g.opt.on)||g.$el.on(g.opt.on),g._undo.classes=g.$el.attr("class"),g._undo.style=g.$el.attr("style"),g.$el.is(g.sel.container)||g.$el.addClass(g.cls.container);var a=c.selectify(g.opt.classes);return null==a||g.$el.is(a)||g.$el.addClass(g.opt.classes),0==g.$el.children().length&&(g.$el.append(g.createChildren()),g._undo.children=!0),g.raise("pre-init").isDefaultPrevented()?e.rejectWith("pre-init default prevented"):void 0}).then(function(){return g.destroying?e.rejectWith("destroy in progress"):g.opt.delay<=0?e.resolved:a.Deferred(function(a){g._delay=setTimeout(function(){g._delay=null,a.resolve()},g.opt.delay)}).promise()}).then(function(){return g.destroying?e.rejectWith("destroy in progress"):g.raise("init").isDefaultPrevented()?e.rejectWith("init default prevented"):g.items.fetch()}).then(function(){if(g.destroying)return e.rejectWith("destroy in progress");if(g.raise("post-init").isDefaultPrevented())return e.rejectWith("post-init default prevented");var b=g.state.parse();g.state.set(d.empty(b)?g.state.initial():b),a(window).on("scroll"+g.namespace,{self:g},g.throttle(g.onWindowScroll,g.opt.throttle)).on("popstate"+g.namespace,{self:g},g.onWindowPopState)}).then(function(){return g.destroying?e.rejectWith("destroy in progress"):(g.raise("first-load"),g.loadAvailable())}).then(function(){if(g.destroying)return e.rejectWith("destroy in progress");g.initializing=!1,g.initialized=!0,g._check(200),g._check(500),g._check(1e3),g._check(2e3),g._check(5e3),g.raise("ready"),h.resolve(g)}).fail(function(a){h.reject(a)}),j.resolve()}).promise().fail(function(a){console.log("initialize failed",g,a),g.destroy()}))},create:function(){var b=this;return a("<div/>",{id:b.id,class:b.cls.container}).addClass(b.opt.classes)},createChildren:function(){return a()},destroy:function(){var b=this;return b.destroyed?e.resolved:(b.destroying=!0,a.Deferred(function(a){b.initializing&&d.promise(b._initialize)?b._initialize.always(function(){b.destroying=!1,b._destroy(),a.resolve()}):(b.destroying=!1,b._destroy(),a.resolve())}).promise())},_destroy:function(){var c=this;c.destroyed||(c.raise("destroy"),a(window).off(c.namespace),c.state.destroy(),c.filter&&c.filter.destroy(),c.pages&&c.pages.destroy(),c.items.destroy(),d.empty(c.opt.on)||c.$el.off(c.opt.on),c.raise("destroyed"),c.$el.removeData(b.dataTemplate),d.empty(c._undo.classes)?c.$el.removeAttr("class"):c.$el.attr("class",c._undo.classes),d.empty(c._undo.style)?c.$el.removeAttr("style"):c.$el.attr("style",c._undo.style),c._undo.children&&c.$el.empty(),c._undo.create&&c.$el.remove(),c.$el=c.state=c.items=c.pages=null,c.destroyed=!0,c.initializing=!1,c.initialized=!1)},getAvailable:function(){return this.pages?this.pages.available():this.items.available()},loadAvailable:function(){return this.items.load(this.getAvailable())},_check:function(a){a=d.number(a)?a:0;var b=this;setTimeout(function(){!b.initialized||b.destroying&&b.destroyed||b.loadAvailable()},a)},raise:function(c,e){if(!d.string(c)||d.empty(c))return null;e=d.array(e)?e:[];var g=this,h=c.split(".")[0],i=f.camel("on-"+h),j=a.Event(h+".foogallery");return e.unshift(g),g.$el.trigger(j,e),b.debug.logf("{id}|{name}:",{id:g.id,name:h},e),d.fn(g[i])&&(e.unshift(j),g[i].apply(g.$el.get(0),e)),j},layout:function(){var a=this;null!==a._initialize&&a.raise("layout")},throttle:function(a,b){var c=Date.now();return function(){if(c+b-Date.now()<0){var d=e.arg2arr(arguments);a.apply(this,d),c=Date.now()}}},onWindowPopState:function(a){var b=a.data.self,c=a.originalEvent.state;d.empty(c)||c.id!==b.id||(b.state.set(c),b.loadAvailable())},onWindowScroll:function(a){a.data.self.loadAvailable()}}),b.template.register("core",b.Template,{id:null,type:"core",classes:"",on:{},lazy:!0,viewport:200,items:[],delay:100,throttle:50,timeout:6e4,srcset:"data-srcset",src:"data-src",template:{}},{container:"foogallery"},{},-100)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.str),function(a,b){a.Component=b.Class.extend({construct:function(a){this.tmpl=a},destroy:function(){this.tmpl=null}}),a.components=new b.Factory}(FooGallery,FooGallery.utils),function(a,b,c,d){b.State=b.Component.extend({construct:function(a){var b=this;b._super(a),b.apiEnabled=!!window.history&&!!history.replaceState,b.opt=b.tmpl.opt.state,b.enabled=b.opt.enabled,b.pushOrReplace=b.isPushOrReplace(b.opt.pushOrReplace)?b.opt.pushOrReplace:"replace";var c=d.escapeRegExp(b.tmpl.id),e=d.escapeRegExp(b.opt.values),f=d.escapeRegExp(b.opt.pair);b.regex={exists:new RegExp("^#"+c+"\\"+e+".+?"),values:new RegExp("(\\w+)"+f+"([^"+e+"]+)","g")}},destroy:function(){var a=this;a.clear(),a.opt=a.regex={},a._super()},isPushOrReplace:function(b){return-1!==a.inArray(b,["push","replace"])},exists:function(){return this.regex.exists.test(location.hash)&&this.regex.values.test(location.hash)},parse:function(){var b=this,d={};if(b.exists())if(b.enabled){d.id=b.tmpl.id;var e=location.hash.match(b.regex.values);a.each(e,function(e,f){var g=f.split(b.opt.pair);2===g.length&&(d[g[0]]=-1===g[1].indexOf(b.opt.array)?decodeURIComponent(g[1]):a.map(g[1].split(b.opt.array),function(a){return decodeURIComponent(a)}),c.string(d[g[0]])&&!isNaN(d[g[0]])&&(d[g[0]]=parseInt(d[g[0]])))})}else b.apiEnabled?history.replaceState(null,"",location.pathname+location.search):location.hash="#";return d},hashify:function(b){var d=this;if(c.hash(b)){var e=[];return a.each(b,function(b,f){c.empty(f)||"id"===b||(f=c.array(f)?a.map(f,function(a){return encodeURIComponent(a)}).join("+"):encodeURIComponent(f),e.push(b+d.opt.pair+f))}),e.length>0&&e.unshift("#"+d.tmpl.id),e.join(d.opt.values)}return""},replace:function(a){var b=this;if(b.enabled&&b.apiEnabled){a.id=b.tmpl.id;var d=b.hashify(a),e=c.empty(d);history.replaceState(e?null:a,"",e?location.pathname+location.search:d)}},push:function(a){var b=this;if(b.enabled&&b.apiEnabled){a.id=b.tmpl.id;var d=b.hashify(a),e=c.empty(d);history.pushState(e?null:a,"",e?location.pathname+location.search:d)}},update:function(a,b){var c=this;c.enabled&&c.apiEnabled&&(b=c.isPushOrReplace(b)?b:c.pushOrReplace,c[b](a))},clear:function(){this.exists()&&this.replace({})},initial:function(){var a=this,b=a.tmpl,d={};return b.filter&&!c.empty(b.filter.current)&&(d.f=b.filter.current),b.pages&&b.pages.current>1&&(d.p=b.pages.current),d},get:function(a){var d=this,e=d.tmpl,f={};return a instanceof b.Item&&(f.i=a.id),e.filter&&!c.empty(e.filter.current)&&(f.f=e.filter.current),e.pages&&e.pages.isValid(e.pages.current)&&(f.p=e.pages.current),f},set:function(a){var b=this,d=b.tmpl;if(c.hash(a)){d.items.reset();var e=d.items.get(a.i);if(d.filter){d.filter.rebuild();var f=c.empty(a.f)?[]:a.f;d.filter.set(f,!1)}if(d.pages){d.pages.rebuild();var g=d.pages.number(a.p);e&&!d.pages.contains(g,e)&&(g=d.pages.find(e),g=0!==g?g:1),d.pages.set(g,!c.empty(a),!1),e&&d.pages.contains(g,e)&&e.scrollTo()}else d.items.detach(d.items.all()),d.items.create(d.items.available(),!0),e&&e.scrollTo();c.empty(a.i)||(a.i=null,b.replace(a))}}}),b.template.configure("core",{state:{enabled:!1,pushOrReplace:"replace",values:"/",pair:":",array:"+"}}),b.components.register("state",b.State)}(FooGallery.$,FooGallery,FooGallery.utils.is,FooGallery.utils.str),function(a,b,c,d,e,f){b.Item=b.Component.extend({construct:function(a,b){var c=this;c._super(a),c.cls=a.cls.item,c.il8n=a.il8n.item,c.sel=a.sel.item,c.opt=f.extend({},a.opt.item,b),c.isAttached=!1,c.isCreated=!1,c.isLoading=!1,c.isLoaded=!1,c.isError=!1,c.isParsed=!1,c.$el=null,c.$inner=null,c.$anchor=null,c.$image=null,c.$caption=null,c.type=c.opt.type,c.id=c.opt.id,c.href=c.opt.href,c.src=c.opt.src,c.srcset=c.opt.srcset,c.width=c.opt.width,c.height=c.opt.height,c.title=c.opt.title,c.alt=c.opt.alt,c.caption=d.empty(c.opt.caption)?c.title:c.opt.caption,c.description=d.empty(c.opt.description)?c.alt:c.opt.description,c.attr=c.opt.attr,c.tags=c.opt.tags,c.maxWidth=c.opt.maxWidth,c.maxCaptionLength=c.opt.maxCaptionLength,c.maxDescriptionLength=c.opt.maxDescriptionLength,c.showCaptionTitle=c.opt.showCaptionTitle,c.showCaptionDescription=c.opt.showCaptionDescription,c._thumbUrl=null,c._placeholder=null,c._load=null,c._undo={classes:"",style:"",loader:!1,placeholder:!1}},destroy:function(){var a=this;return a.tmpl.raise("destroy-item").isDefaultPrevented()||(a.doDestroyItem(),a._super()),null===a.tmpl},doDestroyItem:function(){var a=this;a.isParsed?(a.append(),d.empty(a._undo.classes)?a.$el.removeAttr("class"):a.$el.attr("class",a._undo.classes),d.empty(a._undo.style)?a.$el.removeAttr("style"):a.$el.attr("style",a._undo.style),a._undo.loader&&a.$el.find(a.sel.loader).remove(),a._undo.placeholder&&a.$image.prop("src")==a._placeholder&&a.$image.removeAttr("src")):a.isCreated&&(a.detach(),a.$el.remove())},parse:function(b){var c=this,d=a(b);return!c.tmpl.raise("parse-item",[c,d]).isDefaultPrevented()&&(c.isCreated=d.is(c.sel.elem))&&(c.isParsed=c.doParseItem(d),c.fix()),c.isParsed&&c.tmpl.raise("parsed-item",[c]),c.isParsed},doParseItem:function(c){var e=this,f=e.tmpl.opt,g=e.cls,h=e.sel;return e._undo.classes=c.attr("class")||"",e._undo.style=c.attr("style")||"",e.$el=c.data(b.dataItem,e),e.$inner=e.$el.find(h.inner),e.$anchor=e.$el.find(h.anchor).on("click.foogallery",{self:e},e.onAnchorClick),e.$image=e.$anchor.find(h.image),e.$caption=e.$el.find(h.caption.elem).on("click.foogallery",{self:e},e.onCaptionClick),e.isAttached=e.$el.parent().length>0,e.isLoading=e.$el.is(h.loading),e.isLoaded=e.$el.is(h.loaded),e.isError=e.$el.is(h.error),e.id=e.$anchor.data("id")||e.id,e.tags=e.$anchor.data("tags")||e.tags,e.href=e.$anchor.attr("href")||e.href,e.src=e.$image.attr(f.src)||e.src,e.srcset=e.$image.attr(f.srcset)||e.srcset,e.width=parseInt(e.$image.attr("width"))||e.width,e.height=parseInt(e.$image.attr("height"))||e.height,e.title=e.$image.attr("title")||e.title,e.alt=e.$image.attr("alt")||e.alt,e.caption=e.$anchor.data("title")||e.$anchor.data("captionTitle")||e.caption||e.title,e.description=e.$anchor.data("description")||e.$anchor.data("captionDesc")||e.description||e.alt,d.empty(e.caption)&&(e.caption=a.trim(e.$caption.find(h.caption.title).html())),
10
- d.empty(e.description)&&(e.description=a.trim(e.$caption.find(h.caption.description).html())),d.number(e.maxCaptionLength)&&e.maxCaptionLength>0&&!d.empty(e.caption)&&d.string(e.caption)&&e.caption.length>e.maxCaptionLength&&e.$caption.find(h.caption.title).html(e.caption.substr(0,e.maxCaptionLength)+"&hellip;"),d.number(e.maxDescriptionLength)&&e.maxDescriptionLength>0&&!d.empty(e.description)&&d.string(e.description)&&e.description.length>e.maxDescriptionLength&&e.$caption.find(h.caption.description).html(e.description.substr(0,e.maxDescriptionLength)+"&hellip;"),0===e.$el.find(h.loader).length&&(e.$el.append(a("<div/>",{class:g.loader})),e._undo.loader=!0),d.empty(e.$image.prop("src"))&&(e._placeholder=e.tmpl.items.placeholder(e.width,e.height),e.$image.prop("src",e._placeholder),e._undo.placeholder=!0),!e.isCreated||!e.isAttached||e.isLoading||e.isLoaded||e.isError||e.$el.addClass(g.idle),!0},create:function(){var a=this;if(!a.isCreated&&d.string(a.href)&&d.string(a.src)&&d.number(a.width)&&d.number(a.height)){a.tmpl.raise("create-item",[a]).isDefaultPrevented()||(a.isCreated=a.doCreateItem()),a.isCreated&&a.tmpl.raise("created-item",[a])}return a.isCreated},doCreateItem:function(){var c=this,e=c.tmpl.opt,f=c.cls,g=c.attr;g.elem.class=f.elem+" "+f.idle,g.inner.class=f.inner,g.anchor.class=f.anchor,g.anchor.href=c.href,g.anchor["data-id"]=c.id,g.anchor["data-title"]=c.caption,g.anchor["data-description"]=c.description,d.empty(c.tags)||(g.anchor["data-tags"]=JSON.stringify(c.tags)),g.image.class=f.image,g.image.src=c.tmpl.items.placeholder(c.width,c.height),g.image[e.src]=c.src,g.image[e.srcset]=c.srcset,g.image.width=c.width,g.image.height=c.height,g.image.title=c.title,g.image.alt=c.alt,c.$el=a("<div/>").attr(g.elem).data(b.dataItem,c),c.$inner=a("<figure/>").attr(g.inner).appendTo(c.$el),c.$anchor=a("<a/>").attr(g.anchor).appendTo(c.$inner).on("click.foogallery",{self:c},c.onAnchorClick),c.$image=a("<img/>").attr(g.image).appendTo(c.$anchor),f=c.cls.caption,g=c.attr.caption,g.elem.class=f.elem,c.$caption=a("<figcaption/>").attr(g.elem).on("click.foogallery",{self:c},c.onCaptionClick);var h=!d.empty(c.caption),i=!d.empty(c.description);if(h||i){g.inner.class=f.inner,g.title.class=f.title,g.description.class=f.description;var j=a("<div/>").attr(g.inner).appendTo(c.$caption);if(h){var k;k=d.number(c.maxCaptionLength)&&c.maxCaptionLength>0&&d.string(c.caption)&&c.caption.length>c.maxCaptionLength?a("<div/>").attr(g.title).html(c.caption.substr(0,c.maxCaptionLength)+"&hellip;"):a("<div/>").attr(g.title).html(c.caption),j.append(k)}if(i){var l;l=d.number(c.maxDescriptionLength)&&c.maxDescriptionLength>0&&d.string(c.description)&&c.description.length>c.maxDescriptionLength?a("<div/>").attr(g.description).html(c.description.substr(0,c.maxDescriptionLength)+"&hellip;"):a("<div/>").attr(g.description).html(c.description),j.append(l)}}return c.$caption.appendTo(c.$inner),0===c.$el.find(c.sel.loader).length&&c.$el.append(a("<div/>",{class:c.cls.loader})),!0},append:function(){var a=this;if(a.isCreated&&!a.isAttached){a.tmpl.raise("append-item",[a]).isDefaultPrevented()||(a.tmpl.$el.append(a.$el),a.fix(),a.isAttached=!0),a.isAttached&&a.tmpl.raise("appended-item",[a])}return a.isAttached},detach:function(){var a=this;if(a.isCreated&&a.isAttached){a.tmpl.raise("detach-item",[a]).isDefaultPrevented()||(a.$el.detach(),a.unfix(),a.isAttached=!1),a.isAttached||a.tmpl.raise("detached-item",[a])}return!a.isAttached},load:function(){var b=this;if(d.promise(b._load))return b._load;if(!b.isCreated||!b.isAttached)return e.rejectWith("not created or attached");if(b.tmpl.raise("load-item",[b]).isDefaultPrevented())return e.rejectWith("default prevented");var c=b.cls,f=b.$image.get(0),g=f.src;return b.isLoading=!0,b.$el.removeClass(c.idle).removeClass(c.loaded).removeClass(c.error).addClass(c.loading),b._load=a.Deferred(function(a){d.undef(window.InstallTrigger)||(f.src=""),f.onload=function(){f.onload=f.onerror=null,b.isLoading=!1,b.isLoaded=!0,b.$el.removeClass(c.loading).addClass(c.loaded),b.unfix(),b.tmpl.raise("loaded-item",[b]),a.resolve(b)},f.onerror=function(){f.onload=f.onerror=null,b.isLoading=!1,b.isError=!0,b.$el.removeClass(c.loading).addClass(c.error),d.string(g)&&b.$image.prop("src",g),b.tmpl.raise("error-item",[b]),a.reject(b)},f.src=b.getThumbUrl()}).promise()},fix:function(){var a=this;if(!a.tmpl.raise("fix-item",[a]).isDefaultPrevented()&&a.isCreated&&!a.isLoading&&!a.isLoaded&&!a.isError){var b=a.width,c=a.height;if(!isNaN(b)&&!isNaN(c)){var e=d.fn(a.maxWidth)?a.maxWidth(a):a.$image.width();e<=0&&(e=b);var f=e/b,g=c*f;a.$image.css({width:e,height:g})}}return a},unfix:function(){var a=this;return!a.tmpl.raise("unfix-item",[a]).isDefaultPrevented()&&a.isCreated&&a.$image.css({width:"",height:""}),a},getThumbUrl:function(a){a=!!d.boolean(a)&&a;var c=this;return!a&&d.string(c._thumbUrl)?c._thumbUrl:c._thumbUrl=b.parseSrc(c.src,c.width,c.height,c.srcset,c.$anchor.innerWidth(),c.$anchor.innerHeight())},scrollTo:function(a){var b=this;if(b.isAttached){var d=b.bounds(),e=c.getViewportBounds();switch(a){case"top":d.left+=d.width/2-e.width/2,d.top-=e.height/5;break;default:d.left+=d.width/2-e.width/2,d.top+=d.height/2-e.height/2}window.scrollTo(d.left,d.top)}return b},bounds:function(){return this.isAttached?c.getElementBounds(this.$el):null},intersects:function(a){return!!this.isAttached&&this.bounds().intersects(a)},onAnchorClick:function(a){var b=a.data.self,c=b.tmpl.state.get(b);b.tmpl.state.update(c)},onCaptionClick:function(b){var c=b.data.self;a(b.target).is(c.sel.caption.all)&&c.$anchor.length>0&&c.$anchor.get(0).click()}}),b.template.configure("core",{item:{type:"item",id:"",href:"",src:"",srcset:"",width:0,height:0,title:"",alt:"",caption:"",description:"",tags:[],maxWidth:null,maxCaptionLength:0,maxDescriptionLength:0,showCaptionTitle:!0,showCaptionDescription:!0,attr:{elem:{},inner:{},anchor:{},image:{},caption:{elem:{},inner:{},title:{},description:{}}}}},{item:{elem:"fg-item",inner:"fg-item-inner",anchor:"fg-thumb",image:"fg-image",loader:"fg-loader",idle:"fg-idle",loading:"fg-loading",loaded:"fg-loaded",error:"fg-error",caption:{elem:"fg-caption",inner:"fg-caption-inner",title:"fg-caption-title",description:"fg-caption-desc"}}},{item:{}}),b.components.register("item",b.Item)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d,e,f){b.Items=b.Component.extend({construct:function(a){var b=this;b._super(a),b.idMap={},b._fetched=null,b._arr=[],b._available=[],b._canvas=document.createElement("canvas");var d=b.tmpl.cls.item.caption;b.tmpl.sel.item.caption.all=c.selectify([d.elem,d.inner,d.title,d.description])},destroy:function(){var b=this,c=b.all(),d=[];c.length>0&&(b.tmpl.raise("destroy-items",[c]),d=a.map(c,function(a){return a.destroy()?a:null}),d.length>0&&b.tmpl.raise("destroyed-items",[d])),b.idMap={},b._canvas=b._fetched=null,b._arr=[],b._available=[],b._super()},fetch:function(b){var c=this;if(!b&&d.promise(c._fetched))return c._fetched;var e=c.tmpl,f=e.sel,g=e.opt.items,h=a.Deferred(),i=c.make(e.$el.find(f.item.elem));return d.empty(g)?(i.push.apply(i,c.make(window[e.id+"-items"])),h.resolve(i)):d.array(g)?(i.push.apply(i,c.make(g)),h.resolve(i)):d.string(g)?a.get(g).then(function(a){i.push.apply(i,c.make(a)),h.resolve(i)},function(a,b,c){console.log("FooGallery: GET items error.",g,a,b,c),h.resolve(i)}):h.resolve(i),h.then(function(a){c.setAll(a)}),c._fetched=h.promise()},all:function(){return this._arr.slice()},count:function(a){return a?this.all().length:this.available().length},available:function(){return this._available.slice()},get:function(a){return!d.empty(a)&&this.idMap[a]?this.idMap[a]:null},setAll:function(a){this._arr=d.array(a)?a:[],this.idMap=this.createIdMap(a),this._available=this.all()},setAvailable:function(a){this._available=d.array(a)?a:[]},reset:function(){this.setAvailable(this.all())},placeholder:function(a,c){return this._canvas&&this._canvas.toDataURL&&d.number(a)&&d.number(c)?(this._canvas.width=a,this._canvas.height=c,this._canvas.toDataURL()):b.emptyImage},loadable:function(b){var e,f=this,g=f.tmpl.opt;return g.lazy&&(e=c.getViewportBounds(g.viewport)),d.array(b)?a.map(b,function(a){return a.isCreated&&a.isAttached&&!a.isLoading&&!a.isLoaded&&!a.isError&&(!g.lazy||g.lazy&&a.intersects(e))?a:null}):[]},creatable:function(c){return d.array(c)?a.map(c,function(a){return a instanceof b.Item&&!a.isCreated?a:null}):[]},appendable:function(c){return d.array(c)?a.map(c,function(a){return a instanceof b.Item&&a.isCreated&&!a.isAttached?a:null}):[]},detachable:function(c){return d.array(c)?a.map(c,function(a){return a instanceof b.Item&&a.isCreated&&a.isAttached?a:null}):[]},jquerify:function(b){return a(a.map(b,function(a){return a.$el.get()}))},make:function(c){var e=this,g=[];if(d.jq(c)||d.array(c)){var h=[],i=a.makeArray(c);if(0===i.length)return g;e.tmpl.raise("make-items",[i]).isDefaultPrevented()||(g=a.map(i,function(a){var c=e.type(a),g=f.extend(d.hash(a)?a:{},{type:c}),i=b.components.make(c,e.tmpl,g);return d.element(a)?i.parse(a)?(h.push(i),i):null:i})),g.length>0&&e.tmpl.raise("made-items",[g]),h.length>0&&e.tmpl.raise("parsed-items",[h])}return g},type:function(c){var e;return d.hash(c)?e=c.type:d.element(c)&&(e=a(c).find(this.tmpl.sel.item.anchor).data("type")),d.string(e)&&b.components.contains(e)?e:"item"},create:function(b,c){var e=this,f=[],g=e.creatable(b);if(g.length>0){e.tmpl.raise("create-items",[g]).isDefaultPrevented()||(f=a.map(g,function(a){return a.create()?a:null})),f.length>0&&e.tmpl.raise("created-items",[f])}return d.boolean(c)&&c?e.append(b):f},append:function(b){var c=this,d=[],e=c.appendable(b);if(e.length>0){c.tmpl.raise("append-items",[e]).isDefaultPrevented()||(d=a.map(e,function(a){return a.append()?a:null})),d.length>0&&c.tmpl.raise("appended-items",[d])}return d},detach:function(b){var c=this,d=[],e=c.detachable(b);if(e.length>0){c.tmpl.raise("detach-items",[e]).isDefaultPrevented()||(d=a.map(e,function(a){return a.detach()?a:null})),d.length>0&&c.tmpl.raise("detached-items",[d])}return d},load:function(b){var c=this;if(b=c.loadable(b),b.length>0){if(!c.tmpl.raise("load-items",[b]).isDefaultPrevented()){var d=a.map(b,function(a){return a.load()});return e.when(d).done(function(a){c.tmpl.raise("loaded-items",[a])})}}return e.resolveWith([])},createIdMap:function(b){var c={};return a.each(b,function(a,b){d.empty(b.id)&&(b.id=""+(a+1)),c[b.id]=b}),c}}),b.components.register("items",b.Items)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d){b.Paging=b.Component.extend({construct:function(a){var b=this;b._super(a),b.opt=b.tmpl.opt.paging,b.cls=b.tmpl.cls.paging,b.il8n=b.tmpl.il8n.paging,b.sel=b.tmpl.sel.paging,b.pushOrReplace=b.opt.pushOrReplace,b.type=b.opt.type,b.theme=b.opt.theme,b.size=b.opt.size,b.position=b.opt.position,b.scrollToTop=b.opt.scrollToTop,b.current=0,b.total=0,b.ctrls=[],b._arr=[]},destroy:function(){var b=this;b._arr.splice(0,b._arr.length),a.each(b.ctrls.splice(0,b.ctrls.length),function(a,b){b.destroy()}),b._super()},build:function(){var a=this,c=a.tmpl.items.available();a.total=a.size>0&&c.length>0?Math.ceil(c.length/a.size):1;for(var d=0;d<a.total;d++)a._arr.push(c.splice(0,a.size));if(a.total>1&&b.paging.hasCtrl(a.type)){var e,f,g=a.position;"both"!==g&&"top"!==g||(e=b.paging.makeCtrl(a.type,a.tmpl,a,"top"),e.create()&&(e.append(),a.ctrls.push(e))),"both"!==g&&"bottom"!==g||(f=b.paging.makeCtrl(a.type,a.tmpl,a,"bottom"),f.create()&&(f.append(),a.ctrls.push(f)))}},rebuild:function(){var b=this;b.current=0,b.total=0,b._arr.splice(0,b._arr.length),a.each(b.ctrls.splice(0,b.ctrls.length),function(a,b){b.destroy()}),b.build()},all:function(){return this._arr.slice()},available:function(){return this.get(this.current)},controls:function(b){var c=this;c.isValid(b)&&a.each(c.ctrls,function(a,c){c.update(b)})},isValid:function(a){return d.number(a)&&a>0&&a<=this.total},number:function(a){return this.isValid(a)?a:0===this.current?1:this.current},create:function(a,b){var c=this;a=c.number(a);var d=a-1;c.tmpl.items.detach(c.tmpl.items.all()),c.tmpl.items.create(c._arr[d],!0),c.current=a},get:function(a){var b=this;return b.isValid(a)?(a=b.number(a),b._arr[a-1]):[]},set:function(a,b,c,e){var f=this;if(f.isValid(a)){var g,h=f.number(a);if(h!==f.current){var i=f.current,j=function(){if(c=!d.boolean(c)||c,e=!!d.boolean(e)&&e,c&&1===f.current&&!f.tmpl.state.exists()&&(g=f.tmpl.state.get(),f.tmpl.state.update(g,f.pushOrReplace)),f.controls(a),f.create(h,e),c&&(g=f.tmpl.state.get(),f.tmpl.state.update(g,f.pushOrReplace)),f.scrollToTop&&d.boolean(b)&&b){var j=f.get(f.current);j.length>0&&j[0].scrollTo("top")}f.tmpl.raise("after-page-change",[f.current,i,e])};return!f.tmpl.raise("before-page-change",[f.current,h,j,e]).isDefaultPrevented()&&(j(),!0)}}return!1},find:function(b){for(var c=this,d=0,e=c._arr.length;d<e;d++)if(-1!==a.inArray(b,c._arr[d]))return d+1;return 0},contains:function(b,c){var d=this.get(b);return-1!==a.inArray(c,d)},first:function(){this.goto(1)},last:function(){this.goto(this._arr.length)},prev:function(){this.goto(this.current-1)},next:function(){this.goto(this.current+1)},goto:function(a){var b=this;b.set(a,!0)&&b.tmpl.loadAvailable()}}),b.PagingControl=b.Component.extend({construct:function(a,b,c){var d=this;d._super(a),d.pages=b,d.position=c,d.$container=null},create:function(){var b=this;return b.$container=a("<nav/>",{class:b.pages.cls.container}).addClass(b.pages.theme),!0},destroy:function(){var a=this;a.$container.remove(),a.$container=null},append:function(){var a=this;"top"===a.position?a.$container.insertBefore(a.tmpl.$el):a.$container.insertAfter(a.tmpl.$el)},update:function(a){}}),b.paging.register("default",b.Paging,null,{type:"none",theme:"fg-light",size:30,pushOrReplace:"push",position:"none",scrollToTop:!0},{container:"fg-paging-container"},null,-100)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d){b.Dots=b.Paging.extend({}),b.DotsControl=b.PagingControl.extend({construct:function(b,c,d){this._super(b,c,d),this.$container=a(),this.$list=a(),this.$items=a()},create:function(){for(var b,c=this,d=c.pages.cls,e=c.pages.il8n,f=[],g=a("<ul/>",{class:d.list}),h=0,i=c.pages.total;h<i;h++)f.push(b=c.createItem(h+1,e.page)),g.append(b);return c.$list=g,c.$container=a("<nav/>",{class:d.container}).addClass(c.pages.theme).append(g),c.$items=a(a.map(f,function(a){return a.get()})),!0},append:function(){var a=this;"top"===a.position?a.$container.insertBefore(a.tmpl.$el):a.$container.insertAfter(a.tmpl.$el)},destroy:function(){var b=this,c=b.pages.sel;b.$list.find(c.link).off("click.foogallery",b.onLinkClick),b.$container.remove(),b.$container=a(),b.$list=a(),b.$items=a()},update:function(a){this.setSelected(a-1)},setSelected:function(b){var c=this,e=c.pages.cls,f=c.pages.il8n,g=c.pages.sel;c.$items.filter(g.selected).removeClass(e.selected).each(function(b,c){var e=a(c),f=e.data("label"),h=e.find(g.reader);d.string(f)&&0!==h.length&&h.html(f)}),c.$items.eq(b).addClass(e.selected).each(function(b,c){var e=a(c),h=e.find(g.reader),i=h.html();d.string(i)&&0!==h.length&&(e.data("label",i),h.html(f.current))})},createItem:function(b,c,e,f,g){e=d.string(e)?e:b,c=d.string(c)?c:"";var h=this,i=h.pages.opt,j=h.pages.cls,k=a("<a/>",{class:j.link,href:"#page-"+b}).html(e).on("click.foogallery",{self:h,page:b},h.onLinkClick);d.empty(c)||k.attr("title",c.replace(/\{PAGE}/g,b).replace(/\{LIMIT}/g,i.limit+"")),g=d.string(g)?g:c,d.empty(g)||k.prepend(a("<span/>",{class:j.reader,text:g.replace(/\{PAGE}/g,"").replace(/\{LIMIT}/g,i.limit+"")}));var l=a("<li/>",{class:j.item}).append(k);return f=d.string(f)?f:"",d.empty(f)||l.addClass(f),l},onLinkClick:function(b){b.preventDefault();var c=b.data.self,d=b.data.page,e=c.pages.sel;a(this).closest(e.item).is(e.disabled)||(c.pages.set(d,!0),c.tmpl.loadAvailable())}}),b.paging.register("dots",b.Dots,b.DotsControl,{type:"dots",position:"both",pushOrReplace:"push"},{list:"fg-dots",item:"fg-dot-item",link:"fg-dot-link",disabled:"fg-disabled",selected:"fg-selected",visible:"fg-visible",reader:"fg-sr-only"},{current:"Current page",page:"Page {PAGE}"})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c){b.DefaultTemplate=b.Template.extend({}),b.template.register("default",b.DefaultTemplate,null,{container:"foogallery fg-default"})}(FooGallery.$,FooGallery,FooGallery.utils),function(a,b,c,d){b.MasonryTemplate=b.Template.extend({construct:function(a,b){this._super(a,b),this.masonry=null,this.style=null,this.$columnWidth=null},getStylesheet:function(){var a=this;return null===a.style&&(a.style=document.createElement("style"),a.style.appendChild(document.createTextNode("")),document.head.appendChild(a.style)),a.style.sheet},onPreInit:function(b,c){var e=c.sel,f=c.cls;f.layouts=a.map(f.layout,function(a){return a}).join(" ");for(var g=a.map(f.layout,function(a,b){return{key:b,value:a}}),h=0,i=g.length;h<i;h++)if(c.$el.hasClass(g[h].value)){c.template.layout=g[h].key;break}d.string(f.layout[c.template.layout])||(c.template.layout="col4");var j,k,l="fixed"===c.template.layout;if(c.template.isFitWidth=l,c.template.percentPosition=!l,c.template.transitionDuration=0,c.template.itemSelector=e.item.elem,c.$el.removeClass(f.layouts).addClass(f.layout[c.template.layout]),l||(0===c.$el.find(e.gutterWidth).length&&c.$el.prepend(a("<div/>").addClass(f.gutterWidth)),c.template.gutter=e.gutterWidth),0===c.$el.find(e.columnWidth).length&&c.$el.prepend(a("<div/>").addClass(f.columnWidth)),l&&d.number(c.template.columnWidth)){var m=c.$el.find(e.columnWidth).width(c.template.columnWidth);j=c.getStylesheet(),k="#"+c.id+e.container+" "+e.item.elem+" { width: "+m.outerWidth()+"px; }",j.insertRule(k,0)}c.template.columnWidth=e.columnWidth,l&&d.number(c.template.gutter)&&(j=c.getStylesheet(),k="#"+c.id+e.container+" "+e.item.elem+" { margin-bottom: "+c.template.gutter+"px; }",j.insertRule(k,0)),c.masonry=new Masonry(c.$el.get(0),c.template)},onPostInit:function(a,b){b.masonry.layout()},onFirstLoad:function(a,b){b.masonry.layout()},onReady:function(a,b){b.masonry.layout()},onDestroy:function(a,b){b.$el.find(b.sel.columnWidth).remove(),b.$el.find(b.sel.gutterWidth).remove(),b.style&&b.style.parentNode&&b.style.parentNode.removeChild(b.style)},onDestroyed:function(a,b){b.masonry instanceof Masonry&&b.masonry.destroy()},onLayout:function(a,b){b.masonry.layout()},onParsedItems:function(a,b,c){b.masonry.layout()},onAppendedItems:function(a,b,c){c=b.items.jquerify(c),c=b.masonry.addItems(c),b.masonry.layoutItems(c,!0)},onDetachItem:function(a,b,c){a.isDefaultPrevented()||(a.preventDefault(),b.masonry.remove(c.$el),c.isAttached=!1,c.unfix())},onDetachedItems:function(a,b,c){b.masonry.layout()},onLoadedItems:function(a,b,c){b.masonry.layout()}}),b.template.register("masonry",b.MasonryTemplate,{template:{initLayout:!1,isInitLayout:!1,layout:"col4"}},{container:"foogallery fg-masonry",columnWidth:"fg-column-width",gutterWidth:"fg-gutter-width",layout:{fixed:"fg-masonry-fixed",col2:"fg-masonry-2col",col3:"fg-masonry-3col",col4:"fg-masonry-4col",col5:"fg-masonry-5col"}})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d){b.Justified=c.Class.extend({construct:function(c,d){this.$el=a(c),this.options=a.extend(!0,{},b.Justified.defaults,d),this._items=[]},init:function(){var b=this;d.string(b.options.maxRowHeight)&&(b.options.maxRowHeight.indexOf("%")?b.options.maxRowHeight=b.options.rowHeight*(parseInt(b.options.maxRowHeight)/100):b.options.maxRowHeight=parseInt(b.options.maxRowHeight)),a(window).on("resize.justified",{self:b},b.onWindowResize)},destroy:function(){a(window).off("resize.justified"),this.$el.removeAttr("style")},parse:function(){var b=this,c=b.$el.is(":visible"),d=a("<div/>",{class:b.$el.attr("class")}).css({position:"absolute",top:0,left:-9999,visibility:"hidden",maxWidth:b.getContainerWidth()}).appendTo("body");return b._items=b.$el.find(b.options.itemSelector).removeAttr("style").removeClass("fg-positioned").map(function(e,f){var g,h=a(f),i=0,j=0;if(c)i=h.outerWidth(),j=h.outerHeight();else{var k=h.clone();k.appendTo(d),i=k.outerWidth(),j=k.outerHeight()}return g=b.options.rowHeight/j,{index:e,width:i*g,height:b.options.rowHeight,top:0,left:0,$item:h}}).get(),d.remove(),b._items},round:function(a){return Math.round(a)},getContainerWidth:function(){var a=this;return a.$el.is(":visible")?a.$el.width():a.$el.parents(":visible:first").innerWidth()},layout:function(a,b){a=!!d.boolean(a)&&a,b=!d.boolean(b)||b,(a||0===this._items.length)&&this.parse();for(var c,e=this,f=e.getContainerWidth(),g=e.rows(f),h=0,i=0,j=g.length;i<j;i++)c=g[i],h=i===j-1?e.lastRow(c,f,h):e.justify(c,f,h),e.render(c);e.$el.height(h),b&&e.getContainerWidth()<f&&e.layout(!1,!1)},render:function(a){for(var b,c=0,d=a.items.length;c<d;c++)b=a.items[c],a.visible?b.$item.css({width:b.width,height:b.height,top:b.top,left:b.left,display:"",maxHeight:this.options.maxRowHeight>0?this.options.maxRowHeight:""}).addClass("fg-positioned"):b.$item.css("display","none")},lastRow:function(a,b,c){var d=this;switch(d.options.lastRow){case"hide":a.visible=!1;break;case"justify":c=d.justify(a,b,c);break;case"nojustify":c=a.width/b>d.options.justifyThreshold?d.justify(a,b,c):d.position(a,b,c,"left");break;case"right":case"center":case"left":c=d.position(a,b,c,d.options.lastRow);break;default:c=d.position(a,b,c,"left")}return c},justify:function(a,b,c){var d=this,e=0,f=d.options.margins*(a.items.length-1),g=(b-f)/a.width;a.index>0&&(c+=d.options.margins),a.top=c,a.width=d.round(a.width*g),a.height=d.round(a.height*g);for(var h,i=0,j=a.items.length;i<j;i++)h=a.items[i],h.width=d.round(h.width*g),h.height=d.round(h.height*g),h.top=c,i>0&&(e+=d.options.margins),h.left=e,e+=h.width;return c+(a.height>d.options.maxRowHeight?d.options.maxRowHeight:a.height)},position:function(a,b,c,d){var e=this,f=a.items[a.items.length-1],g=b-(f.left+f.width);a.index>0&&(c+=e.options.margins),a.top=c;for(var h,i=0,j=a.items.length;i<j;i++)h=a.items[i],h.top=c,"center"===d?h.left+=g/2:"right"===d&&(h.left+=g);return c+a.height},items:function(){return a.map(this._items,function(a){return{index:a.index,width:a.width,height:a.height,$item:a.$item,top:a.top,left:a.left}})},rows:function(a){for(var b=this,c=b.items(),d=[],e=c.length>0,f=-1,g=0;e;){f+=1,f>0&&(g+=b.options.margins);for(var h,i,j,k={index:f,visible:!0,top:g,width:0,height:b.options.rowHeight,items:[]},l=[],m=0,n=0,o=c.length;n<o&&(i=c[n],!((h=k.width+i.width)>a&&n>0));n++)h>a&&0==n&&(h=a,j=a/i.width,i.width=b.round(i.width*j),i.height=b.round(i.height*j),k.height=i.height),i.top=k.top,n>0&&(m+=b.options.margins),i.left=m,m+=i.width,k.width=h,k.items.push(i),l.push(n);if(0===l.length){e=!1;break}l.sort(function(a,b){return b-a});for(var p=0,q=l.length;p<q;p++)c.splice(l[p],1);d.push(k),e=c.length>0}return d},onWindowResize:function(a){a.data.self.layout()}}),b.Justified.defaults={itemSelector:".fg-item",rowHeight:150,maxRowHeight:"200%",margins:0,lastRow:"center",justifyThreshold:.5}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c){b.JustifiedTemplate=b.Template.extend({onPreInit:function(a,c){c.justified=new b.Justified(c.$el.get(0),c.template)},onInit:function(a,b){b.justified.init()},onFirstLoad:function(a,b){b.justified.layout(!0)},onReady:function(a,b){b.justified.layout(!0)},onDestroy:function(a,b){b.justified.destroy()},onLayout:function(a,b){b.justified.layout(!0)},onParsedItems:function(a,b,c){b.justified.layout(!0)},onAppendedItems:function(a,b,c){b.justified.layout(!0)},onDetachedItems:function(a,b,c){b.justified.layout(!0)}}),b.template.register("justified",b.JustifiedTemplate,null,{container:"foogallery fg-justified"})}(FooGallery.$,FooGallery,FooGallery.utils),function(a,b,c,d){b.Portfolio=c.Class.extend({construct:function(c,d){this.$el=a(c),this.options=a.extend(!0,{},b.Portfolio.defaults,d),this._items=[]},init:function(){var b=this;a(window).on("resize.portfolio",{self:b},b.onWindowResize)},destroy:function(){a(window).off("resize.portfolio"),this.$el.removeAttr("style")},parse:function(){var b=this,c=b.$el.is(":visible"),d=a("<div/>",{class:b.$el.attr("class")}).css({position:"absolute",top:0,left:-9999,visibility:"hidden",maxWidth:b.getContainerWidth()}).appendTo("body");return b._items=b.$el.find(".fg-item").removeAttr("style").removeClass("fg-positioned").map(function(b,e){var f=a(e),g=f.find(".fg-thumb"),h=f.find(".fg-image"),i=0,j=0;if(f.find(".fg-caption").css("max-width",parseFloat(h.attr("width"))),h.css({width:h.attr("width"),height:h.attr("height")}),c)i=f.outerWidth(),j=f.outerHeight();else{var k=f.clone();k.appendTo(d),i=k.outerWidth(),j=k.outerHeight()}return h.css({width:"",height:""}),{index:b,width:i,height:j,top:0,left:0,$item:f,$thumb:g}}).get(),d.remove(),b._items},round:function(a){return Math.round(2*a)/2},getContainerWidth:function(){var a=this;return a.$el.is(":visible")?a.$el.width():a.$el.parents(":visible:first").innerWidth()},layout:function(a,b){a=!!d.boolean(a)&&a,b=!d.boolean(b)||b,(a||0===this._items.length)&&this.parse();for(var c,e=this,f=e.getContainerWidth(),g=e.rows(f),h=0,i=0,j=g.length;i<j;i++)c=g[i],h=e.position(c,f,h,e.options.align),e.render(c);e.$el.height(h),b&&e.getContainerWidth()<f&&e.layout(!1,!1)},render:function(a){for(var b,c=0,d=a.items.length;c<d;c++)b=a.items[c],a.visible?b.$item.css({width:b.width,height:a.height,top:b.top,left:b.left,display:""}).addClass("fg-positioned"):b.$item.css("display","none")},position:function(a,b,c,d){var e=this,f=a.items[a.items.length-1],g=b-(f.left+f.width);a.index>0&&(c+=e.options.gutter),a.top=c;for(var h,i=0,j=a.items.length;i<j;i++)h=a.items[i],h.top=c,"center"===d?h.left+=g/2:"right"===d&&(h.left+=g);return c+a.height},items:function(){return a.map(this._items,function(a){return{index:a.index,width:a.width,height:a.height,$item:a.$item,$thumb:a.$thumb,top:a.top,left:a.left}})},rows:function(a){for(var b=this,c=b.items(),d=[],e=c.length>0,f=-1,g=0;e;){f+=1,f>0&&(g+=b.options.gutter);for(var h,i,j,k={index:f,visible:!0,top:g,width:0,height:0,items:[]},l=[],m=0,n=0,o=c.length;n<o&&(i=c[n],!((h=k.width+i.width)>a&&n>0));n++)h>a&&0==n&&(h=a,j=a/i.width,i.width=b.round(i.width*j),i.height=b.round(i.height*j),k.height=i.height),i.top=k.top,n>0&&(m+=b.options.gutter),n!==o-1&&(h+=b.options.gutter),i.left=m,m+=i.width,i.height>k.height&&(k.height=i.height),k.width=h,k.items.push(i),l.push(n);if(0===l.length){e=!1;break}l.sort(function(a,b){return b-a});for(var p=0,q=l.length;p<q;p++)c.splice(l[p],1);d.push(k),e=c.length>0}return d},onWindowResize:function(a){a.data.self.layout()}}),b.Portfolio.defaults={gutter:40,align:"center"}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c){b.PortfolioTemplate=b.Template.extend({construct:function(a,b){this._super(a,b),this.portfolio=null},onPreInit:function(a,c){c.portfolio=new b.Portfolio(c.$el.get(0),c.template)},onInit:function(a,b){b.portfolio.init()},onFirstLoad:function(a,b){b.portfolio.layout(!0)},onReady:function(a,b){b.portfolio.layout(!0)},onDestroy:function(a,b){b.portfolio.destroy()},onLayout:function(a,b){b.portfolio.layout(!0)},onParsedItems:function(a,b,c){b.portfolio.layout(!0)},onAppendedItems:function(a,b,c){b.portfolio.layout(!0)},onDetachedItems:function(a,b,c){b.portfolio.layout(!0)}}),b.template.register("simple_portfolio",b.PortfolioTemplate,{gutter:40},{container:"foogallery fg-simple_portfolio"})}(FooGallery.$,FooGallery,FooGallery.utils),function(a,b,c,d){b.ImageViewerTemplate=b.Template.extend({construct:function(b,c){this._super(d.extend({},b,{paging:{pushOrReplace:"replace",theme:"fg-light",type:"default",size:1,position:"none",scrollToTop:!1}}),c),this.$inner=a(),this.$current=a(),this.$total=a(),this.$prev=a(),this.$next=a()},createChildren:function(){var b=this;return a("<div/>",{class:b.cls.inner}).append(a("<div/>",{class:b.cls.innerContainer}),a("<div/>",{class:b.cls.controls}).append(a("<div/>",{class:b.cls.prev}).append(a("<span/>",{text:b.il8n.prev})),a("<label/>",{class:b.cls.count,text:b.il8n.count}).prepend(a("<span/>",{class:b.cls.countCurrent,text:"0"})).append(a("<span/>",{class:b.cls.countTotal,text:"0"})),a("<div/>",{class:b.cls.next}).append(a("<span/>",{text:b.il8n.next}))))},onPreInit:function(a,b){b.$inner=b.$el.find(b.sel.innerContainer),b.$current=b.$el.find(b.sel.countCurrent),b.$total=b.$el.find(b.sel.countTotal),b.$prev=b.$el.find(b.sel.prev),b.$next=b.$el.find(b.sel.next)},onInit:function(a,b){b.template.attachFooBox&&b.$el.on("foobox.previous",{self:b},b.onFooBoxPrev).on("foobox.next",{self:b},b.onFooBoxNext),b.$prev.on("click",{self:b},b.onPrevClick),b.$next.on("click",{self:b},b.onNextClick)},onFirstLoad:function(a,b){b.update()},onDestroy:function(a,b){b.template.attachFooBox&&b.$el.off({"foobox.previous":b.onFooBoxPrev,"foobox.next":b.onFooBoxNext}),b.$prev.off("click",b.onPrevClick),b.$next.off("click",b.onNextClick)},onAppendItem:function(a,b,c){a.preventDefault(),b.$inner.append(c.$el),c.fix(),c.isAttached=!0},onAfterPageChange:function(a,b,c,d,e){e||b.update()},onAfterFilterChange:function(a,b){b.update()},update:function(){this.pages&&(this.$current.text(this.pages.current),this.$total.text(this.pages.total))},prev:function(){this.pages&&(this.template.loop&&1===this.pages.current?this.pages.last():this.pages.prev(),this.update())},next:function(){this.pages&&(this.template.loop&&this.pages.current===this.pages.total?this.pages.first():this.pages.next(),this.update())},onFooBoxPrev:function(a){a.data.self.prev()},onFooBoxNext:function(a){a.data.self.next()},onPrevClick:function(a){a.preventDefault(),a.stopPropagation(),a.data.self.prev()},onNextClick:function(a){a.preventDefault(),a.stopPropagation(),a.data.self.next()}}),b.template.register("image-viewer",b.ImageViewerTemplate,{template:{attachFooBox:!1,loop:!1}},{container:"foogallery fg-image-viewer",inner:"fiv-inner",innerContainer:"fiv-inner-container",controls:"fiv-ctrls",prev:"fiv-prev",next:"fiv-next",count:"fiv-count",countCurrent:"fiv-count-current",countTotal:"fiv-count-total"},{prev:"Prev",next:"Next",count:"of"})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.obj),function(a,b,c){b.ThumbnailTemplate=b.Template.extend({construct:function(b,d){this._super(c.extend({},b,{filtering:{type:"none"},paging:{type:"none"}}),d),this.$hidden=a()},createChildren:function(){var b=this;return b.$hidden=a("<div/>",{class:b.cls.hidden})},onPreInit:function(a,b){b.$hidden=b.$el.find(b.sel.hidden)},onPostInit:function(b,c){for(var d,e=c.items.all().slice(1),f=0,g=e.length;f<g;f++)d=e[f],c.$hidden.append(a("<a/>",{href:d.href,rel:"lightbox["+c.id+"]"}).attr(d.attr.anchor));c.items.setAll(c.items.all().slice(0,1))}}),b.template.register("thumbnail",b.ThumbnailTemplate,null,{container:"foogallery fg-thumbnail",hidden:"fg-st-hidden"})}(FooGallery.$,FooGallery,FooGallery.utils.obj),function(a,b,c,d){b.triggerPostLoad=function(b,c,d,e,f){("first-load"===b.type||c.initialized&&("after-page-change"===b.type&&!f||"after-filter-change"===b.type))&&a("body").trigger("post-load")},b.autoDefaults={on:{"first-load.foogallery after-page-change.foogallery after-filter-change.foogallery":b.triggerPostLoad}},b.auto=function(a){b.autoDefaults=d.merge(b.autoDefaults,a)},a(function(){a('[id^="foogallery-gallery-"]:not(.fg-ready)').foogallery(b.autoDefaults)}),c.ready(function(){a('[id^="foogallery-gallery-"].fg-ready').foogallery(b.autoDefaults)})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.obj);
 
1
  /*
2
  * FooGallery - The Most Intuitive and Extensible Gallery Creation and Management Tool Ever Created for WordPress
3
+ * @version 1.0.26
4
  * @link
5
  * @copyright Steven Usher & Brad Vincent 2015
6
  * @license Released under the GPLv3 license.
7
  */
8
 
9
  !function(a,b){b.$=a}(jQuery,window.FooGallery=window.FooGallery||{}),function(a){if(!a)return void console.warn("jQuery must be included in the page prior to the FooGallery.utils library.");var b={$:a,version:"0.0.8"};b.versionCompare=function(a,b){function c(a){for(var b=a.split("."),c=0,d=b.length;c<d;c++)b[c]=parseInt(b[c]),isNaN(b[c])&&(b[c]=0);return b}if(!/[\d.]/.test(a)||!/[\d.]/.test(b))return NaN;for(var d=c(a),e=c(b);d.length<e.length;)d.push(0);for(;e.length<d.length;)e.push(0);for(var f=0;f<d.length;++f){if(e.length==f)return 1;if(d[f]!=e[f])return d[f]>e[f]?1:-1}return d.length!=e.length?-1:0},!function(){try{return!!window.FooGallery.utils}catch(a){return!1}}()?window.FooGallery.utils=b:b.versionCompare(b.version,window.FooGallery.utils.version)>0?(console.warn("An older version of FooGallery.utils ("+window.FooGallery.utils.version+") already exists in the page, version "+b.version+" will override it."),window.FooGallery.utils=b):console.warn("A newer version of FooGallery.utils ("+window.FooGallery.utils.version+") already exists in the page, version "+b.version+" will not register itself.")}(jQuery),function(a,b){"0.0.8"===b.version&&(b.is={},b.is.array=function(a){return"[object Array]"===Object.prototype.toString.call(a)},b.is.boolean=function(a){return"[object Boolean]"===Object.prototype.toString.call(a)},b.is.element=function(a){return"object"==typeof HTMLElement?a instanceof HTMLElement:!!a&&"object"==typeof a&&null!==a&&1===a.nodeType&&"string"==typeof a.nodeName},b.is.empty=function(a){if(b.is.undef(a)||null===a)return!0;if(b.is.number(a)&&0==a)return!0;if(b.is.boolean(a)&&!1===a)return!0;if(b.is.string(a)&&0===a.length)return!0;if(b.is.array(a)&&0===a.length)return!0;if(b.is.jq(a)&&0===a.length)return!0;if(b.is.hash(a)){for(var c in a)if(a.hasOwnProperty(c))return!1;return!0}return!1},b.is.error=function(a){return"[object Error]"===Object.prototype.toString.call(a)},b.is.fn=function(a){return a===window.alert||"[object Function]"===Object.prototype.toString.call(a)},b.is.hash=function(a){return b.is.object(a)&&a.constructor===Object&&!a.nodeType&&!a.setInterval},b.is.jq=function(c){return!b.is.undef(a)&&c instanceof a},b.is.number=function(a){return"[object Number]"===Object.prototype.toString.call(a)&&!isNaN(a)},b.is.object=function(a){return"[object Object]"===Object.prototype.toString.call(a)&&!b.is.undef(a)&&null!==a},b.is.promise=function(a){return b.is.object(a)&&b.is.fn(a.then)&&b.is.fn(a.promise)},b.is.size=function(a){return!!(b.is.string(a)&&!b.is.empty(a)||b.is.number(a))&&/^(auto|none|(?:[\d\.]*)+?(?:%|px|mm|q|cm|in|pt|pc|em|ex|ch|rem|vh|vw|vmin|vmax)?)$/.test(a)},b.is.string=function(a){return"[object String]"===Object.prototype.toString.call(a)},b.is.undef=function(a){return void 0===a})}(FooGallery.utils.$,FooGallery.utils),function(a,b,c){if("0.0.8"===b.version){b.fn={};var d=Function.prototype.toString;b.fn.CONTAINS_SUPER=/xyz/.test(d.call(function(){xyz}))?/\b_super\b/:/.*/,b.fn.addOrOverride=function(a,e,f){if(c.object(a)&&c.string(e)&&!c.empty(e)&&c.fn(f)){var g=a[e],h=c.fn(g)&&b.fn.CONTAINS_SUPER.test(d.call(f));a[e]=h?function(a,b){return function(){var c=this._super;this._super=a;var d=b.apply(this,arguments);return this._super=c,d}}(g,f):f}},b.fn.apply=function(a,b){function d(){return a.apply(this,b)}return b=c.array(b)?b:[],d.prototype=a.prototype,new d},b.fn.arg2arr=function(a){return Array.prototype.slice.call(a)},b.fn.check=function(d,e,f,g){function h(a){return function(){return a.apply(d,arguments)}}return f=c.fn(f)?f:a.noop,d=c.object(d)?d:window,e=c.string(e)?b.fn.fetch(e,g):e,h(c.fn(e)?e:f)},b.fn.fetch=function(b,d){return!c.string(b)||c.empty(b)?null:(d=c.object(d)?d:window,a.each(b.split("."),function(a,b){if(!d[b])return!1;d=d[b]}),c.fn(d)?d:null)},b.fn.enqueue=function(d,e,f,g){function h(a,b){try{return n.push(a),b.apply(a,i)}catch(a){return j.reject(a,n),j}}var i=b.fn.arg2arr(arguments),j=a.Deferred(),k=a.Deferred(),l=k.promise(),m=[],n=[],o=!0;return d=i.shift(),e=i.shift(),a.each(d,function(a,d){c.fn(d[e])&&(l=l.then(function(){if(!o){var a=b.fn.arg2arr(arguments);m.push(a)}return o=!1,h(d,d[e])}))}),l.then(function(){if(!o){var a=b.fn.arg2arr(arguments);m.push(a)}o=!1,j.resolve(m)}),l.fail(function(){var a=b.fn.arg2arr(arguments);a.push(n),j.reject.apply(j,a)}),k.resolve(),j.promise()},b.fn.when=function(b){if(!c.array(b)||c.empty(b))return a.when();for(var d=a.Deferred(),e=[],f=b.length,g=0;g<b.length;g++)b[g].then(function(a){e.push(a)}).always(function(){--f||d.resolve(e)});return d.promise()},b.fn.rejectWith=function(c,d){var e=a.Deferred(),f=b.fn.arg2arr(arguments);return e.reject.apply(e,f).promise()},b.fn.resolveWith=function(c,d){var e=a.Deferred(),f=b.fn.arg2arr(arguments);return e.resolve.apply(e,f).promise()},b.fn.resolved=a.Deferred().resolve().promise(),b.fn.rejected=a.Deferred().reject().promise()}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b){if("0.0.8"===a.version){a.url={};var c=document.createElement("a");a.url.parts=function(a){return c.href=a,{hash:c.hash,host:c.host,hostname:c.hostname,href:c.href,origin:c.origin,pathname:c.pathname,port:c.port,protocol:c.protocol,search:c.search}},a.url.full=function(a){return!b.string(a)||b.empty(a)?null:(c.href=a,c.href)},a.url.param=function(a,c,d){if(!b.string(a)||!b.string(c)||b.empty(c))return a;var e,f,g,h;return b.undef(d)?(e=new RegExp("[?|&]"+c+"=([^&;]+?)(&|#|;|$)"),f=e.exec(a)||[,""],g=f[1].replace(/\+/g,"%20"),b.string(g)&&!b.empty(g)?decodeURIComponent(g):null):(""===d||null===d?(e=new RegExp("^([^#]*?)(([^#]*)&)?"+c+"(=[^&#]*)?(&|#|$)"),g=a.replace(e,"$1$3$5").replace(/^([^#]*)((\?)&|\?(#|$))/,"$1$3$4")):(e=new RegExp("([?&])"+c+"[^&]*"),h=c+"="+encodeURIComponent(d),(g=a.replace(e,"$1"+h))!==a||e.test(g)||(g+=(-1!==g.indexOf("?")?"&":"?")+h)),g)}}}(FooGallery.utils,FooGallery.utils.is),function(a,b,c){"0.0.8"===a.version&&(a.str={},a.str.camel=function(a){return b.empty(a)?a:a.toUpperCase()===a?a.toLowerCase():a.replace(/^([A-Z])|[-\s_]+(\w)/g,function(a,c,d){return b.string(d)?d.toUpperCase():c.toLowerCase()})},a.str.contains=function(a,c,d){return!(!b.string(a)||b.empty(a)||!b.string(c)||b.empty(c))&&(c.length<=a.length&&-1!==(d?a.toUpperCase().indexOf(c.toUpperCase()):a.indexOf(c)))},a.str.containsWord=function(a,c,d){if(!b.string(a)||b.empty(a)||!b.string(c)||b.empty(c)||a.length<c.length)return!1;for(var e=a.split(/\W/),f=0,g=e.length;f<g;f++)if(d?e[f].toUpperCase()==c.toUpperCase():e[f]==c)return!0;return!1},a.str.endsWith=function(a,c){return!b.string(a)||b.empty(a)||!b.string(c)||b.empty(c)?a==c:a.slice(a.length-c.length)==c},a.str.escapeRegExp=function(a){return b.empty(a)?a:a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},a.str.fnv1a=function(a){if(!b.string(a)||b.empty(a))return null;var c,d,e=2166136261;for(c=0,d=a.length;c<d;c++)e^=a.charCodeAt(c),e+=(e<<1)+(e<<4)+(e<<7)+(e<<8)+(e<<24);return e>>>0},a.str.from=function(c,d){return!b.string(c)||b.empty(c)||!b.string(d)||b.empty(d)?null:a.str.contains(c,d)?c.substring(c.indexOf(d)+d.length):null},a.str.join=function(d,e,f){if(!b.string(d)||!b.string(e))return null;var g=c.arg2arr(arguments);d=g.shift();var h,i,j=g.shift();for(h=0,i=g.length;h<i;h++)e=g[h],b.empty(e)||(a.str.endsWith(j,d)&&(j=j.slice(0,j.length-d.length)),a.str.startsWith(e,d)&&(e=e.slice(d.length)),j+=d+e);return j},a.str.startsWith=function(a,c){return!b.empty(a)&&!b.empty(c)&&a.slice(0,c.length)==c},a.str.until=function(c,d){return b.empty(c)||b.empty(d)?c:a.str.contains(c,d)?c.substring(0,c.indexOf(d)):c},a.str.format=function(a,d,e){var f=c.arg2arr(arguments);if(a=f.shift(),b.empty(a)||b.empty(f))return a;1===f.length&&(b.array(f[0])||b.object(f[0]))&&(f=f[0]);for(var g in f)a=a.replace(new RegExp("\\{"+g+"\\}","gi"),f[g]);return a})}(FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn),function(a,b,c,d,e){if("0.0.8"===b.version){b.obj={};var f=function(){};b.obj.create=function(a){if(!c.object(a))throw TypeError("Argument must be an object");f.prototype=a;var b=new f;return f.prototype=null,b},b.obj.extend=function(e,f,g){e=c.object(e)?e:{};var h=d.arg2arr(arguments);return h.shift(),a.each(h,function(a,c){b.obj.merge(e,c)}),e},b.obj.merge=function(a,d){a=c.hash(a)?a:{},d=c.hash(d)?d:{};for(var e in d)d.hasOwnProperty(e)&&(c.hash(d[e])?(a[e]=c.hash(a[e])?a[e]:{},b.obj.merge(a[e],d[e])):c.array(d[e])?a[e]=d[e].slice():a[e]=d[e]);return a},b.obj.mergeValid=function(d,e,f,g){if(!c.hash(f)||!c.hash(e))return d;e=c.hash(e)?e:{},g=c.hash(g)?g:{};var h,i,j;for(h in e)e.hasOwnProperty(h)&&c.fn(e[h])&&(i=c.array(g[h])?g[h]:c.string(g[h])?[g[h]]:[h],a.each(i,function(a,g){if(j=b.obj.prop(f,g),!c.undef(j))return e[h](j)?(b.obj.prop(d,h,j),!1):void 0}));return d},b.obj.prop=function(b,d,f){if(c.object(b)&&!c.empty(d)){var g,h;if(c.undef(f))return e.contains(d,".")?(g=d.split("."),h=g.length-1,a.each(g,function(a,d){if(a===h)f=b[d];else{if(!c.hash(b[d]))return!1;b=b[d]}})):c.undef(b[d])||(f=b[d]),f;e.contains(d,".")?(g=d.split("."),h=g.length-1,a.each(g,function(a,d){a===h?b[d]=f:b=c.hash(b[d])?b[d]:b[d]={}})):c.undef(b[d])||(b[d]=f)}}}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.str),function(a,b,c){if("0.0.8"===b.version){b.ready=function(a){function c(){try{a.call(window,b.$)}catch(a){console.error(a)}}(Function("/*@cc_on return true@*/")()?"complete"===document.readyState:"loading"!==document.readyState)?c():document.addEventListener("DOMContentLoaded",c,!1)};var d=0;b.uniqueId=function(a,b){var e=a.attr("id");return c.empty(e)&&(b=c.string(b)&&!c.empty(b)?b:"uid-",e=b+ ++d,a.attr("id",e).data("__uniqueId__",!0)),e},b.removeUniqueId=function(a){a.data("__uniqueId__")&&a.removeAttr("id").removeData("__uniqueId__")}}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b,c){if("0.0.8"===b.version){b.transition={};var d=document.createElement("div");b.transition.supported=function(a){var b=a.style;return c.string(b.transition)||c.string(b.WebkitTransition)||c.string(b.MozTransition)||c.string(b.msTransition)||c.string(b.OTransition)}(d),b.transition.end=function(a){var b=a.style;return c.string(b.transition)?"transitionend":c.string(b.WebkitTransition)?"webkitTransitionEnd":c.string(b.MozTransition)?"transitionend":c.string(b.msTransition)?"msTransitionEnd":c.string(b.OTransition)?"oTransitionEnd":null}(d),b.transition.duration=function(a,b){if(b=c.number(b)?b:0,!c.jq(a))return b;var d=a.css("transition-duration");if(/^([\d\.]*)+?(ms|s)$/i.test(d)){var e=d.match(/^([\d\.]*)+?(ms|s)$/i),f=parseFloat(e[1]);return"s"===e[2].toLowerCase()&&(f*=1e3),f}return b},b.transition.start=function(d,e,f,g){var h=a.Deferred();if(d=d.first(),b.transition.supported){var i=d.data("transition_safety");c.hash(i)&&c.number(i.timer)&&(clearTimeout(i.timer),d.removeData("transition_safety").off(b.transition.end+".utils"),i.deferred.reject()),g=c.number(g)?g:b.transition.duration(d)+50,i={deferred:h,timer:setTimeout(function(){d.removeData("transition_safety").off(b.transition.end+".utils"),h.resolve()},g)},d.data("transition_safety",i),d.on(b.transition.end+".utils",function(a){d.is(a.target)&&(clearTimeout(i.timer),d.removeData("transition_safety").off(b.transition.end+".utils"),h.resolve())})}return setTimeout(function(){c.fn(e)?e.apply(d.get(0),[d]):d.toggleClass(e,f),b.transition.supported||h.resolve()},20),h.promise()}}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d,e){"0.0.8"===b.version&&(b.Class=function(){},b.Class.extend=function(a){function f(){if(!c.fn(this.construct))throw new SyntaxError('FooGallery.utils.Class objects must be constructed with the "new" keyword.');this.construct.apply(this,arguments)}a=c.hash(a)?a:{};var g=d.create(this.prototype);for(var h in a)a.hasOwnProperty(h)&&e.addOrOverride(g,h,a[h]);return g.construct=c.fn(g.construct)?g.construct:function(){},f.prototype=g,f.prototype.constructor=c.fn(g.__ctor__)?g.__ctor__:f,f.extend=b.Class.extend,f.override=b.Class.override,f},b.Class.override=function(a,b){e.addOrOverride(this.prototype,a,b)})}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj,FooGallery.utils.fn),function(a,b,c){if("0.0.8"===b.version){b.Bounds=b.Class.extend({construct:function(){var a=this;a.top=0,a.right=0,a.bottom=0,a.left=0,a.width=0,a.height=0},inflate:function(a){var b=this;return c.number(a)&&(b.top-=a,b.right+=a,b.bottom+=a,b.left-=a,b.width+=2*a,b.height+=2*a),b},intersects:function(a){var b=this;return b.left<=a.right&&a.left<=b.right&&b.top<=a.bottom&&a.top<=b.bottom}});var d;b.getViewportBounds=function(c){d||(d=a(window));var e=new b.Bounds;return e.top=d.scrollTop(),e.left=d.scrollLeft(),e.width=d.width(),e.height=d.height(),e.right=e.left+e.width,e.bottom=e.top+e.height,e.inflate(c),e},b.getElementBounds=function(d){c.jq(d)||(d=a(d));var e=new b.Bounds;if(0!==d.length){var f=d.offset();e.top=f.top,e.left=f.left,e.width=d.width(),e.height=d.height()}return e.right=e.left+e.width,e.bottom=e.top+e.height,e}}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d){"0.0.8"===b.version&&(b.Factory=b.Class.extend({construct:function(){this.registered={}},contains:function(a){return!c.undef(this.registered[a])},load:function(b,e,f){var g,h,i=this,j=d.arg2arr(arguments),k=[],l=[];b=j.shift()||{};for(g in i.registered)if(i.registered.hasOwnProperty(g)){var m=i.registered[g];b.hasOwnProperty(g)&&(h=b[g],c.string(h)&&(h=d.fetch(b[g])),c.fn(h)&&(m={name:g,klass:h,priority:i.registered[g].priority})),k.push(m)}for(g in b)b.hasOwnProperty(g)&&!i.registered.hasOwnProperty(g)&&(h=b[g],c.string(h)&&(h=d.fetch(b[g])),c.fn(h)&&k.push({name:g,klass:h,priority:0}));return k.sort(function(a,b){return b.priority-a.priority}),a.each(k,function(a,b){c.fn(b.klass)&&l.push(d.apply(b.klass,j))}),l},make:function(a,b,e){var f,g=this,h=d.arg2arr(arguments);return a=h.shift(),f=g.registered[a],c.hash(f)&&c.fn(f.klass)?d.apply(f.klass,h):null},names:function(b){b=!!c.boolean(b)&&b;var d,e=[];if(b){var f=[];for(d in this.registered)this.registered.hasOwnProperty(d)&&f.push(this.registered[d]);f.sort(function(a,b){return b.priority-a.priority}),a.each(f,function(a,b){e.push(b.name)})}else for(d in this.registered)this.registered.hasOwnProperty(d)&&e.push(d);return e},register:function(a,b,d){if(!c.string(a)||c.empty(a)||!c.fn(b))return!1;d=c.number(d)?d:0;var e=this.registered[a];return this.registered[a]={name:a,klass:b,priority:c.undef(e)?d:e.priority},!0}}))}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn),function(a,b,c){if("0.0.8"===a.version){var d=!1;try{d=!!window.localStorage}catch(a){d=!1}a.Debugger=a.Class.extend({construct:function(a){this.key=a,this.enabled=!!d&&!!localStorage.getItem(this.key)},enable:function(){d&&(this.enabled=!0,localStorage.setItem(this.key,this.enabled))},disable:function(){d&&(this.enabled=!1,localStorage.removeItem(this.key))},log:function(a,c){this.enabled&&console.log.apply(console,b.arg2arr(arguments))},logf:function(a,d,e){if(this.enabled){var f=b.arg2arr(arguments);a=f.shift(),d=f.shift(),f.unshift(c.format(a,d)),this.log.apply(this,f)}}})}}(FooGallery.utils,FooGallery.utils.fn,FooGallery.utils.str),function(a,b,c){"0.0.8"===b.version&&(b.Throttle=b.Class.extend({construct:function(a){this.id=null,this.active=!1,this.idle=c.number(a)?a:0},limit:function(a){if(c.fn(a)){this.clear();var b=this;this.active=!0,this.id=setTimeout(function(){b.active=!1,b.id=null,a()},this.idle)}},clear:function(){c.number(this.id)&&(clearTimeout(this.id),this.active=!1,this.id=null)}}))}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d,e){b.debug=new c.Debugger("__FooGallery__"),c.selectify=function(b){if(d.empty(b))return null;if(d.hash(b)){var e,f={};for(var g in b)b.hasOwnProperty(g)&&(e=c.selectify(b[g]))&&(f[g]=e);return f}return d.string(b)||d.array(b)?(d.string(b)&&(b=[b]),a.map(b,function(a){return d.string(a)?"."+a.split(/\s/g).join("."):null}).join(",")):null},b.emptyImage="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",b.dataTemplate="__FooGallery__",b.dataItem="__FooGalleryItem__",b.init=function(a,c){return b.template.make(a,c).initialize()},b.initAll=function(c){return e.when(a(".foogallery").map(function(a,d){return b.init(c,d)}).get())},b.parseSrc=function(b,c,e,f,g,h){if(!d.string(b))return null;if(!d.string(f))return b;var i=a.map(f.replace(/(\s[\d.]+[whx]),/g,"$1 @,@ ").split(" @,@ "),function(a){return{url:/^\s*(\S*)/.exec(a)[1],w:parseFloat((/\S\s+(\d+)w/.exec(a)||[0,1/0])[1]),h:parseFloat((/\S\s+(\d+)h/.exec(a)||[0,1/0])[1]),x:parseFloat((/\S\s+([\d.]+)x/.exec(a)||[0,1])[1])}});if(!i.length)return b;i.unshift({url:b,w:i[0].w!==1/0&&i[0].h===1/0?c:1/0,h:i[0].h!==1/0&&i[0].w===1/0?e:1/0,x:1});var j,k=window.devicePixelRatio||1,l={w:g*k,h:h*k,x:k};for(j in l)l.hasOwnProperty(j)&&(i=a.grep(i,function(a,b){return function(c){return c[a]>=l[a]||c[a]===b}}(j,Math.max.apply(null,a.map(i,function(a){return a[j]})))));for(j in l)l.hasOwnProperty(j)&&(i=a.grep(i,function(a,b){return function(c){return c[a]===b}}(j,Math.min.apply(null,a.map(i,function(a){return a[j]})))));return i[0].url},a.fn.foogallery=function(c,e){return this.each(function(f,g){if(d.string(c)){var h=a.data(g,b.dataTemplate);if(h instanceof b.Template)switch(c){case"layout":return void h.layout();case"destroy":return void h.destroy()}}else b.template.make(c,g).initialize().then(function(a){d.fn(e)&&e(a)})})}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn),function(a,b,c,d,e,f){b.TemplateFactory=c.Factory.extend({construct:function(){this.registered={}},register:function(a,b,c,e,f,g){var h=this,i=h._super(a,b,g);if(i){var j=h.registered;j[a].opt=d.hash(c)?c:{},j[a].cls=d.hash(e)?e:{},j[a].il8n=d.hash(f)?f:{}}return i},make:function(b,c){c=d.jq(c)?c:a(c),b=f.extend({},b,c.data("foogallery"));var e=this,g=e.type(b,c);return e.contains(g)?(b=e.options(g,b),e._super(g,b,c)):null},type:function(b,e){e=d.jq(e)?e:a(e);var f=this,g=d.hash(b)&&d.hash(b)&&d.string(b.type)&&f.contains(b.type)?b.type:"core";if("core"===g&&e.length>0)for(var h=f.registered,i=f.names(!0),j=0,k=i.length;j<k;j++)if(h.hasOwnProperty(i[j])){var l=i[j],m=h[l].cls;if(d.string(m.container)){var n=c.selectify(m.container);if(e.is(n)){g=i[j];break}}}return g},configure:function(a,b,c,d){var e=this;if(e.contains(a)){var g=e.registered;f.extend(g[a].opt,b),f.extend(g[a].cls,c),f.extend(g[a].il8n,d)}},options:function(a,c){c=f.extend({type:a},c);var e=this,g=e.registered,h=g.core.opt,i=g.core.cls,j=g.core.il8n;return d.hash(c.cls)||(c.cls={}),d.hash(c.il8n)||(c.il8n={}),d.undef(b.filtering)||(c=b.filtering.merge(c)),d.undef(b.paging)||(c=b.paging.merge(c)),"core"!==a&&e.contains(a)?(c=f.extend({},h,g[a].opt,c),c.cls=f.extend({},i,g[a].cls,c.cls),c.il8n=f.extend({},j,g[a].il8n,c.il8n)):(c=f.extend({},h,c),c.cls=f.extend({},i,c.cls),c.il8n=f.extend({},j,c.il8n)),c}}),b.template=new b.TemplateFactory}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d,e){a.PagingFactory=b.Factory.extend({construct:function(){this.registered={}},register:function(a,b,d,e,f,g,h){var i=this,j=i._super(a,b,h);if(j){var k=i.registered;k[a].ctrl=c.fn(d)?d:null,k[a].opt=c.hash(e)?e:{},k[a].cls=c.hash(f)?f:{},k[a].il8n=c.hash(g)?g:{}}return j},type:function(a){var b,d=this;return c.hash(a)&&c.hash(b=a.paging)&&c.string(b.type)&&d.contains(b.type)?b.type:null},merge:function(a){a=e.extend({},a);var b=this,d=b.type(a),f=b.registered,g=f.default.opt,h=f.default.cls,i=f.default.il8n,j=c.hash(a.paging)?a.paging:{},k=c.hash(a.cls)&&c.hash(a.cls.paging)?e.extend({},a.cls.paging):{},l=c.hash(a.il8n)&&c.hash(a.il8n.paging)?e.extend({},a.il8n.paging):{};return c.hash(a.cls)||(a.cls={}),c.hash(a.il8n)||(a.il8n={}),"default"!==d&&b.contains(d)?(a.paging=e.extend({},g,f[d].opt,j,{type:d}),a.cls=e.extend(a.cls,{paging:h},{paging:f[d].cls},{paging:k}),a.il8n=e.extend(a.il8n,{paging:i},{paging:f[d].il8n},{paging:l})):(a.paging=e.extend({},g,j,{type:d}),a.cls=e.extend(a.cls,{paging:h},{paging:k}),a.il8n=e.extend(a.il8n,{paging:i},{paging:l})),a},configure:function(a,b,c,d){var f=this;if(f.contains(a)){var g=f.registered;e.extend(g[a].opt,b),e.extend(g[a].cls,c),e.extend(g[a].il8n,d)}},hasCtrl:function(a){var b=this,d=b.registered[a];return c.hash(d)&&c.fn(d.ctrl)},makeCtrl:function(a,b,d,e){var f=this,g=f.registered[a];return c.hash(g)&&c.fn(g.ctrl)?new g.ctrl(b,d,e):null}}),a.paging=new a.PagingFactory}(FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d,e,f){var g=0;b.Template=c.Class.extend({construct:function(e,f){var h=this;h.namespace=".foogallery-"+ ++g,h.$el=d.jq(f)?f:a(f),h.opt=e,h.template=e.template,h.id=h.$el.prop("id")||e.id,h.cls=e.cls,h.il8n=e.il8n,h.sel=c.selectify(h.cls),h.items=b.components.make("items",h),h.pages=d.undef(b.paging)?null:b.paging.make(e.paging.type,h),h.filter=d.undef(b.filtering)?null:b.filtering.make(e.filtering.type,h),h.state=b.components.make("state",h),h._initialize=null,h.initializing=!1,h.initialized=!1,h.destroying=!1,h.destroyed=!1,h._undo={classes:"",style:"",create:!1,children:!1}},initialize:function(f){var g=this;return d.promise(g._initialize)?g._initialize:(f=d.jq(f)?f:a(f),g._initialize=a.Deferred(function(h){if(g.initializing=!0,0===f.length&&0===g.$el.parent().length)return void h.reject("A parent element is required.");0===g.$el.length&&(g.$el=g.create(),g._undo.create=!0),f.length>0&&g.$el.appendTo(f);var i,j=a.Deferred(),k=j.promise();g.$el.length>0&&(i=g.$el.data(b.dataTemplate))instanceof b.Template?k=k.then(function(){return i.destroy().then(function(){g.$el.data(b.dataTemplate,g)})}):g.$el.data(b.dataTemplate,g),k.then(function(){if(g.destroying)return e.rejectWith("destroy in progress");d.empty(g.opt.on)||g.$el.on(g.opt.on),g._undo.classes=g.$el.attr("class"),g._undo.style=g.$el.attr("style"),g.$el.is(g.sel.container)||g.$el.addClass(g.cls.container);var a=c.selectify(g.opt.classes);return null==a||g.$el.is(a)||g.$el.addClass(g.opt.classes),0==g.$el.children().length&&(g.$el.append(g.createChildren()),g._undo.children=!0),g.raise("pre-init").isDefaultPrevented()?e.rejectWith("pre-init default prevented"):void 0}).then(function(){return g.destroying?e.rejectWith("destroy in progress"):g.opt.delay<=0?e.resolved:a.Deferred(function(a){g._delay=setTimeout(function(){g._delay=null,a.resolve()},g.opt.delay)}).promise()}).then(function(){return g.destroying?e.rejectWith("destroy in progress"):g.raise("init").isDefaultPrevented()?e.rejectWith("init default prevented"):g.items.fetch()}).then(function(){if(g.destroying)return e.rejectWith("destroy in progress");if(g.raise("post-init").isDefaultPrevented())return e.rejectWith("post-init default prevented");var b=g.state.parse();g.state.set(d.empty(b)?g.state.initial():b),a(window).on("scroll"+g.namespace,{self:g},g.throttle(g.onWindowScroll,g.opt.throttle)).on("popstate"+g.namespace,{self:g},g.onWindowPopState)}).then(function(){return g.destroying?e.rejectWith("destroy in progress"):(g.raise("first-load"),g.loadAvailable())}).then(function(){if(g.destroying)return e.rejectWith("destroy in progress");g.initializing=!1,g.initialized=!0,g._check(200),g._check(500),g._check(1e3),g._check(2e3),g._check(5e3),g.raise("ready"),h.resolve(g)}).fail(function(a){h.reject(a)}),j.resolve()}).promise().fail(function(a){console.log("initialize failed",g,a),g.destroy()}))},create:function(){var b=this;return a("<div/>",{id:b.id,class:b.cls.container}).addClass(b.opt.classes)},createChildren:function(){return a()},destroy:function(){var b=this;return b.destroyed?e.resolved:(b.destroying=!0,a.Deferred(function(a){b.initializing&&d.promise(b._initialize)?b._initialize.always(function(){b.destroying=!1,b._destroy(),a.resolve()}):(b.destroying=!1,b._destroy(),a.resolve())}).promise())},_destroy:function(){var c=this;c.destroyed||(c.raise("destroy"),a(window).off(c.namespace),c.state.destroy(),c.filter&&c.filter.destroy(),c.pages&&c.pages.destroy(),c.items.destroy(),d.empty(c.opt.on)||c.$el.off(c.opt.on),c.raise("destroyed"),c.$el.removeData(b.dataTemplate),d.empty(c._undo.classes)?c.$el.removeAttr("class"):c.$el.attr("class",c._undo.classes),d.empty(c._undo.style)?c.$el.removeAttr("style"):c.$el.attr("style",c._undo.style),c._undo.children&&c.$el.empty(),c._undo.create&&c.$el.remove(),c.$el=c.state=c.items=c.pages=null,c.destroyed=!0,c.initializing=!1,c.initialized=!1)},getAvailable:function(){return this.pages?this.pages.available():this.items.available()},loadAvailable:function(){return this.items.load(this.getAvailable())},_check:function(a){a=d.number(a)?a:0;var b=this;setTimeout(function(){!b.initialized||b.destroying&&b.destroyed||b.loadAvailable()},a)},raise:function(c,e){if(!d.string(c)||d.empty(c))return null;e=d.array(e)?e:[];var g=this,h=c.split(".")[0],i=f.camel("on-"+h),j=a.Event(h+".foogallery");return e.unshift(g),g.$el.trigger(j,e),b.debug.logf("{id}|{name}:",{id:g.id,name:h},e),d.fn(g[i])&&(e.unshift(j),g[i].apply(g.$el.get(0),e)),j},layout:function(){var a=this;null!==a._initialize&&a.raise("layout")},throttle:function(a,b){var c=Date.now();return function(){if(c+b-Date.now()<0){var d=e.arg2arr(arguments);a.apply(this,d),c=Date.now()}}},onWindowPopState:function(a){var b=a.data.self,c=a.originalEvent.state;d.empty(c)||c.id!==b.id||(b.state.set(c),b.loadAvailable())},onWindowScroll:function(a){a.data.self.loadAvailable()}}),b.template.register("core",b.Template,{id:null,type:"core",classes:"",on:{},lazy:!0,viewport:200,items:[],delay:100,throttle:50,timeout:6e4,srcset:"data-srcset",src:"data-src",template:{}},{container:"foogallery"},{},-100)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.str),function(a,b){a.Component=b.Class.extend({construct:function(a){this.tmpl=a},destroy:function(){this.tmpl=null}}),a.components=new b.Factory}(FooGallery,FooGallery.utils),function(a,b,c,d){b.State=b.Component.extend({construct:function(a){var b=this;b._super(a),b.apiEnabled=!!window.history&&!!history.replaceState,b.opt=b.tmpl.opt.state,b.enabled=b.opt.enabled,b.pushOrReplace=b.isPushOrReplace(b.opt.pushOrReplace)?b.opt.pushOrReplace:"replace";var c=d.escapeRegExp(b.tmpl.id),e=d.escapeRegExp(b.opt.values),f=d.escapeRegExp(b.opt.pair);b.regex={exists:new RegExp("^#"+c+"\\"+e+".+?"),values:new RegExp("(\\w+)"+f+"([^"+e+"]+)","g")}},destroy:function(){var a=this;a.clear(),a.opt=a.regex={},a._super()},isPushOrReplace:function(b){return-1!==a.inArray(b,["push","replace"])},exists:function(){return this.regex.exists.test(location.hash)&&this.regex.values.test(location.hash)},parse:function(){var b=this,d={};if(b.exists())if(b.enabled){d.id=b.tmpl.id;var e=location.hash.match(b.regex.values);a.each(e,function(e,f){var g=f.split(b.opt.pair);2===g.length&&(d[g[0]]=-1===g[1].indexOf(b.opt.array)?decodeURIComponent(g[1]):a.map(g[1].split(b.opt.array),function(a){return decodeURIComponent(a)}),c.string(d[g[0]])&&!isNaN(d[g[0]])&&(d[g[0]]=parseInt(d[g[0]])))})}else b.apiEnabled?history.replaceState(null,"",location.pathname+location.search):location.hash="#";return d},hashify:function(b){var d=this;if(c.hash(b)){var e=[];return a.each(b,function(b,f){c.empty(f)||"id"===b||(f=c.array(f)?a.map(f,function(a){return encodeURIComponent(a)}).join("+"):encodeURIComponent(f),e.push(b+d.opt.pair+f))}),e.length>0&&e.unshift("#"+d.tmpl.id),e.join(d.opt.values)}return""},replace:function(a){var b=this;if(b.enabled&&b.apiEnabled){a.id=b.tmpl.id;var d=b.hashify(a),e=c.empty(d);history.replaceState(e?null:a,"",e?location.pathname+location.search:d)}},push:function(a){var b=this;if(b.enabled&&b.apiEnabled){a.id=b.tmpl.id;var d=b.hashify(a),e=c.empty(d);history.pushState(e?null:a,"",e?location.pathname+location.search:d)}},update:function(a,b){var c=this;c.enabled&&c.apiEnabled&&(b=c.isPushOrReplace(b)?b:c.pushOrReplace,c[b](a))},clear:function(){this.exists()&&this.replace({})},initial:function(){var a=this,b=a.tmpl,d={};return b.filter&&!c.empty(b.filter.current)&&(d.f=b.filter.current),b.pages&&b.pages.current>1&&(d.p=b.pages.current),d},get:function(a){var d=this,e=d.tmpl,f={};return a instanceof b.Item&&(f.i=a.id),e.filter&&!c.empty(e.filter.current)&&(f.f=e.filter.current),e.pages&&e.pages.isValid(e.pages.current)&&(f.p=e.pages.current),f},set:function(a){var b=this,d=b.tmpl;if(c.hash(a)){d.items.reset();var e=d.items.get(a.i);if(d.filter){d.filter.rebuild();var f=c.empty(a.f)?[]:a.f;d.filter.set(f,!1)}if(d.pages){d.pages.rebuild();var g=d.pages.number(a.p);e&&!d.pages.contains(g,e)&&(g=d.pages.find(e),g=0!==g?g:1),d.pages.set(g,!c.empty(a),!1),e&&d.pages.contains(g,e)&&e.scrollTo()}else d.items.detach(d.items.all()),d.items.create(d.items.available(),!0),e&&e.scrollTo();c.empty(a.i)||(a.i=null,b.replace(a))}}}),b.template.configure("core",{state:{enabled:!1,pushOrReplace:"replace",values:"/",pair:":",array:"+"}}),b.components.register("state",b.State)}(FooGallery.$,FooGallery,FooGallery.utils.is,FooGallery.utils.str),function(a,b,c,d,e,f){b.Item=b.Component.extend({construct:function(a,b){var c=this;c._super(a),c.cls=a.cls.item,c.il8n=a.il8n.item,c.sel=a.sel.item,c.opt=f.extend({},a.opt.item,b),c.isAttached=!1,c.isCreated=!1,c.isLoading=!1,c.isLoaded=!1,c.isError=!1,c.isParsed=!1,c.$el=null,c.$inner=null,c.$anchor=null,c.$image=null,c.$caption=null,c.type=c.opt.type,c.id=c.opt.id,c.href=c.opt.href,c.src=c.opt.src,c.srcset=c.opt.srcset,c.width=c.opt.width,c.height=c.opt.height,c.title=c.opt.title,c.alt=c.opt.alt,c.caption=d.empty(c.opt.caption)?c.title:c.opt.caption,c.description=d.empty(c.opt.description)?c.alt:c.opt.description,c.attr=c.opt.attr,c.tags=c.opt.tags,c.maxWidth=c.opt.maxWidth,c.maxCaptionLength=c.opt.maxCaptionLength,c.maxDescriptionLength=c.opt.maxDescriptionLength,c.showCaptionTitle=c.opt.showCaptionTitle,c.showCaptionDescription=c.opt.showCaptionDescription,c._thumbUrl=null,c._placeholder=null,c._load=null,c._undo={classes:"",style:"",loader:!1,placeholder:!1}},destroy:function(){var a=this;return a.tmpl.raise("destroy-item").isDefaultPrevented()||(a.doDestroyItem(),a._super()),null===a.tmpl},doDestroyItem:function(){var a=this;a.isParsed?(a.append(),d.empty(a._undo.classes)?a.$el.removeAttr("class"):a.$el.attr("class",a._undo.classes),d.empty(a._undo.style)?a.$el.removeAttr("style"):a.$el.attr("style",a._undo.style),a._undo.loader&&a.$el.find(a.sel.loader).remove(),a._undo.placeholder&&a.$image.prop("src")==a._placeholder&&a.$image.removeAttr("src")):a.isCreated&&(a.detach(),a.$el.remove())},parse:function(b){var c=this,d=a(b);return!c.tmpl.raise("parse-item",[c,d]).isDefaultPrevented()&&(c.isCreated=d.is(c.sel.elem))&&(c.isParsed=c.doParseItem(d),c.fix()),c.isParsed&&c.tmpl.raise("parsed-item",[c]),c.isParsed},doParseItem:function(c){var e=this,f=e.tmpl.opt,g=e.cls,h=e.sel;return e._undo.classes=c.attr("class")||"",e._undo.style=c.attr("style")||"",e.$el=c.data(b.dataItem,e),e.$inner=e.$el.find(h.inner),e.$anchor=e.$el.find(h.anchor).on("click.foogallery",{self:e},e.onAnchorClick),e.$image=e.$anchor.find(h.image),e.$caption=e.$el.find(h.caption.elem).on("click.foogallery",{self:e},e.onCaptionClick),e.isAttached=e.$el.parent().length>0,e.isLoading=e.$el.is(h.loading),e.isLoaded=e.$el.is(h.loaded),e.isError=e.$el.is(h.error),e.id=e.$anchor.data("id")||e.id,e.tags=e.$anchor.data("tags")||e.tags,e.href=e.$anchor.attr("href")||e.href,e.src=e.$image.attr(f.src)||e.src,e.srcset=e.$image.attr(f.srcset)||e.srcset,e.width=parseInt(e.$image.attr("width"))||e.width,e.height=parseInt(e.$image.attr("height"))||e.height,e.title=e.$image.attr("title")||e.title,e.alt=e.$image.attr("alt")||e.alt,e.caption=e.$anchor.data("title")||e.$anchor.data("captionTitle")||e.caption||e.title,e.description=e.$anchor.data("description")||e.$anchor.data("captionDesc")||e.description||e.alt,d.empty(e.caption)&&(e.caption=a.trim(e.$caption.find(h.caption.title).html())),
10
+ d.empty(e.description)&&(e.description=a.trim(e.$caption.find(h.caption.description).html())),d.number(e.maxCaptionLength)&&e.maxCaptionLength>0&&!d.empty(e.caption)&&d.string(e.caption)&&e.caption.length>e.maxCaptionLength&&e.$caption.find(h.caption.title).html(e.caption.substr(0,e.maxCaptionLength)+"&hellip;"),d.number(e.maxDescriptionLength)&&e.maxDescriptionLength>0&&!d.empty(e.description)&&d.string(e.description)&&e.description.length>e.maxDescriptionLength&&e.$caption.find(h.caption.description).html(e.description.substr(0,e.maxDescriptionLength)+"&hellip;"),0===e.$el.find(h.loader).length&&(e.$el.append(a("<div/>",{class:g.loader})),e._undo.loader=!0),d.empty(e.$image.prop("src"))&&(e._placeholder=e.tmpl.items.placeholder(e.width,e.height),e.$image.prop("src",e._placeholder),e._undo.placeholder=!0),!e.isCreated||!e.isAttached||e.isLoading||e.isLoaded||e.isError||e.$el.addClass(g.idle),!0},create:function(){var a=this;if(!a.isCreated&&d.string(a.href)&&d.string(a.src)&&d.number(a.width)&&d.number(a.height)){a.tmpl.raise("create-item",[a]).isDefaultPrevented()||(a.isCreated=a.doCreateItem()),a.isCreated&&a.tmpl.raise("created-item",[a])}return a.isCreated},doCreateItem:function(){var c=this,e=c.tmpl.opt,f=c.cls,g=c.attr;g.elem.class=f.elem+" "+f.idle,g.inner.class=f.inner,g.anchor.class=f.anchor,g.anchor.href=c.href,g.anchor["data-id"]=c.id,g.anchor["data-title"]=c.caption,g.anchor["data-description"]=c.description,d.empty(c.tags)||(g.anchor["data-tags"]=JSON.stringify(c.tags)),g.image.class=f.image,g.image.src=c.tmpl.items.placeholder(c.width,c.height),g.image[e.src]=c.src,g.image[e.srcset]=c.srcset,g.image.width=c.width,g.image.height=c.height,g.image.title=c.title,g.image.alt=c.alt,c.$el=a("<div/>").attr(g.elem).data(b.dataItem,c),c.$inner=a("<figure/>").attr(g.inner).appendTo(c.$el),c.$anchor=a("<a/>").attr(g.anchor).appendTo(c.$inner).on("click.foogallery",{self:c},c.onAnchorClick),c.$image=a("<img/>").attr(g.image).appendTo(c.$anchor),f=c.cls.caption,g=c.attr.caption,g.elem.class=f.elem,c.$caption=a("<figcaption/>").attr(g.elem).on("click.foogallery",{self:c},c.onCaptionClick);var h=!d.empty(c.caption),i=!d.empty(c.description);if(h||i){g.inner.class=f.inner,g.title.class=f.title,g.description.class=f.description;var j=a("<div/>").attr(g.inner).appendTo(c.$caption);if(h){var k;k=d.number(c.maxCaptionLength)&&c.maxCaptionLength>0&&d.string(c.caption)&&c.caption.length>c.maxCaptionLength?a("<div/>").attr(g.title).html(c.caption.substr(0,c.maxCaptionLength)+"&hellip;"):a("<div/>").attr(g.title).html(c.caption),j.append(k)}if(i){var l;l=d.number(c.maxDescriptionLength)&&c.maxDescriptionLength>0&&d.string(c.description)&&c.description.length>c.maxDescriptionLength?a("<div/>").attr(g.description).html(c.description.substr(0,c.maxDescriptionLength)+"&hellip;"):a("<div/>").attr(g.description).html(c.description),j.append(l)}}return c.$caption.appendTo(c.$inner),0===c.$el.find(c.sel.loader).length&&c.$el.append(a("<div/>",{class:c.cls.loader})),!0},append:function(){var a=this;if(a.isCreated&&!a.isAttached){a.tmpl.raise("append-item",[a]).isDefaultPrevented()||(a.tmpl.$el.append(a.$el),a.fix(),a.isAttached=!0),a.isAttached&&a.tmpl.raise("appended-item",[a])}return a.isAttached},detach:function(){var a=this;if(a.isCreated&&a.isAttached){a.tmpl.raise("detach-item",[a]).isDefaultPrevented()||(a.$el.detach(),a.unfix(),a.isAttached=!1),a.isAttached||a.tmpl.raise("detached-item",[a])}return!a.isAttached},load:function(){var b=this;if(d.promise(b._load))return b._load;if(!b.isCreated||!b.isAttached)return e.rejectWith("not created or attached");if(b.tmpl.raise("load-item",[b]).isDefaultPrevented())return e.rejectWith("default prevented");var c=b.cls,f=b.$image.get(0),g=f.src;return b.isLoading=!0,b.$el.removeClass(c.idle).removeClass(c.loaded).removeClass(c.error).addClass(c.loading),b._load=a.Deferred(function(a){d.undef(window.InstallTrigger)||(f.src=""),f.onload=function(){f.onload=f.onerror=null,b.isLoading=!1,b.isLoaded=!0,b.$el.removeClass(c.loading).addClass(c.loaded),b.unfix(),b.tmpl.raise("loaded-item",[b]),a.resolve(b)},f.onerror=function(){f.onload=f.onerror=null,b.isLoading=!1,b.isError=!0,b.$el.removeClass(c.loading).addClass(c.error),d.string(g)&&b.$image.prop("src",g),b.tmpl.raise("error-item",[b]),a.reject(b)},f.src=b.getThumbUrl()}).promise()},fix:function(){var a=this;if(!a.tmpl.raise("fix-item",[a]).isDefaultPrevented()&&a.isCreated&&!a.isLoading&&!a.isLoaded&&!a.isError){var b=a.width,c=a.height;if(!isNaN(b)&&!isNaN(c)){var e=d.fn(a.maxWidth)?a.maxWidth(a):a.$image.width();e<=0&&(e=b);var f=e/b,g=c*f;a.$image.css({width:e,height:g})}}return a},unfix:function(){var a=this;return!a.tmpl.raise("unfix-item",[a]).isDefaultPrevented()&&a.isCreated&&a.$image.css({width:"",height:""}),a},getThumbUrl:function(a){a=!!d.boolean(a)&&a;var c=this;return!a&&d.string(c._thumbUrl)?c._thumbUrl:c._thumbUrl=b.parseSrc(c.src,c.width,c.height,c.srcset,c.$anchor.innerWidth(),c.$anchor.innerHeight())},scrollTo:function(a){var b=this;if(b.isAttached){var d=b.bounds(),e=c.getViewportBounds();switch(a){case"top":d.left+=d.width/2-e.width/2,d.top-=e.height/5;break;default:d.left+=d.width/2-e.width/2,d.top+=d.height/2-e.height/2}window.scrollTo(d.left,d.top)}return b},bounds:function(){return this.isAttached?c.getElementBounds(this.$el):null},intersects:function(a){return!!this.isAttached&&this.bounds().intersects(a)},onAnchorClick:function(a){var b=a.data.self,c=b.tmpl.state.get(b);b.tmpl.state.update(c)},onCaptionClick:function(b){var c=b.data.self;a(b.target).is(c.sel.caption.all)&&c.$anchor.length>0&&c.$anchor.get(0).click()}}),b.template.configure("core",{item:{type:"item",id:"",href:"",src:"",srcset:"",width:0,height:0,title:"",alt:"",caption:"",description:"",tags:[],maxWidth:null,maxCaptionLength:0,maxDescriptionLength:0,showCaptionTitle:!0,showCaptionDescription:!0,attr:{elem:{},inner:{},anchor:{},image:{},caption:{elem:{},inner:{},title:{},description:{}}}}},{item:{elem:"fg-item",inner:"fg-item-inner",anchor:"fg-thumb",image:"fg-image",loader:"fg-loader",idle:"fg-idle",loading:"fg-loading",loaded:"fg-loaded",error:"fg-error",caption:{elem:"fg-caption",inner:"fg-caption-inner",title:"fg-caption-title",description:"fg-caption-desc"}}},{item:{}}),b.components.register("item",b.Item)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d,e,f){b.Items=b.Component.extend({construct:function(a){var b=this;b._super(a),b.idMap={},b._fetched=null,b._arr=[],b._available=[],b._canvas=document.createElement("canvas");var d=b.tmpl.cls.item.caption;b.tmpl.sel.item.caption.all=c.selectify([d.elem,d.inner,d.title,d.description])},destroy:function(){var b=this,c=b.all(),d=[];c.length>0&&(b.tmpl.raise("destroy-items",[c]),d=a.map(c,function(a){return a.destroy()?a:null}),d.length>0&&b.tmpl.raise("destroyed-items",[d])),b.idMap={},b._canvas=b._fetched=null,b._arr=[],b._available=[],b._super()},fetch:function(b){var c=this;if(!b&&d.promise(c._fetched))return c._fetched;var e=c.tmpl,f=e.sel,g=e.opt.items,h=a.Deferred(),i=c.make(e.$el.find(f.item.elem));return d.empty(g)?(i.push.apply(i,c.make(window[e.id+"-items"])),h.resolve(i)):d.array(g)?(i.push.apply(i,c.make(g)),h.resolve(i)):d.string(g)?a.get(g).then(function(a){i.push.apply(i,c.make(a)),h.resolve(i)},function(a,b,c){console.log("FooGallery: GET items error.",g,a,b,c),h.resolve(i)}):h.resolve(i),h.then(function(a){c.setAll(a)}),c._fetched=h.promise()},all:function(){return this._arr.slice()},count:function(a){return a?this.all().length:this.available().length},available:function(){return this._available.slice()},get:function(a){return!d.empty(a)&&this.idMap[a]?this.idMap[a]:null},setAll:function(a){this._arr=d.array(a)?a:[],this.idMap=this.createIdMap(a),this._available=this.all()},setAvailable:function(a){this._available=d.array(a)?a:[]},reset:function(){this.setAvailable(this.all())},placeholder:function(a,c){return this._canvas&&this._canvas.toDataURL&&d.number(a)&&d.number(c)?(this._canvas.width=a,this._canvas.height=c,this._canvas.toDataURL()):b.emptyImage},loadable:function(b){var e,f=this,g=f.tmpl.opt;return g.lazy&&(e=c.getViewportBounds(g.viewport)),d.array(b)?a.map(b,function(a){return a.isCreated&&a.isAttached&&!a.isLoading&&!a.isLoaded&&!a.isError&&(!g.lazy||g.lazy&&a.intersects(e))?a:null}):[]},creatable:function(c){return d.array(c)?a.map(c,function(a){return a instanceof b.Item&&!a.isCreated?a:null}):[]},appendable:function(c){return d.array(c)?a.map(c,function(a){return a instanceof b.Item&&a.isCreated&&!a.isAttached?a:null}):[]},detachable:function(c){return d.array(c)?a.map(c,function(a){return a instanceof b.Item&&a.isCreated&&a.isAttached?a:null}):[]},jquerify:function(b){return a(a.map(b,function(a){return a.$el.get()}))},make:function(c){var e=this,g=[];if(d.jq(c)||d.array(c)){var h=[],i=a.makeArray(c);if(0===i.length)return g;e.tmpl.raise("make-items",[i]).isDefaultPrevented()||(g=a.map(i,function(a){var c=e.type(a),g=f.extend(d.hash(a)?a:{},{type:c}),i=b.components.make(c,e.tmpl,g);return d.element(a)?i.parse(a)?(h.push(i),i):null:i})),g.length>0&&e.tmpl.raise("made-items",[g]),h.length>0&&e.tmpl.raise("parsed-items",[h])}return g},type:function(c){var e;return d.hash(c)?e=c.type:d.element(c)&&(e=a(c).find(this.tmpl.sel.item.anchor).data("type")),d.string(e)&&b.components.contains(e)?e:"item"},create:function(b,c){var e=this,f=[],g=e.creatable(b);if(g.length>0){e.tmpl.raise("create-items",[g]).isDefaultPrevented()||(f=a.map(g,function(a){return a.create()?a:null})),f.length>0&&e.tmpl.raise("created-items",[f])}return d.boolean(c)&&c?e.append(b):f},append:function(b){var c=this,d=[],e=c.appendable(b);if(e.length>0){c.tmpl.raise("append-items",[e]).isDefaultPrevented()||(d=a.map(e,function(a){return a.append()?a:null})),d.length>0&&c.tmpl.raise("appended-items",[d])}return d},detach:function(b){var c=this,d=[],e=c.detachable(b);if(e.length>0){c.tmpl.raise("detach-items",[e]).isDefaultPrevented()||(d=a.map(e,function(a){return a.detach()?a:null})),d.length>0&&c.tmpl.raise("detached-items",[d])}return d},load:function(b){var c=this;if(b=c.loadable(b),b.length>0){if(!c.tmpl.raise("load-items",[b]).isDefaultPrevented()){var d=a.map(b,function(a){return a.load()});return e.when(d).done(function(a){c.tmpl.raise("loaded-items",[a])})}}return e.resolveWith([])},createIdMap:function(b){var c={};return a.each(b,function(a,b){d.empty(b.id)&&(b.id=""+(a+1)),c[b.id]=b}),c}}),b.components.register("items",b.Items)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d){b.Paging=b.Component.extend({construct:function(a){var b=this;b._super(a),b.opt=b.tmpl.opt.paging,b.cls=b.tmpl.cls.paging,b.il8n=b.tmpl.il8n.paging,b.sel=b.tmpl.sel.paging,b.pushOrReplace=b.opt.pushOrReplace,b.type=b.opt.type,b.theme=b.opt.theme,b.size=b.opt.size,b.position=b.opt.position,b.scrollToTop=b.opt.scrollToTop,b.current=0,b.total=0,b.ctrls=[],b._arr=[]},destroy:function(){var b=this;b._arr.splice(0,b._arr.length),a.each(b.ctrls.splice(0,b.ctrls.length),function(a,b){b.destroy()}),b._super()},build:function(){var a=this,c=a.tmpl.items.available();a.total=a.size>0&&c.length>0?Math.ceil(c.length/a.size):1;for(var d=0;d<a.total;d++)a._arr.push(c.splice(0,a.size));if(a.total>1&&b.paging.hasCtrl(a.type)){var e,f,g=a.position;"both"!==g&&"top"!==g||(e=b.paging.makeCtrl(a.type,a.tmpl,a,"top"),e.create()&&(e.append(),a.ctrls.push(e))),"both"!==g&&"bottom"!==g||(f=b.paging.makeCtrl(a.type,a.tmpl,a,"bottom"),f.create()&&(f.append(),a.ctrls.push(f)))}},rebuild:function(){var b=this;b.current=0,b.total=0,b._arr.splice(0,b._arr.length),a.each(b.ctrls.splice(0,b.ctrls.length),function(a,b){b.destroy()}),b.build()},all:function(){return this._arr.slice()},available:function(){return this.get(this.current)},controls:function(b){var c=this;c.isValid(b)&&a.each(c.ctrls,function(a,c){c.update(b)})},isValid:function(a){return d.number(a)&&a>0&&a<=this.total},number:function(a){return this.isValid(a)?a:0===this.current?1:this.current},create:function(a,b){var c=this;a=c.number(a);var d=a-1;c.tmpl.items.detach(c.tmpl.items.all()),c.tmpl.items.create(c._arr[d],!0),c.current=a},get:function(a){var b=this;return b.isValid(a)?(a=b.number(a),b._arr[a-1]):[]},set:function(a,b,c,e){var f=this;if(f.isValid(a)){var g,h=f.number(a);if(h!==f.current){var i=f.current,j=function(){if(c=!d.boolean(c)||c,e=!!d.boolean(e)&&e,c&&1===f.current&&!f.tmpl.state.exists()&&(g=f.tmpl.state.get(),f.tmpl.state.update(g,f.pushOrReplace)),f.controls(a),f.create(h,e),c&&(g=f.tmpl.state.get(),f.tmpl.state.update(g,f.pushOrReplace)),f.scrollToTop&&d.boolean(b)&&b){var j=f.get(f.current);j.length>0&&j[0].scrollTo("top")}f.tmpl.raise("after-page-change",[f.current,i,e])};return!f.tmpl.raise("before-page-change",[f.current,h,j,e]).isDefaultPrevented()&&(j(),!0)}}return!1},find:function(b){for(var c=this,d=0,e=c._arr.length;d<e;d++)if(-1!==a.inArray(b,c._arr[d]))return d+1;return 0},contains:function(b,c){var d=this.get(b);return-1!==a.inArray(c,d)},first:function(){this.goto(1)},last:function(){this.goto(this._arr.length)},prev:function(){this.goto(this.current-1)},next:function(){this.goto(this.current+1)},goto:function(a){var b=this;b.set(a,!0)&&b.tmpl.loadAvailable()}}),b.PagingControl=b.Component.extend({construct:function(a,b,c){var d=this;d._super(a),d.pages=b,d.position=c,d.$container=null},create:function(){var b=this;return b.$container=a("<nav/>",{class:b.pages.cls.container}).addClass(b.pages.theme),!0},destroy:function(){var a=this;a.$container.remove(),a.$container=null},append:function(){var a=this;"top"===a.position?a.$container.insertBefore(a.tmpl.$el):a.$container.insertAfter(a.tmpl.$el)},update:function(a){}}),b.paging.register("default",b.Paging,null,{type:"none",theme:"fg-light",size:30,pushOrReplace:"push",position:"none",scrollToTop:!0},{container:"fg-paging-container"},null,-100)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d){b.Dots=b.Paging.extend({}),b.DotsControl=b.PagingControl.extend({construct:function(b,c,d){this._super(b,c,d),this.$container=a(),this.$list=a(),this.$items=a()},create:function(){for(var b,c=this,d=c.pages.cls,e=c.pages.il8n,f=[],g=a("<ul/>",{class:d.list}),h=0,i=c.pages.total;h<i;h++)f.push(b=c.createItem(h+1,e.page)),g.append(b);return c.$list=g,c.$container=a("<nav/>",{class:d.container}).addClass(c.pages.theme).append(g),c.$items=a(a.map(f,function(a){return a.get()})),!0},append:function(){var a=this;"top"===a.position?a.$container.insertBefore(a.tmpl.$el):a.$container.insertAfter(a.tmpl.$el)},destroy:function(){var b=this,c=b.pages.sel;b.$list.find(c.link).off("click.foogallery",b.onLinkClick),b.$container.remove(),b.$container=a(),b.$list=a(),b.$items=a()},update:function(a){this.setSelected(a-1)},setSelected:function(b){var c=this,e=c.pages.cls,f=c.pages.il8n,g=c.pages.sel;c.$items.filter(g.selected).removeClass(e.selected).each(function(b,c){var e=a(c),f=e.data("label"),h=e.find(g.reader);d.string(f)&&0!==h.length&&h.html(f)}),c.$items.eq(b).addClass(e.selected).each(function(b,c){var e=a(c),h=e.find(g.reader),i=h.html();d.string(i)&&0!==h.length&&(e.data("label",i),h.html(f.current))})},createItem:function(b,c,e,f,g){e=d.string(e)?e:b,c=d.string(c)?c:"";var h=this,i=h.pages.opt,j=h.pages.cls,k=a("<a/>",{class:j.link,href:"#page-"+b}).html(e).on("click.foogallery",{self:h,page:b},h.onLinkClick);d.empty(c)||k.attr("title",c.replace(/\{PAGE}/g,b).replace(/\{LIMIT}/g,i.limit+"")),g=d.string(g)?g:c,d.empty(g)||k.prepend(a("<span/>",{class:j.reader,text:g.replace(/\{PAGE}/g,"").replace(/\{LIMIT}/g,i.limit+"")}));var l=a("<li/>",{class:j.item}).append(k);return f=d.string(f)?f:"",d.empty(f)||l.addClass(f),l},onLinkClick:function(b){b.preventDefault();var c=b.data.self,d=b.data.page,e=c.pages.sel;a(this).closest(e.item).is(e.disabled)||(c.pages.set(d,!0),c.tmpl.loadAvailable())}}),b.paging.register("dots",b.Dots,b.DotsControl,{type:"dots",position:"both",pushOrReplace:"push"},{list:"fg-dots",item:"fg-dot-item",link:"fg-dot-link",disabled:"fg-disabled",selected:"fg-selected",visible:"fg-visible",reader:"fg-sr-only"},{current:"Current page",page:"Page {PAGE}"})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c){b.DefaultTemplate=b.Template.extend({}),b.template.register("default",b.DefaultTemplate,null,{container:"foogallery fg-default"})}(FooGallery.$,FooGallery,FooGallery.utils),function(a,b,c,d){b.MasonryTemplate=b.Template.extend({construct:function(a,b){this._super(a,b),this.masonry=null,this.style=null,this.$columnWidth=null},getStylesheet:function(){var a=this;return null===a.style&&(a.style=document.createElement("style"),a.style.appendChild(document.createTextNode("")),document.head.appendChild(a.style)),a.style.sheet},onPreInit:function(b,c){var e=c.sel,f=c.cls;f.layouts=a.map(f.layout,function(a){return a}).join(" ");for(var g=a.map(f.layout,function(a,b){return{key:b,value:a}}),h=0,i=g.length;h<i;h++)if(c.$el.hasClass(g[h].value)){c.template.layout=g[h].key;break}d.string(f.layout[c.template.layout])||(c.template.layout="col4");var j,k,l="fixed"===c.template.layout;if(c.template.isFitWidth=l,c.template.percentPosition=!l,c.template.transitionDuration=0,c.template.itemSelector=e.item.elem,c.$el.removeClass(f.layouts).addClass(f.layout[c.template.layout]),l||(0===c.$el.find(e.gutterWidth).length&&c.$el.prepend(a("<div/>").addClass(f.gutterWidth)),c.template.gutter=e.gutterWidth),0===c.$el.find(e.columnWidth).length&&c.$el.prepend(a("<div/>").addClass(f.columnWidth)),l&&d.number(c.template.columnWidth)){var m=c.$el.find(e.columnWidth).width(c.template.columnWidth);j=c.getStylesheet(),k="#"+c.id+e.container+" "+e.item.elem+" { width: "+m.outerWidth()+"px; }",j.insertRule(k,0)}c.template.columnWidth=e.columnWidth,l&&d.number(c.template.gutter)&&(j=c.getStylesheet(),k="#"+c.id+e.container+" "+e.item.elem+" { margin-bottom: "+c.template.gutter+"px; }",j.insertRule(k,0)),c.masonry=new Masonry(c.$el.get(0),c.template)},onPostInit:function(a,b){b.masonry.layout()},onFirstLoad:function(a,b){b.masonry.layout()},onReady:function(a,b){b.masonry.layout()},onDestroy:function(a,b){b.$el.find(b.sel.columnWidth).remove(),b.$el.find(b.sel.gutterWidth).remove(),b.style&&b.style.parentNode&&b.style.parentNode.removeChild(b.style)},onDestroyed:function(a,b){b.masonry instanceof Masonry&&b.masonry.destroy()},onLayout:function(a,b){b.masonry.layout()},onParsedItems:function(a,b,c){b.masonry.layout()},onAppendedItems:function(a,b,c){c=b.items.jquerify(c),c=b.masonry.addItems(c),b.masonry.layoutItems(c,!0)},onDetachItem:function(a,b,c){a.isDefaultPrevented()||(a.preventDefault(),b.masonry.remove(c.$el),c.isAttached=!1,c.unfix())},onDetachedItems:function(a,b,c){b.masonry.layout()},onLoadedItems:function(a,b,c){b.masonry.layout()}}),b.template.register("masonry",b.MasonryTemplate,{template:{initLayout:!1,isInitLayout:!1,layout:"col4"}},{container:"foogallery fg-masonry",columnWidth:"fg-column-width",gutterWidth:"fg-gutter-width",layout:{fixed:"fg-masonry-fixed",col2:"fg-masonry-2col",col3:"fg-masonry-3col",col4:"fg-masonry-4col",col5:"fg-masonry-5col"}})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d){b.Justified=c.Class.extend({construct:function(c,d){this.$el=a(c),this.options=a.extend(!0,{},b.Justified.defaults,d),this._items=[],this._lastRefresh=0,this._refresh=null},init:function(){var b=this;d.string(b.options.maxRowHeight)&&(b.options.maxRowHeight.indexOf("%")?b.options.maxRowHeight=b.options.rowHeight*(parseInt(b.options.maxRowHeight)/100):b.options.maxRowHeight=parseInt(b.options.maxRowHeight)),a(window).on("resize.justified",{self:b},b.onWindowResize),this._refresh=setInterval(function(){b.refresh()},b.options.refreshInterval)},destroy:function(){this._refresh&&clearInterval(this._refresh),a(window).off("resize.justified"),this.$el.removeAttr("style")},refresh:function(){var a=this.getContainerWidth();a!=this._lastRefresh&&(this.layout(),this._lastRefresh=a)},parse:function(){var b=this,c=b.$el.is(":visible"),d=a("<div/>",{class:b.$el.attr("class")}).css({position:"absolute",top:0,left:-9999,visibility:"hidden",maxWidth:b.getContainerWidth()}).appendTo("body");return b._items=b.$el.find(b.options.itemSelector).removeAttr("style").removeClass("fg-positioned").map(function(b,e){var f=a(e),g=0,h=0;if(c)g=f.outerWidth(),h=f.outerHeight();else{var i=f.clone();i.appendTo(d),g=i.outerWidth(),h=i.outerHeight()}return{index:b,width:g,height:h,top:0,left:0,$item:f}}).get(),d.remove(),b._items},getMaxRowHeight:function(){var a=this;return d.string(a.options.maxRowHeight)&&(a.options.maxRowHeight.indexOf("%")?a.options.maxRowHeight=a.options.rowHeight*(parseInt(a.options.maxRowHeight)/100):a.options.maxRowHeight=parseInt(a.options.maxRowHeight)),d.number(a.options.maxRowHeight)?a.options.maxRowHeight:a.options.rowHeight},getContainerWidth:function(){var a=this;return a.$el.is(":visible")?a.$el.width():a.$el.parents(":visible:first").innerWidth()},layout:function(b,c){b=!!d.boolean(b)&&b,c=!d.boolean(c)||c,(b||0===this._items.length)&&this.parse();var e=this,f=0,g=e.getContainerWidth(),h=e.getMaxRowHeight(),i=e.rows(g,h);a.each(i,function(a,b){b.visible&&(a>0&&(f+=e.options.margins),f+=b.height,e.render(b))}),e.$el.height(f),c&&e.getContainerWidth()<g&&e.layout(!1,!1)},render:function(a){for(var b,c=0,d=a.items.length;c<d;c++)b=a.items[c],a.visible?b.$item.css({width:b.width,height:b.height,top:b.top,left:b.left,display:"",maxHeight:this.options.maxRowHeight>0?this.options.maxRowHeight:""}).addClass("fg-positioned"):b.$item.css("display","none")},justify:function(a,b,c,d){var e=this,f=e.options.margins*(a.items.length-1),g=c-f,h=g/a.width;a.width=a.width*h,a.height=a.height*h,a.top=b,a.height>d&&(a.height=d),a.left=0,a.width<g&&(a.left=(g-a.width)/2),a.width+=f;for(var i,j=a.left,k=0,l=a.items.length;k<l;k++)k>0&&(j+=e.options.margins),i=a.items[k],i.left=j,i.top=b,i.width=i.width*h,i.height=i.height*h,i.height>d&&(i.height=d),j+=i.width;return a.height},position:function(a,b,c,d){var e=this,f=e.options.margins*(a.items.length-1),g=c-f;if(a.top=b,a.left=0,a.width<g)switch(d){case"center":a.left=(g-a.width)/2;break;case"right":a.left=g-a.width}a.width+=f;for(var h,i=a.left,j=0,k=a.items.length;j<k;j++)j>0&&(i+=e.options.margins),h=a.items[j],h.left=i,h.top=b,i+=h.width;return a.height},lastRow:function(a,b,c,d){var e=this,f=e.options.margins*(a.items.length-1),g=c-f,h=a.width/g>e.options.justifyThreshold;switch(e.options.lastRow){case"hide":h?e.justify(a,b,c,d):a.visible=!1;break;case"justify":e.justify(a,b,c,d);break;case"nojustify":h?e.justify(a,b,c,d):e.position(a,b,c,"left");break;case"left":case"center":case"right":h?e.justify(a,b,c,d):e.position(a,b,c,e.options.lastRow)}},items:function(){return a.map(this._items,function(a){return{index:a.index,width:a.width,height:a.height,$item:a.$item,top:a.top,left:a.left}})},rows:function(a,b){function c(){var a={index:++h,visible:!0,width:0,height:e.options.rowHeight,top:0,left:0,items:[]};return g.push(a),a}for(var d,e=this,f=e.items(),g=[],h=-1,i=c(),j=0,k=0,l=0,m=f.length;l<m;l++){if(d=f[l],d.height!=e.options.rowHeight){var n=e.options.rowHeight/d.height;d.height=d.height*n,d.width=d.width*n}k+d.width>a&&l>0&&(g.length>1&&(j+=e.options.margins),j+=e.justify(i,j,a,b),i=c(),k=0),i.items.length>0&&(k+=e.options.margins),k+=d.width,i.width+=d.width,i.items.push(d)}return g.length>1&&(j+=e.options.margins),e.lastRow(i,j,a,b),g},onWindowResize:function(a){a.data.self.layout()}}),b.Justified.defaults={itemSelector:".fg-item",rowHeight:150,maxRowHeight:"200%",margins:0,lastRow:"center",justifyThreshold:.5,refreshInterval:250}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c){b.JustifiedTemplate=b.Template.extend({onPreInit:function(a,c){c.justified=new b.Justified(c.$el.get(0),c.template)},onInit:function(a,b){b.justified.init()},onFirstLoad:function(a,b){b.justified.layout(!0)},onReady:function(a,b){b.justified.layout(!0)},onDestroy:function(a,b){b.justified.destroy()},onLayout:function(a,b){b.justified.layout(!0)},onParsedItems:function(a,b,c){b.initialized&&b.justified.layout(!0)},onAppendedItems:function(a,b,c){b.initialized&&b.justified.layout(!0)},onDetachedItems:function(a,b,c){b.initialized&&b.justified.layout(!0)}}),b.template.register("justified",b.JustifiedTemplate,null,{container:"foogallery fg-justified"})}(FooGallery.$,FooGallery,FooGallery.utils),function(a,b,c,d){b.Portfolio=c.Class.extend({construct:function(c,d){this.$el=a(c),this.options=a.extend(!0,{},b.Portfolio.defaults,d),this._items=[]},init:function(){var b=this;a(window).on("resize.portfolio",{self:b},b.onWindowResize)},destroy:function(){a(window).off("resize.portfolio"),this.$el.removeAttr("style")},parse:function(){var b=this,c=b.$el.is(":visible"),d=a("<div/>",{class:b.$el.attr("class")}).css({position:"absolute",top:0,left:-9999,visibility:"hidden",maxWidth:b.getContainerWidth()}).appendTo("body");return b._items=b.$el.find(".fg-item").removeAttr("style").removeClass("fg-positioned").map(function(b,e){var f=a(e),g=f.find(".fg-thumb"),h=f.find(".fg-image"),i=0,j=0;if(f.find(".fg-caption").css("max-width",parseFloat(h.attr("width"))),h.css({width:h.attr("width"),height:h.attr("height")}),c)i=f.outerWidth(),j=f.outerHeight();else{var k=f.clone();k.appendTo(d),i=k.outerWidth(),j=k.outerHeight()}return h.css({width:"",height:""}),{index:b,width:i,height:j,top:0,left:0,$item:f,$thumb:g}}).get(),d.remove(),b._items},round:function(a){return Math.round(2*a)/2},getContainerWidth:function(){var a=this;return a.$el.is(":visible")?a.$el.width():a.$el.parents(":visible:first").innerWidth()},layout:function(a,b){a=!!d.boolean(a)&&a,b=!d.boolean(b)||b,(a||0===this._items.length)&&this.parse();for(var c,e=this,f=e.getContainerWidth(),g=e.rows(f),h=0,i=0,j=g.length;i<j;i++)c=g[i],h=e.position(c,f,h,e.options.align),e.render(c);e.$el.height(h),b&&e.getContainerWidth()<f&&e.layout(!1,!1)},render:function(a){for(var b,c=0,d=a.items.length;c<d;c++)b=a.items[c],a.visible?b.$item.css({width:b.width,height:a.height,top:b.top,left:b.left,display:""}).addClass("fg-positioned"):b.$item.css("display","none")},position:function(a,b,c,d){var e=this,f=a.items[a.items.length-1],g=b-(f.left+f.width);a.index>0&&(c+=e.options.gutter),a.top=c;for(var h,i=0,j=a.items.length;i<j;i++)h=a.items[i],h.top=c,"center"===d?h.left+=g/2:"right"===d&&(h.left+=g);return c+a.height},items:function(){return a.map(this._items,function(a){return{index:a.index,width:a.width,height:a.height,$item:a.$item,$thumb:a.$thumb,top:a.top,left:a.left}})},rows:function(a){for(var b=this,c=b.items(),d=[],e=c.length>0,f=-1,g=0;e;){f+=1,f>0&&(g+=b.options.gutter);for(var h,i,j,k={index:f,visible:!0,top:g,width:0,height:0,items:[]},l=[],m=0,n=0,o=c.length;n<o&&(i=c[n],!((h=k.width+i.width)>a&&n>0));n++)h>a&&0==n&&(h=a,j=a/i.width,i.width=b.round(i.width*j),i.height=b.round(i.height*j),k.height=i.height),i.top=k.top,n>0&&(m+=b.options.gutter),n!==o-1&&(h+=b.options.gutter),i.left=m,m+=i.width,i.height>k.height&&(k.height=i.height),k.width=h,k.items.push(i),l.push(n);if(0===l.length){e=!1;break}l.sort(function(a,b){return b-a});for(var p=0,q=l.length;p<q;p++)c.splice(l[p],1);d.push(k),e=c.length>0}return d},onWindowResize:function(a){a.data.self.layout()}}),b.Portfolio.defaults={gutter:40,align:"center"}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c){b.PortfolioTemplate=b.Template.extend({construct:function(a,b){this._super(a,b),this.portfolio=null},onPreInit:function(a,c){c.portfolio=new b.Portfolio(c.$el.get(0),c.template)},onInit:function(a,b){b.portfolio.init()},onFirstLoad:function(a,b){b.portfolio.layout(!0)},onReady:function(a,b){b.portfolio.layout(!0)},onDestroy:function(a,b){b.portfolio.destroy()},onLayout:function(a,b){b.portfolio.layout(!0)},onParsedItems:function(a,b,c){b.initialized&&b.portfolio.layout(!0)},onAppendedItems:function(a,b,c){b.initialized&&b.portfolio.layout(!0)},onDetachedItems:function(a,b,c){b.initialized&&b.portfolio.layout(!0)}}),b.template.register("simple_portfolio",b.PortfolioTemplate,{gutter:40},{container:"foogallery fg-simple_portfolio"})}(FooGallery.$,FooGallery,FooGallery.utils),function(a,b,c,d){b.ImageViewerTemplate=b.Template.extend({construct:function(b,c){this._super(d.extend({},b,{paging:{pushOrReplace:"replace",theme:"fg-light",type:"default",size:1,position:"none",scrollToTop:!1}}),c),this.$inner=a(),this.$current=a(),this.$total=a(),this.$prev=a(),this.$next=a()},createChildren:function(){var b=this;return a("<div/>",{class:b.cls.inner}).append(a("<div/>",{class:b.cls.innerContainer}),a("<div/>",{class:b.cls.controls}).append(a("<div/>",{class:b.cls.prev}).append(a("<span/>",{text:b.il8n.prev})),a("<label/>",{class:b.cls.count,text:b.il8n.count}).prepend(a("<span/>",{class:b.cls.countCurrent,text:"0"})).append(a("<span/>",{class:b.cls.countTotal,text:"0"})),a("<div/>",{class:b.cls.next}).append(a("<span/>",{text:b.il8n.next}))))},onPreInit:function(a,b){b.$inner=b.$el.find(b.sel.innerContainer),b.$current=b.$el.find(b.sel.countCurrent),b.$total=b.$el.find(b.sel.countTotal),b.$prev=b.$el.find(b.sel.prev),b.$next=b.$el.find(b.sel.next)},onInit:function(a,b){b.template.attachFooBox&&b.$el.on("foobox.previous",{self:b},b.onFooBoxPrev).on("foobox.next",{self:b},b.onFooBoxNext),b.$prev.on("click",{self:b},b.onPrevClick),b.$next.on("click",{self:b},b.onNextClick)},onFirstLoad:function(a,b){b.update()},onDestroy:function(a,b){b.template.attachFooBox&&b.$el.off({"foobox.previous":b.onFooBoxPrev,"foobox.next":b.onFooBoxNext}),b.$prev.off("click",b.onPrevClick),b.$next.off("click",b.onNextClick)},onAppendItem:function(a,b,c){a.preventDefault(),b.$inner.append(c.$el),c.fix(),c.isAttached=!0},onAfterPageChange:function(a,b,c,d,e){e||b.update()},onAfterFilterChange:function(a,b){b.update()},update:function(){this.pages&&(this.$current.text(this.pages.current),this.$total.text(this.pages.total))},prev:function(){this.pages&&(this.template.loop&&1===this.pages.current?this.pages.last():this.pages.prev(),this.update())},next:function(){this.pages&&(this.template.loop&&this.pages.current===this.pages.total?this.pages.first():this.pages.next(),this.update())},onFooBoxPrev:function(a){a.data.self.prev()},onFooBoxNext:function(a){a.data.self.next()},onPrevClick:function(a){a.preventDefault(),a.stopPropagation(),a.data.self.prev()},onNextClick:function(a){a.preventDefault(),a.stopPropagation(),a.data.self.next()}}),b.template.register("image-viewer",b.ImageViewerTemplate,{template:{attachFooBox:!1,loop:!1}},{container:"foogallery fg-image-viewer",inner:"fiv-inner",innerContainer:"fiv-inner-container",controls:"fiv-ctrls",prev:"fiv-prev",next:"fiv-next",count:"fiv-count",countCurrent:"fiv-count-current",countTotal:"fiv-count-total"},{prev:"Prev",next:"Next",count:"of"})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.obj),function(a,b,c){b.ThumbnailTemplate=b.Template.extend({construct:function(b,d){this._super(c.extend({},b,{filtering:{type:"none"},paging:{type:"none"}}),d),this.$hidden=a()},createChildren:function(){var b=this;return b.$hidden=a("<div/>",{class:b.cls.hidden})},onPreInit:function(a,b){b.$hidden=b.$el.find(b.sel.hidden)},onPostInit:function(b,c){for(var d,e=c.items.all().slice(1),f=0,g=e.length;f<g;f++)d=e[f],c.$hidden.append(a("<a/>",{href:d.href,rel:"lightbox["+c.id+"]"}).attr(d.attr.anchor));c.items.setAll(c.items.all().slice(0,1))}}),b.template.register("thumbnail",b.ThumbnailTemplate,null,{container:"foogallery fg-thumbnail",hidden:"fg-st-hidden"})}(FooGallery.$,FooGallery,FooGallery.utils.obj),function(a,b,c,d){b.triggerPostLoad=function(b,c,d,e,f){("first-load"===b.type||c.initialized&&("after-page-change"===b.type&&!f||"after-filter-change"===b.type))&&a("body").trigger("post-load")},b.autoDefaults={on:{
11
+ "first-load.foogallery after-page-change.foogallery after-filter-change.foogallery":b.triggerPostLoad}},b.auto=function(a){b.autoDefaults=d.merge(b.autoDefaults,a)},a(function(){a('[id^="foogallery-gallery-"]:not(.fg-ready)').foogallery(b.autoDefaults)}),c.ready(function(){a('[id^="foogallery-gallery-"].fg-ready').foogallery(b.autoDefaults)})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.obj);
extensions/default-templates/simple-portfolio/class-simple-portfolio-gallery-template.php CHANGED
@@ -264,11 +264,17 @@ if ( !class_exists( 'FooGallery_Simple_Portfolio_Gallery_Template' ) ) {
264
  */
265
  function build_thumbnail_dimensions_from_arguments( $dimensions, $arguments ) {
266
  if ( array_key_exists( 'thumbnail_dimensions', $arguments) ) {
267
- return array(
268
  'height' => intval($arguments['thumbnail_dimensions']['height']),
269
  'width' => intval($arguments['thumbnail_dimensions']['width']),
270
  'crop' => '1'
271
  );
 
 
 
 
 
 
272
  }
273
  return null;
274
  }
@@ -284,9 +290,15 @@ if ( !class_exists( 'FooGallery_Simple_Portfolio_Gallery_Template' ) ) {
284
  function get_thumbnail_dimensions( $dimensions, $foogallery ) {
285
  $dimensions = $foogallery->get_meta( 'simple_portfolio_thumbnail_dimensions', array(
286
  'width' => 250,
287
- 'height' => 200
 
288
  ) );
289
- $dimensions['crop'] = true;
 
 
 
 
 
290
  return $dimensions;
291
  }
292
 
@@ -299,6 +311,9 @@ if ( !class_exists( 'FooGallery_Simple_Portfolio_Gallery_Template' ) ) {
299
  function build_gallery_template_arguments( $args ) {
300
  $args = foogallery_gallery_template_setting( 'thumbnail_dimensions', array() );
301
  $args['crop'] = '1'; //we now force thumbs to be cropped
 
 
 
302
  $args['link'] = foogallery_gallery_template_setting( 'thumbnail_link', 'image' );
303
  $args['image_attributes'] = array(
304
  'class' => 'bf-img',
264
  */
265
  function build_thumbnail_dimensions_from_arguments( $dimensions, $arguments ) {
266
  if ( array_key_exists( 'thumbnail_dimensions', $arguments) ) {
267
+ $dimensions = array(
268
  'height' => intval($arguments['thumbnail_dimensions']['height']),
269
  'width' => intval($arguments['thumbnail_dimensions']['width']),
270
  'crop' => '1'
271
  );
272
+
273
+ if ( 'on' === foogallery_get_setting('enable_legacy_thumb_cropping') ) {
274
+ $dimensions['crop'] = '0';
275
+ }
276
+
277
+ return $dimensions;
278
  }
279
  return null;
280
  }
290
  function get_thumbnail_dimensions( $dimensions, $foogallery ) {
291
  $dimensions = $foogallery->get_meta( 'simple_portfolio_thumbnail_dimensions', array(
292
  'width' => 250,
293
+ 'height' => 200,
294
+ 'crop' => true
295
  ) );
296
+
297
+ if ( 'on' === foogallery_get_setting('enable_legacy_thumb_cropping') ) {
298
+ $dimensions['crop'] = false;
299
+ } else {
300
+ $dimensions['crop'] = true;
301
+ }
302
  return $dimensions;
303
  }
304
 
311
  function build_gallery_template_arguments( $args ) {
312
  $args = foogallery_gallery_template_setting( 'thumbnail_dimensions', array() );
313
  $args['crop'] = '1'; //we now force thumbs to be cropped
314
+ if ( 'on' === foogallery_get_setting('enable_legacy_thumb_cropping') ) {
315
+ $args['crop'] = '0';
316
+ }
317
  $args['link'] = foogallery_gallery_template_setting( 'thumbnail_link', 'image' );
318
  $args['image_attributes'] = array(
319
  'class' => 'bf-img',
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.4.29
7
  Author: FooPlugins
8
  Plugin URI: https://foo.gallery
9
  Author URI: http://fooplugins.com
@@ -23,7 +23,7 @@ if ( !class_exists( 'FooGallery_Plugin' ) ) {
23
  define( 'FOOGALLERY_PATH', plugin_dir_path( __FILE__ ) );
24
  define( 'FOOGALLERY_URL', plugin_dir_url( __FILE__ ) );
25
  define( 'FOOGALLERY_FILE', __FILE__ );
26
- define( 'FOOGALLERY_VERSION', '1.4.29' );
27
  define( 'FOOGALLERY_SETTINGS_VERSION', '2' );
28
  require_once FOOGALLERY_PATH . 'includes/constants.php';
29
  // Create a helper function for easy SDK access.
3
  /*
4
  Plugin Name: FooGallery
5
  Description: FooGallery is the most intuitive and extensible gallery management tool ever created for WordPress
6
+ Version: 1.4.30
7
  Author: FooPlugins
8
  Plugin URI: https://foo.gallery
9
  Author URI: http://fooplugins.com
23
  define( 'FOOGALLERY_PATH', plugin_dir_path( __FILE__ ) );
24
  define( 'FOOGALLERY_URL', plugin_dir_url( __FILE__ ) );
25
  define( 'FOOGALLERY_FILE', __FILE__ );
26
+ define( 'FOOGALLERY_VERSION', '1.4.30' );
27
  define( 'FOOGALLERY_SETTINGS_VERSION', '2' );
28
  require_once FOOGALLERY_PATH . 'includes/constants.php';
29
  // Create a helper function for easy SDK access.
freemius/.codeclimate.yml CHANGED
@@ -1,19 +1,19 @@
1
- engines:
2
- phpcodesniffer:
3
- enabled: true
4
- config:
5
- standard: "WordPress"
6
- checks:
7
- Squiz Commenting InlineComment InvalidEndChar:
8
- enabled: false
9
- Squiz Commenting InlineComment SpacingBefore:
10
- enabled: false
11
- Squiz Commenting InlineComment WrongStyle:
12
- enabled: false
13
- Generic Commenting DocComment MissingShort:
14
- enabled: false
15
- Generic WhiteSpace ScopeIndent IncorrectExact:
16
- enabled: false
17
- ratings:
18
- paths:
19
- - "**.php"
1
+ engines:
2
+ phpcodesniffer:
3
+ enabled: true
4
+ config:
5
+ standard: "WordPress"
6
+ checks:
7
+ Squiz Commenting InlineComment InvalidEndChar:
8
+ enabled: false
9
+ Squiz Commenting InlineComment SpacingBefore:
10
+ enabled: false
11
+ Squiz Commenting InlineComment WrongStyle:
12
+ enabled: false
13
+ Generic Commenting DocComment MissingShort:
14
+ enabled: false
15
+ Generic WhiteSpace ScopeIndent IncorrectExact:
16
+ enabled: false
17
+ ratings:
18
+ paths:
19
+ - "**.php"
freemius/.github/ISSUE_TEMPLATE.md CHANGED
@@ -1,29 +1,29 @@
1
- **Actual Behavior**:
2
- - `What is the issue? (*)`
3
- - `What is the expected behavior?`
4
-
5
- **Versions**: (*)
6
- - `Freemius SDK Version:`
7
- - `WordPress Version:`
8
- - `PHP Version:`
9
-
10
- **Plugin / Theme**: (*)
11
- - `Name:`
12
- - `Slug:`
13
- - `Freemius ID:`
14
-
15
- **Additional Information**:
16
- - `Browser Type: (*)`
17
- - `Browser Version: (*)`
18
- - `OS: (*)`
19
- - `Stack Traces:`
20
-
21
- ----
22
- **Note:** `(*)` indicates required information. Without this information, your issue may be auto-closed.
23
-
24
- > You can find your Freemius SDK version at `/freemius/start.php`
25
-
26
- > You can find your Freemius product ID in the Freemius dashboard: `SETTINGS -> INTEGRATION`.
27
-
28
- > Do not modify the titles or questions. Simply add your responses to the ends of the questions.
29
- Add more lines if needed.
1
+ **Actual Behavior**:
2
+ - `What is the issue? (*)`
3
+ - `What is the expected behavior?`
4
+
5
+ **Versions**: (*)
6
+ - `Freemius SDK Version:`
7
+ - `WordPress Version:`
8
+ - `PHP Version:`
9
+
10
+ **Plugin / Theme**: (*)
11
+ - `Name:`
12
+ - `Slug:`
13
+ - `Freemius ID:`
14
+
15
+ **Additional Information**:
16
+ - `Browser Type: (*)`
17
+ - `Browser Version: (*)`
18
+ - `OS: (*)`
19
+ - `Stack Traces:`
20
+
21
+ ----
22
+ **Note:** `(*)` indicates required information. Without this information, your issue may be auto-closed.
23
+
24
+ > You can find your Freemius SDK version at `/freemius/start.php`
25
+
26
+ > You can find your Freemius product ID in the Freemius dashboard: `SETTINGS -> INTEGRATION`.
27
+
28
+ > Do not modify the titles or questions. Simply add your responses to the ends of the questions.
29
+ Add more lines if needed.
freemius/.travis.yml CHANGED
@@ -1,11 +1,11 @@
1
- sudo: false
2
-
3
- language: php
4
-
5
- php:
6
- - 5.3
7
- - 5.4
8
- - 5.5
9
- - 5.6
10
- - 7.0
11
- - hhvm
1
+ sudo: false
2
+
3
+ language: php
4
+
5
+ php:
6
+ - 5.3
7
+ - 5.4
8
+ - 5.5
9
+ - 5.6
10
+ - 7.0
11
+ - hhvm
freemius/assets/css/admin/account.css CHANGED
@@ -1 +1 @@
1
- #fs_account .postbox,#fs_account .widefat{max-width:700px}#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 .button i.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}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_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
+ #fs_account .postbox,#fs_account .widefat{max-width:700px}#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 .button i.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}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_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/affiliation.css CHANGED
@@ -1 +1 @@
1
- @charset "UTF-8";#fs_affiliation_content_wrapper #messages{margin-top:25px}#fs_affiliation_content_wrapper h3{font-size:24px;padding:0;margin-left:0}#fs_affiliation_content_wrapper ul li{box-sizing:border-box;list-style-type:none}#fs_affiliation_content_wrapper ul li:before{content:'✓';margin-right:10px;font-weight:bold}#fs_affiliation_content_wrapper p:not(.description),#fs_affiliation_content_wrapper li,#fs_affiliation_content_wrapper label{font-size:16px !important;line-height:26px !important}#fs_affiliation_content_wrapper .button{margin-top:20px;margin-bottom:7px;line-height:35px;height:40px;font-size:16px}#fs_affiliation_content_wrapper .button#cancel_button{margin-right:5px}#fs_affiliation_content_wrapper form .input-container{margin-bottom:15px}#fs_affiliation_content_wrapper form .input-container .input-label{font-weight:bold;display:block;width:100%}#fs_affiliation_content_wrapper form .input-container.input-container-text label,#fs_affiliation_content_wrapper form .input-container.input-container-text input,#fs_affiliation_content_wrapper form .input-container.input-container-text textarea{display:block}#fs_affiliation_content_wrapper form .input-container #add_domain,#fs_affiliation_content_wrapper form .input-container .remove-domain{text-decoration:none;display:inline-block;margin-top:3px}#fs_affiliation_content_wrapper form .input-container #add_domain:focus,#fs_affiliation_content_wrapper form .input-container .remove-domain:focus{box-shadow:none}#fs_affiliation_content_wrapper form .input-container #add_domain.disabled,#fs_affiliation_content_wrapper form .input-container .remove-domain.disabled{color:#aaa;cursor:default}#fs_affiliation_content_wrapper form #extra_domains_container .description{margin-top:0;position:relative;top:-4px}#fs_affiliation_content_wrapper form #extra_domains_container .extra-domain-input-container{margin-bottom:15px}#fs_affiliation_content_wrapper form #extra_domains_container .extra-domain-input-container .domain{display:inline-block;margin-right:5px}#fs_affiliation_content_wrapper form #extra_domains_container .extra-domain-input-container .domain:last-of-type{margin-bottom:0}
1
+ @charset "UTF-8";#fs_affiliation_content_wrapper #messages{margin-top:25px}#fs_affiliation_content_wrapper h3{font-size:24px;padding:0;margin-left:0}#fs_affiliation_content_wrapper ul li{box-sizing:border-box;list-style-type:none}#fs_affiliation_content_wrapper ul li:before{content:'✓';margin-right:10px;font-weight:bold}#fs_affiliation_content_wrapper p:not(.description),#fs_affiliation_content_wrapper li,#fs_affiliation_content_wrapper label{font-size:16px !important;line-height:26px !important}#fs_affiliation_content_wrapper .button{margin-top:20px;margin-bottom:7px;line-height:35px;height:40px;font-size:16px}#fs_affiliation_content_wrapper .button#cancel_button{margin-right:5px}#fs_affiliation_content_wrapper form .input-container{margin-bottom:15px}#fs_affiliation_content_wrapper form .input-container .input-label{font-weight:bold;display:block;width:100%}#fs_affiliation_content_wrapper form .input-container.input-container-text label,#fs_affiliation_content_wrapper form .input-container.input-container-text input,#fs_affiliation_content_wrapper form .input-container.input-container-text textarea{display:block}#fs_affiliation_content_wrapper form .input-container #add_domain,#fs_affiliation_content_wrapper form .input-container .remove-domain{text-decoration:none;display:inline-block;margin-top:3px}#fs_affiliation_content_wrapper form .input-container #add_domain:focus,#fs_affiliation_content_wrapper form .input-container .remove-domain:focus{box-shadow:none}#fs_affiliation_content_wrapper form .input-container #add_domain.disabled,#fs_affiliation_content_wrapper form .input-container .remove-domain.disabled{color:#aaa;cursor:default}#fs_affiliation_content_wrapper form #extra_domains_container .description{margin-top:0;position:relative;top:-4px}#fs_affiliation_content_wrapper form #extra_domains_container .extra-domain-input-container{margin-bottom:15px}#fs_affiliation_content_wrapper form #extra_domains_container .extra-domain-input-container .domain{display:inline-block;margin-right:5px}#fs_affiliation_content_wrapper form #extra_domains_container .extra-domain-input-container .domain:last-of-type{margin-bottom:0}
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 .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 div{margin-left:55px}#fs_connect .fs-permissions ul li div span{font-weight:bold;text-transform:uppercase;color:#23282d}#fs_connect .fs-permissions ul li div 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}.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 div{margin-right:55px;margin-left:0}.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 .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 div{margin-left:55px}#fs_connect .fs-permissions ul li div span{font-weight:bold;text-transform:uppercase;color:#23282d}#fs_connect .fs-permissions ul li div 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}.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 div{margin-right:55px;margin-left:0}.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}
freemius/assets/css/admin/dialog-boxes.css CHANGED
@@ -1,2 +1,2 @@
1
- .fs-modal{position:fixed;overflow:auto;height:100%;width:100%;top:0;z-index:100000;display:none;background:rgba(0,0,0,0.6)}.fs-modal .fs-modal-dialog{background:transparent;position:absolute;left:50%;margin-left:-298px;padding-bottom:30px;top:-100%;z-index:100001;width:596px}@media (max-width: 650px){.fs-modal .fs-modal-dialog{margin-left:-50%;box-sizing:border-box;padding-left:10px;padding-right:10px;width:100%}.fs-modal .fs-modal-dialog .fs-modal-panel>h3>strong{font-size:1.3em}}.fs-modal.active{display:block}.fs-modal.active:before{display:block}.fs-modal.active .fs-modal-dialog{top:10%}.fs-modal.fs-success .fs-modal-header{border-bottom-color:#46b450}.fs-modal.fs-success .fs-modal-body{background-color:#f7fff7}.fs-modal.fs-warn .fs-modal-header{border-bottom-color:#ffb900}.fs-modal.fs-warn .fs-modal-body{background-color:#fff8e5}.fs-modal.fs-error .fs-modal-header{border-bottom-color:#dc3232}.fs-modal.fs-error .fs-modal-body{background-color:#ffeaea}.fs-modal .fs-modal-body,.fs-modal .fs-modal-footer{border:0;background:#fefefe;padding:20px}.fs-modal .fs-modal-header{border-bottom:#eeeeee solid 1px;background:#fbfbfb;padding:15px 20px;position:relative;margin-bottom:-10px}.fs-modal .fs-modal-header h4{margin:0;padding:0;text-transform:uppercase;font-size:1.2em;font-weight:bold;color:#cacaca;text-shadow:1px 1px 1px #fff;letter-spacing:0.6px;-webkit-font-smoothing:antialiased}.fs-modal .fs-modal-header .fs-close{position:absolute;right:10px;top:12px;cursor:pointer;color:#bbb;-moz-border-radius:20px;-webkit-border-radius:20px;border-radius:20px;padding:3px;-moz-transition:all 0.2s ease-in-out;-o-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.fs-modal .fs-modal-header .fs-close:hover{color:#fff;background:#aaa}.fs-modal .fs-modal-body{border-bottom:0}.fs-modal .fs-modal-body p{font-size:14px}.fs-modal .fs-modal-body h2{font-size:20px;line-height:1.5em}.fs-modal .fs-modal-body>div{margin-top:10px}.fs-modal .fs-modal-body>div h2{font-weight:bold;font-size:20px;margin-top:0}.fs-modal .fs-modal-footer{border-top:#eeeeee solid 1px;text-align:right}.fs-modal .fs-modal-footer>.button{margin:0 7px}.fs-modal .fs-modal-footer>.button:first-child{margin:0}.fs-modal .fs-modal-panel>.notice.inline{margin:0;display:none}.fs-modal .fs-modal-panel:not(.active){display:none}.rtl .fs-modal .fs-modal-header .fs-close{right:auto;left:20px}body.has-fs-modal{overflow:hidden}.fs-modal.fs-modal-deactivation-feedback .reason-input,.fs-modal.fs-modal-deactivation-feedback .internal-message{margin:3px 0 3px 22px}.fs-modal.fs-modal-deactivation-feedback .reason-input input,.fs-modal.fs-modal-deactivation-feedback .reason-input textarea,.fs-modal.fs-modal-deactivation-feedback .internal-message input,.fs-modal.fs-modal-deactivation-feedback .internal-message textarea{width:100%}.fs-modal.fs-modal-deactivation-feedback li.reason.has-internal-message .internal-message{border:1px solid #ccc;padding:7px;display:none}@media (max-width: 650px){.fs-modal.fs-modal-deactivation-feedback li.reason li.reason{margin-bottom:10px}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason .reason-input,.fs-modal.fs-modal-deactivation-feedback li.reason li.reason .internal-message{margin-left:29px}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason label{display:table}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason label>span{display:table-cell;font-size:1.3em}}.fs-modal.fs-modal-deactivation-feedback .anonymous-feedback-label{float:left}.fs-modal.fs-modal-deactivation-feedback .fs-modal-panel{margin-top:0 !important}.fs-modal.fs-modal-deactivation-feedback .fs-modal-panel h3{margin-top:0;line-height:1.5em}#the-list .deactivate>.fs-slug{display:none}.fs-modal.fs-modal-license-activation .fs-modal-body input.license_key{width:100%}.fs-modal.fs-modal-license-key-resend .email-address-container{overflow:hidden;padding-right:2px}.fs-modal.fs-modal-license-key-resend.fs-freemium input.email-address{width:300px}.fs-modal.fs-modal-license-key-resend.fs-freemium label{display:block;margin-bottom:10px}.fs-modal.fs-modal-license-key-resend.fs-premium input.email-address{width:100%}.fs-modal.fs-modal-license-key-resend.fs-premium .button-container{float:right;margin-left:7px}@media (max-width: 650px){.fs-modal.fs-modal-license-key-resend.fs-premium .button-container{margin-top:2px}}
2
- .rtl .fs-modal.fs-modal-license-key-resend .fs-modal-body .input-container>.email-address-container{padding-left:2px;padding-right:0}.rtl .fs-modal.fs-modal-license-key-resend .fs-modal-body .button-container{float:left;margin-right:7px;margin-left:0}a.show-license-resend-modal{margin-top:4px;display:inline-block}.fs-ajax-loader{position:relative;width:170px;height:20px;margin:auto}.fs-ajax-loader .fs-ajax-loader-bar{position:absolute;top:0;background-color:#0074a3;width:20px;height:20px;-webkit-animation-name:bounce_ajaxLoader;-moz-animation-name:bounce_ajaxLoader;-ms-animation-name:bounce_ajaxLoader;-o-animation-name:bounce_ajaxLoader;animation-name:bounce_ajaxLoader;-webkit-animation-duration:1.5s;-moz-animation-duration:1.5s;-ms-animation-duration:1.5s;-o-animation-duration:1.5s;animation-duration:1.5s;animation-iteration-count:infinite;-o-animation-iteration-count:infinite;-ms-animation-iteration-count:infinite;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;-webkit-animation-direction:normal;-moz-animation-direction:normal;-ms-animation-direction:normal;-o-animation-direction:normal;animation-direction:normal;-moz-transform:0.3;-o-transform:0.3;-ms-transform:0.3;-webkit-transform:0.3;transform:0.3}.fs-ajax-loader .fs-ajax-loader-bar-1{left:0px;animation-delay:0.6s;-o-animation-delay:0.6s;-ms-animation-delay:0.6s;-webkit-animation-delay:0.6s;-moz-animation-delay:0.6s}.fs-ajax-loader .fs-ajax-loader-bar-2{left:19px;animation-delay:0.75s;-o-animation-delay:0.75s;-ms-animation-delay:0.75s;-webkit-animation-delay:0.75s;-moz-animation-delay:0.75s}.fs-ajax-loader .fs-ajax-loader-bar-3{left:38px;animation-delay:0.9s;-o-animation-delay:0.9s;-ms-animation-delay:0.9s;-webkit-animation-delay:0.9s;-moz-animation-delay:0.9s}.fs-ajax-loader .fs-ajax-loader-bar-4{left:57px;animation-delay:1.05s;-o-animation-delay:1.05s;-ms-animation-delay:1.05s;-webkit-animation-delay:1.05s;-moz-animation-delay:1.05s}.fs-ajax-loader .fs-ajax-loader-bar-5{left:76px;animation-delay:1.2s;-o-animation-delay:1.2s;-ms-animation-delay:1.2s;-webkit-animation-delay:1.2s;-moz-animation-delay:1.2s}.fs-ajax-loader .fs-ajax-loader-bar-6{left:95px;animation-delay:1.35s;-o-animation-delay:1.35s;-ms-animation-delay:1.35s;-webkit-animation-delay:1.35s;-moz-animation-delay:1.35s}.fs-ajax-loader .fs-ajax-loader-bar-7{left:114px;animation-delay:1.5s;-o-animation-delay:1.5s;-ms-animation-delay:1.5s;-webkit-animation-delay:1.5s;-moz-animation-delay:1.5s}.fs-ajax-loader .fs-ajax-loader-bar-8{left:133px;animation-delay:1.65s;-o-animation-delay:1.65s;-ms-animation-delay:1.65s;-webkit-animation-delay:1.65s;-moz-animation-delay:1.65s}@-moz-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-ms-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-o-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-webkit-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}.fs-modal-auto-install #request-filesystem-credentials-form h2,.fs-modal-auto-install #request-filesystem-credentials-form .request-filesystem-credentials-action-buttons{display:none}.fs-modal-auto-install #request-filesystem-credentials-form input[type=password],.fs-modal-auto-install #request-filesystem-credentials-form input[type=email],.fs-modal-auto-install #request-filesystem-credentials-form input[type=text]{-webkit-appearance:none;padding:10px 10px 5px 10px;width:300px;max-width:100%}.fs-modal-auto-install #request-filesystem-credentials-form>div,.fs-modal-auto-install #request-filesystem-credentials-form label,.fs-modal-auto-install #request-filesystem-credentials-form fieldset{width:300px;max-width:100%;margin:0 auto;display:block}
1
+ .fs-modal{position:fixed;overflow:auto;height:100%;width:100%;top:0;z-index:100000;display:none;background:rgba(0,0,0,0.6)}.fs-modal .fs-modal-dialog{background:transparent;position:absolute;left:50%;margin-left:-298px;padding-bottom:30px;top:-100%;z-index:100001;width:596px}@media (max-width: 650px){.fs-modal .fs-modal-dialog{margin-left:-50%;box-sizing:border-box;padding-left:10px;padding-right:10px;width:100%}.fs-modal .fs-modal-dialog .fs-modal-panel>h3>strong{font-size:1.3em}}.fs-modal.active{display:block}.fs-modal.active:before{display:block}.fs-modal.active .fs-modal-dialog{top:10%}.fs-modal.fs-success .fs-modal-header{border-bottom-color:#46b450}.fs-modal.fs-success .fs-modal-body{background-color:#f7fff7}.fs-modal.fs-warn .fs-modal-header{border-bottom-color:#ffb900}.fs-modal.fs-warn .fs-modal-body{background-color:#fff8e5}.fs-modal.fs-error .fs-modal-header{border-bottom-color:#dc3232}.fs-modal.fs-error .fs-modal-body{background-color:#ffeaea}.fs-modal .fs-modal-body,.fs-modal .fs-modal-footer{border:0;background:#fefefe;padding:20px}.fs-modal .fs-modal-header{border-bottom:#eeeeee solid 1px;background:#fbfbfb;padding:15px 20px;position:relative;margin-bottom:-10px}.fs-modal .fs-modal-header h4{margin:0;padding:0;text-transform:uppercase;font-size:1.2em;font-weight:bold;color:#cacaca;text-shadow:1px 1px 1px #fff;letter-spacing:0.6px;-webkit-font-smoothing:antialiased}.fs-modal .fs-modal-header .fs-close{position:absolute;right:10px;top:12px;cursor:pointer;color:#bbb;-moz-border-radius:20px;-webkit-border-radius:20px;border-radius:20px;padding:3px;-moz-transition:all 0.2s ease-in-out;-o-transition:all 0.2s ease-in-out;-ms-transition:all 0.2s ease-in-out;-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.fs-modal .fs-modal-header .fs-close:hover{color:#fff;background:#aaa}.fs-modal .fs-modal-body{border-bottom:0}.fs-modal .fs-modal-body p{font-size:14px}.fs-modal .fs-modal-body h2{font-size:20px;line-height:1.5em}.fs-modal .fs-modal-body>div{margin-top:10px}.fs-modal .fs-modal-body>div h2{font-weight:bold;font-size:20px;margin-top:0}.fs-modal .fs-modal-footer{border-top:#eeeeee solid 1px;text-align:right}.fs-modal .fs-modal-footer>.button{margin:0 7px}.fs-modal .fs-modal-footer>.button:first-child{margin:0}.fs-modal .fs-modal-panel>.notice.inline{margin:0;display:none}.fs-modal .fs-modal-panel:not(.active){display:none}.rtl .fs-modal .fs-modal-header .fs-close{right:auto;left:20px}body.has-fs-modal{overflow:hidden}.fs-modal.fs-modal-deactivation-feedback .reason-input,.fs-modal.fs-modal-deactivation-feedback .internal-message{margin:3px 0 3px 22px}.fs-modal.fs-modal-deactivation-feedback .reason-input input,.fs-modal.fs-modal-deactivation-feedback .reason-input textarea,.fs-modal.fs-modal-deactivation-feedback .internal-message input,.fs-modal.fs-modal-deactivation-feedback .internal-message textarea{width:100%}.fs-modal.fs-modal-deactivation-feedback li.reason.has-internal-message .internal-message{border:1px solid #ccc;padding:7px;display:none}@media (max-width: 650px){.fs-modal.fs-modal-deactivation-feedback li.reason li.reason{margin-bottom:10px}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason .reason-input,.fs-modal.fs-modal-deactivation-feedback li.reason li.reason .internal-message{margin-left:29px}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason label{display:table}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason label>span{display:table-cell;font-size:1.3em}}.fs-modal.fs-modal-deactivation-feedback .anonymous-feedback-label{float:left}.fs-modal.fs-modal-deactivation-feedback .fs-modal-panel{margin-top:0 !important}.fs-modal.fs-modal-deactivation-feedback .fs-modal-panel h3{margin-top:0;line-height:1.5em}#the-list .deactivate>.fs-slug{display:none}.fs-modal.fs-modal-license-activation .fs-modal-body input.license_key{width:100%}.fs-modal.fs-modal-license-key-resend .email-address-container{overflow:hidden;padding-right:2px}.fs-modal.fs-modal-license-key-resend.fs-freemium input.email-address{width:300px}.fs-modal.fs-modal-license-key-resend.fs-freemium label{display:block;margin-bottom:10px}.fs-modal.fs-modal-license-key-resend.fs-premium input.email-address{width:100%}.fs-modal.fs-modal-license-key-resend.fs-premium .button-container{float:right;margin-left:7px}@media (max-width: 650px){.fs-modal.fs-modal-license-key-resend.fs-premium .button-container{margin-top:2px}}
2
+ .rtl .fs-modal.fs-modal-license-key-resend .fs-modal-body .input-container>.email-address-container{padding-left:2px;padding-right:0}.rtl .fs-modal.fs-modal-license-key-resend .fs-modal-body .button-container{float:left;margin-right:7px;margin-left:0}a.show-license-resend-modal{margin-top:4px;display:inline-block}.fs-ajax-loader{position:relative;width:170px;height:20px;margin:auto}.fs-ajax-loader .fs-ajax-loader-bar{position:absolute;top:0;background-color:#0074a3;width:20px;height:20px;-webkit-animation-name:bounce_ajaxLoader;-moz-animation-name:bounce_ajaxLoader;-ms-animation-name:bounce_ajaxLoader;-o-animation-name:bounce_ajaxLoader;animation-name:bounce_ajaxLoader;-webkit-animation-duration:1.5s;-moz-animation-duration:1.5s;-ms-animation-duration:1.5s;-o-animation-duration:1.5s;animation-duration:1.5s;animation-iteration-count:infinite;-o-animation-iteration-count:infinite;-ms-animation-iteration-count:infinite;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;-webkit-animation-direction:normal;-moz-animation-direction:normal;-ms-animation-direction:normal;-o-animation-direction:normal;animation-direction:normal;-moz-transform:0.3;-o-transform:0.3;-ms-transform:0.3;-webkit-transform:0.3;transform:0.3}.fs-ajax-loader .fs-ajax-loader-bar-1{left:0px;animation-delay:0.6s;-o-animation-delay:0.6s;-ms-animation-delay:0.6s;-webkit-animation-delay:0.6s;-moz-animation-delay:0.6s}.fs-ajax-loader .fs-ajax-loader-bar-2{left:19px;animation-delay:0.75s;-o-animation-delay:0.75s;-ms-animation-delay:0.75s;-webkit-animation-delay:0.75s;-moz-animation-delay:0.75s}.fs-ajax-loader .fs-ajax-loader-bar-3{left:38px;animation-delay:0.9s;-o-animation-delay:0.9s;-ms-animation-delay:0.9s;-webkit-animation-delay:0.9s;-moz-animation-delay:0.9s}.fs-ajax-loader .fs-ajax-loader-bar-4{left:57px;animation-delay:1.05s;-o-animation-delay:1.05s;-ms-animation-delay:1.05s;-webkit-animation-delay:1.05s;-moz-animation-delay:1.05s}.fs-ajax-loader .fs-ajax-loader-bar-5{left:76px;animation-delay:1.2s;-o-animation-delay:1.2s;-ms-animation-delay:1.2s;-webkit-animation-delay:1.2s;-moz-animation-delay:1.2s}.fs-ajax-loader .fs-ajax-loader-bar-6{left:95px;animation-delay:1.35s;-o-animation-delay:1.35s;-ms-animation-delay:1.35s;-webkit-animation-delay:1.35s;-moz-animation-delay:1.35s}.fs-ajax-loader .fs-ajax-loader-bar-7{left:114px;animation-delay:1.5s;-o-animation-delay:1.5s;-ms-animation-delay:1.5s;-webkit-animation-delay:1.5s;-moz-animation-delay:1.5s}.fs-ajax-loader .fs-ajax-loader-bar-8{left:133px;animation-delay:1.65s;-o-animation-delay:1.65s;-ms-animation-delay:1.65s;-webkit-animation-delay:1.65s;-moz-animation-delay:1.65s}@-moz-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-ms-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-o-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-webkit-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}.fs-modal-auto-install #request-filesystem-credentials-form h2,.fs-modal-auto-install #request-filesystem-credentials-form .request-filesystem-credentials-action-buttons{display:none}.fs-modal-auto-install #request-filesystem-credentials-form input[type=password],.fs-modal-auto-install #request-filesystem-credentials-form input[type=email],.fs-modal-auto-install #request-filesystem-credentials-form input[type=text]{-webkit-appearance:none;padding:10px 10px 5px 10px;width:300px;max-width:100%}.fs-modal-auto-install #request-filesystem-credentials-form>div,.fs-modal-auto-install #request-filesystem-credentials-form label,.fs-modal-auto-install #request-filesystem-credentials-form fieldset{width:300px;max-width:100%;margin:0 auto;display:block}
freemius/assets/css/admin/index.php CHANGED
@@ -1,3 +1,3 @@
1
- <?php
2
- // Silence is golden.
3
  // Hide file structure from users on unprotected servers.
1
+ <?php
2
+ // Silence is golden.
3
  // Hide file structure from users on unprotected servers.
freemius/assets/css/index.php CHANGED
@@ -1,3 +1,3 @@
1
- <?php
2
- // Silence is golden.
3
  // Hide file structure from users on unprotected servers.
1
+ <?php
2
+ // Silence is golden.
3
  // Hide file structure from users on unprotected servers.
freemius/assets/img/index.php CHANGED
@@ -1,3 +1,3 @@
1
- <?php
2
- // Silence is golden.
3
  // Hide file structure from users on unprotected servers.
1
+ <?php
2
+ // Silence is golden.
3
  // Hide file structure from users on unprotected servers.
freemius/assets/js/index.php CHANGED
@@ -1,3 +1,3 @@
1
- <?php
2
- // Silence is golden.
3
  // Hide file structure from users on unprotected servers.
1
+ <?php
2
+ // Silence is golden.
3
  // Hide file structure from users on unprotected servers.
freemius/assets/scss/_colors.scss CHANGED
@@ -1,65 +1,65 @@
1
- $menu-hover-color: #333;
2
- $darkest-color: #000;
3
- $fms-live-color: #71ae00;
4
- $fms-test-color: #f7941d;
5
- $fms-link-color: #29abe1;
6
- $fms-link-hover-color: darken(#29abe1, 10%);
7
- $body-bkg: #111;
8
- $special-color: #d3135a;
9
- $body-color: #f1f1f1;
10
- $fms-white: #f1f1f1;
11
- $container-bkg: #222;
12
- $container-bkg-odd: #262626;
13
- $container-border-color: #333;
14
- $table-head-bkg: #333;
15
- $table-head-color: #999;
16
- $info-color: #999;
17
- $error-color: #ff0000;
18
-
19
- $fs-logo-blue-color: #29abe1;
20
- $fs-logo-green-color: #71ae00;
21
- $fs-logo-magenta-color: #d3135a;
22
-
23
- // WordPress colors.
24
- $page-header-bkg: #333;
25
- $page-header-color: $fms-white;
26
- $text-dark-color: #333;
27
- $text-light-color: #666;
28
- $text-lightest-color: #999;
29
-
30
- // Notices.
31
- $wp-notice-success-color: #f7fff7;
32
- $wp-notice-success-dark-color: #46b450;
33
- $wp-notice-error-color: #ffeaea;
34
- $wp-notice-error-dark-color: #dc3232;
35
- $wp-notice-warn-color: #fff8e5;
36
- $wp-notice-warn-dark-color: #ffb900;
37
- $fs-notice-promotion-border-color: #00a0d2;
38
- $fs-notice-promotion-bkg: #f2fcff;
39
-
40
- // WP Buttons.
41
- $button-primary-bkg: #6bc406;
42
- $button-primary-color: $fms-white;
43
- $button-secondary-bkg: #333;
44
- $button-secondary-color: $fms-white;
45
- $featured-color: #6bc406;
46
- $wp-selected-color: #0074a3;
47
-
48
- $wordpress_color: #01749A;
49
- $blogger_color: #ff8100;
50
- $wix_color: #fac102;
51
- $shopify_color: #80d100;
52
- $addthis_color: #fe6d4e;
53
- $tumblr_color: #34506b;
54
- $zepo_color: #00baf2;
55
- $jquery_color: #000919;
56
- $javascript_color: #00baf2;
57
- $squarespace_color: #000;
58
-
59
- $blog_color: #ff6600;
60
- $facebook_color: #3b5998;
61
- $twitter_color: #4099ff;
62
- $linkedin_color: #4875b4;
63
- $youtube_color: #ff3333;
64
- $gplus_color: #c63d2d;
65
-
1
+ $menu-hover-color: #333;
2
+ $darkest-color: #000;
3
+ $fms-live-color: #71ae00;
4
+ $fms-test-color: #f7941d;
5
+ $fms-link-color: #29abe1;
6
+ $fms-link-hover-color: darken(#29abe1, 10%);
7
+ $body-bkg: #111;
8
+ $special-color: #d3135a;
9
+ $body-color: #f1f1f1;
10
+ $fms-white: #f1f1f1;
11
+ $container-bkg: #222;
12
+ $container-bkg-odd: #262626;
13
+ $container-border-color: #333;
14
+ $table-head-bkg: #333;
15
+ $table-head-color: #999;
16
+ $info-color: #999;
17
+ $error-color: #ff0000;
18
+
19
+ $fs-logo-blue-color: #29abe1;
20
+ $fs-logo-green-color: #71ae00;
21
+ $fs-logo-magenta-color: #d3135a;
22
+
23
+ // WordPress colors.
24
+ $page-header-bkg: #333;
25
+ $page-header-color: $fms-white;
26
+ $text-dark-color: #333;
27
+ $text-light-color: #666;
28
+ $text-lightest-color: #999;
29
+
30
+ // Notices.
31
+ $wp-notice-success-color: #f7fff7;
32
+ $wp-notice-success-dark-color: #46b450;
33
+ $wp-notice-error-color: #ffeaea;
34
+ $wp-notice-error-dark-color: #dc3232;
35
+ $wp-notice-warn-color: #fff8e5;
36
+ $wp-notice-warn-dark-color: #ffb900;
37
+ $fs-notice-promotion-border-color: #00a0d2;
38
+ $fs-notice-promotion-bkg: #f2fcff;
39
+
40
+ // WP Buttons.
41
+ $button-primary-bkg: #6bc406;
42
+ $button-primary-color: $fms-white;
43
+ $button-secondary-bkg: #333;
44
+ $button-secondary-color: $fms-white;
45
+ $featured-color: #6bc406;
46
+ $wp-selected-color: #0074a3;
47
+
48
+ $wordpress_color: #01749A;
49
+ $blogger_color: #ff8100;
50
+ $wix_color: #fac102;
51
+ $shopify_color: #80d100;
52
+ $addthis_color: #fe6d4e;
53
+ $tumblr_color: #34506b;
54
+ $zepo_color: #00baf2;
55
+ $jquery_color: #000919;
56
+ $javascript_color: #00baf2;
57
+ $squarespace_color: #000;
58
+
59
+ $blog_color: #ff6600;
60
+ $facebook_color: #3b5998;
61
+ $twitter_color: #4099ff;
62
+ $linkedin_color: #4875b4;
63
+ $youtube_color: #ff3333;
64
+ $gplus_color: #c63d2d;
65
+
freemius/assets/scss/admin/_license-activation.scss CHANGED
@@ -1,7 +1,7 @@
1
- .fs-modal.fs-modal-license-activation {
2
- .fs-modal-body {
3
- input.license_key {
4
- width: 100%;
5
- }
6
- }
7
  }
1
+ .fs-modal.fs-modal-license-activation {
2
+ .fs-modal-body {
3
+ input.license_key {
4
+ width: 100%;
5
+ }
6
+ }
7
  }
freemius/assets/scss/admin/_modal-common.scss CHANGED
@@ -1,186 +1,186 @@
1
- @import "../colors";
2
- @import "../mixins";
3
-
4
- .fs-modal {
5
- position: fixed;
6
- overflow: auto;
7
- height: 100%;
8
- width: 100%;
9
- top: 0;
10
- z-index: 100000;
11
- display: none;
12
- background: rgba(0, 0, 0, 0.6);
13
-
14
- .fs-modal-dialog {
15
- background: transparent;
16
- position: absolute;
17
- left: 50%;
18
- margin-left: -298px;
19
- padding-bottom: 30px;
20
- top: -100%;
21
- z-index: 100001;
22
- width: 596px;
23
-
24
- @media (max-width: 650px) {
25
- margin-left: -50%;
26
- box-sizing: border-box;
27
- padding-left: 10px;
28
- padding-right: 10px;
29
- width: 100%;
30
-
31
- .fs-modal-panel > h3 > strong {
32
- font-size: 1.3em;
33
- }
34
- }
35
- }
36
-
37
- &.active {
38
- display: block;
39
-
40
- &:before {
41
- display: block;
42
- }
43
-
44
- .fs-modal-dialog {
45
- top: 10%;
46
- }
47
- }
48
-
49
- &.fs-success {
50
- .fs-modal-header {
51
- border-bottom-color: $wp-notice-success-dark-color;
52
- }
53
-
54
- .fs-modal-body {
55
- background-color: $wp-notice-success-color;
56
- }
57
- }
58
-
59
- &.fs-warn {
60
- .fs-modal-header {
61
- border-bottom-color: $wp-notice-warn-dark-color;
62
- }
63
-
64
- .fs-modal-body {
65
- background-color: $wp-notice-warn-color;
66
- }
67
- }
68
-
69
- &.fs-error {
70
- .fs-modal-header {
71
- border-bottom-color: $wp-notice-error-dark-color;
72
- }
73
-
74
- .fs-modal-body {
75
- background-color: $wp-notice-error-color;
76
- }
77
- }
78
-
79
-
80
- .fs-modal-body,
81
- .fs-modal-footer {
82
- border: 0;
83
- background: #fefefe;
84
- padding: 20px;
85
- }
86
-
87
- .fs-modal-header {
88
- border-bottom: #eeeeee solid 1px;
89
- background: #fbfbfb;
90
- padding: 15px 20px;
91
- position: relative;
92
- margin-bottom: -10px;
93
- // z-index: 2;
94
-
95
- h4 {
96
- margin: 0;
97
- padding: 0;
98
- text-transform: uppercase;
99
- font-size: 1.2em;
100
- font-weight: bold;
101
- color: #cacaca;
102
- text-shadow: 1px 1px 1px #fff;
103
- letter-spacing: 0.6px;
104
- -webkit-font-smoothing: antialiased;
105
- }
106
-
107
- .fs-close {
108
- position: absolute;
109
- right: 10px;
110
- top: 12px;
111
- cursor: pointer;
112
- color: #bbb;
113
- @include border-radius(20px);
114
- padding: 3px;
115
- @include transition(all 0.2s ease-in-out);
116
-
117
- &:hover {
118
- color: #fff;
119
- background: #aaa;
120
- }
121
- }
122
- }
123
-
124
- .fs-modal-body {
125
- border-bottom: 0;
126
-
127
- p {
128
- font-size: 14px;
129
- }
130
-
131
- h2 {
132
- font-size: 20px;
133
- line-height: 1.5em;
134
- }
135
-
136
- > div {
137
- margin-top: 10px;
138
-
139
- h2 {
140
- font-weight: bold;
141
- font-size: 20px;
142
- margin-top: 0;
143
- }
144
- }
145
- }
146
-
147
- .fs-modal-footer {
148
- border-top: #eeeeee solid 1px;
149
- text-align: right;
150
-
151
- > .button {
152
- margin: 0 7px;
153
-
154
- &:first-child {
155
- margin: 0;
156
- }
157
- }
158
- }
159
-
160
- .fs-modal-panel {
161
- > .notice.inline {
162
- margin: 0;
163
- display: none;
164
- }
165
-
166
- &:not(.active) {
167
- display: none;
168
- }
169
- }
170
- }
171
-
172
- .rtl
173
- {
174
- .fs-modal {
175
- .fs-modal-header {
176
- .fs-close {
177
- right: auto;
178
- left: 20px;
179
- }
180
- }
181
- }
182
- }
183
-
184
- body.has-fs-modal {
185
- overflow: hidden;
186
  }
1
+ @import "../colors";
2
+ @import "../mixins";
3
+
4
+ .fs-modal {
5
+ position: fixed;
6
+ overflow: auto;
7
+ height: 100%;
8
+ width: 100%;
9
+ top: 0;
10
+ z-index: 100000;
11
+ display: none;
12
+ background: rgba(0, 0, 0, 0.6);
13
+
14
+ .fs-modal-dialog {
15
+ background: transparent;
16
+ position: absolute;
17
+ left: 50%;
18
+ margin-left: -298px;
19
+ padding-bottom: 30px;
20
+ top: -100%;
21
+ z-index: 100001;
22
+ width: 596px;
23
+
24
+ @media (max-width: 650px) {
25
+ margin-left: -50%;
26
+ box-sizing: border-box;
27
+ padding-left: 10px;
28
+ padding-right: 10px;
29
+ width: 100%;
30
+
31
+ .fs-modal-panel > h3 > strong {
32
+ font-size: 1.3em;
33
+ }
34
+ }
35
+ }
36
+
37
+ &.active {
38
+ display: block;
39
+
40
+ &:before {
41
+ display: block;
42
+ }
43
+
44
+ .fs-modal-dialog {
45
+ top: 10%;
46
+ }
47
+ }
48
+
49
+ &.fs-success {
50
+ .fs-modal-header {
51
+ border-bottom-color: $wp-notice-success-dark-color;
52
+ }
53
+
54
+ .fs-modal-body {
55
+ background-color: $wp-notice-success-color;
56
+ }
57
+ }
58
+
59
+ &.fs-warn {
60
+ .fs-modal-header {
61
+ border-bottom-color: $wp-notice-warn-dark-color;
62
+ }
63
+
64
+ .fs-modal-body {
65
+ background-color: $wp-notice-warn-color;
66
+ }
67
+ }
68
+
69
+ &.fs-error {
70
+ .fs-modal-header {
71
+ border-bottom-color: $wp-notice-error-dark-color;
72
+ }
73
+
74
+ .fs-modal-body {
75
+ background-color: $wp-notice-error-color;
76
+ }
77
+ }
78
+
79
+
80
+ .fs-modal-body,
81
+ .fs-modal-footer {
82
+ border: 0;
83
+ background: #fefefe;
84
+ padding: 20px;
85
+ }
86
+
87
+ .fs-modal-header {
88
+ border-bottom: #eeeeee solid 1px;
89
+ background: #fbfbfb;
90
+ padding: 15px 20px;
91
+ position: relative;
92
+ margin-bottom: -10px;
93
+ // z-index: 2;
94
+
95
+ h4 {
96
+ margin: 0;
97
+ padding: 0;
98
+ text-transform: uppercase;
99
+ font-size: 1.2em;
100
+ font-weight: bold;
101
+ color: #cacaca;
102
+ text-shadow: 1px 1px 1px #fff;
103
+ letter-spacing: 0.6px;
104
+ -webkit-font-smoothing: antialiased;
105
+ }
106
+
107
+ .fs-close {
108
+ position: absolute;
109
+ right: 10px;
110
+ top: 12px;
111
+ cursor: pointer;
112
+ color: #bbb;
113
+ @include border-radius(20px);
114
+ padding: 3px;
115
+ @include transition(all 0.2s ease-in-out);
116
+
117
+ &:hover {
118
+ color: #fff;
119
+ background: #aaa;
120
+ }
121
+ }
122
+ }
123
+
124
+ .fs-modal-body {
125
+ border-bottom: 0;
126
+
127
+ p {
128
+ font-size: 14px;
129
+ }
130
+
131
+ h2 {
132
+ font-size: 20px;
133
+ line-height: 1.5em;
134
+ }
135
+
136
+ > div {
137
+ margin-top: 10px;
138
+
139
+ h2 {
140
+ font-weight: bold;
141
+ font-size: 20px;
142
+ margin-top: 0;
143
+ }
144
+ }
145
+ }
146
+
147
+ .fs-modal-footer {
148
+ border-top: #eeeeee solid 1px;
149
+ text-align: right;
150
+
151
+ > .button {
152
+ margin: 0 7px;
153
+
154
+ &:first-child {
155
+ margin: 0;
156
+ }
157
+ }
158
+ }
159
+
160
+ .fs-modal-panel {
161
+ > .notice.inline {
162
+ margin: 0;
163
+ display: none;
164
+ }
165
+
166
+ &:not(.active) {
167
+ display: none;
168
+ }
169
+ }
170
+ }
171
+
172
+ .rtl
173
+ {
174
+ .fs-modal {
175
+ .fs-modal-header {
176
+ .fs-close {
177
+ right: auto;
178
+ left: 20px;
179
+ }
180
+ }
181
+ }
182
+ }
183
+
184
+ body.has-fs-modal {
185
+ overflow: hidden;
186
  }
freemius/assets/scss/admin/account.scss CHANGED
@@ -1,256 +1,256 @@
1
- @import "../start";
2
-
3
- #fs_account
4
- {
5
- .postbox,
6
- .widefat
7
- {
8
- max-width: 700px;
9
- }
10
-
11
- h3
12
- {
13
- font-size: 1.3em;
14
- padding: 12px 15px;
15
- margin: 0 0 12px 0;
16
- line-height: 1.4;
17
- border-bottom: 1px solid #F1F1F1;
18
-
19
- .dashicons {
20
- width: 26px;
21
- height: 26px;
22
- font-size: 1.3em;
23
- }
24
- }
25
-
26
- i.dashicons
27
- {
28
- font-size: 1.2em;
29
- height: 1.2em;
30
- width: 1.2em;
31
- }
32
-
33
- .button
34
- {
35
- i.dashicons
36
- {
37
- vertical-align: middle;
38
- }
39
- }
40
-
41
- .fs-header-actions
42
- {
43
- position: absolute;
44
- top: 17px;
45
- right: 15px;
46
- font-size: 0.9em;
47
-
48
- ul
49
- {
50
- margin: 0;
51
- }
52
-
53
- li
54
- {
55
- form
56
- {
57
- display: inline-block;
58
- }
59
-
60
- float: left;
61
- a
62
- {
63
- text-decoration: none;
64
- }
65
- }
66
- }
67
- }
68
-
69
- #fs_account_details .button-group {
70
- float: right;
71
- }
72
-
73
- .rtl #fs_account .fs-header-actions
74
- {
75
- left: 15px;
76
- right: auto;
77
- }
78
-
79
- .fs-key-value-table
80
- {
81
- width: 100%;
82
-
83
- form
84
- {
85
- display: inline-block;
86
- }
87
-
88
- tr
89
- {
90
- td:first-child
91
- {
92
- nobr
93
- {
94
- font-weight: bold;
95
- }
96
-
97
- text-align: right;
98
-
99
- form
100
- {
101
- display: block;
102
- }
103
- }
104
-
105
- td.fs-right
106
- {
107
- text-align: right;
108
- }
109
-
110
- &.fs-odd
111
- {
112
- background: #ebebeb;
113
- }
114
- }
115
-
116
- td, th
117
- {
118
- padding: 10px;
119
- }
120
-
121
- code {
122
- line-height: 28px;
123
- }
124
-
125
- var, code, input[type="text"]
126
- {
127
- color: #0073AA;
128
- font-size: 16px;
129
- background: none;
130
- }
131
-
132
- input[type="text"] {
133
- width: 100%;
134
- font-weight: bold;
135
- }
136
- }
137
-
138
- label.fs-tag
139
- {
140
- background: #ffba00;
141
- color: #fff;
142
- display: inline-block;
143
- border-radius: 3px;
144
- padding: 5px;
145
- font-size: 11px;
146
- line-height: 11px;
147
- vertical-align: baseline;
148
-
149
- &.fs-warn
150
- {
151
- background: #ffba00;
152
- }
153
- &.fs-success
154
- {
155
- background: #46b450;
156
- }
157
- &.fs-error
158
- {
159
- background: #dc3232;
160
- }
161
- }
162
-
163
- #fs_addons
164
- {
165
- h3
166
- {
167
- border: none;
168
- margin-bottom: 0;
169
- padding: 4px 5px;
170
- }
171
-
172
- td
173
- {
174
- vertical-align: middle;
175
- }
176
-
177
- thead {
178
- white-space: nowrap;
179
- }
180
-
181
- td:first-child,
182
- th:first-child
183
- {
184
- text-align: left;
185
- font-weight: bold;
186
- }
187
- td:last-child,
188
- th:last-child
189
- {
190
- text-align: right;
191
- }
192
- th
193
- {
194
- font-weight: bold;
195
- }
196
- }
197
-
198
- #fs_billing_address {
199
- width: 100%;
200
-
201
- tr {
202
- td {
203
- width: 50%;
204
- padding: 5px;
205
- }
206
-
207
- &:first-of-type {
208
- td {
209
- padding-top: 0;
210
- }
211
- }
212
- }
213
-
214
- @mixin read-mode {
215
- border-color: transparent;
216
- color: #777;
217
- border-bottom: 1px dashed #ccc;
218
- padding-left: 0;
219
- background: none;
220
- }
221
-
222
- span {
223
- font-weight: bold;
224
- }
225
-
226
- input, select {
227
- @include placeholder(transparent);
228
-
229
- display: block;
230
- width: 100%;
231
- margin-top: 5px;
232
-
233
- &.fs-read-mode {
234
- @include read-mode();
235
- }
236
- }
237
-
238
-
239
- &.fs-read-mode {
240
- td span {
241
- display: none;
242
- }
243
-
244
- input, select
245
- {
246
- @include read-mode();
247
- @include placeholder(#ccc);
248
- }
249
- }
250
-
251
-
252
- button {
253
- display: block;
254
- width: 100%;
255
- }
256
  }
1
+ @import "../start";
2
+
3
+ #fs_account
4
+ {
5
+ .postbox,
6
+ .widefat
7
+ {
8
+ max-width: 700px;
9
+ }
10
+
11
+ h3
12
+ {
13
+ font-size: 1.3em;
14
+ padding: 12px 15px;
15
+ margin: 0 0 12px 0;
16
+ line-height: 1.4;
17
+ border-bottom: 1px solid #F1F1F1;
18
+
19
+ .dashicons {
20
+ width: 26px;
21
+ height: 26px;
22
+ font-size: 1.3em;
23
+ }
24
+ }
25
+
26
+ i.dashicons
27
+ {
28
+ font-size: 1.2em;
29
+ height: 1.2em;
30
+ width: 1.2em;
31
+ }
32
+
33
+ .button
34
+ {
35
+ i.dashicons
36
+ {
37
+ vertical-align: middle;
38
+ }
39
+ }
40
+
41
+ .fs-header-actions
42
+ {
43
+ position: absolute;
44
+ top: 17px;
45
+ right: 15px;
46
+ font-size: 0.9em;
47
+
48
+ ul
49
+ {
50
+ margin: 0;
51
+ }
52
+
53
+ li
54
+ {
55
+ form
56
+ {
57
+ display: inline-block;
58
+ }
59
+
60
+ float: left;
61
+ a
62
+ {
63
+ text-decoration: none;
64
+ }
65
+ }
66
+ }
67
+ }
68
+
69
+ #fs_account_details .button-group {
70
+ float: right;
71
+ }
72
+
73
+ .rtl #fs_account .fs-header-actions
74
+ {
75
+ left: 15px;
76
+ right: auto;
77
+ }
78
+
79
+ .fs-key-value-table
80
+ {
81
+ width: 100%;
82
+
83
+ form
84
+ {
85
+ display: inline-block;
86
+ }
87
+
88
+ tr
89
+ {
90
+ td:first-child
91
+ {
92
+ nobr
93
+ {
94
+ font-weight: bold;
95
+ }
96
+
97
+ text-align: right;
98
+
99
+ form
100
+ {
101
+ display: block;
102
+ }
103
+ }
104
+
105
+ td.fs-right
106
+ {
107
+ text-align: right;
108
+ }
109
+
110
+ &.fs-odd
111
+ {
112
+ background: #ebebeb;
113
+ }
114
+ }
115
+
116
+ td, th
117
+ {
118
+ padding: 10px;
119
+ }
120
+
121
+ code {
122
+ line-height: 28px;
123
+ }
124
+
125
+ var, code, input[type="text"]
126
+ {
127
+ color: #0073AA;
128
+ font-size: 16px;
129
+ background: none;
130
+ }
131
+
132
+ input[type="text"] {
133
+ width: 100%;
134
+ font-weight: bold;
135
+ }
136
+ }
137
+
138
+ label.fs-tag
139
+ {
140
+ background: #ffba00;
141
+ color: #fff;
142
+ display: inline-block;
143
+ border-radius: 3px;
144
+ padding: 5px;
145
+ font-size: 11px;
146
+ line-height: 11px;
147
+ vertical-align: baseline;
148
+
149
+ &.fs-warn
150
+ {
151
+ background: #ffba00;
152
+ }
153
+ &.fs-success
154
+ {
155
+ background: #46b450;
156
+ }
157
+ &.fs-error
158
+ {
159
+ background: #dc3232;
160
+ }
161
+ }
162
+
163
+ #fs_addons
164
+ {
165
+ h3
166
+ {
167
+ border: none;
168
+ margin-bottom: 0;
169
+ padding: 4px 5px;
170
+ }
171
+
172
+ td
173
+ {
174
+ vertical-align: middle;
175
+ }
176
+
177
+ thead {
178
+ white-space: nowrap;
179
+ }
180
+
181
+ td:first-child,
182
+ th:first-child
183
+ {
184
+ text-align: left;
185
+ font-weight: bold;
186
+ }
187
+ td:last-child,
188
+ th:last-child
189
+ {
190
+ text-align: right;
191
+ }
192
+ th
193
+ {
194
+ font-weight: bold;
195
+ }
196
+ }
197
+
198
+ #fs_billing_address {
199
+ width: 100%;
200
+
201
+ tr {
202
+ td {
203
+ width: 50%;
204
+ padding: 5px;
205
+ }
206
+
207
+ &:first-of-type {
208
+ td {
209
+ padding-top: 0;
210
+ }
211
+ }
212
+ }
213
+
214
+ @mixin read-mode {
215
+ border-color: transparent;
216
+ color: #777;
217
+ border-bottom: 1px dashed #ccc;
218
+ padding-left: 0;
219
+ background: none;
220
+ }
221
+
222
+ span {
223
+ font-weight: bold;
224
+ }
225
+
226
+ input, select {
227
+ @include placeholder(transparent);
228
+
229
+ display: block;
230
+ width: 100%;
231
+ margin-top: 5px;
232
+
233
+ &.fs-read-mode {
234
+ @include read-mode();
235
+ }
236
+ }
237
+
238
+
239
+ &.fs-read-mode {
240
+ td span {
241
+ display: none;
242
+ }
243
+
244
+ input, select
245
+ {
246
+ @include read-mode();
247
+ @include placeholder(#ccc);
248
+ }
249
+ }
250
+
251
+
252
+ button {
253
+ display: block;
254
+ width: 100%;
255
+ }
256
  }
freemius/assets/scss/admin/dialog-boxes.scss CHANGED
@@ -1,7 +1,7 @@
1
- @import "../start";
2
- @import "modal-common";
3
- @import "deactivation-feedback";
4
- @import "license-activation";
5
- @import "license-key-resend";
6
- @import "ajax-loader";
7
  @import "auto-install";
1
+ @import "../start";
2
+ @import "modal-common";
3
+ @import "deactivation-feedback";
4
+ @import "license-activation";
5
+ @import "license-key-resend";
6
+ @import "ajax-loader";
7
  @import "auto-install";
freemius/assets/scss/admin/index.php CHANGED
@@ -1,3 +1,3 @@
1
- <?php
2
- // Silence is golden.
3
  // Hide file structure from users on unprotected servers.
1
+ <?php
2
+ // Silence is golden.
3
  // Hide file structure from users on unprotected servers.
freemius/assets/scss/index.php CHANGED
@@ -1,3 +1,3 @@
1
- <?php
2
- // Silence is golden.
3
  // Hide file structure from users on unprotected servers.
1
+ <?php
2
+ // Silence is golden.
3
  // Hide file structure from users on unprotected servers.
freemius/gulpfile.js CHANGED
@@ -1,167 +1,167 @@
1
- var gulp = require('gulp');
2
- var path = require('path');
3
- var filesystem = require('fs');
4
- var wpPot = require('gulp-wp-pot');
5
- var gettext = require('gulp-gettext');
6
- var sort = require('gulp-sort');
7
- var pofill = require('gulp-pofill');
8
- var rename = require('gulp-rename');
9
- var clean = require('gulp-clean');
10
-
11
- var languagesFolder = './languages/';
12
-
13
- var options = require('./transifex-config.json');
14
-
15
- function getFolders(dir) {
16
- return filesystem.readdirSync(dir)
17
- .filter(function (file) {
18
- return filesystem.statSync(path.join(dir, file)).isDirectory();
19
- });
20
- }
21
-
22
- var transifex = require('gulp-transifex').createClient(options);
23
-
24
- // Create POT out of i18n.php.
25
- gulp.task('prepare-source', function () {
26
- gulp.src('**/*.php')
27
- .pipe(sort())
28
- .pipe(wpPot({
29
- destFile : 'freemius.pot',
30
- package : 'freemius',
31
- bugReport : 'https://github.com/Freemius/wordpress-sdk/issues',
32
- lastTranslator : 'Vova Feldman <vova@freemius.com>',
33
- team : 'Freemius Team <admin@freemius.com>',
34
- /*gettextMethods: {
35
- instances: ['this', '_fs'],
36
- methods: [
37
- 'get_text_inline'
38
- ]
39
- },*/
40
- gettextFunctions: [
41
- {name: 'get_text_inline'},
42
-
43
- {name: 'fs_text_inline'},
44
- {name: 'fs_echo_inline'},
45
- {name: 'fs_esc_js_inline'},
46
- {name: 'fs_esc_attr_inline'},
47
- {name: 'fs_esc_attr_echo_inline'},
48
- {name: 'fs_esc_html_inline'},
49
- {name: 'fs_esc_html_echo_inline'},
50
-
51
- {name: 'get_text_x_inline', context: 2},
52
- {name: 'fs_text_x_inline', context: 2},
53
- {name: 'fs_echo_x_inline', context: 2},
54
- {name: 'fs_esc_attr_x_inline', context: 2},
55
- {name: 'fs_esc_js_x_inline', context: 2},
56
- {name: 'fs_esc_js_echo_x_inline', context: 2},
57
- {name: 'fs_esc_html_x_inline', context: 2},
58
- {name: 'fs_esc_html_echo_x_inline', context: 2}
59
- /*,
60
-
61
-
62
- {name: '_fs_text'},
63
- {name: '_fs_x', context: 2},
64
- {name: '_fs_echo'},
65
- {name: '_fs_esc_attr'},
66
- {name: '_fs_esc_attr_echo'},
67
- {name: '_fs_esc_html'},
68
- {name: '_fs_esc_html_echo'},
69
- {name: '_fs_ex', context: 2},
70
- {name: '_fs_esc_attr_x', context: 2},
71
- {name: '_fs_esc_html_x', context: 2},
72
-
73
- {name: '_fs_n', plural: 2},
74
- {name: '_fs_n_noop', plural: 2},
75
- {name: '_fs_nx', plural: 2, context: 4},
76
- {name: '_fs_nx_noop', plural: 2, context: 3}*/
77
- ]
78
- }))
79
- .pipe(gulp.dest(languagesFolder + 'freemius.pot'));
80
-
81
- // Create English PO out of the POT.
82
- return gulp.src(languagesFolder + 'freemius.pot')
83
- .pipe(pofill({
84
- items: function (item) {
85
- // If msgstr is empty, use identity translation
86
- if (!item.msgstr.length) {
87
- item.msgstr = [''];
88
- }
89
- if (!item.msgstr[0]) {
90
- item.msgstr[0] = item.msgid;
91
- }
92
- return item;
93
- }
94
- }))
95
- .pipe(rename('freemius-en.po'))
96
- .pipe(gulp.dest(languagesFolder));
97
- });
98
-
99
- // Push updated po resource to transifex.
100
- gulp.task('update-transifex', ['prepare-source'], function () {
101
- return gulp.src(languagesFolder + 'freemius-en.po')
102
- .pipe(transifex.pushResource());
103
- });
104
-
105
- // Download latest *.po translations.
106
- gulp.task('download-translations', ['update-transifex'], function () {
107
- return gulp.src(languagesFolder + 'freemius-en.po')
108
- .pipe(transifex.pullResource());
109
- });
110
-
111
- // Move translations to languages root.
112
- gulp.task('prepare-translations', ['download-translations'], function () {
113
- var folders = getFolders(languagesFolder);
114
-
115
- return folders.map(function (folder) {
116
- return gulp.src(path.join(languagesFolder, folder, 'freemius-en.po'))
117
- .pipe(rename('freemius-' + folder + '.po'))
118
- .pipe(gulp.dest(languagesFolder));
119
- });
120
- });
121
-
122
- // Feel up empty translations with English.
123
- gulp.task('translations-feelup', ['prepare-translations'], function () {
124
- return gulp.src(languagesFolder + '*.po')
125
- .pipe(pofill({
126
- items: function (item) {
127
- // If msgstr is empty, use identity translation
128
- if (0 == item.msgstr.length) {
129
- item.msgstr = [''];
130
- }
131
- if (0 == item.msgstr[0].length) {
132
- // item.msgid[0] = item.msgid;
133
- item.msgstr[0] = item.msgid;
134
- }
135
- return item;
136
- }
137
- }))
138
- .pipe(gulp.dest(languagesFolder));
139
- });
140
-
141
- // Cleanup temporary translation folders.
142
- gulp.task('cleanup', ['prepare-translations'], function () {
143
- var folders = getFolders(languagesFolder);
144
-
145
- return folders.map(function (folder) {
146
- return gulp.src(path.join(languagesFolder, folder), {read: false})
147
- .pipe(clean());
148
- });
149
- });
150
-
151
- // Compile *.po to *.mo binaries for usage.
152
- gulp.task('compile-translations', ['translations-feelup'], function () {
153
- // Compile POs to MOs.
154
- return gulp.src(languagesFolder + '*.po')
155
- .pipe(gettext())
156
- .pipe(gulp.dest(languagesFolder))
157
- });
158
-
159
- gulp.task('default', [], function () {
160
- gulp.run('prepare-source');
161
- gulp.run('update-transifex');
162
- gulp.run('download-translations');
163
- gulp.run('prepare-translations');
164
- gulp.run('translations-feelup');
165
- gulp.run('cleanup');
166
- gulp.run('compile-translations');
167
  });
1
+ var gulp = require('gulp');
2
+ var path = require('path');
3
+ var filesystem = require('fs');
4
+ var wpPot = require('gulp-wp-pot');
5
+ var gettext = require('gulp-gettext');
6
+ var sort = require('gulp-sort');
7
+ var pofill = require('gulp-pofill');
8
+ var rename = require('gulp-rename');
9
+ var clean = require('gulp-clean');
10
+
11
+ var languagesFolder = './languages/';
12
+
13
+ var options = require('./transifex-config.json');
14
+
15
+ function getFolders(dir) {
16
+ return filesystem.readdirSync(dir)
17
+ .filter(function (file) {
18
+ return filesystem.statSync(path.join(dir, file)).isDirectory();
19
+ });
20
+ }
21
+
22
+ var transifex = require('gulp-transifex').createClient(options);
23
+
24
+ // Create POT out of i18n.php.
25
+ gulp.task('prepare-source', function () {
26
+ gulp.src('**/*.php')
27
+ .pipe(sort())
28
+ .pipe(wpPot({
29
+ destFile : 'freemius.pot',
30
+ package : 'freemius',
31
+ bugReport : 'https://github.com/Freemius/wordpress-sdk/issues',
32
+ lastTranslator : 'Vova Feldman <vova@freemius.com>',
33
+ team : 'Freemius Team <admin@freemius.com>',
34
+ /*gettextMethods: {
35
+ instances: ['this', '_fs'],
36
+ methods: [
37
+ 'get_text_inline'
38
+ ]
39
+ },*/
40
+ gettextFunctions: [
41
+ {name: 'get_text_inline'},
42
+
43
+ {name: 'fs_text_inline'},
44
+ {name: 'fs_echo_inline'},
45
+ {name: 'fs_esc_js_inline'},
46
+ {name: 'fs_esc_attr_inline'},
47
+ {name: 'fs_esc_attr_echo_inline'},
48
+ {name: 'fs_esc_html_inline'},
49
+ {name: 'fs_esc_html_echo_inline'},
50
+
51
+ {name: 'get_text_x_inline', context: 2},
52
+ {name: 'fs_text_x_inline', context: 2},
53
+ {name: 'fs_echo_x_inline', context: 2},
54
+ {name: 'fs_esc_attr_x_inline', context: 2},
55
+ {name: 'fs_esc_js_x_inline', context: 2},
56
+ {name: 'fs_esc_js_echo_x_inline', context: 2},
57
+ {name: 'fs_esc_html_x_inline', context: 2},
58
+ {name: 'fs_esc_html_echo_x_inline', context: 2}
59
+ /*,
60
+
61
+
62
+ {name: '_fs_text'},
63
+ {name: '_fs_x', context: 2},
64
+ {name: '_fs_echo'},
65
+ {name: '_fs_esc_attr'},
66
+ {name: '_fs_esc_attr_echo'},
67
+ {name: '_fs_esc_html'},
68
+ {name: '_fs_esc_html_echo'},
69
+ {name: '_fs_ex', context: 2},
70
+ {name: '_fs_esc_attr_x', context: 2},
71
+ {name: '_fs_esc_html_x', context: 2},
72
+
73
+ {name: '_fs_n', plural: 2},
74
+ {name: '_fs_n_noop', plural: 2},
75
+ {name: '_fs_nx', plural: 2, context: 4},
76
+ {name: '_fs_nx_noop', plural: 2, context: 3}*/
77
+ ]
78
+ }))
79
+ .pipe(gulp.dest(languagesFolder + 'freemius.pot'));
80
+
81
+ // Create English PO out of the POT.
82
+ return gulp.src(languagesFolder + 'freemius.pot')
83
+ .pipe(pofill({
84
+ items: function (item) {
85
+ // If msgstr is empty, use identity translation
86
+ if (!item.msgstr.length) {
87
+ item.msgstr = [''];
88
+ }
89
+ if (!item.msgstr[0]) {
90
+ item.msgstr[0] = item.msgid;
91
+ }
92
+ return item;
93
+ }
94
+ }))
95
+ .pipe(rename('freemius-en.po'))
96
+ .pipe(gulp.dest(languagesFolder));
97
+ });
98
+
99
+ // Push updated po resource to transifex.
100
+ gulp.task('update-transifex', ['prepare-source'], function () {
101
+ return gulp.src(languagesFolder + 'freemius-en.po')
102
+ .pipe(transifex.pushResource());
103
+ });
104
+
105
+ // Download latest *.po translations.
106
+ gulp.task('download-translations', ['update-transifex'], function () {
107
+ return gulp.src(languagesFolder + 'freemius-en.po')
108
+ .pipe(transifex.pullResource());
109
+ });
110
+
111
+ // Move translations to languages root.
112
+ gulp.task('prepare-translations', ['download-translations'], function () {
113
+ var folders = getFolders(languagesFolder);
114
+
115
+ return folders.map(function (folder) {
116
+ return gulp.src(path.join(languagesFolder, folder, 'freemius-en.po'))
117
+ .pipe(rename('freemius-' + folder + '.po'))
118
+ .pipe(gulp.dest(languagesFolder));
119
+ });
120
+ });
121
+
122
+ // Feel up empty translations with English.
123
+ gulp.task('translations-feelup', ['prepare-translations'], function () {
124
+ return gulp.src(languagesFolder + '*.po')
125
+ .pipe(pofill({
126
+ items: function (item) {
127
+ // If msgstr is empty, use identity translation
128
+ if (0 == item.msgstr.length) {
129
+ item.msgstr = [''];
130
+ }
131
+ if (0 == item.msgstr[0].length) {
132
+ // item.msgid[0] = item.msgid;
133
+ item.msgstr[0] = item.msgid;
134
+ }
135
+ return item;
136
+ }
137
+ }))
138
+ .pipe(gulp.dest(languagesFolder));
139
+ });
140
+
141
+ // Cleanup temporary translation folders.
142
+ gulp.task('cleanup', ['prepare-translations'], function () {
143
+ var folders = getFolders(languagesFolder);
144
+
145
+ return folders.map(function (folder) {
146
+ return gulp.src(path.join(languagesFolder, folder), {read: false})
147
+ .pipe(clean());
148
+ });
149
+ });
150
+
151
+ // Compile *.po to *.mo binaries for usage.
152
+ gulp.task('compile-translations', ['translations-feelup'], function () {
153
+ // Compile POs to MOs.
154
+ return gulp.src(languagesFolder + '*.po')
155
+ .pipe(gettext())
156
+ .pipe(gulp.dest(languagesFolder))
157
+ });
158
+
159
+ gulp.task('default', [], function () {
160
+ gulp.run('prepare-source');
161
+ gulp.run('update-transifex');
162
+ gulp.run('download-translations');
163
+ gulp.run('prepare-translations');
164
+ gulp.run('translations-feelup');
165
+ gulp.run('cleanup');
166
+ gulp.run('compile-translations');
167
  });
freemius/includes/class-fs-logger.php CHANGED
@@ -1,688 +1,688 @@
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 ) && isset( $api_result->error ) ) {
224
- $message = $api_result->error->message;
225
- } else if ( is_object( $api_result ) ) {
226
- $message = var_export( $api_result, true );
227
- } else if ( is_string( $api_result ) ) {
228
- $message = $api_result;
229
- } else if ( empty( $api_result ) ) {
230
- $message = 'Empty API result.';
231
- }
232
-
233
- $message = 'API Error: ' . $message;
234
-
235
- $this->_log( $message, 'error', $wrapper );
236
- }
237
-
238
- function entrance( $message = '', $wrapper = false ) {
239
- $msg = 'Entrance' . ( empty( $message ) ? '' : ' > ' ) . $message;
240
-
241
- $this->_log( $msg, 'log', $wrapper );
242
- }
243
-
244
- function departure( $message = '', $wrapper = false ) {
245
- $msg = 'Departure' . ( empty( $message ) ? '' : ' > ' ) . $message;
246
-
247
- $this->_log( $msg, 'log', $wrapper );
248
- }
249
-
250
- #--------------------------------------------------------------------------------
251
- #region Log Formatting
252
- #--------------------------------------------------------------------------------
253
-
254
- private static function format( $log, $show_type = true ) {
255
- 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'] . ']';
256
- }
257
-
258
- private static function format_html( $log ) {
259
- 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>';
260
- }
261
-
262
- #endregion
263
-
264
- static function dump() {
265
- ?>
266
- <!-- BEGIN: Freemius PHP Console Log -->
267
- <script type="text/javascript">
268
- <?php
269
- foreach ( self::$LOG as $log ) {
270
- echo 'console.' . $log['log_type'] . '(' . json_encode( self::format( $log, false ) ) . ')' . "\n";
271
- }
272
- ?>
273
- </script>
274
- <!-- END: Freemius PHP Console Log -->
275
- <?php
276
- }
277
-
278
- static function get_log() {
279
- return self::$LOG;
280
- }
281
-
282
- #--------------------------------------------------------------------------------
283
- #region Database Logging
284
- #--------------------------------------------------------------------------------
285
-
286
- /**
287
- * @author Vova Feldman (@svovaf)
288
- * @since 1.2.1.6
289
- *
290
- * @return bool
291
- */
292
- public static function is_storage_logging_on() {
293
- if ( ! isset( self::$_isStorageLoggingOn ) ) {
294
- self::$_isStorageLoggingOn = ( 1 == get_option( 'fs_storage_logger', 0 ) );
295
- }
296
-
297
- return self::$_isStorageLoggingOn;
298
- }
299
-
300
- /**
301
- * Turns on/off database persistent debugging to capture
302
- * multi-session logs to debug complex flows like
303
- * plugin auto-deactivate on premium version activation.
304
- *
305
- * @todo Check if Theme Check has issues with DB tables for themes.
306
- *
307
- * @author Vova Feldman (@svovaf)
308
- * @since 1.2.1.6
309
- *
310
- * @param bool $is_on
311
- *
312
- * @return bool
313
- */
314
- public static function _set_storage_logging( $is_on = true ) {
315
- global $wpdb;
316
-
317
- $table = "{$wpdb->prefix}fs_logger";
318
-
319
- if ( $is_on ) {
320
- /**
321
- * Create logging table.
322
- *
323
- * NOTE:
324
- * dbDelta must use KEY and not INDEX for indexes.
325
- *
326
- * @link https://core.trac.wordpress.org/ticket/2695
327
- */
328
- $result = $wpdb->query( "CREATE TABLE {$table} (
329
- `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
330
- `process_id` INT UNSIGNED NOT NULL,
331
- `user_name` VARCHAR(64) NOT NULL,
332
- `logger` VARCHAR(128) NOT NULL,
333
- `log_order` INT UNSIGNED NOT NULL,
334
- `type` ENUM('log','info','warn','error') NOT NULL DEFAULT 'log',
335
- `message` TEXT NOT NULL,
336
- `file` VARCHAR(256) NOT NULL,
337
- `line` INT UNSIGNED NOT NULL,
338
- `function` VARCHAR(256) NOT NULL,
339
- `request_type` ENUM('call','ajax','cron') NOT NULL DEFAULT 'call',
340
- `request_url` VARCHAR(1024) NOT NULL,
341
- `created` DECIMAL(16, 6) NOT NULL,
342
- PRIMARY KEY (`id`),
343
- KEY `process_id` (`process_id` ASC),
344
- KEY `process_logger` (`process_id` ASC, `logger` ASC),
345
- KEY `function` (`function` ASC),
346
- KEY `type` (`type` ASC))" );
347
- } else {
348
- /**
349
- * Drop logging table.
350
- */
351
- $result = $wpdb->query( "DROP TABLE IF EXISTS $table;" );
352
- }
353
-
354
- if ( false !== $result ) {
355
- update_option( 'fs_storage_logger', ( $is_on ? 1 : 0 ) );
356
- }
357
-
358
- return ( false !== $result );
359
- }
360
-
361
- /**
362
- * @author Vova Feldman (@svovaf)
363
- * @since 1.2.1.6
364
- *
365
- * @param string $type
366
- * @param string $message
367
- * @param int $log_order
368
- * @param array $caller
369
- *
370
- * @return false|int
371
- */
372
- private function db_log(
373
- &$type,
374
- &$message,
375
- &$log_order,
376
- &$caller
377
- ) {
378
- global $wpdb;
379
-
380
- $request_type = 'call';
381
- if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
382
- $request_type = 'cron';
383
- } else if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
384
- $request_type = 'ajax';
385
- }
386
-
387
- $request_url = WP_FS__IS_HTTP_REQUEST ?
388
- $_SERVER['REQUEST_URI'] :
389
- '';
390
-
391
- return $wpdb->insert(
392
- "{$wpdb->prefix}fs_logger",
393
- array(
394
- 'process_id' => self::$_processID,
395
- 'user_name' => self::$_ownerName,
396
- 'logger' => $this->_id,
397
- 'log_order' => $log_order,
398
- 'type' => $type,
399
- 'request_type' => $request_type,
400
- 'request_url' => $request_url,
401
- 'message' => $message,
402
- 'file' => isset( $caller['file'] ) ?
403
- substr( $caller['file'], self::$_abspathLength ) :
404
- '',
405
- 'line' => $caller['line'],
406
- 'function' => ( ! empty( $caller['class'] ) ? $caller['class'] . $caller['type'] : '' ) . $caller['function'],
407
- 'created' => microtime( true ),
408
- )
409
- );
410
- }
411
-
412
- /**
413
- * Persistent DB logger columns.
414
- *
415
- * @var array
416
- */
417
- private static $_log_columns = array(
418
- 'id',
419
- 'process_id',
420
- 'user_name',
421
- 'logger',
422
- 'log_order',
423
- 'type',
424
- 'message',
425
- 'file',
426
- 'line',
427
- 'function',
428
- 'request_type',
429
- 'request_url',
430
- 'created',
431
- );
432
-
433
- /**
434
- * Create DB logs query.
435
- *
436
- * @author Vova Feldman (@svovaf)
437
- * @since 1.2.1.6
438
- *
439
- * @param bool $filters
440
- * @param int $limit
441
- * @param int $offset
442
- * @param bool $order
443
- * @param bool $escape_eol
444
- *
445
- * @return string
446
- */
447
- private static function build_db_logs_query(
448
- $filters = false,
449
- $limit = 200,
450
- $offset = 0,
451
- $order = false,
452
- $escape_eol = false
453
- ) {
454
- global $wpdb;
455
-
456
- $select = '*';
457
-
458
- if ( $escape_eol ) {
459
- $select = '';
460
- for ( $i = 0, $len = count( self::$_log_columns ); $i < $len; $i ++ ) {
461
- if ( $i > 0 ) {
462
- $select .= ', ';
463
- }
464
-
465
- if ( 'message' !== self::$_log_columns[ $i ] ) {
466
- $select .= self::$_log_columns[ $i ];
467
- } else {
468
- $select .= 'REPLACE(message , \'\n\', \' \') AS message';
469
- }
470
- }
471
- }
472
-
473
- $query = "SELECT {$select} FROM {$wpdb->prefix}fs_logger";
474
- if ( is_array( $filters ) ) {
475
- $criteria = array();
476
-
477
- if ( ! empty( $filters['type'] ) && 'all' !== $filters['type'] ) {
478
- $filters['type'] = strtolower( $filters['type'] );
479
-
480
- switch ( $filters['type'] ) {
481
- case 'warn_error':
482
- $criteria[] = array( 'col' => 'type', 'val' => array( 'warn', 'error' ) );
483
- break;
484
- case 'error':
485
- case 'warn':
486
- $criteria[] = array( 'col' => 'type', 'val' => $filters['type'] );
487
- break;
488
- case 'info':
489
- default:
490
- $criteria[] = array( 'col' => 'type', 'val' => array( 'info', 'log' ) );
491
- break;
492
- }
493
- }
494
-
495
- if ( ! empty( $filters['request_type'] ) ) {
496
- $filters['request_type'] = strtolower( $filters['request_type'] );
497
-
498
- if ( in_array( $filters['request_type'], array( 'call', 'ajax', 'cron' ) ) ) {
499
- $criteria[] = array( 'col' => 'request_type', 'val' => $filters['request_type'] );
500
- }
501
- }
502
-
503
- if ( ! empty( $filters['file'] ) ) {
504
- $criteria[] = array(
505
- 'col' => 'file',
506
- 'op' => 'LIKE',
507
- 'val' => '%' . esc_sql( $filters['file'] ),
508
- );
509
- }
510
-
511
- if ( ! empty( $filters['function'] ) ) {
512
- $criteria[] = array(
513
- 'col' => 'function',
514
- 'op' => 'LIKE',
515
- 'val' => '%' . esc_sql( $filters['function'] ),
516
- );
517
- }
518
-
519
- if ( ! empty( $filters['process_id'] ) && is_numeric( $filters['process_id'] ) ) {
520
- $criteria[] = array( 'col' => 'process_id', 'val' => $filters['process_id'] );
521
- }
522
-
523
- if ( ! empty( $filters['logger'] ) ) {
524
- $criteria[] = array(
525
- 'col' => 'logger',
526
- 'op' => 'LIKE',
527
- 'val' => '%' . esc_sql( $filters['logger'] ) . '%',
528
- );
529
- }
530
-
531
- if ( ! empty( $filters['message'] ) ) {
532
- $criteria[] = array(
533
- 'col' => 'message',
534
- 'op' => 'LIKE',
535
- 'val' => '%' . esc_sql( $filters['message'] ) . '%',
536
- );
537
- }
538
-
539
- if ( 0 < count( $criteria ) ) {
540
- $query .= "\nWHERE\n";
541
-
542
- $first = true;
543
- foreach ( $criteria as $c ) {
544
- if ( ! $first ) {
545
- $query .= "AND\n";
546
- }
547
-
548
- if ( is_array( $c['val'] ) ) {
549
- $operator = 'IN';
550
-
551
- for ( $i = 0, $len = count( $c['val'] ); $i < $len; $i ++ ) {
552
- $c['val'][ $i ] = "'" . esc_sql( $c['val'][ $i ] ) . "'";
553
- }
554
-
555
- $val = '(' . implode( ',', $c['val'] ) . ')';
556
- } else {
557
- $operator = ! empty( $c['op'] ) ? $c['op'] : '=';
558
- $val = "'" . esc_sql( $c['val'] ) . "'";
559
- }
560
-
561
- $query .= "`{$c['col']}` {$operator} {$val}\n";
562
-
563
- $first = false;
564
- }
565
- }
566
- }
567
-
568
- if ( ! is_array( $order ) ) {
569
- $order = array(
570
- 'col' => 'id',
571
- 'order' => 'desc'
572
- );
573
- }
574
-
575
- $query .= " ORDER BY {$order['col']} {$order['order']} LIMIT {$offset},{$limit}";
576
-
577
- return $query;
578
- }
579
-
580
- /**
581
- * Load logs from DB.
582
- *
583
- * @author Vova Feldman (@svovaf)
584
- * @since 1.2.1.6
585
- *
586
- * @param bool $filters
587
- * @param int $limit
588
- * @param int $offset
589
- * @param bool $order
590
- *
591
- * @return object[]|null
592
- */
593
- public static function load_db_logs(
594
- $filters = false,
595
- $limit = 200,
596
- $offset = 0,
597
- $order = false
598
- ) {
599
- global $wpdb;
600
-
601
- $query = self::build_db_logs_query(
602
- $filters,
603
- $limit,
604
- $offset,
605
- $order
606
- );
607
-
608
- return $wpdb->get_results( $query );
609
- }
610
-
611
- /**
612
- * Load logs from DB.
613
- *
614
- * @author Vova Feldman (@svovaf)
615
- * @since 1.2.1.6
616
- *
617
- * @param bool $filters
618
- * @param string $filename
619
- * @param int $limit
620
- * @param int $offset
621
- * @param bool $order
622
- *
623
- * @return false|string File download URL or false on failure.
624
- */
625
- public static function download_db_logs(
626
- $filters = false,
627
- $filename = '',
628
- $limit = 10000,
629
- $offset = 0,
630
- $order = false
631
- ) {
632
- global $wpdb;
633
-
634
- $query = self::build_db_logs_query(
635
- $filters,
636
- $limit,
637
- $offset,
638
- $order,
639
- true
640
- );
641
-
642
- $upload_dir = wp_upload_dir();
643
- if ( empty( $filename ) ) {
644
- $filename = 'fs-logs-' . date( 'Y-m-d_H-i-s', WP_FS__SCRIPT_START_TIME ) . '.csv';
645
- }
646
- $filepath = rtrim( $upload_dir['path'], '/' ) . "/{$filename}";
647
-
648
- $query .= " INTO OUTFILE '{$filepath}' FIELDS TERMINATED BY '\t' ESCAPED BY '\\\\' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\\n'";
649
-
650
- $columns = '';
651
- for ( $i = 0, $len = count( self::$_log_columns ); $i < $len; $i ++ ) {
652
- if ( $i > 0 ) {
653
- $columns .= ', ';
654
- }
655
-
656
- $columns .= "'" . self::$_log_columns[ $i ] . "'";
657
- }
658
-
659
- $query = "SELECT {$columns} UNION ALL " . $query;
660
-
661
- $result = $wpdb->query( $query );
662
-
663
- if ( false === $result ) {
664
- return false;
665
- }
666
-
667
- return rtrim( $upload_dir['url'], '/' ) . '/' . $filename;
668
- }
669
-
670
- /**
671
- * @author Vova Feldman (@svovaf)
672
- * @since 1.2.1.6
673
- *
674
- * @param string $filename
675
- *
676
- * @return string
677
- */
678
- public static function get_logs_download_url( $filename = '' ) {
679
- $upload_dir = wp_upload_dir();
680
- if ( empty( $filename ) ) {
681
- $filename = 'fs-logs-' . date( 'Y-m-d_H-i-s', WP_FS__SCRIPT_START_TIME ) . '.csv';
682
- }
683
-
684
- return rtrim( $upload_dir['url'], '/' ) . $filename;
685
- }
686
-
687
- #endregion
688
  }
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 ) && isset( $api_result->error ) ) {
224
+ $message = $api_result->error->message;
225
+ } else if ( is_object( $api_result ) ) {
226
+ $message = var_export( $api_result, true );
227
+ } else if ( is_string( $api_result ) ) {
228
+ $message = $api_result;
229
+ } else if ( empty( $api_result ) ) {
230
+ $message = 'Empty API result.';
231
+ }
232
+
233
+ $message = 'API Error: ' . $message;
234
+
235
+ $this->_log( $message, 'error', $wrapper );
236
+ }
237
+
238
+ function entrance( $message = '', $wrapper = false ) {
239
+ $msg = 'Entrance' . ( empty( $message ) ? '' : ' > ' ) . $message;
240
+
241
+ $this->_log( $msg, 'log', $wrapper );
242
+ }
243
+
244
+ function departure( $message = '', $wrapper = false ) {
245
+ $msg = 'Departure' . ( empty( $message ) ? '' : ' > ' ) . $message;
246
+
247
+ $this->_log( $msg, 'log', $wrapper );
248
+ }
249
+
250
+ #--------------------------------------------------------------------------------
251
+ #region Log Formatting
252
+ #--------------------------------------------------------------------------------
253
+
254
+ private static function format( $log, $show_type = true ) {
255
+ 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'] . ']';
256
+ }
257
+
258
+ private static function format_html( $log ) {
259
+ 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>';
260
+ }
261
+
262
+ #endregion
263
+
264
+ static function dump() {
265
+ ?>
266
+ <!-- BEGIN: Freemius PHP Console Log -->
267
+ <script type="text/javascript">
268
+ <?php
269
+ foreach ( self::$LOG as $log ) {
270
+ echo 'console.' . $log['log_type'] . '(' . json_encode( self::format( $log, false ) ) . ')' . "\n";
271
+ }
272
+ ?>
273
+ </script>
274
+ <!-- END: Freemius PHP Console Log -->
275
+ <?php
276
+ }
277
+
278
+ static function get_log() {
279
+ return self::$LOG;
280
+ }
281
+
282
+ #--------------------------------------------------------------------------------
283
+ #region Database Logging
284
+ #--------------------------------------------------------------------------------
285
+
286
+ /**
287
+ * @author Vova Feldman (@svovaf)
288
+ * @since 1.2.1.6
289
+ *
290
+ * @return bool
291
+ */
292
+ public static function is_storage_logging_on() {
293
+ if ( ! isset( self::$_isStorageLoggingOn ) ) {
294
+ self::$_isStorageLoggingOn = ( 1 == get_option( 'fs_storage_logger', 0 ) );
295
+ }
296
+
297
+ return self::$_isStorageLoggingOn;
298
+ }
299
+
300
+ /**
301
+ * Turns on/off database persistent debugging to capture
302
+ * multi-session logs to debug complex flows like
303
+ * plugin auto-deactivate on premium version activation.
304
+ *
305
+ * @todo Check if Theme Check has issues with DB tables for themes.
306
+ *
307
+ * @author Vova Feldman (@svovaf)
308
+ * @since 1.2.1.6
309
+ *
310
+ * @param bool $is_on
311
+ *
312
+ * @return bool
313
+ */
314
+ public static function _set_storage_logging( $is_on = true ) {
315
+ global $wpdb;
316
+
317
+ $table = "{$wpdb->prefix}fs_logger";
318
+
319
+ if ( $is_on ) {
320
+ /**
321
+ * Create logging table.
322
+ *
323
+ * NOTE:
324
+ * dbDelta must use KEY and not INDEX for indexes.
325
+ *
326
+ * @link https://core.trac.wordpress.org/ticket/2695
327
+ */
328
+ $result = $wpdb->query( "CREATE TABLE {$table} (
329
+ `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
330
+ `process_id` INT UNSIGNED NOT NULL,
331
+ `user_name` VARCHAR(64) NOT NULL,
332
+ `logger` VARCHAR(128) NOT NULL,
333
+ `log_order` INT UNSIGNED NOT NULL,
334
+ `type` ENUM('log','info','warn','error') NOT NULL DEFAULT 'log',
335
+ `message` TEXT NOT NULL,
336
+ `file` VARCHAR(256) NOT NULL,
337
+ `line` INT UNSIGNED NOT NULL,
338
+ `function` VARCHAR(256) NOT NULL,
339
+ `request_type` ENUM('call','ajax','cron') NOT NULL DEFAULT 'call',
340
+ `request_url` VARCHAR(1024) NOT NULL,
341
+ `created` DECIMAL(16, 6) NOT NULL,
342
+ PRIMARY KEY (`id`),
343
+ KEY `process_id` (`process_id` ASC),
344
+ KEY `process_logger` (`process_id` ASC, `logger` ASC),
345
+ KEY `function` (`function` ASC),
346
+ KEY `type` (`type` ASC))" );
347
+ } else {
348
+ /**
349
+ * Drop logging table.
350
+ */
351
+ $result = $wpdb->query( "DROP TABLE IF EXISTS $table;" );
352
+ }
353
+
354
+ if ( false !== $result ) {
355
+ update_option( 'fs_storage_logger', ( $is_on ? 1 : 0 ) );
356
+ }
357
+
358
+ return ( false !== $result );
359
+ }
360
+
361
+ /**
362
+ * @author Vova Feldman (@svovaf)
363
+ * @since 1.2.1.6
364
+ *
365
+ * @param string $type
366
+ * @param string $message
367
+ * @param int $log_order
368
+ * @param array $caller
369
+ *
370
+ * @return false|int
371
+ */
372
+ private function db_log(
373
+ &$type,
374
+ &$message,
375
+ &$log_order,
376
+ &$caller
377
+ ) {
378
+ global $wpdb;
379
+
380
+ $request_type = 'call';
381
+ if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
382
+ $request_type = 'cron';
383
+ } else if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
384
+ $request_type = 'ajax';
385
+ }
386
+
387
+ $request_url = WP_FS__IS_HTTP_REQUEST ?
388
+ $_SERVER['REQUEST_URI'] :
389
+ '';
390
+
391
+ return $wpdb->insert(
392
+ "{$wpdb->prefix}fs_logger",
393
+ array(
394
+ 'process_id' => self::$_processID,
395
+ 'user_name' => self::$_ownerName,
396
+ 'logger' => $this->_id,
397
+ 'log_order' => $log_order,
398
+ 'type' => $type,
399
+ 'request_type' => $request_type,
400
+ 'request_url' => $request_url,
401
+ 'message' => $message,
402
+ 'file' => isset( $caller['file'] ) ?
403
+ substr( $caller['file'], self::$_abspathLength ) :
404
+ '',
405
+ 'line' => $caller['line'],
406
+ 'function' => ( ! empty( $caller['class'] ) ? $caller['class'] . $caller['type'] : '' ) . $caller['function'],
407
+ 'created' => microtime( true ),
408
+ )
409
+ );
410
+ }
411
+
412
+ /**
413
+ * Persistent DB logger columns.
414
+ *
415
+ * @var array
416
+ */
417
+ private static $_log_columns = array(
418
+ 'id',
419
+ 'process_id',
420
+ 'user_name',
421
+ 'logger',
422
+ 'log_order',
423
+ 'type',
424
+ 'message',
425
+ 'file',
426
+ 'line',
427
+ 'function',
428
+ 'request_type',
429
+ 'request_url',
430
+ 'created',
431
+ );
432
+
433
+ /**
434
+ * Create DB logs query.
435
+ *
436
+ * @author Vova Feldman (@svovaf)
437
+ * @since 1.2.1.6
438
+ *
439
+ * @param bool $filters
440
+ * @param int $limit
441
+ * @param int $offset
442
+ * @param bool $order
443
+ * @param bool $escape_eol
444
+ *
445
+ * @return string
446
+ */
447
+ private static function build_db_logs_query(
448
+ $filters = false,
449
+ $limit = 200,
450
+ $offset = 0,
451
+ $order = false,
452
+ $escape_eol = false
453
+ ) {
454
+ global $wpdb;
455
+
456
+ $select = '*';
457
+
458
+ if ( $escape_eol ) {
459
+ $select = '';
460
+ for ( $i = 0, $len = count( self::$_log_columns ); $i < $len; $i ++ ) {
461
+ if ( $i > 0 ) {
462
+ $select .= ', ';
463
+ }
464
+
465
+ if ( 'message' !== self::$_log_columns[ $i ] ) {
466
+ $select .= self::$_log_columns[ $i ];
467
+ } else {
468
+ $select .= 'REPLACE(message , \'\n\', \' \') AS message';
469
+ }
470
+ }
471
+ }
472
+
473
+ $query = "SELECT {$select} FROM {$wpdb->prefix}fs_logger";
474
+ if ( is_array( $filters ) ) {
475
+ $criteria = array();
476
+
477
+ if ( ! empty( $filters['type'] ) && 'all' !== $filters['type'] ) {
478
+ $filters['type'] = strtolower( $filters['type'] );
479
+
480
+ switch ( $filters['type'] ) {
481
+ case 'warn_error':
482
+ $criteria[] = array( 'col' => 'type', 'val' => array( 'warn', 'error' ) );
483
+ break;
484
+ case 'error':
485
+ case 'warn':
486
+ $criteria[] = array( 'col' => 'type', 'val' => $filters['type'] );
487
+ break;
488
+ case 'info':
489
+ default:
490
+ $criteria[] = array( 'col' => 'type', 'val' => array( 'info', 'log' ) );
491
+ break;
492
+ }
493
+ }
494
+
495
+ if ( ! empty( $filters['request_type'] ) ) {
496
+ $filters['request_type'] = strtolower( $filters['request_type'] );
497
+
498
+ if ( in_array( $filters['request_type'], array( 'call', 'ajax', 'cron' ) ) ) {
499
+ $criteria[] = array( 'col' => 'request_type', 'val' => $filters['request_type'] );
500
+ }
501
+ }
502
+
503
+ if ( ! empty( $filters['file'] ) ) {
504
+ $criteria[] = array(
505
+ 'col' => 'file',
506
+ 'op' => 'LIKE',
507
+ 'val' => '%' . esc_sql( $filters['file'] ),
508
+ );
509
+ }
510
+
511
+ if ( ! empty( $filters['function'] ) ) {
512
+ $criteria[] = array(
513
+ 'col' => 'function',
514
+ 'op' => 'LIKE',
515
+ 'val' => '%' . esc_sql( $filters['function'] ),
516
+ );
517
+ }
518
+
519
+ if ( ! empty( $filters['process_id'] ) && is_numeric( $filters['process_id'] ) ) {
520
+ $criteria[] = array( 'col' => 'process_id', 'val' => $filters['process_id'] );
521
+ }
522
+
523
+ if ( ! empty( $filters['logger'] ) ) {
524
+ $criteria[] = array(
525
+ 'col' => 'logger',
526
+ 'op' => 'LIKE',
527
+ 'val' => '%' . esc_sql( $filters['logger'] ) . '%',
528
+ );
529
+ }
530
+
531
+ if ( ! empty( $filters['message'] ) ) {
532
+ $criteria[] = array(
533
+ 'col' => 'message',
534
+ 'op' => 'LIKE',
535
+ 'val' => '%' . esc_sql( $filters['message'] ) . '%',
536
+ );
537
+ }
538
+
539
+ if ( 0 < count( $criteria ) ) {
540
+ $query .= "\nWHERE\n";
541
+
542
+ $first = true;
543
+ foreach ( $criteria as $c ) {
544
+ if ( ! $first ) {
545
+ $query .= "AND\n";
546
+ }
547
+
548
+ if ( is_array( $c['val'] ) ) {
549
+ $operator = 'IN';
550
+
551
+ for ( $i = 0, $len = count( $c['val'] ); $i < $len; $i ++ ) {
552
+ $c['val'][ $i ] = "'" . esc_sql( $c['val'][ $i ] ) . "'";
553
+ }
554
+
555
+ $val = '(' . implode( ',', $c['val'] ) . ')';
556
+ } else {
557
+ $operator = ! empty( $c['op'] ) ? $c['op'] : '=';
558
+ $val = "'" . esc_sql( $c['val'] ) . "'";
559
+ }
560
+
561
+ $query .= "`{$c['col']}` {$operator} {$val}\n";
562
+
563
+ $first = false;
564
+ }
565
+ }
566
+ }
567
+
568
+ if ( ! is_array( $order ) ) {
569
+ $order = array(
570
+ 'col' => 'id',
571
+ 'order' => 'desc'
572
+ );
573
+ }
574
+
575
+ $query .= " ORDER BY {$order['col']} {$order['order']} LIMIT {$offset},{$limit}";
576
+
577
+ return $query;
578
+ }
579
+
580
+ /**
581
+ * Load logs from DB.
582
+ *
583
+ * @author Vova Feldman (@svovaf)
584
+ * @since 1.2.1.6
585
+ *
586
+ * @param bool $filters
587
+ * @param int $limit
588
+ * @param int $offset
589
+ * @param bool $order
590
+ *
591
+ * @return object[]|null
592
+ */
593
+ public static function load_db_logs(
594
+ $filters = false,
595
+ $limit = 200,
596
+ $offset = 0,
597
+ $order = false
598
+ ) {
599
+ global $wpdb;
600
+
601
+ $query = self::build_db_logs_query(
602
+ $filters,
603
+ $limit,
604
+ $offset,
605
+ $order
606
+ );
607
+
608
+ return $wpdb->get_results( $query );
609
+ }
610
+
611
+ /**
612
+ * Load logs from DB.
613
+ *
614
+ * @author Vova Feldman (@svovaf)
615
+ * @since 1.2.1.6
616
+ *
617
+ * @param bool $filters
618
+ * @param string $filename
619
+ * @param int $limit
620
+ * @param int $offset
621
+ * @param bool $order
622
+ *
623
+ * @return false|string File download URL or false on failure.
624
+ */
625
+ public static function download_db_logs(
626
+ $filters = false,
627
+ $filename = '',
628
+ $limit = 10000,
629
+ $offset = 0,
630
+ $order = false
631
+ ) {
632
+ global $wpdb;
633
+
634
+ $query = self::build_db_logs_query(
635
+ $filters,
636
+ $limit,
637
+ $offset,
638
+ $order,
639
+ true
640
+ );
641
+
642
+ $upload_dir = wp_upload_dir();
643
+ if ( empty( $filename ) ) {
644
+ $filename = 'fs-logs-' . date( 'Y-m-d_H-i-s', WP_FS__SCRIPT_START_TIME ) . '.csv';
645
+ }
646
+ $filepath = rtrim( $upload_dir['path'], '/' ) . "/{$filename}";
647
+
648
+ $query .= " INTO OUTFILE '{$filepath}' FIELDS TERMINATED BY '\t' ESCAPED BY '\\\\' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\\n'";
649
+
650
+ $columns = '';
651
+ for ( $i = 0, $len = count( self::$_log_columns ); $i < $len; $i ++ ) {
652
+ if ( $i > 0 ) {
653
+ $columns .= ', ';
654
+ }
655
+
656
+ $columns .= "'" . self::$_log_columns[ $i ] . "'";
657
+ }
658
+
659
+ $query = "SELECT {$columns} UNION ALL " . $query;
660
+
661
+ $result = $wpdb->query( $query );
662
+
663
+ if ( false === $result ) {
664
+ return false;
665
+ }
666
+
667
+ return rtrim( $upload_dir['url'], '/' ) . '/' . $filename;
668
+ }
669
+
670
+ /**
671
+ * @author Vova Feldman (@svovaf)
672
+ * @since 1.2.1.6
673
+ *
674
+ * @param string $filename
675
+ *
676
+ * @return string
677
+ */
678
+ public static function get_logs_download_url( $filename = '' ) {
679
+ $upload_dir = wp_upload_dir();
680
+ if ( empty( $filename ) ) {
681
+ $filename = 'fs-logs-' . date( 'Y-m-d_H-i-s', WP_FS__SCRIPT_START_TIME ) . '.csv';
682
+ }
683
+
684
+ return rtrim( $upload_dir['url'], '/' ) . $filename;
685
+ }
686
+
687
+ #endregion
688
  }
freemius/includes/customizer/class-fs-customizer-support-section.php CHANGED
@@ -1,102 +1,102 @@
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.2.7
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * Class Zerif_Customizer_Theme_Info_Main
15
- *
16
- * @since 1.0.0
17
- * @access public
18
- */
19
- class FS_Customizer_Support_Section extends WP_Customize_Section {
20
-
21
- function __construct( $manager, $id, $args = array() ) {
22
- $manager->register_section_type( 'FS_Customizer_Support_Section' );
23
-
24
- parent::__construct( $manager, $id, $args );
25
- }
26
-
27
- /**
28
- * The type of customize section being rendered.
29
- *
30
- * @since 1.0.0
31
- * @access public
32
- * @var string
33
- */
34
- public $type = 'freemius-support-section';
35
-
36
- /**
37
- * @var Freemius
38
- */
39
- public $fs = null;
40
-
41
- /**
42
- * Add custom parameters to pass to the JS via JSON.
43
- *
44
- * @since 1.0.0
45
- */
46
- public function json() {
47
- $json = parent::json();
48
-
49
- $is_contact_visible = $this->fs->is_page_visible( 'contact' );
50
- $is_support_visible = $this->fs->is_page_visible( 'support' );
51
-
52
- $json['theme_title'] = $this->fs->get_plugin_name();
53
-
54
- if ( $is_contact_visible && $is_support_visible ) {
55
- $json['theme_title'] .= ' ' . $this->fs->get_text_inline( 'Support', 'support' );
56
- }
57
-
58
- if ( $is_contact_visible ) {
59
- $json['contact'] = array(
60
- 'label' => $this->fs->get_text_inline( 'Contact Us', 'contact-us' ),
61
- 'url' => $this->fs->contact_url(),
62
- );
63
- }
64
-
65
- if ( $is_support_visible ) {
66
- $json['support'] = array(
67
- 'label' => $this->fs->get_text_inline( 'Support Forum', 'support-forum' ),
68
- 'url' => $this->fs->get_support_forum_url()
69
- );
70
- }
71
-
72
- return $json;
73
- }
74
-
75
- /**
76
- * Outputs the Underscore.js template.
77
- *
78
- * @since 1.0.0
79
- */
80
- protected function render_template() {
81
- ?>
82
- <li id="fs_customizer_support"
83
- class="accordion-section control-section control-section-{{ data.type }} cannot-expand">
84
- <h3 class="accordion-section-title">
85
- <span>{{ data.theme_title }}</span>
86
- <# if ( data.contact && data.support ) { #>
87
- <div class="button-group">
88
- <# } #>
89
- <# if ( data.contact ) { #>
90
- <a class="button" href="{{ data.contact.url }}" target="_blank">{{ data.contact.label }} </a>
91
- <# } #>
92
- <# if ( data.support ) { #>
93
- <a class="button" href="{{ data.support.url }}" target="_blank">{{ data.support.label }} </a>
94
- <# } #>
95
- <# if ( data.contact && data.support ) { #>
96
- </div>
97
- <# } #>
98
- </h3>
99
- </li>
100
- <?php
101
- }
102
  }
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.2.7
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * Class Zerif_Customizer_Theme_Info_Main
15
+ *
16
+ * @since 1.0.0
17
+ * @access public
18
+ */
19
+ class FS_Customizer_Support_Section extends WP_Customize_Section {
20
+
21
+ function __construct( $manager, $id, $args = array() ) {
22
+ $manager->register_section_type( 'FS_Customizer_Support_Section' );
23
+
24
+ parent::__construct( $manager, $id, $args );
25
+ }
26
+
27
+ /**
28
+ * The type of customize section being rendered.
29
+ *
30
+ * @since 1.0.0
31
+ * @access public
32
+ * @var string
33
+ */
34
+ public $type = 'freemius-support-section';
35
+
36
+ /**
37
+ * @var Freemius
38
+ */
39
+ public $fs = null;
40
+
41
+ /**
42
+ * Add custom parameters to pass to the JS via JSON.
43
+ *
44
+ * @since 1.0.0
45
+ */
46
+ public function json() {
47
+ $json = parent::json();
48
+
49
+ $is_contact_visible = $this->fs->is_page_visible( 'contact' );
50
+ $is_support_visible = $this->fs->is_page_visible( 'support' );
51
+
52
+ $json['theme_title'] = $this->fs->get_plugin_name();
53
+
54
+ if ( $is_contact_visible && $is_support_visible ) {
55
+ $json['theme_title'] .= ' ' . $this->fs->get_text_inline( 'Support', 'support' );
56
+ }
57
+
58
+ if ( $is_contact_visible ) {
59
+ $json['contact'] = array(
60
+ 'label' => $this->fs->get_text_inline( 'Contact Us', 'contact-us' ),
61
+ 'url' => $this->fs->contact_url(),
62
+ );
63
+ }
64
+
65
+ if ( $is_support_visible ) {
66
+ $json['support'] = array(
67
+ 'label' => $this->fs->get_text_inline( 'Support Forum', 'support-forum' ),
68
+ 'url' => $this->fs->get_support_forum_url()
69
+ );
70
+ }
71
+
72
+ return $json;
73
+ }
74
+
75
+ /**
76
+ * Outputs the Underscore.js template.
77
+ *
78
+ * @since 1.0.0
79
+ */
80
+ protected function render_template() {
81
+ ?>
82
+ <li id="fs_customizer_support"
83
+ class="accordion-section control-section control-section-{{ data.type }} cannot-expand">
84
+ <h3 class="accordion-section-title">
85
+ <span>{{ data.theme_title }}</span>
86
+ <# if ( data.contact && data.support ) { #>
87
+ <div class="button-group">
88
+ <# } #>
89
+ <# if ( data.contact ) { #>
90
+ <a class="button" href="{{ data.contact.url }}" target="_blank">{{ data.contact.label }} </a>
91
+ <# } #>
92
+ <# if ( data.support ) { #>
93
+ <a class="button" href="{{ data.support.url }}" target="_blank">{{ data.support.label }} </a>
94
+ <# } #>
95
+ <# if ( data.contact && data.support ) { #>
96
+ </div>
97
+ <# } #>
98
+ </h3>
99
+ </li>
100
+ <?php
101
+ }
102
  }
freemius/includes/customizer/class-fs-customizer-upsell-control.php CHANGED
@@ -1,157 +1,157 @@
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.2.7
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * Class FS_Customizer_Upsell_Control
15
- */
16
- class FS_Customizer_Upsell_Control extends WP_Customize_Control {
17
-
18
- /**
19
- * Control type
20
- *
21
- * @var string control type
22
- */
23
- public $type = 'freemius-upsell-control';
24
-
25
- /**
26
- * @var Freemius
27
- */
28
- public $fs = null;
29
-
30
- /**
31
- * @param WP_Customize_Manager $manager the customize manager class.
32
- * @param string $id id.
33
- * @param array $args customizer manager parameters.
34
- */
35
- public function __construct( WP_Customize_Manager $manager, $id, array $args ) {
36
- $manager->register_control_type( 'FS_Customizer_Upsell_Control' );
37
-
38
- parent::__construct( $manager, $id, $args );
39
- }
40
-
41
- /**
42
- * Enqueue resources for the control.
43
- */
44
- public function enqueue() {
45
- fs_enqueue_local_style( 'fs_customizer', 'customizer.css' );
46
- }
47
-
48
- /**
49
- * Json conversion
50
- */
51
- public function to_json() {
52
- $pricing_cta = esc_html( $this->fs->get_pricing_cta_label() ) . '&nbsp;&nbsp;' . ( is_rtl() ? '&#x2190;' : '&#x27a4;' );
53
-
54
- parent::to_json();
55
-
56
- $this->json['button_text'] = $pricing_cta;
57
- $this->json['button_url'] = $this->fs->is_in_trial_promotion() ?
58
- $this->fs->get_trial_url() :
59
- $this->fs->get_upgrade_url();
60
-
61
- // Load features.
62
- $pricing = $this->fs->get_api_plugin_scope()->get( 'pricing.json' );
63
-
64
- if ( $this->fs->is_api_result_object( $pricing, 'plans' ) ) {
65
- // Add support features.
66
- if ( is_array( $pricing->plans ) && 0 < count( $pricing->plans ) ) {
67
- $support_features = array(
68
- 'kb' => 'Help Center',
69
- 'forum' => 'Support Forum',
70
- 'email' => 'Priority Email Support',
71
- 'phone' => 'Phone Support',
72
- 'skype' => 'Skype Support',
73
- 'is_success_manager' => 'Personal Success Manager',
74
- );
75
-
76
- for ( $i = 0, $len = count( $pricing->plans ); $i < $len; $i ++ ) {
77
- if ( 'free' == $pricing->plans[$i]->name ) {
78
- continue;
79
- }
80
-
81
- if ( ! isset( $pricing->plans[ $i ]->features ) ||
82
- ! is_array( $pricing->plans[ $i ]->features ) ) {
83
- $pricing->plans[$i]->features = array();
84
- }
85
-
86
- foreach ( $support_features as $key => $label ) {
87
- $key = ( 'is_success_manager' !== $key ) ?
88
- "support_{$key}" :
89
- $key;
90
-
91
- if ( ! empty( $pricing->plans[ $i ]->{$key} ) ) {
92
-
93
- $support_feature = new stdClass();
94
- $support_feature->title = $label;
95
-
96
- $pricing->plans[ $i ]->features[] = $support_feature;
97
- }
98
- }
99
- }
100
- }
101
- }
102
-
103
- $this->json['plans'] = $pricing->plans;
104
-
105
- $this->json['strings'] = array(
106
- 'plan' => $this->fs->get_text_x_inline( 'Plan', 'as product pricing plan', 'plan' ),
107
- );
108
- }
109
-
110
- /**
111
- * Control content
112
- */
113
- public function content_template() {
114
- ?>
115
- <div id="fs_customizer_upsell">
116
- <# if ( data.plans ) { #>
117
- <ul class="fs-customizer-plans">
118
- <# for (i in data.plans) { #>
119
- <# if ( 'free' != data.plans[i].name && (null != data.plans[i].features && 0 < data.plans[i].features.length) ) { #>
120
- <li class="fs-customizer-plan">
121
- <div class="fs-accordion-section-open">
122
- <h2 class="fs-accordion-section-title menu-item">
123
- <span>{{ data.plans[i].title }}</span>
124
- <button type="button" class="button-link item-edit" aria-expanded="true">
125
- <span class="screen-reader-text">Toggle section: {{ data.plans[i].title }} {{ data.strings.plan }}</span>
126
- <span class="toggle-indicator" aria-hidden="true"></span>
127
- </button>
128
- </h2>
129
- <div class="fs-accordion-section-content">
130
- <# if ( data.plans[i].description ) { #>
131
- <h3>{{ data.plans[i].description }}</h3>
132
- <# } #>
133
- <# if ( data.plans[i].features ) { #>
134
- <ul>
135
- <# for ( j in data.plans[i].features ) { #>
136
- <li><div class="fs-feature">
137
- <span class="dashicons dashicons-yes"></span><span><# if ( data.plans[i].features[j].value ) { #>{{ data.plans[i].features[j].value }} <# } #>{{ data.plans[i].features[j].title }}</span>
138
- <# if ( data.plans[i].features[j].description ) { #>
139
- <span class="dashicons dashicons-editor-help"><span class="fs-feature-desc">{{ data.plans[i].features[j].description }}</span></span>
140
- <# } #>
141
- </div></li>
142
- <# } #>
143
- </ul>
144
- <# } #>
145
- <# if ( 'free' != data.plans[i].name ) { #>
146
- <a href="{{ data.button_url }}" class="button button-primary" target="_blank">{{{ data.button_text }}}</a>
147
- <# } #>
148
- </div>
149
- </div>
150
- </li>
151
- <# } #>
152
- <# } #>
153
- </ul>
154
- <# } #>
155
- </div>
156
- <?php }
157
  }
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.2.7
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * Class FS_Customizer_Upsell_Control
15
+ */
16
+ class FS_Customizer_Upsell_Control extends WP_Customize_Control {
17
+
18
+ /**
19
+ * Control type
20
+ *
21
+ * @var string control type
22
+ */
23
+ public $type = 'freemius-upsell-control';
24
+
25
+ /**
26
+ * @var Freemius
27
+ */
28
+ public $fs = null;
29
+
30
+ /**
31
+ * @param WP_Customize_Manager $manager the customize manager class.
32
+ * @param string $id id.
33
+ * @param array $args customizer manager parameters.
34
+ */
35
+ public function __construct( WP_Customize_Manager $manager, $id, array $args ) {
36
+ $manager->register_control_type( 'FS_Customizer_Upsell_Control' );
37
+
38
+ parent::__construct( $manager, $id, $args );
39
+ }
40
+
41
+ /**
42
+ * Enqueue resources for the control.
43
+ */
44
+ public function enqueue() {
45
+ fs_enqueue_local_style( 'fs_customizer', 'customizer.css' );
46
+ }
47
+
48
+ /**
49
+ * Json conversion
50
+ */
51
+ public function to_json() {
52
+ $pricing_cta = esc_html( $this->fs->get_pricing_cta_label() ) . '&nbsp;&nbsp;' . ( is_rtl() ? '&#x2190;' : '&#x27a4;' );
53
+
54
+ parent::to_json();
55
+
56
+ $this->json['button_text'] = $pricing_cta;
57
+ $this->json['button_url'] = $this->fs->is_in_trial_promotion() ?
58
+ $this->fs->get_trial_url() :
59
+ $this->fs->get_upgrade_url();
60
+
61
+ // Load features.
62
+ $pricing = $this->fs->get_api_plugin_scope()->get( 'pricing.json' );
63
+
64
+ if ( $this->fs->is_api_result_object( $pricing, 'plans' ) ) {
65
+ // Add support features.
66
+ if ( is_array( $pricing->plans ) && 0 < count( $pricing->plans ) ) {
67
+ $support_features = array(
68
+ 'kb' => 'Help Center',
69
+ 'forum' => 'Support Forum',
70
+ 'email' => 'Priority Email Support',
71
+ 'phone' => 'Phone Support',
72
+ 'skype' => 'Skype Support',
73
+ 'is_success_manager' => 'Personal Success Manager',
74
+ );
75
+
76
+ for ( $i = 0, $len = count( $pricing->plans ); $i < $len; $i ++ ) {
77
+ if ( 'free' == $pricing->plans[$i]->name ) {
78
+ continue;
79
+ }
80
+
81
+ if ( ! isset( $pricing->plans[ $i ]->features ) ||
82
+ ! is_array( $pricing->plans[ $i ]->features ) ) {
83
+ $pricing->plans[$i]->features = array();
84
+ }
85
+
86
+ foreach ( $support_features as $key => $label ) {
87
+ $key = ( 'is_success_manager' !== $key ) ?
88
+ "support_{$key}" :
89
+ $key;
90
+
91
+ if ( ! empty( $pricing->plans[ $i ]->{$key} ) ) {
92
+
93
+ $support_feature = new stdClass();
94
+ $support_feature->title = $label;
95
+
96
+ $pricing->plans[ $i ]->features[] = $support_feature;
97
+ }
98
+ }
99
+ }
100
+ }
101
+ }
102
+
103
+ $this->json['plans'] = $pricing->plans;
104
+
105
+ $this->json['strings'] = array(
106
+ 'plan' => $this->fs->get_text_x_inline( 'Plan', 'as product pricing plan', 'plan' ),
107
+ );
108
+ }
109
+
110
+ /**
111
+ * Control content
112
+ */
113
+ public function content_template() {
114
+ ?>
115
+ <div id="fs_customizer_upsell">
116
+ <# if ( data.plans ) { #>
117
+ <ul class="fs-customizer-plans">
118
+ <# for (i in data.plans) { #>
119
+ <# if ( 'free' != data.plans[i].name && (null != data.plans[i].features && 0 < data.plans[i].features.length) ) { #>
120
+ <li class="fs-customizer-plan">
121
+ <div class="fs-accordion-section-open">
122
+ <h2 class="fs-accordion-section-title menu-item">
123
+ <span>{{ data.plans[i].title }}</span>
124
+ <button type="button" class="button-link item-edit" aria-expanded="true">
125
+ <span class="screen-reader-text">Toggle section: {{ data.plans[i].title }} {{ data.strings.plan }}</span>
126
+ <span class="toggle-indicator" aria-hidden="true"></span>
127
+ </button>
128
+ </h2>
129
+ <div class="fs-accordion-section-content">
130
+ <# if ( data.plans[i].description ) { #>
131
+ <h3>{{ data.plans[i].description }}</h3>
132
+ <# } #>
133
+ <# if ( data.plans[i].features ) { #>
134
+ <ul>
135
+ <# for ( j in data.plans[i].features ) { #>
136
+ <li><div class="fs-feature">
137
+ <span class="dashicons dashicons-yes"></span><span><# if ( data.plans[i].features[j].value ) { #>{{ data.plans[i].features[j].value }} <# } #>{{ data.plans[i].features[j].title }}</span>
138
+ <# if ( data.plans[i].features[j].description ) { #>
139
+ <span class="dashicons dashicons-editor-help"><span class="fs-feature-desc">{{ data.plans[i].features[j].description }}</span></span>
140
+ <# } #>
141
+ </div></li>
142
+ <# } #>
143
+ </ul>
144
+ <# } #>
145
+ <# if ( 'free' != data.plans[i].name ) { #>
146
+ <a href="{{ data.button_url }}" class="button button-primary" target="_blank">{{{ data.button_text }}}</a>
147
+ <# } #>
148
+ </div>
149
+ </div>
150
+ </li>
151
+ <# } #>
152
+ <# } #>
153
+ </ul>
154
+ <# } #>
155
+ </div>
156
+ <?php }
157
  }
freemius/includes/customizer/index.php CHANGED
@@ -1,3 +1,3 @@
1
- <?php
2
- // Silence is golden.
3
  // Hide file structure from users on unprotected servers.
1
+ <?php
2
+ // Silence is golden.
3
  // Hide file structure from users on unprotected servers.
freemius/includes/debug/class-fs-debug-bar-panel.php CHANGED
@@ -1,64 +1,64 @@
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.1.7.3
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * Extends Debug Bar plugin by adding a panel to show all Freemius API requests.
15
- *
16
- * @author Vova Feldman (@svovaf)
17
- * @since 1.1.7.3
18
- *
19
- * Class Freemius_Debug_Bar_Panel
20
- */
21
- class Freemius_Debug_Bar_Panel extends Debug_Bar_Panel {
22
- function init() {
23
- $this->title( 'Freemius' );
24
- }
25
-
26
- static function requests_count() {
27
- if ( class_exists( 'Freemius_Api_WordPress' ) ) {
28
- $logger = Freemius_Api_WordPress::GetLogger();
29
- } else {
30
- $logger = array();
31
- }
32
-
33
- return number_format( count( $logger ) );
34
- }
35
-
36
- static function total_time() {
37
- if ( class_exists( 'Freemius_Api_WordPress' ) ) {
38
- $logger = Freemius_Api_WordPress::GetLogger();
39
- } else {
40
- $logger = array();
41
- }
42
-
43
- $total_time = .0;
44
- foreach ( $logger as $l ) {
45
- $total_time += $l['total'];
46
- }
47
-
48
- return number_format( 100 * $total_time, 2 ) . ' ' . fs_text_x_inline( 'ms', 'milliseconds' );
49
- }
50
-
51
- function render() {
52
- ?>
53
- <div id='debug-bar-php'>
54
- <?php fs_require_template( '/debug/api-calls.php' ) ?>
55
- <br>
56
- <?php fs_require_template( '/debug/scheduled-crons.php' ) ?>
57
- <br>
58
- <?php fs_require_template( '/debug/plugins-themes-sync.php' ) ?>
59
- <br>
60
- <?php fs_require_template( '/debug/logger.php' ) ?>
61
- </div>
62
- <?php
63
- }
64
- }
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.1.7.3
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * Extends Debug Bar plugin by adding a panel to show all Freemius API requests.
15
+ *
16
+ * @author Vova Feldman (@svovaf)
17
+ * @since 1.1.7.3
18
+ *
19
+ * Class Freemius_Debug_Bar_Panel
20
+ */
21
+ class Freemius_Debug_Bar_Panel extends Debug_Bar_Panel {
22
+ function init() {
23
+ $this->title( 'Freemius' );
24
+ }
25
+
26
+ static function requests_count() {
27
+ if ( class_exists( 'Freemius_Api_WordPress' ) ) {
28
+ $logger = Freemius_Api_WordPress::GetLogger();
29
+ } else {
30
+ $logger = array();
31
+ }
32
+
33
+ return number_format( count( $logger ) );
34
+ }
35
+
36
+ static function total_time() {
37
+ if ( class_exists( 'Freemius_Api_WordPress' ) ) {
38
+ $logger = Freemius_Api_WordPress::GetLogger();
39
+ } else {
40
+ $logger = array();
41
+ }
42
+
43
+ $total_time = .0;
44
+ foreach ( $logger as $l ) {
45
+ $total_time += $l['total'];
46
+ }
47
+
48
+ return number_format( 100 * $total_time, 2 ) . ' ' . fs_text_x_inline( 'ms', 'milliseconds' );
49
+ }
50
+
51
+ function render() {
52
+ ?>
53
+ <div id='debug-bar-php'>
54
+ <?php fs_require_template( '/debug/api-calls.php' ) ?>
55
+ <br>
56
+ <?php fs_require_template( '/debug/scheduled-crons.php' ) ?>
57
+ <br>
58
+ <?php fs_require_template( '/debug/plugins-themes-sync.php' ) ?>
59
+ <br>
60
+ <?php fs_require_template( '/debug/logger.php' ) ?>
61
+ </div>
62
+ <?php
63
+ }
64
+ }
freemius/includes/debug/debug-bar-start.php CHANGED
@@ -1,52 +1,52 @@
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.1.7.3
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- if ( ! WP_FS__DEBUG_SDK ) {
14
- return;
15
- }
16
-
17
- /**
18
- * Initialize Freemius custom debug panels.
19
- *
20
- * @param array $panels Debug bar panels objects
21
- *
22
- * @return array Debug bar panels with your custom panels
23
- */
24
- function fs_custom_panels_init( $panels ) {
25
- if ( class_exists( 'Debug_Bar_Panel' ) ) {
26
- if ( FS_API__LOGGER_ON ) {
27
- require_once dirname( __FILE__ ) . '/class-fs-debug-bar-panel.php';
28
- $panels[] = new Freemius_Debug_Bar_Panel();
29
- }
30
- }
31
-
32
- return $panels;
33
- }
34
-
35
- function fs_custom_status_init( $statuses ) {
36
- if ( class_exists( 'Debug_Bar_Panel' ) ) {
37
- if ( FS_API__LOGGER_ON ) {
38
- require_once dirname( __FILE__ ) . '/class-fs-debug-bar-panel.php';
39
- $statuses[] = array(
40
- 'fs_api_requests',
41
- fs_text_inline( 'Freemius API' ),
42
- Freemius_Debug_Bar_Panel::requests_count() . ' ' . fs_text_inline( 'Requests' ) .
43
- ' (' . Freemius_Debug_Bar_Panel::total_time() . ')'
44
- );
45
- }
46
- }
47
-
48
- return $statuses;
49
- }
50
-
51
- add_filter( 'debug_bar_panels', 'fs_custom_panels_init' );
52
  add_filter( 'debug_bar_statuses', 'fs_custom_status_init' );
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.1.7.3
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ if ( ! WP_FS__DEBUG_SDK ) {
14
+ return;
15
+ }
16
+
17
+ /**
18
+ * Initialize Freemius custom debug panels.
19
+ *
20
+ * @param array $panels Debug bar panels objects
21
+ *
22
+ * @return array Debug bar panels with your custom panels
23
+ */
24
+ function fs_custom_panels_init( $panels ) {
25
+ if ( class_exists( 'Debug_Bar_Panel' ) ) {
26
+ if ( FS_API__LOGGER_ON ) {
27
+ require_once dirname( __FILE__ ) . '/class-fs-debug-bar-panel.php';
28
+ $panels[] = new Freemius_Debug_Bar_Panel();
29
+ }
30
+ }
31
+
32
+ return $panels;
33
+ }
34
+
35
+ function fs_custom_status_init( $statuses ) {
36
+ if ( class_exists( 'Debug_Bar_Panel' ) ) {
37
+ if ( FS_API__LOGGER_ON ) {
38
+ require_once dirname( __FILE__ ) . '/class-fs-debug-bar-panel.php';
39
+ $statuses[] = array(
40
+ 'fs_api_requests',
41
+ fs_text_inline( 'Freemius API' ),
42
+ Freemius_Debug_Bar_Panel::requests_count() . ' ' . fs_text_inline( 'Requests' ) .
43
+ ' (' . Freemius_Debug_Bar_Panel::total_time() . ')'
44
+ );
45
+ }
46
+ }
47
+
48
+ return $statuses;
49
+ }
50
+
51
+ add_filter( 'debug_bar_panels', 'fs_custom_panels_init' );
52
  add_filter( 'debug_bar_statuses', 'fs_custom_status_init' );
freemius/includes/entities/class-fs-plugin-license.php CHANGED
@@ -1,224 +1,224 @@
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.5
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * Class FS_Plugin_License
15
- */
16
- class FS_Plugin_License extends FS_Entity {
17
-
18
- #region Properties
19
-
20
- /**
21
- * @var number
22
- */
23
- public $plugin_id;
24
- /**
25
- * @var number
26
- */
27
- public $user_id;
28
- /**
29
- * @var number
30
- */
31
- public $plan_id;
32
- /**
33
- * @var number
34
- */
35
- public $pricing_id;
36
- /**
37
- * @var int|null
38
- */
39
- public $quota;
40
- /**
41
- * @var int
42
- */
43
- public $activated;
44
- /**
45
- * @var int
46
- */
47
- public $activated_local;
48
- /**
49
- * @var string
50
- */
51
- public $expiration;
52
- /**
53
- * @var string
54
- */
55
- public $secret_key;
56
- /**
57
- * @var bool $is_free_localhost Defaults to true. If true, allow unlimited localhost installs with the same
58
- * license.
59
- */
60
- public $is_free_localhost;
61
- /**
62
- * @var bool $is_block_features Defaults to true. If false, don't block features after license expiry - only
63
- * block updates and support.
64
- */
65
- public $is_block_features;
66
- /**
67
- * @var bool
68
- */
69
- public $is_cancelled;
70
-
71
- #endregion Properties
72
-
73
- /**
74
- * @param stdClass|bool $license
75
- */
76
- function __construct( $license = false ) {
77
- parent::__construct( $license );
78
- }
79
-
80
- /**
81
- * Get entity type.
82
- *
83
- * @return string
84
- */
85
- static function get_type() {
86
- return 'license';
87
- }
88
-
89
- /**
90
- * Check how many site activations left.
91
- *
92
- * @author Vova Feldman (@svovaf)
93
- * @since 1.0.5
94
- *
95
- * @return int
96
- */
97
- function left() {
98
- if ( ! $this->is_active() || $this->is_expired() ) {
99
- return 0;
100
- }
101
-
102
- if ( $this->is_unlimited() ) {
103
- return 999;
104
- }
105
-
106
- return ( $this->quota - $this->activated - ( $this->is_free_localhost ? 0 : $this->activated_local ) );
107
- }
108
-
109
- /**
110
- * Check if single site license.
111
- *
112
- * @author Vova Feldman (@svovaf)
113
- * @since 1.1.8.1
114
- *
115
- * @return bool
116
- */
117
- function is_single_site() {
118
- return ( is_numeric( $this->quota ) && 1 == $this->quota );
119
- }
120
-
121
- /**
122
- * @author Vova Feldman (@svovaf)
123
- * @since 1.0.5
124
- *
125
- * @return bool
126
- */
127
- function is_expired() {
128
- return ! $this->is_lifetime() && ( strtotime( $this->expiration ) < WP_FS__SCRIPT_START_TIME );
129
- }
130
-
131
- /**
132
- * Check if license is not expired.
133
- *
134
- * @author Vova Feldman (@svovaf)
135
- * @since 1.2.1
136
- *
137
- * @return bool
138
- */
139
- function is_valid() {
140
- return ! $this->is_expired();
141
- }
142
-
143
- /**
144
- * @author Vova Feldman (@svovaf)
145
- * @since 1.0.6
146
- *
147
- * @return bool
148
- */
149
- function is_lifetime() {
150
- return is_null( $this->expiration );
151
- }
152
-
153
- /**
154
- * @author Vova Feldman (@svovaf)
155
- * @since 1.2.0
156
- *
157
- * @return bool
158
- */
159
- function is_unlimited() {
160
- return is_null( $this->quota );
161
- }
162
-
163
- /**
164
- * Check if license is fully utilized.
165
- *
166
- * @author Vova Feldman (@svovaf)
167
- * @since 1.0.6
168
- *
169
- * @param bool $is_localhost
170
- *
171
- * @return bool
172
- */
173
- function is_utilized( $is_localhost = null ) {
174
- if ( is_null( $is_localhost ) ) {
175
- $is_localhost = WP_FS__IS_LOCALHOST_FOR_SERVER;
176
- }
177
-
178
- if ( $this->is_unlimited() ) {
179
- return false;
180
- }
181
-
182
- return ! ( $this->is_free_localhost && $is_localhost ) &&
183
- ( $this->quota <= $this->activated + ( $this->is_free_localhost ? 0 : $this->activated_local ) );
184
- }
185
-
186
- /**
187
- * @author Vova Feldman (@svovaf)
188
- * @since 1.2.1
189
- *
190
- * @return bool
191
- */
192
- function is_active() {
193
- return ( ! $this->is_cancelled );
194
- }
195
-
196
- /**
197
- * Check if license's plan features are enabled.
198
- *
199
- * - Either if plan not expired
200
- * - If expired, based on the configuration to block features or not.
201
- *
202
- * @author Vova Feldman (@svovaf)
203
- * @since 1.0.6
204
- *
205
- * @return bool
206
- */
207
- function is_features_enabled() {
208
- return $this->is_active() && ( ! $this->is_block_features || ! $this->is_expired() );
209
- }
210
-
211
- /**
212
- * Subscription considered to be new without any payments
213
- * if the license expires in less than 24 hours
214
- * from the license creation.
215
- *
216
- * @author Vova Feldman (@svovaf)
217
- * @since 1.0.9
218
- *
219
- * @return bool
220
- */
221
- function is_first_payment_pending() {
222
- return ( WP_FS__TIME_24_HOURS_IN_SEC >= strtotime( $this->expiration ) - strtotime( $this->created ) );
223
- }
224
- }
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.5
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * Class FS_Plugin_License
15
+ */
16
+ class FS_Plugin_License extends FS_Entity {
17
+
18
+ #region Properties
19
+
20
+ /**
21
+ * @var number
22
+ */
23
+ public $plugin_id;
24
+ /**
25
+ * @var number
26
+ */
27
+ public $user_id;
28
+ /**
29
+ * @var number
30
+ */
31
+ public $plan_id;
32
+ /**
33
+ * @var number
34
+ */
35
+ public $pricing_id;
36
+ /**
37
+ * @var int|null
38
+ */
39
+ public $quota;
40
+ /**
41
+ * @var int
42
+ */
43
+ public $activated;
44
+ /**
45
+ * @var int
46
+ */
47
+ public $activated_local;
48
+ /**
49
+ * @var string
50
+ */
51
+ public $expiration;
52
+ /**
53
+ * @var string
54
+ */
55
+ public $secret_key;
56
+ /**
57
+ * @var bool $is_free_localhost Defaults to true. If true, allow unlimited localhost installs with the same
58
+ * license.
59
+ */
60
+ public $is_free_localhost;
61
+ /**
62
+ * @var bool $is_block_features Defaults to true. If false, don't block features after license expiry - only
63
+ * block updates and support.
64
+ */
65
+ public $is_block_features;
66
+ /**
67
+ * @var bool
68
+ */
69
+ public $is_cancelled;
70
+
71
+ #endregion Properties
72
+
73
+ /**
74
+ * @param stdClass|bool $license
75
+ */
76
+ function __construct( $license = false ) {
77
+ parent::__construct( $license );
78
+ }
79
+
80
+ /**
81
+ * Get entity type.
82
+ *
83
+ * @return string
84
+ */
85
+ static function get_type() {
86
+ return 'license';
87
+ }
88
+
89
+ /**
90
+ * Check how many site activations left.
91
+ *
92
+ * @author Vova Feldman (@svovaf)
93
+ * @since 1.0.5
94
+ *
95
+ * @return int
96
+ */
97
+ function left() {
98
+ if ( ! $this->is_active() || $this->is_expired() ) {
99
+ return 0;
100
+ }
101
+
102
+ if ( $this->is_unlimited() ) {
103
+ return 999;
104
+ }
105
+
106
+ return ( $this->quota - $this->activated - ( $this->is_free_localhost ? 0 : $this->activated_local ) );
107
+ }
108
+
109
+ /**
110
+ * Check if single site license.
111
+ *
112
+ * @author Vova Feldman (@svovaf)
113
+ * @since 1.1.8.1
114
+ *
115
+ * @return bool
116
+ */
117
+ function is_single_site() {
118
+ return ( is_numeric( $this->quota ) && 1 == $this->quota );
119
+ }
120
+
121
+ /**
122
+ * @author Vova Feldman (@svovaf)
123
+ * @since 1.0.5
124
+ *
125
+ * @return bool
126
+ */
127
+ function is_expired() {
128
+ return ! $this->is_lifetime() && ( strtotime( $this->expiration ) < WP_FS__SCRIPT_START_TIME );
129
+ }
130
+
131
+ /**
132
+ * Check if license is not expired.
133
+ *
134
+ * @author Vova Feldman (@svovaf)
135
+ * @since 1.2.1
136
+ *
137
+ * @return bool
138
+ */
139
+ function is_valid() {
140
+ return ! $this->is_expired();
141
+ }
142
+
143
+ /**
144
+ * @author Vova Feldman (@svovaf)
145
+ * @since 1.0.6
146
+ *
147
+ * @return bool
148
+ */
149
+ function is_lifetime() {
150
+ return is_null( $this->expiration );
151
+ }
152
+
153
+ /**
154
+ * @author Vova Feldman (@svovaf)
155
+ * @since 1.2.0
156
+ *
157
+ * @return bool
158
+ */
159
+ function is_unlimited() {
160
+ return is_null( $this->quota );
161
+ }
162
+
163
+ /**
164
+ * Check if license is fully utilized.
165
+ *
166
+ * @author Vova Feldman (@svovaf)
167
+ * @since 1.0.6
168
+ *
169
+ * @param bool $is_localhost
170
+ *
171
+ * @return bool
172
+ */
173
+ function is_utilized( $is_localhost = null ) {
174
+ if ( is_null( $is_localhost ) ) {
175
+ $is_localhost = WP_FS__IS_LOCALHOST_FOR_SERVER;
176
+ }
177
+
178
+ if ( $this->is_unlimited() ) {
179
+ return false;
180
+ }
181
+
182
+ return ! ( $this->is_free_localhost && $is_localhost ) &&
183
+ ( $this->quota <= $this->activated + ( $this->is_free_localhost ? 0 : $this->activated_local ) );
184
+ }
185
+
186
+ /**
187
+ * @author Vova Feldman (@svovaf)
188
+ * @since 1.2.1
189
+ *
190
+ * @return bool
191
+ */
192
+ function is_active() {
193
+ return ( ! $this->is_cancelled );
194
+ }
195
+
196
+ /**
197
+ * Check if license's plan features are enabled.
198
+ *
199
+ * - Either if plan not expired
200
+ * - If expired, based on the configuration to block features or not.
201
+ *
202
+ * @author Vova Feldman (@svovaf)
203
+ * @since 1.0.6
204
+ *
205
+ * @return bool
206
+ */
207
+ function is_features_enabled() {
208
+ return $this->is_active() && ( ! $this->is_block_features || ! $this->is_expired() );
209
+ }
210
+
211
+ /**
212
+ * Subscription considered to be new without any payments
213
+ * if the license expires in less than 24 hours
214
+ * from the license creation.
215
+ *
216
+ * @author Vova Feldman (@svovaf)
217
+ * @since 1.0.9
218
+ *
219
+ * @return bool
220
+ */
221
+ function is_first_payment_pending() {
222
+ return ( WP_FS__TIME_24_HOURS_IN_SEC >= strtotime( $this->expiration ) - strtotime( $this->created ) );
223
+ }
224
+ }
freemius/includes/entities/class-fs-plugin-tag.php CHANGED
@@ -1,24 +1,24 @@
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.4
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- class FS_Plugin_Tag extends FS_Entity {
14
- public $version;
15
- public $url;
16
-
17
- function __construct( $tag = false ) {
18
- parent::__construct( $tag );
19
- }
20
-
21
- static function get_type() {
22
- return 'tag';
23
- }
24
  }
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.4
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ class FS_Plugin_Tag extends FS_Entity {
14
+ public $version;
15
+ public $url;
16
+
17
+ function __construct( $tag = false ) {
18
+ parent::__construct( $tag );
19
+ }
20
+
21
+ static function get_type() {
22
+ return 'tag';
23
+ }
24
  }
freemius/includes/entities/class-fs-plugin.php CHANGED
@@ -1,117 +1,117 @@
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_Plugin extends FS_Scope_Entity {
14
- /**
15
- * @since 1.0.6
16
- * @var null|number
17
- */
18
- public $parent_plugin_id;
19
- /**
20
- * @var string
21
- */
22
- public $title;
23
- /**
24
- * @var string
25
- */
26
- public $slug;
27
- /**
28
- * @since 1.2.2
29
- *
30
- * @var string 'plugin' or 'theme'
31
- */
32
- public $type;
33
-
34
- #region Install Specific Properties
35
-
36
- /**
37
- * @var string
38
- */
39
- public $file;
40
- /**
41
- * @var string
42
- */
43
- public $version;
44
- /**
45
- * @var bool
46
- */
47
- public $auto_update;
48
- /**
49
- * @var FS_Plugin_Info
50
- */
51
- public $info;
52
- /**
53
- * @since 1.0.9
54
- *
55
- * @var bool
56
- */
57
- public $is_premium;
58
- /**
59
- * @since 1.0.9
60
- *
61
- * @var bool
62
- */
63
- public $is_live;
64
- /**
65
- * @author Leo Fajardo (@leorw)
66
- *
67
- * @since 1.2.3
68
- *
69
- * @var string|false false if the module doesn't have an affiliate program or one of the following:
70
- * 'selected', 'customers', or 'all'.
71
- */
72
- public $affiliate_moderation;
73
-
74
- const AFFILIATE_MODERATION_CUSTOMERS = 'customers';
75
-
76
- #endregion Install Specific Properties
77
-
78
- /**
79
- * @param stdClass|bool $plugin
80
- */
81
- function __construct( $plugin = false ) {
82
- parent::__construct( $plugin );
83
-
84
- $this->is_premium = false;
85
- $this->is_live = true;
86
-
87
- if ( isset( $plugin->info ) && is_object( $plugin->info ) ) {
88
- $this->info = new FS_Plugin_Info( $plugin->info );
89
- }
90
- }
91
-
92
- /**
93
- * Check if plugin is an add-on (has parent).
94
- *
95
- * @author Vova Feldman (@svovaf)
96
- * @since 1.0.6
97
- *
98
- * @return bool
99
- */
100
- function is_addon() {
101
- return isset( $this->parent_plugin_id ) && is_numeric( $this->parent_plugin_id );
102
- }
103
-
104
- /**
105
- * @author Leo Fajardo (@leorw)
106
- * @since 1.2.3
107
- *
108
- * @return bool
109
- */
110
- function has_affiliate_program() {
111
- return ( ! empty( $this->affiliate_moderation ) );
112
- }
113
-
114
- static function get_type() {
115
- return 'plugin';
116
- }
117
  }
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_Plugin extends FS_Scope_Entity {
14
+ /**
15
+ * @since 1.0.6
16
+ * @var null|number
17
+ */
18
+ public $parent_plugin_id;
19
+ /**
20
+ * @var string
21
+ */
22
+ public $title;
23
+ /**
24
+ * @var string
25
+ */
26
+ public $slug;
27
+ /**
28
+ * @since 1.2.2
29
+ *
30
+ * @var string 'plugin' or 'theme'
31
+ */
32
+ public $type;
33
+
34
+ #region Install Specific Properties
35
+
36
+ /**
37
+ * @var string
38
+ */
39
+ public $file;
40
+ /**
41
+ * @var string
42
+ */
43
+ public $version;
44
+ /**
45
+ * @var bool
46
+ */
47
+ public $auto_update;
48
+ /**
49
+ * @var FS_Plugin_Info
50
+ */
51
+ public $info;
52
+ /**
53
+ * @since 1.0.9
54
+ *
55
+ * @var bool
56
+ */
57
+ public $is_premium;
58
+ /**
59
+ * @since 1.0.9
60
+ *
61
+ * @var bool
62
+ */
63
+ public $is_live;
64
+ /**
65
+ * @author Leo Fajardo (@leorw)
66
+ *
67
+ * @since 1.2.3
68
+ *
69
+ * @var string|false false if the module doesn't have an affiliate program or one of the following:
70
+ * 'selected', 'customers', or 'all'.
71
+ */
72
+ public $affiliate_moderation;
73
+
74
+ const AFFILIATE_MODERATION_CUSTOMERS = 'customers';
75
+
76
+ #endregion Install Specific Properties
77
+
78
+ /**
79
+ * @param stdClass|bool $plugin
80
+ */
81
+ function __construct( $plugin = false ) {
82
+ parent::__construct( $plugin );
83
+
84
+ $this->is_premium = false;
85
+ $this->is_live = true;
86
+
87
+ if ( isset( $plugin->info ) && is_object( $plugin->info ) ) {
88
+ $this->info = new FS_Plugin_Info( $plugin->info );
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Check if plugin is an add-on (has parent).
94
+ *
95
+ * @author Vova Feldman (@svovaf)
96
+ * @since 1.0.6
97
+ *
98
+ * @return bool
99
+ */
100
+ function is_addon() {
101
+ return isset( $this->parent_plugin_id ) && is_numeric( $this->parent_plugin_id );
102
+ }
103
+
104
+ /**
105
+ * @author Leo Fajardo (@leorw)
106
+ * @since 1.2.3
107
+ *
108
+ * @return bool
109
+ */
110
+ function has_affiliate_program() {
111
+ return ( ! empty( $this->affiliate_moderation ) );
112
+ }
113
+
114
+ static function get_type() {
115
+ return 'plugin';
116
+ }
117
  }
freemius/includes/entities/class-fs-site.php CHANGED
@@ -1,148 +1,148 @@
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 string
16
- */
17
- public $slug;
18
- /**
19
- * @var number
20
- */
21
- public $site_id;
22
- /**
23
- * @var number
24
- */
25
- public $plugin_id;
26
- /**
27
- * @var number
28
- */
29
- public $user_id;
30
- /**
31
- * @var string
32
- */
33
- public $title;
34
- /**
35
- * @var string
36
- */
37
- public $url;
38
- /**
39
- * @var string
40
- */
41
- public $version;
42
- /**
43
- * @var string E.g. en-GB
44
- */
45
- public $language;
46
- /**
47
- * @var string E.g. UTF-8
48
- */
49
- public $charset;
50
- /**
51
- * @var string Platform version (e.g WordPress version).
52
- */
53
- public $platform_version;
54
- /**
55
- * Freemius SDK version
56
- *
57
- * @author Leo Fajardo (@leorw)
58
- * @since 1.2.2
59
- *
60
- * @var string SDK version (e.g.: 1.2.2)
61
- */
62
- public $sdk_version;
63
- /**
64
- * @var string Programming language version (e.g PHP version).
65
- */
66
- public $programming_language_version;
67
- /**
68
- * @var FS_Plugin_Plan $plan
69
- */
70
- public $plan;
71
- /**
72
- * @var number|null
73
- */
74
- public $license_id;
75
- /**
76
- * @var number|null
77
- */
78
- public $trial_plan_id;
79
- /**
80
- * @var string|null
81
- */
82
- public $trial_ends;
83
- /**
84
- * @since 1.0.9
85
- *
86
- * @var bool
87
- */
88
- public $is_premium = false;
89
- /**
90
- * @author Leo Fajardo (@leorw)
91
- *
92
- * @since 1.2.1.5
93
- *
94
- * @var bool
95
- */
96
- public $is_disconnected = false;
97
-
98
- /**
99
- * @param stdClass|bool $site
100
- */
101
- function __construct( $site = false ) {
102
- $this->plan = new FS_Plugin_Plan();
103
-
104
- parent::__construct( $site );
105
-
106
- if ( is_object( $site ) ) {
107
- $this->plan->id = $site->plan_id;
108
- }
109
-
110
- if ( ! is_bool( $this->is_disconnected ) ) {
111
- $this->is_disconnected = false;
112
- }
113
- }
114
-
115
- static function get_type() {
116
- return 'install';
117
- }
118
-
119
- function is_localhost() {
120
- // The server has no way to verify if localhost unless localhost appears in domain.
121
- return WP_FS__IS_LOCALHOST_FOR_SERVER;
122
- // return (substr($_SERVER['REMOTE_ADDR'], 0, 4) == '127.' || $_SERVER['REMOTE_ADDR'] == '::1');
123
- }
124
-
125
- /**
126
- * Check if site in trial.
127
- *
128
- * @author Vova Feldman (@svovaf)
129
- * @since 1.0.9
130
- *
131
- * @return bool
132
- */
133
- function is_trial() {
134
- return is_numeric( $this->trial_plan_id ) && ( strtotime( $this->trial_ends ) > WP_FS__SCRIPT_START_TIME );
135
- }
136
-
137
- /**
138
- * Check if user already utilized the trial with the current install.
139
- *
140
- * @author Vova Feldman (@svovaf)
141
- * @since 1.0.9
142
- *
143
- * @return bool
144
- */
145
- function is_trial_utilized() {
146
- return is_numeric( $this->trial_plan_id );
147
- }
148
  }
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 string
16
+ */
17
+ public $slug;
18
+ /**
19
+ * @var number
20
+ */
21
+ public $site_id;
22
+ /**
23
+ * @var number
24
+ */
25
+ public $plugin_id;
26
+ /**
27
+ * @var number
28
+ */
29
+ public $user_id;
30
+ /**
31
+ * @var string
32
+ */
33
+ public $title;
34
+ /**
35
+ * @var string
36
+ */
37
+ public $url;
38
+ /**
39
+ * @var string
40
+ */
41
+ public $version;
42
+ /**
43
+ * @var string E.g. en-GB
44
+ */
45
+ public $language;
46
+ /**
47
+ * @var string E.g. UTF-8
48
+ */
49
+ public $charset;
50
+ /**
51
+ * @var string Platform version (e.g WordPress version).
52
+ */
53
+ public $platform_version;
54
+ /**
55
+ * Freemius SDK version
56
+ *
57
+ * @author Leo Fajardo (@leorw)
58
+ * @since 1.2.2
59
+ *
60
+ * @var string SDK version (e.g.: 1.2.2)
61
+ */
62
+ public $sdk_version;
63
+ /**
64
+ * @var string Programming language version (e.g PHP version).
65
+ */
66
+ public $programming_language_version;
67
+ /**
68
+ * @var FS_Plugin_Plan $plan
69
+ */
70
+ public $plan;
71
+ /**
72
+ * @var number|null
73
+ */
74
+ public $license_id;
75
+ /**
76
+ * @var number|null
77
+ */
78
+ public $trial_plan_id;
79
+ /**
80
+ * @var string|null
81
+ */
82
+ public $trial_ends;
83
+ /**
84
+ * @since 1.0.9
85
+ *
86
+ * @var bool
87
+ */
88
+ public $is_premium = false;
89
+ /**
90
+ * @author Leo Fajardo (@leorw)
91
+ *
92
+ * @since 1.2.1.5
93
+ *
94
+ * @var bool
95
+ */
96
+ public $is_disconnected = false;
97
+
98
+ /**
99
+ * @param stdClass|bool $site
100
+ */
101
+ function __construct( $site = false ) {
102
+ $this->plan = new FS_Plugin_Plan();
103
+
104
+ parent::__construct( $site );
105
+
106
+ if ( is_object( $site ) ) {
107
+ $this->plan->id = $site->plan_id;
108
+ }
109
+
110
+ if ( ! is_bool( $this->is_disconnected ) ) {
111
+ $this->is_disconnected = false;
112
+ }
113
+ }
114
+
115
+ static function get_type() {
116
+ return 'install';
117
+ }
118
+
119
+ function is_localhost() {
120
+ // The server has no way to verify if localhost unless localhost appears in domain.
121
+ return WP_FS__IS_LOCALHOST_FOR_SERVER;
122
+ // return (substr($_SERVER['REMOTE_ADDR'], 0, 4) == '127.' || $_SERVER['REMOTE_ADDR'] == '::1');
123
+ }
124
+
125
+ /**
126
+ * Check if site in trial.
127
+ *
128
+ * @author Vova Feldman (@svovaf)
129
+ * @since 1.0.9
130
+ *
131
+ * @return bool
132
+ */
133
+ function is_trial() {
134
+ return is_numeric( $this->trial_plan_id ) && ( strtotime( $this->trial_ends ) > WP_FS__SCRIPT_START_TIME );
135
+ }
136
+
137
+ /**
138
+ * Check if user already utilized the trial with the current install.
139
+ *
140
+ * @author Vova Feldman (@svovaf)
141
+ * @since 1.0.9
142
+ *
143
+ * @return bool
144
+ */
145
+ function is_trial_utilized() {
146
+ return is_numeric( $this->trial_plan_id );
147
+ }
148
  }
freemius/includes/l10n.php CHANGED
@@ -1,48 +1,48 @@
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.1.6
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * Retrieve the translation of $text.
15
- *
16
- * @since 1.2.1.6
17
- *
18
- * @param string $text
19
- *
20
- * @return string
21
- */
22
- function _fs_text( $text ) {
23
- // Avoid misleading Theme Check warning.
24
- $fn = 'translate';
25
- return $fn( $text, 'freemius' );
26
- }
27
-
28
- /**
29
- * Retrieve translated string with gettext context.
30
- *
31
- * Quite a few times, there will be collisions with similar translatable text
32
- * found in more than two places, but with different translated context.
33
- *
34
- * By including the context in the pot file, translators can translate the two
35
- * strings differently.
36
- *
37
- * @since 1.2.1.6
38
- *
39
- * @param string $text
40
- * @param string $context
41
- *
42
- * @return string
43
- */
44
- function _fs_x( $text, $context ) {
45
- // Avoid misleading Theme Check warning.
46
- $fn = 'translate_with_gettext_context';
47
- return $fn( $text, $context, 'freemius' );
48
- }
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.1.6
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * Retrieve the translation of $text.
15
+ *
16
+ * @since 1.2.1.6
17
+ *
18
+ * @param string $text
19
+ *
20
+ * @return string
21
+ */
22
+ function _fs_text( $text ) {
23
+ // Avoid misleading Theme Check warning.
24
+ $fn = 'translate';
25
+ return $fn( $text, 'freemius' );
26
+ }
27
+
28
+ /**
29
+ * Retrieve translated string with gettext context.
30
+ *
31
+ * Quite a few times, there will be collisions with similar translatable text
32
+ * found in more than two places, but with different translated context.
33
+ *
34
+ * By including the context in the pot file, translators can translate the two
35
+ * strings differently.
36
+ *
37
+ * @since 1.2.1.6
38
+ *
39
+ * @param string $text
40
+ * @param string $context
41
+ *
42
+ * @return string
43
+ */
44
+ function _fs_x( $text, $context ) {
45
+ // Avoid misleading Theme Check warning.
46
+ $fn = 'translate_with_gettext_context';
47
+ return $fn( $text, $context, 'freemius' );
48
+ }
freemius/includes/managers/class-fs-admin-menu-manager.php CHANGED
@@ -1,850 +1,850 @@
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.1.3
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- class FS_Admin_Menu_Manager {
14
-
15
- #region Properties
16
-
17
- /**
18
- * @since 1.2.2
19
- *
20
- * @var string
21
- */
22
- protected $_module_unique_affix;
23
-
24
- /**
25
- * @since 1.2.2
26
- *
27
- * @var number
28
- */
29
- protected $_module_id;
30
-
31
- /**
32
- * @since 1.2.2
33
- *
34
- * @var string
35
- */
36
- protected $_module_type;
37
-
38
- /**
39
- * @since 1.0.6
40
- *
41
- * @var string
42
- */
43
- private $_menu_slug;
44
- /**
45
- * @since 1.1.3
46
- *
47
- * @var string
48
- */
49
- private $_parent_slug;
50
- /**
51
- * @since 1.1.3
52
- *
53
- * @var string
54
- */
55
- private $_parent_type;
56
- /**
57
- * @since 1.1.3
58
- *
59
- * @var string
60
- */
61
- private $_type;
62
- /**
63
- * @since 1.1.3
64
- *
65
- * @var bool
66
- */
67
- private $_is_top_level;
68
- /**
69
- * @since 1.1.3
70
- *
71
- * @var bool
72
- */
73
- private $_is_override_exact;
74
- /**
75
- * @since 1.1.3
76
- *
77
- * @var array<string,bool>
78
- */
79
- private $_default_submenu_items;
80
- /**
81
- * @since 1.1.3
82
- *
83
- * @var string
84
- */
85
- private $_first_time_path;
86
- /**
87
- * @since 1.2.2
88
- *
89
- * @var bool
90
- */
91
- private $_menu_exists;
92
-
93
- #endregion Properties
94
-
95
- /**
96
- * @var FS_Logger
97
- */
98
- protected $_logger;
99
-
100
- #region Singleton
101
-
102
- /**
103
- * @var FS_Admin_Menu_Manager[]
104
- */
105
- private static $_instances = array();
106
-
107
- /**
108
- * @param number $module_id
109
- * @param string $module_type
110
- * @param string $module_unique_affix
111
- *
112
- * @return FS_Admin_Menu_Manager
113
- */
114
- static function instance( $module_id, $module_type, $module_unique_affix ) {
115
- $key = 'm_' . $module_id;
116
-
117
- if ( ! isset( self::$_instances[ $key ] ) ) {
118
- self::$_instances[ $key ] = new FS_Admin_Menu_Manager( $module_id, $module_type, $module_unique_affix );
119
- }
120
-
121
- return self::$_instances[ $key ];
122
- }
123
-
124
- protected function __construct( $module_id, $module_type, $module_unique_affix ) {
125
- $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $module_id . '_admin_menu', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
126
-
127
- $this->_module_id = $module_id;
128
- $this->_module_type = $module_type;
129
- $this->_module_unique_affix = $module_unique_affix;
130
- }
131
-
132
- #endregion Singleton
133
-
134
- #region Helpers
135
-
136
- private function get_option( &$options, $key, $default = false ) {
137
- return ! empty( $options[ $key ] ) ? $options[ $key ] : $default;
138
- }
139
-
140
- private function get_bool_option( &$options, $key, $default = false ) {
141
- return isset( $options[ $key ] ) && is_bool( $options[ $key ] ) ? $options[ $key ] : $default;
142
- }
143
-
144
- #endregion Helpers
145
-
146
- /**
147
- * @param array $menu
148
- * @param bool $is_addon
149
- */
150
- function init( $menu, $is_addon = false ) {
151
- $this->_menu_exists = ( isset( $menu['slug'] ) && ! empty( $menu['slug'] ) );
152
-
153
- $this->_menu_slug = ( $this->_menu_exists ? $menu['slug'] : $this->_module_unique_affix );
154
-
155
- $this->_default_submenu_items = array();
156
- // @deprecated
157
- $this->_type = 'page';
158
- $this->_is_top_level = true;
159
- $this->_is_override_exact = false;
160
- $this->_parent_slug = false;
161
- // @deprecated
162
- $this->_parent_type = 'page';
163
-
164
- if ( ! $is_addon && isset( $menu ) ) {
165
- $this->_default_submenu_items = array(
166
- 'contact' => $this->get_bool_option( $menu, 'contact', true ),
167
- 'support' => $this->get_bool_option( $menu, 'support', true ),
168
- 'affiliation' => $this->get_bool_option( $menu, 'affiliation', true ),
169
- 'account' => $this->get_bool_option( $menu, 'account', true ),
170
- 'pricing' => $this->get_bool_option( $menu, 'pricing', true ),
171
- 'addons' => $this->get_bool_option( $menu, 'addons', true ),
172
- );
173
-
174
- // @deprecated
175
- $this->_type = $this->get_option( $menu, 'type', 'page' );
176
- $this->_is_override_exact = $this->get_bool_option( $menu, 'override_exact' );
177
-
178
- if ( isset( $menu['parent'] ) ) {
179
- $this->_parent_slug = $this->get_option( $menu['parent'], 'slug' );
180
- // @deprecated
181
- $this->_parent_type = $this->get_option( $menu['parent'], 'type', 'page' );
182
-
183
- // If parent's slug is different, then it's NOT a top level menu item.
184
- $this->_is_top_level = ( $this->_parent_slug === $this->_menu_slug );
185
- } else {
186
- /**
187
- * If no parent then top level if:
188
- * - Has custom admin menu ('page')
189
- * - CPT menu type ('cpt')
190
- */
191
- // $this->_is_top_level = in_array( $this->_type, array(
192
- // 'cpt',
193
- // 'page'
194
- // ) );
195
- }
196
-
197
- $this->_first_time_path = $this->get_option( $menu, 'first-path', false );
198
- if ( ! empty( $this->_first_time_path ) && is_string( $this->_first_time_path ) ) {
199
- $this->_first_time_path = admin_url( $this->_first_time_path, 'admin' );
200
- }
201
- }
202
- }
203
-
204
- /**
205
- * Check if top level menu.
206
- *
207
- * @author Vova Feldman (@svovaf)
208
- * @since 1.1.3
209
- *
210
- * @return bool False if submenu item.
211
- */
212
- function is_top_level() {
213
- return $this->_is_top_level;
214
- }
215
-
216
- /**
217
- * Check if the page should be override on exact URL match.
218
- *
219
- * @author Vova Feldman (@svovaf)
220
- * @since 1.1.3
221
- *
222
- * @return bool False if submenu item.
223
- */
224
- function is_override_exact() {
225
- return $this->_is_override_exact;
226
- }
227
-
228
-
229
- /**
230
- * Get the path of the page the user should be forwarded to after first activation.
231
- *
232
- * @author Vova Feldman (@svovaf)
233
- * @since 1.1.3
234
- *
235
- * @return string
236
- */
237
- function get_first_time_path() {
238
- return $this->_first_time_path;
239
- }
240
-
241
- /**
242
- * Check if plugin's menu item is part of a custom top level menu.
243
- *
244
- * @author Vova Feldman (@svovaf)
245
- * @since 1.1.3
246
- *
247
- * @return bool
248
- */
249
- function has_custom_parent() {
250
- return ! $this->_is_top_level && is_string( $this->_parent_slug );
251
- }
252
-
253
- /**
254
- * @author Leo Fajardo (@leorw)
255
- * @since 1.2.2
256
- *
257
- * @return bool
258
- */
259
- function has_menu() {
260
- return $this->_menu_exists;
261
- }
262
-
263
- /**
264
- * @author Vova Feldman (@svovaf)
265
- * @since 1.1.3
266
- *
267
- * @param string $id
268
- * @param bool $default
269
- * @param bool $ignore_menu_existence Since 1.2.2.7 If true, check if the submenu item visible even if there's no parent menu.
270
- *
271
- * @return bool
272
- */
273
- function is_submenu_item_visible( $id, $default = true, $ignore_menu_existence = false ) {
274
- if ( ! $ignore_menu_existence && ! $this->has_menu() ) {
275
- return false;
276
- }
277
-
278
- return fs_apply_filter(
279
- $this->_module_unique_affix,
280
- 'is_submenu_visible',
281
- $this->get_bool_option( $this->_default_submenu_items, $id, $default ),
282
- $id
283
- );
284
- }
285
-
286
- /**
287
- * Calculates admin settings menu slug.
288
- * If plugin's menu slug is a file (e.g. CPT), uses plugin's slug as the menu slug.
289
- *
290
- * @author Vova Feldman (@svovaf)
291
- * @since 1.1.3
292
- *
293
- * @param string $page
294
- *
295
- * @return string
296
- */
297
- function get_slug( $page = '' ) {
298
- return ( ( false === strpos( $this->_menu_slug, '.php?' ) ) ?
299
- $this->_menu_slug :
300
- $this->_module_unique_affix ) . ( empty( $page ) ? '' : ( '-' . $page ) );
301
- }
302
-
303
- /**
304
- * @author Vova Feldman (@svovaf)
305
- * @since 1.1.3
306
- *
307
- * @return string
308
- */
309
- function get_parent_slug() {
310
- return $this->_parent_slug;
311
- }
312
-
313
- /**
314
- * @author Vova Feldman (@svovaf)
315
- * @since 1.1.3
316
- *
317
- * @return string
318
- */
319
- function get_type() {
320
- return $this->_type;
321
- }
322
-
323
- /**
324
- * @author Vova Feldman (@svovaf)
325
- * @since 1.1.3
326
- *
327
- * @return bool
328
- */
329
- function is_cpt() {
330
- return ( 0 === strpos( $this->_menu_slug, 'edit.php?post_type=' ) ||
331
- // Back compatibility.
332
- 'cpt' === $this->_type
333
- );
334
- }
335
-
336
- /**
337
- * @author Vova Feldman (@svovaf)
338
- * @since 1.1.3
339
- *
340
- * @return string
341
- */
342
- function get_parent_type() {
343
- return $this->_parent_type;
344
- }
345
-
346
- /**
347
- * @author Vova Feldman (@svovaf)
348
- * @since 1.1.3
349
- *
350
- * @return string
351
- */
352
- function get_raw_slug() {
353
- return $this->_menu_slug;
354
- }
355
-
356
- /**
357
- * Get plugin's original menu slug.
358
- *
359
- * @author Vova Feldman (@svovaf)
360
- * @since 1.1.3
361
- *
362
- * @return string
363
- */
364
- function get_original_menu_slug() {
365
- if ( 'cpt' === $this->_type ) {
366
- return add_query_arg( array(
367
- 'post_type' => $this->_menu_slug
368
- ), 'edit.php' );
369
- }
370
-
371
- if ( false === strpos( $this->_menu_slug, '.php?' ) ) {
372
- return $this->_menu_slug;
373
- } else {
374
- return $this->_module_unique_affix;
375
- }
376
- }
377
-
378
- /**
379
- * @author Vova Feldman (@svovaf)
380
- * @since 1.1.3
381
- *
382
- * @return string
383
- */
384
- function get_top_level_menu_slug() {
385
- return $this->has_custom_parent() ?
386
- $this->get_parent_slug() :
387
- $this->get_raw_slug();
388
- }
389
-
390
- /**
391
- * Is user on plugin's admin activation page.
392
- *
393
- * @author Vova Feldman (@svovaf)
394
- * @since 1.0.8
395
- *
396
- * @return bool
397
- */
398
- function is_main_settings_page() {
399
- if ( $this->_menu_exists &&
400
- ( fs_is_plugin_page( $this->_menu_slug ) || fs_is_plugin_page( $this->_module_unique_affix ) )
401
- ) {
402
- /**
403
- * Module has a settings menu and the context page is the main settings page, so assume it's in
404
- * activation (doesn't really check if already opted-in/skipped or not).
405
- *
406
- * @since 1.2.2
407
- */
408
- return true;
409
- }
410
-
411
- global $pagenow;
412
- if ( ( WP_FS__MODULE_TYPE_THEME === $this->_module_type ) && Freemius::is_themes_page() ) {
413
- /**
414
- * In activation only when show_optin query string param is given.
415
- *
416
- * @since 1.2.2
417
- */
418
- return fs_request_get_bool( $this->_module_unique_affix . '_show_optin' );
419
- }
420
-
421
- return false;
422
- }
423
-
424
- #region Submenu Override
425
-
426
- /**
427
- * Override submenu's action.
428
- *
429
- * @author Vova Feldman (@svovaf)
430
- * @since 1.1.0
431
- *
432
- * @param string $parent_slug
433
- * @param string $menu_slug
434
- * @param callable $function
435
- *
436
- * @return false|string If submenu exist, will return the hook name.
437
- */
438
- function override_submenu_action( $parent_slug, $menu_slug, $function ) {
439
- global $submenu;
440
-
441
- $menu_slug = plugin_basename( $menu_slug );
442
- $parent_slug = plugin_basename( $parent_slug );
443
-
444
- if ( ! isset( $submenu[ $parent_slug ] ) ) {
445
- // Parent menu not exist.
446
- return false;
447
- }
448
-
449
- $found_submenu_item = false;
450
- foreach ( $submenu[ $parent_slug ] as $submenu_item ) {
451
- if ( $menu_slug === $submenu_item[2] ) {
452
- $found_submenu_item = $submenu_item;
453
- break;
454
- }
455
- }
456
-
457
- if ( false === $found_submenu_item ) {
458
- // Submenu item not found.
459
- return false;
460
- }
461
-
462
- // Remove current function.
463
- $hookname = get_plugin_page_hookname( $menu_slug, $parent_slug );
464
- remove_all_actions( $hookname );
465
-
466
- // Attach new action.
467
- add_action( $hookname, $function );
468
-
469
- return $hookname;
470
- }
471
-
472
- #endregion Submenu Override
473
-
474
- #region Top level menu Override
475
-
476
- /**
477
- * Find plugin's admin dashboard main menu item.
478
- *
479
- * @author Vova Feldman (@svovaf)
480
- * @since 1.0.2
481
- *
482
- * @return string[]|false
483
- */
484
- private function find_top_level_menu() {
485
- global $menu;
486
-
487
- $position = - 1;
488
- $found_menu = false;
489
-
490
- $menu_slug = $this->get_raw_slug();
491
-
492
- $hook_name = get_plugin_page_hookname( $menu_slug, '' );
493
- foreach ( $menu as $pos => $m ) {
494
- if ( $menu_slug === $m[2] ) {
495
- $position = $pos;
496
- $found_menu = $m;
497
- break;
498
- }
499
- }
500
-
501
- if ( false === $found_menu ) {
502
- return false;
503
- }
504
-
505
- return array(
506
- 'menu' => $found_menu,
507
- 'position' => $position,
508
- 'hook_name' => $hook_name
509
- );
510
- }
511
-
512
- /**
513
- * Find plugin's admin dashboard main submenu item.
514
- *
515
- * @author Vova Feldman (@svovaf)
516
- * @since 1.2.1.6
517
- *
518
- * @return array|false
519
- */
520
- private function find_main_submenu() {
521
- global $submenu;
522
-
523
- $top_level_menu_slug = $this->get_top_level_menu_slug();
524
-
525
- if ( ! isset( $submenu[ $top_level_menu_slug ] ) ) {
526
- return false;
527
- }
528
-
529
- $submenu_slug = $this->get_raw_slug();
530
-
531
- $position = - 1;
532
- $found_submenu = false;
533
-
534
- $hook_name = get_plugin_page_hookname( $submenu_slug, '' );
535
-
536
- foreach ( $submenu[ $top_level_menu_slug ] as $pos => $sub ) {
537
- if ( $submenu_slug === $sub[2] ) {
538
- $position = $pos;
539
- $found_submenu = $sub;
540
- }
541
- }
542
-
543
- if ( false === $found_submenu ) {
544
- return false;
545
- }
546
-
547
- return array(
548
- 'menu' => $found_submenu,
549
- 'parent_slug' => $top_level_menu_slug,
550
- 'position' => $position,
551
- 'hook_name' => $hook_name
552
- );
553
- }
554
-
555
- /**
556
- * Remove all sub-menu items.
557
- *
558
- * @author Vova Feldman (@svovaf)
559
- * @since 1.0.7
560
- *
561
- * @return bool If submenu with plugin's menu slug was found.
562
- */
563
- private function remove_all_submenu_items() {
564
- global $submenu;
565
-
566
- $menu_slug = $this->get_raw_slug();
567
-
568
- if ( ! isset( $submenu[ $menu_slug ] ) ) {
569
- return false;
570
- }
571
-
572
- /**
573
- * This method is NOT executed for WordPress.org themes.
574
- * Since we maintain only one version of the SDK we added this small
575
- * hack to avoid the error from Theme Check since it's a false-positive.
576
- *
577
- * @author Vova Feldman (@svovaf)
578
- * @since 1.2.2.7
579
- */
580
- $submenu_ref = &$submenu;
581
- $submenu_ref[ $menu_slug ] = array();
582
-
583
- return true;
584
- }
585
-
586
- /**
587
- *
588
- * @author Vova Feldman (@svovaf)
589
- * @since 1.0.9
590
- *
591
- * @return false|array[string]mixed
592
- */
593
- function remove_menu_item() {
594
- $this->_logger->entrance();
595
-
596
- // Find main menu item.
597
- $menu = $this->find_top_level_menu();
598
-
599
- if ( false === $menu ) {
600
- return false;
601
- }
602
-
603
- // Remove it with its actions.
604
- remove_all_actions( $menu['hook_name'] );
605
-
606
- // Remove all submenu items.
607
- $this->remove_all_submenu_items();
608
-
609
- return $menu;
610
- }
611
-
612
- /**
613
- * Get module's main admin setting page URL.
614
- *
615
- * @todo This method was only tested for wp.org compliant themes with a submenu item. Need to test for plugins with top level, submenu, and CPT top level, menu items.
616
- *
617
- * @author Vova Feldman (@svovaf)
618
- * @since 1.2.2.7
619
- *
620
- * @return string
621
- */
622
- function main_menu_url() {
623
- $this->_logger->entrance();
624
-
625
- if ( $this->_is_top_level ) {
626
- $menu = $this->find_top_level_menu();
627
- } else {
628
- $menu = $this->find_main_submenu();
629
- }
630
-
631
- $parent_slug = isset( $menu['parent_slug'] ) ?
632
- $menu['parent_slug'] :
633
- 'admin.php';
634
-
635
- return admin_url( $parent_slug . '?page=' . $menu['menu'][2] );
636
- }
637
-
638
- /**
639
- * @author Vova Feldman (@svovaf)
640
- * @since 1.1.4
641
- *
642
- * @param callable $function
643
- *
644
- * @return false|array[string]mixed
645
- */
646
- function override_menu_item( $function ) {
647
- $found_menu = $this->remove_menu_item();
648
-
649
- if ( false === $found_menu ) {
650
- return false;
651
- }
652
-
653
- if ( ! $this->is_top_level() || ! $this->is_cpt() ) {
654
- $menu_slug = plugin_basename( $this->get_slug() );
655
-
656
- $hookname = get_plugin_page_hookname( $menu_slug, '' );
657
-
658
- // Override menu action.
659
- add_action( $hookname, $function );
660
- } else {
661
- global $menu;
662
-
663
- // Remove original CPT menu.
664
- unset( $menu[ $found_menu['position'] ] );
665
-
666
- // Create new top-level menu action.
667
- $hookname = self::add_page(
668
- $found_menu['menu'][3],
669
- $found_menu['menu'][0],
670
- 'manage_options',
671
- $this->get_slug(),
672
- $function,
673
- $found_menu['menu'][6],
674
- $found_menu['position']
675
- );
676
- }
677
-
678
- return $hookname;
679
- }
680
-
681
- /**
682
- * Adds a counter to the module's top level menu item.
683
- *
684
- * @author Vova Feldman (@svovaf)
685
- * @since 1.2.1.5
686
- *
687
- * @param int $counter
688
- * @param string $class
689
- */
690
- function add_counter_to_menu_item( $counter = 1, $class = '' ) {
691
- global $menu, $submenu;
692
-
693
- $mask = '%s <span class="update-plugins %s count-%3$s" aria-hidden="true"><span>%3$s<span class="screen-reader-text">%3$s notifications</span></span></span>';
694
-
695
- /**
696
- * This method is NOT executed for WordPress.org themes.
697
- * Since we maintain only one version of the SDK we added this small
698
- * hack to avoid the error from Theme Check since it's a false-positive.
699
- *
700
- * @author Vova Feldman (@svovaf)
701
- * @since 1.2.2.7
702
- */
703
- $menu_ref = &$menu;
704
- $submenu_ref = &$submenu;
705
-
706
- if ( $this->_is_top_level ) {
707
- // Find main menu item.
708
- $found_menu = $this->find_top_level_menu();
709
-
710
- if ( false !== $found_menu ) {
711
- // Override menu label.
712
- $menu_ref[ $found_menu['position'] ][0] = sprintf(
713
- $mask,
714
- $found_menu['menu'][0],
715
- $class,
716
- $counter
717
- );
718
- }
719
- } else {
720
- $found_submenu = $this->find_main_submenu();
721
-
722
- if ( false !== $found_submenu ) {
723
- // Override menu label.
724
- $submenu_ref[ $found_submenu['parent_slug'] ][ $found_submenu['position'] ][0] = sprintf(
725
- $mask,
726
- $found_submenu['menu'][0],
727
- $class,
728
- $counter
729
- );
730
- }
731
- }
732
- }
733
-
734
- #endregion Top level menu Override
735
-
736
- /**
737
- * Add a top-level menu page.
738
- *
739
- * Note for WordPress.org Theme/Plugin reviewer:
740
- *
741
- * This is a replication of `add_menu_page()` to avoid Theme Check warning.
742
- *
743
- * Why?
744
- * ====
745
- * Freemius is an SDK for plugin and theme developers. Since the core
746
- * of the SDK is relevant both for plugins and themes, for obvious reasons,
747
- * we only develop and maintain one code base.
748
- *
749
- * This method will not run for wp.org themes (only plugins) since theme
750
- * admin settings/options are now only allowed in the customizer.
751
- *
752
- * If you have any questions or need clarifications, please don't hesitate
753
- * pinging me on slack, my username is @svovaf.
754
- *
755
- * @author Vova Feldman (@svovaf)
756
- * @since 1.2.2
757
- *
758
- * @param string $page_title The text to be displayed in the title tags of the page when the menu is
759
- * selected.
760
- * @param string $menu_title The text to be used for the menu.
761
- * @param string $capability The capability required for this menu to be displayed to the user.
762
- * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu).
763
- * @param callable|string $function The function to be called to output the content for this page.
764
- * @param string $icon_url The URL to the icon to be used for this menu.
765
- * * Pass a base64-encoded SVG using a data URI, which will be colored to
766
- * match the color scheme. This should begin with
767
- * 'data:image/svg+xml;base64,'.
768
- * * Pass the name of a Dashicons helper class to use a font icon,
769
- * e.g. 'dashicons-chart-pie'.
770
- * * Pass 'none' to leave div.wp-menu-image empty so an icon can be added
771
- * via CSS.
772
- * @param int $position The position in the menu order this one should appear.
773
- *
774
- * @return string The resulting page's hook_suffix.
775
- */
776
- static function add_page(
777
- $page_title,
778
- $menu_title,
779
- $capability,
780
- $menu_slug,
781
- $function = '',
782
- $icon_url = '',
783
- $position = null
784
- ) {
785
- $fn = 'add_menu' . '_page';
786
-
787
- return $fn(
788
- $page_title,
789
- $menu_title,
790
- $capability,
791
- $menu_slug,
792
- $function,
793
- $icon_url,
794
- $position
795
- );
796
- }
797
-
798
- /**
799
- * Add a submenu page.
800
- *
801
- * Note for WordPress.org Theme/Plugin reviewer:
802
- *
803
- * This is a replication of `add_submenu_page()` to avoid Theme Check warning.
804
- *
805
- * Why?
806
- * ====
807
- * Freemius is an SDK for plugin and theme developers. Since the core
808
- * of the SDK is relevant both for plugins and themes, for obvious reasons,
809
- * we only develop and maintain one code base.
810
- *
811
- * This method will not run for wp.org themes (only plugins) since theme
812
- * admin settings/options are now only allowed in the customizer.
813
- *
814
- * If you have any questions or need clarifications, please don't hesitate
815
- * pinging me on slack, my username is @svovaf.
816
- *
817
- * @author Vova Feldman (@svovaf)
818
- * @since 1.2.2
819
- *
820
- * @param string $parent_slug The slug name for the parent menu (or the file name of a standard
821
- * WordPress admin page).
822
- * @param string $page_title The text to be displayed in the title tags of the page when the menu is
823
- * selected.
824
- * @param string $menu_title The text to be used for the menu.
825
- * @param string $capability The capability required for this menu to be displayed to the user.
826
- * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu).
827
- * @param callable|string $function The function to be called to output the content for this page.
828
- *
829
- * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability
830
- * required.
831
- */
832
- static function add_subpage(
833
- $parent_slug,
834
- $page_title,
835
- $menu_title,
836
- $capability,
837
- $menu_slug,
838
- $function = ''
839
- ) {
840
- $fn = 'add_submenu' . '_page';
841
-
842
- return $fn( $parent_slug,
843
- $page_title,
844
- $menu_title,
845
- $capability,
846
- $menu_slug,
847
- $function
848
- );
849
- }
850
  }
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.1.3
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ class FS_Admin_Menu_Manager {
14
+
15
+ #region Properties
16
+
17
+ /**
18
+ * @since 1.2.2
19
+ *
20
+ * @var string
21
+ */
22
+ protected $_module_unique_affix;
23
+
24
+ /**
25
+ * @since 1.2.2
26
+ *
27
+ * @var number
28
+ */
29
+ protected $_module_id;
30
+
31
+ /**
32
+ * @since 1.2.2
33
+ *
34
+ * @var string
35
+ */
36
+ protected $_module_type;
37
+
38
+ /**
39
+ * @since 1.0.6
40
+ *
41
+ * @var string
42
+ */
43
+ private $_menu_slug;
44
+ /**
45
+ * @since 1.1.3
46
+ *
47
+ * @var string
48
+ */
49
+ private $_parent_slug;
50
+ /**
51
+ * @since 1.1.3
52
+ *
53
+ * @var string
54
+ */
55
+ private $_parent_type;
56
+ /**
57
+ * @since 1.1.3
58
+ *
59
+ * @var string
60
+ */
61
+ private $_type;
62
+ /**
63
+ * @since 1.1.3
64
+ *
65
+ * @var bool
66
+ */
67
+ private $_is_top_level;
68
+ /**
69
+ * @since 1.1.3
70
+ *
71
+ * @var bool
72
+ */
73
+ private $_is_override_exact;
74
+ /**
75
+ * @since 1.1.3
76
+ *
77
+ * @var array<string,bool>
78
+ */
79
+ private $_default_submenu_items;
80
+ /**
81
+ * @since 1.1.3
82
+ *
83
+ * @var string
84
+ */
85
+ private $_first_time_path;
86
+ /**
87
+ * @since 1.2.2
88
+ *
89
+ * @var bool
90
+ */
91
+ private $_menu_exists;
92
+
93
+ #endregion Properties
94
+
95
+ /**
96
+ * @var FS_Logger
97
+ */
98
+ protected $_logger;
99
+
100
+ #region Singleton
101
+
102
+ /**
103
+ * @var FS_Admin_Menu_Manager[]
104
+ */
105
+ private static $_instances = array();
106
+
107
+ /**
108
+ * @param number $module_id
109
+ * @param string $module_type
110
+ * @param string $module_unique_affix
111
+ *
112
+ * @return FS_Admin_Menu_Manager
113
+ */
114
+ static function instance( $module_id, $module_type, $module_unique_affix ) {
115
+ $key = 'm_' . $module_id;
116
+
117
+ if ( ! isset( self::$_instances[ $key ] ) ) {
118
+ self::$_instances[ $key ] = new FS_Admin_Menu_Manager( $module_id, $module_type, $module_unique_affix );
119
+ }
120
+
121
+ return self::$_instances[ $key ];
122
+ }
123
+
124
+ protected function __construct( $module_id, $module_type, $module_unique_affix ) {
125
+ $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $module_id . '_admin_menu', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
126
+
127
+ $this->_module_id = $module_id;
128
+ $this->_module_type = $module_type;
129
+ $this->_module_unique_affix = $module_unique_affix;
130
+ }
131
+
132
+ #endregion Singleton
133
+
134
+ #region Helpers
135
+
136
+ private function get_option( &$options, $key, $default = false ) {
137
+ return ! empty( $options[ $key ] ) ? $options[ $key ] : $default;
138
+ }
139
+
140
+ private function get_bool_option( &$options, $key, $default = false ) {
141
+ return isset( $options[ $key ] ) && is_bool( $options[ $key ] ) ? $options[ $key ] : $default;
142
+ }
143
+
144
+ #endregion Helpers
145
+
146
+ /**
147
+ * @param array $menu
148
+ * @param bool $is_addon
149
+ */
150
+ function init( $menu, $is_addon = false ) {
151
+ $this->_menu_exists = ( isset( $menu['slug'] ) && ! empty( $menu['slug'] ) );
152
+
153
+ $this->_menu_slug = ( $this->_menu_exists ? $menu['slug'] : $this->_module_unique_affix );
154
+
155
+ $this->_default_submenu_items = array();
156
+ // @deprecated
157
+ $this->_type = 'page';
158
+ $this->_is_top_level = true;
159
+ $this->_is_override_exact = false;
160
+ $this->_parent_slug = false;
161
+ // @deprecated
162
+ $this->_parent_type = 'page';
163
+
164
+ if ( ! $is_addon && isset( $menu ) ) {
165
+ $this->_default_submenu_items = array(
166
+ 'contact' => $this->get_bool_option( $menu, 'contact', true ),
167
+ 'support' => $this->get_bool_option( $menu, 'support', true ),
168
+ 'affiliation' => $this->get_bool_option( $menu, 'affiliation', true ),
169
+ 'account' => $this->get_bool_option( $menu, 'account', true ),
170
+ 'pricing' => $this->get_bool_option( $menu, 'pricing', true ),
171
+ 'addons' => $this->get_bool_option( $menu, 'addons', true ),
172
+ );
173
+
174
+ // @deprecated
175
+ $this->_type = $this->get_option( $menu, 'type', 'page' );
176
+ $this->_is_override_exact = $this->get_bool_option( $menu, 'override_exact' );
177
+
178
+ if ( isset( $menu['parent'] ) ) {
179
+ $this->_parent_slug = $this->get_option( $menu['parent'], 'slug' );
180
+ // @deprecated
181
+ $this->_parent_type = $this->get_option( $menu['parent'], 'type', 'page' );
182
+
183
+ // If parent's slug is different, then it's NOT a top level menu item.
184
+ $this->_is_top_level = ( $this->_parent_slug === $this->_menu_slug );
185
+ } else {
186
+ /**
187
+ * If no parent then top level if:
188
+ * - Has custom admin menu ('page')
189
+ * - CPT menu type ('cpt')
190
+ */
191
+ // $this->_is_top_level = in_array( $this->_type, array(
192
+ // 'cpt',
193
+ // 'page'
194
+ // ) );
195
+ }
196
+
197
+ $this->_first_time_path = $this->get_option( $menu, 'first-path', false );
198
+ if ( ! empty( $this->_first_time_path ) && is_string( $this->_first_time_path ) ) {
199
+ $this->_first_time_path = admin_url( $this->_first_time_path, 'admin' );
200
+ }
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Check if top level menu.
206
+ *
207
+ * @author Vova Feldman (@svovaf)
208
+ * @since 1.1.3
209
+ *
210
+ * @return bool False if submenu item.
211
+ */
212
+ function is_top_level() {
213
+ return $this->_is_top_level;
214
+ }
215
+
216
+ /**
217
+ * Check if the page should be override on exact URL match.
218
+ *
219
+ * @author Vova Feldman (@svovaf)
220
+ * @since 1.1.3
221
+ *
222
+ * @return bool False if submenu item.
223
+ */
224
+ function is_override_exact() {
225
+ return $this->_is_override_exact;
226
+ }
227
+
228
+
229
+ /**
230
+ * Get the path of the page the user should be forwarded to after first activation.
231
+ *
232
+ * @author Vova Feldman (@svovaf)
233
+ * @since 1.1.3
234
+ *
235
+ * @return string
236
+ */
237
+ function get_first_time_path() {
238
+ return $this->_first_time_path;
239
+ }
240
+
241
+ /**
242
+ * Check if plugin's menu item is part of a custom top level menu.
243
+ *
244
+ * @author Vova Feldman (@svovaf)
245
+ * @since 1.1.3
246
+ *
247
+ * @return bool
248
+ */
249
+ function has_custom_parent() {
250
+ return ! $this->_is_top_level && is_string( $this->_parent_slug );
251
+ }
252
+
253
+ /**
254
+ * @author Leo Fajardo (@leorw)
255
+ * @since 1.2.2
256
+ *
257
+ * @return bool
258
+ */
259
+ function has_menu() {
260
+ return $this->_menu_exists;
261
+ }
262
+
263
+ /**
264
+ * @author Vova Feldman (@svovaf)
265
+ * @since 1.1.3
266
+ *
267
+ * @param string $id
268
+ * @param bool $default
269
+ * @param bool $ignore_menu_existence Since 1.2.2.7 If true, check if the submenu item visible even if there's no parent menu.
270
+ *
271
+ * @return bool
272
+ */
273
+ function is_submenu_item_visible( $id, $default = true, $ignore_menu_existence = false ) {
274
+ if ( ! $ignore_menu_existence && ! $this->has_menu() ) {
275
+ return false;
276
+ }
277
+
278
+ return fs_apply_filter(
279
+ $this->_module_unique_affix,
280
+ 'is_submenu_visible',
281
+ $this->get_bool_option( $this->_default_submenu_items, $id, $default ),
282
+ $id
283
+ );
284
+ }
285
+
286
+ /**
287
+ * Calculates admin settings menu slug.
288
+ * If plugin's menu slug is a file (e.g. CPT), uses plugin's slug as the menu slug.
289
+ *
290
+ * @author Vova Feldman (@svovaf)
291
+ * @since 1.1.3
292
+ *
293
+ * @param string $page
294
+ *
295
+ * @return string
296
+ */
297
+ function get_slug( $page = '' ) {
298
+ return ( ( false === strpos( $this->_menu_slug, '.php?' ) ) ?
299
+ $this->_menu_slug :
300
+ $this->_module_unique_affix ) . ( empty( $page ) ? '' : ( '-' . $page ) );
301
+ }
302
+
303
+ /**
304
+ * @author Vova Feldman (@svovaf)
305
+ * @since 1.1.3
306
+ *
307
+ * @return string
308
+ */
309
+ function get_parent_slug() {
310
+ return $this->_parent_slug;
311
+ }
312
+
313
+ /**
314
+ * @author Vova Feldman (@svovaf)
315
+ * @since 1.1.3
316
+ *
317
+ * @return string
318
+ */
319
+ function get_type() {
320
+ return $this->_type;
321
+ }
322
+
323
+ /**
324
+ * @author Vova Feldman (@svovaf)
325
+ * @since 1.1.3
326
+ *
327
+ * @return bool
328
+ */
329
+ function is_cpt() {
330
+ return ( 0 === strpos( $this->_menu_slug, 'edit.php?post_type=' ) ||
331
+ // Back compatibility.
332
+ 'cpt' === $this->_type
333
+ );
334
+ }
335
+
336
+ /**
337
+ * @author Vova Feldman (@svovaf)
338
+ * @since 1.1.3
339
+ *
340
+ * @return string
341
+ */
342
+ function get_parent_type() {
343
+ return $this->_parent_type;
344
+ }
345
+
346
+ /**
347
+ * @author Vova Feldman (@svovaf)
348
+ * @since 1.1.3
349
+ *
350
+ * @return string
351
+ */
352
+ function get_raw_slug() {
353
+ return $this->_menu_slug;
354
+ }
355
+
356
+ /**
357
+ * Get plugin's original menu slug.
358
+ *
359
+ * @author Vova Feldman (@svovaf)
360
+ * @since 1.1.3
361
+ *
362
+ * @return string
363
+ */
364
+ function get_original_menu_slug() {
365
+ if ( 'cpt' === $this->_type ) {
366
+ return add_query_arg( array(
367
+ 'post_type' => $this->_menu_slug
368
+ ), 'edit.php' );
369
+ }
370
+
371
+ if ( false === strpos( $this->_menu_slug, '.php?' ) ) {
372
+ return $this->_menu_slug;
373
+ } else {
374
+ return $this->_module_unique_affix;
375
+ }
376
+ }
377
+
378
+ /**
379
+ * @author Vova Feldman (@svovaf)
380
+ * @since 1.1.3
381
+ *
382
+ * @return string
383
+ */
384
+ function get_top_level_menu_slug() {
385
+ return $this->has_custom_parent() ?
386
+ $this->get_parent_slug() :
387
+ $this->get_raw_slug();
388
+ }
389
+
390
+ /**
391
+ * Is user on plugin's admin activation page.
392
+ *
393
+ * @author Vova Feldman (@svovaf)
394
+ * @since 1.0.8
395
+ *
396
+ * @return bool
397
+ */
398
+ function is_main_settings_page() {
399
+ if ( $this->_menu_exists &&
400
+ ( fs_is_plugin_page( $this->_menu_slug ) || fs_is_plugin_page( $this->_module_unique_affix ) )
401
+ ) {
402
+ /**
403
+ * Module has a settings menu and the context page is the main settings page, so assume it's in
404
+ * activation (doesn't really check if already opted-in/skipped or not).
405
+ *
406
+ * @since 1.2.2
407
+ */
408
+ return true;
409
+ }
410
+
411
+ global $pagenow;
412
+ if ( ( WP_FS__MODULE_TYPE_THEME === $this->_module_type ) && Freemius::is_themes_page() ) {
413
+ /**
414
+ * In activation only when show_optin query string param is given.
415
+ *
416
+ * @since 1.2.2
417
+ */
418
+ return fs_request_get_bool( $this->_module_unique_affix . '_show_optin' );
419
+ }
420
+
421
+ return false;
422
+ }
423
+
424
+ #region Submenu Override
425
+
426
+ /**
427
+ * Override submenu's action.
428
+ *
429
+ * @author Vova Feldman (@svovaf)
430
+ * @since 1.1.0
431
+ *
432
+ * @param string $parent_slug
433
+ * @param string $menu_slug
434
+ * @param callable $function
435
+ *
436
+ * @return false|string If submenu exist, will return the hook name.
437
+ */
438
+ function override_submenu_action( $parent_slug, $menu_slug, $function ) {
439
+ global $submenu;
440
+
441
+ $menu_slug = plugin_basename( $menu_slug );
442
+ $parent_slug = plugin_basename( $parent_slug );
443
+
444
+ if ( ! isset( $submenu[ $parent_slug ] ) ) {
445
+ // Parent menu not exist.
446
+ return false;
447
+ }
448
+
449
+ $found_submenu_item = false;
450
+ foreach ( $submenu[ $parent_slug ] as $submenu_item ) {
451
+ if ( $menu_slug === $submenu_item[2] ) {
452
+ $found_submenu_item = $submenu_item;
453
+ break;
454
+ }
455
+ }
456
+
457
+ if ( false === $found_submenu_item ) {
458
+ // Submenu item not found.
459
+ return false;
460
+ }
461
+
462
+ // Remove current function.
463
+ $hookname = get_plugin_page_hookname( $menu_slug, $parent_slug );
464
+ remove_all_actions( $hookname );
465
+
466
+ // Attach new action.
467
+ add_action( $hookname, $function );
468
+
469
+ return $hookname;
470
+ }
471
+
472
+ #endregion Submenu Override
473
+
474
+ #region Top level menu Override
475
+
476
+ /**
477
+ * Find plugin's admin dashboard main menu item.
478
+ *
479
+ * @author Vova Feldman (@svovaf)
480
+ * @since 1.0.2
481
+ *
482
+ * @return string[]|false
483
+ */
484
+ private function find_top_level_menu() {
485
+ global $menu;
486
+
487
+ $position = - 1;
488
+ $found_menu = false;
489
+
490
+ $menu_slug = $this->get_raw_slug();
491
+
492
+ $hook_name = get_plugin_page_hookname( $menu_slug, '' );
493
+ foreach ( $menu as $pos => $m ) {
494
+ if ( $menu_slug === $m[2] ) {
495
+ $position = $pos;
496
+ $found_menu = $m;
497
+ break;
498
+ }
499
+ }
500
+
501
+ if ( false === $found_menu ) {
502
+ return false;
503
+ }
504
+
505
+ return array(
506
+ 'menu' => $found_menu,
507
+ 'position' => $position,
508
+ 'hook_name' => $hook_name
509
+ );
510
+ }
511
+
512
+ /**
513
+ * Find plugin's admin dashboard main submenu item.
514
+ *
515
+ * @author Vova Feldman (@svovaf)
516
+ * @since 1.2.1.6
517
+ *
518
+ * @return array|false
519
+ */
520
+ private function find_main_submenu() {
521
+ global $submenu;
522
+
523
+ $top_level_menu_slug = $this->get_top_level_menu_slug();
524
+
525
+ if ( ! isset( $submenu[ $top_level_menu_slug ] ) ) {
526
+ return false;
527
+ }
528
+
529
+ $submenu_slug = $this->get_raw_slug();
530
+
531
+ $position = - 1;
532
+ $found_submenu = false;
533
+
534
+ $hook_name = get_plugin_page_hookname( $submenu_slug, '' );
535
+
536
+ foreach ( $submenu[ $top_level_menu_slug ] as $pos => $sub ) {
537
+ if ( $submenu_slug === $sub[2] ) {
538
+ $position = $pos;
539
+ $found_submenu = $sub;
540
+ }
541
+ }
542
+
543
+ if ( false === $found_submenu ) {
544
+ return false;
545
+ }
546
+
547
+ return array(
548
+ 'menu' => $found_submenu,
549
+ 'parent_slug' => $top_level_menu_slug,
550
+ 'position' => $position,
551
+ 'hook_name' => $hook_name
552
+ );
553
+ }
554
+
555
+ /**
556
+ * Remove all sub-menu items.
557
+ *
558
+ * @author Vova Feldman (@svovaf)
559
+ * @since 1.0.7
560
+ *
561
+ * @return bool If submenu with plugin's menu slug was found.
562
+ */
563
+ private function remove_all_submenu_items() {
564
+ global $submenu;
565
+
566
+ $menu_slug = $this->get_raw_slug();
567
+
568
+ if ( ! isset( $submenu[ $menu_slug ] ) ) {
569
+ return false;
570
+ }
571
+
572
+ /**
573
+ * This method is NOT executed for WordPress.org themes.
574
+ * Since we maintain only one version of the SDK we added this small
575
+ * hack to avoid the error from Theme Check since it's a false-positive.
576
+ *
577
+ * @author Vova Feldman (@svovaf)
578
+ * @since 1.2.2.7
579
+ */
580
+ $submenu_ref = &$submenu;
581
+ $submenu_ref[ $menu_slug ] = array();
582
+
583
+ return true;
584
+ }
585
+
586
+ /**
587
+ *
588
+ * @author Vova Feldman (@svovaf)
589
+ * @since 1.0.9
590
+ *
591
+ * @return false|array[string]mixed
592
+ */
593
+ function remove_menu_item() {
594
+ $this->_logger->entrance();
595
+
596
+ // Find main menu item.
597
+ $menu = $this->find_top_level_menu();
598
+
599
+ if ( false === $menu ) {
600
+ return false;
601
+ }
602
+
603
+ // Remove it with its actions.
604
+ remove_all_actions( $menu['hook_name'] );
605
+
606
+ // Remove all submenu items.
607
+ $this->remove_all_submenu_items();
608
+
609
+ return $menu;
610
+ }
611
+
612
+ /**
613
+ * Get module's main admin setting page URL.
614
+ *
615
+ * @todo This method was only tested for wp.org compliant themes with a submenu item. Need to test for plugins with top level, submenu, and CPT top level, menu items.
616
+ *
617
+ * @author Vova Feldman (@svovaf)
618
+ * @since 1.2.2.7
619
+ *
620
+ * @return string
621
+ */
622
+ function main_menu_url() {
623
+ $this->_logger->entrance();
624
+
625
+ if ( $this->_is_top_level ) {
626
+ $menu = $this->find_top_level_menu();
627
+ } else {
628
+ $menu = $this->find_main_submenu();
629
+ }
630
+
631
+ $parent_slug = isset( $menu['parent_slug'] ) ?
632
+ $menu['parent_slug'] :
633
+ 'admin.php';
634
+
635
+ return admin_url( $parent_slug . '?page=' . $menu['menu'][2] );
636
+ }
637
+
638
+ /**
639
+ * @author Vova Feldman (@svovaf)
640
+ * @since 1.1.4
641
+ *
642
+ * @param callable $function
643
+ *
644
+ * @return false|array[string]mixed
645
+ */
646
+ function override_menu_item( $function ) {
647
+ $found_menu = $this->remove_menu_item();
648
+
649
+ if ( false === $found_menu ) {
650
+ return false;
651
+ }
652
+
653
+ if ( ! $this->is_top_level() || ! $this->is_cpt() ) {
654
+ $menu_slug = plugin_basename( $this->get_slug() );
655
+
656
+ $hookname = get_plugin_page_hookname( $menu_slug, '' );
657
+
658
+ // Override menu action.
659
+ add_action( $hookname, $function );
660
+ } else {
661
+ global $menu;
662
+
663
+ // Remove original CPT menu.
664
+ unset( $menu[ $found_menu['position'] ] );
665
+
666
+ // Create new top-level menu action.
667
+ $hookname = self::add_page(
668
+ $found_menu['menu'][3],
669
+ $found_menu['menu'][0],
670
+ 'manage_options',
671
+ $this->get_slug(),
672
+ $function,
673
+ $found_menu['menu'][6],
674
+ $found_menu['position']
675
+ );
676
+ }
677
+
678
+ return $hookname;
679
+ }
680
+
681
+ /**
682
+ * Adds a counter to the module's top level menu item.
683
+ *
684
+ * @author Vova Feldman (@svovaf)
685
+ * @since 1.2.1.5
686
+ *
687
+ * @param int $counter
688
+ * @param string $class
689
+ */
690
+ function add_counter_to_menu_item( $counter = 1, $class = '' ) {
691
+ global $menu, $submenu;
692
+
693
+ $mask = '%s <span class="update-plugins %s count-%3$s" aria-hidden="true"><span>%3$s<span class="screen-reader-text">%3$s notifications</span></span></span>';
694
+
695
+ /**
696
+ * This method is NOT executed for WordPress.org themes.
697
+ * Since we maintain only one version of the SDK we added this small
698
+ * hack to avoid the error from Theme Check since it's a false-positive.
699
+ *
700
+ * @author Vova Feldman (@svovaf)
701
+ * @since 1.2.2.7
702
+ */
703
+ $menu_ref = &$menu;
704
+ $submenu_ref = &$submenu;
705
+
706
+ if ( $this->_is_top_level ) {
707
+ // Find main menu item.
708
+ $found_menu = $this->find_top_level_menu();
709
+
710
+ if ( false !== $found_menu ) {
711
+ // Override menu label.
712
+ $menu_ref[ $found_menu['position'] ][0] = sprintf(
713
+ $mask,
714
+ $found_menu['menu'][0],
715
+ $class,
716
+ $counter
717
+ );
718
+ }
719
+ } else {
720
+ $found_submenu = $this->find_main_submenu();
721
+
722
+ if ( false !== $found_submenu ) {
723
+ // Override menu label.
724
+ $submenu_ref[ $found_submenu['parent_slug'] ][ $found_submenu['position'] ][0] = sprintf(
725
+ $mask,
726
+ $found_submenu['menu'][0],
727
+ $class,
728
+ $counter
729
+ );
730
+ }
731
+ }
732
+ }
733
+
734
+ #endregion Top level menu Override
735
+
736
+ /**
737
+ * Add a top-level menu page.
738
+ *
739
+ * Note for WordPress.org Theme/Plugin reviewer:
740
+ *
741
+ * This is a replication of `add_menu_page()` to avoid Theme Check warning.
742
+ *
743
+ * Why?
744
+ * ====
745
+ * Freemius is an SDK for plugin and theme developers. Since the core
746
+ * of the SDK is relevant both for plugins and themes, for obvious reasons,
747
+ * we only develop and maintain one code base.
748
+ *
749
+ * This method will not run for wp.org themes (only plugins) since theme
750
+ * admin settings/options are now only allowed in the customizer.
751
+ *
752
+ * If you have any questions or need clarifications, please don't hesitate
753
+ * pinging me on slack, my username is @svovaf.
754
+ *
755
+ * @author Vova Feldman (@svovaf)
756
+ * @since 1.2.2
757
+ *
758
+ * @param string $page_title The text to be displayed in the title tags of the page when the menu is
759
+ * selected.
760
+ * @param string $menu_title The text to be used for the menu.
761
+ * @param string $capability The capability required for this menu to be displayed to the user.
762
+ * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu).
763
+ * @param callable|string $function The function to be called to output the content for this page.
764
+ * @param string $icon_url The URL to the icon to be used for this menu.
765
+ * * Pass a base64-encoded SVG using a data URI, which will be colored to
766
+ * match the color scheme. This should begin with
767
+ * 'data:image/svg+xml;base64,'.
768
+ * * Pass the name of a Dashicons helper class to use a font icon,
769
+ * e.g. 'dashicons-chart-pie'.
770
+ * * Pass 'none' to leave div.wp-menu-image empty so an icon can be added
771
+ * via CSS.
772
+ * @param int $position The position in the menu order this one should appear.
773
+ *
774
+ * @return string The resulting page's hook_suffix.
775
+ */
776
+ static function add_page(
777
+ $page_title,
778
+ $menu_title,
779
+ $capability,
780
+ $menu_slug,
781
+ $function = '',
782
+ $icon_url = '',
783
+ $position = null
784
+ ) {
785
+ $fn = 'add_menu' . '_page';
786
+
787
+ return $fn(
788
+ $page_title,
789
+ $menu_title,
790
+ $capability,
791
+ $menu_slug,
792
+ $function,
793
+ $icon_url,
794
+ $position
795
+ );
796
+ }
797
+
798
+ /**
799
+ * Add a submenu page.
800
+ *
801
+ * Note for WordPress.org Theme/Plugin reviewer:
802
+ *
803
+ * This is a replication of `add_submenu_page()` to avoid Theme Check warning.
804
+ *
805
+ * Why?
806
+ * ====
807
+ * Freemius is an SDK for plugin and theme developers. Since the core
808
+ * of the SDK is relevant both for plugins and themes, for obvious reasons,
809
+ * we only develop and maintain one code base.
810
+ *
811
+ * This method will not run for wp.org themes (only plugins) since theme
812
+ * admin settings/options are now only allowed in the customizer.
813
+ *
814
+ * If you have any questions or need clarifications, please don't hesitate
815
+ * pinging me on slack, my username is @svovaf.
816
+ *
817
+ * @author Vova Feldman (@svovaf)
818
+ * @since 1.2.2
819
+ *
820
+ * @param string $parent_slug The slug name for the parent menu (or the file name of a standard
821
+ * WordPress admin page).
822
+ * @param string $page_title The text to be displayed in the title tags of the page when the menu is
823
+ * selected.
824
+ * @param string $menu_title The text to be used for the menu.
825
+ * @param string $capability The capability required for this menu to be displayed to the user.
826
+ * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu).
827
+ * @param callable|string $function The function to be called to output the content for this page.
828
+ *
829
+ * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability
830
+ * required.
831
+ */
832
+ static function add_subpage(
833
+ $parent_slug,
834
+ $page_title,
835
+ $menu_title,
836
+ $capability,
837
+ $menu_slug,
838
+ $function = ''
839
+ ) {
840
+ $fn = 'add_submenu' . '_page';
841
+
842
+ return $fn( $parent_slug,
843
+ $page_title,
844
+ $menu_title,
845
+ $capability,
846
+ $menu_slug,
847
+ $function
848
+ );
849
+ }
850
  }
freemius/includes/managers/class-fs-cache-manager.php CHANGED
@@ -1,281 +1,281 @@
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.1.6
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- class FS_Cache_Manager {
14
- /**
15
- * @var FS_Option_Manager
16
- */
17
- private $_options;
18
- /**
19
- * @var FS_Logger
20
- */
21
- private $_logger;
22
-
23
- /**
24
- * @var FS_Cache_Manager[]
25
- */
26
- private static $_MANAGERS = array();
27
-
28
- /**
29
- * @author Vova Feldman (@svovaf)
30
- * @since 1.1.3
31
- *
32
- * @param string $id
33
- */
34
- private function __construct( $id ) {
35
- $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_cach_mngr_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
36
-
37
- $this->_logger->entrance();
38
- $this->_logger->log( 'id = ' . $id );
39
-
40
- $this->_options = FS_Option_Manager::get_manager( $id, true );
41
- }
42
-
43
- /**
44
- * @author Vova Feldman (@svovaf)
45
- * @since 1.1.6
46
- *
47
- * @param $id
48
- *
49
- * @return FS_Cache_Manager
50
- */
51
- static function get_manager( $id ) {
52
- $id = strtolower( $id );
53
-
54
- if ( ! isset( self::$_MANAGERS[ $id ] ) ) {
55
- self::$_MANAGERS[ $id ] = new FS_Cache_Manager( $id );
56
- }
57
-
58
- return self::$_MANAGERS[ $id ];
59
- }
60
-
61
- /**
62
- * @author Vova Feldman (@svovaf)
63
- * @since 1.1.6
64
- *
65
- * @return bool
66
- */
67
- function is_empty() {
68
- $this->_logger->entrance();
69
-
70
- return $this->_options->is_empty();
71
- }
72
-
73
- /**
74
- * @author Vova Feldman (@svovaf)
75
- * @since 1.1.6
76
- */
77
- function clear() {
78
- $this->_logger->entrance();
79
-
80
- $this->_options->clear( true );
81
- }
82
-
83
- /**
84
- * Delete cache manager from DB.
85
- *
86
- * @author Vova Feldman (@svovaf)
87
- * @since 1.0.9
88
- */
89
- function delete() {
90
- $this->_options->delete();
91
- }
92
-
93
- /**
94
- * Check if there's a cached item.
95
- *
96
- * @author Vova Feldman (@svovaf)
97
- * @since 1.1.6
98
- *
99
- * @param string $key
100
- *
101
- * @return bool
102
- */
103
- function has( $key ) {
104
- $cache_entry = $this->_options->get_option( $key, false );
105
-
106
- return ( is_object( $cache_entry ) &&
107
- isset( $cache_entry->timestamp ) &&
108
- is_numeric( $cache_entry->timestamp )
109
- );
110
- }
111
-
112
- /**
113
- * Check if there's a valid cached item.
114
- *
115
- * @author Vova Feldman (@svovaf)
116
- * @since 1.1.6
117
- *
118
- * @param string $key
119
- * @param null|int $expiration Since 1.2.2.7
120
- *
121
- * @return bool
122
- */
123
- function has_valid( $key, $expiration = null ) {
124
- $cache_entry = $this->_options->get_option( $key, false );
125
-
126
- $is_valid = ( is_object( $cache_entry ) &&
127
- isset( $cache_entry->timestamp ) &&
128
- is_numeric( $cache_entry->timestamp ) &&
129
- $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME
130
- );
131
-
132
- if ( $is_valid &&
133
- is_numeric( $expiration ) &&
134
- isset( $cache_entry->created ) &&
135
- is_numeric( $cache_entry->created ) &&
136
- $cache_entry->created + $expiration < WP_FS__SCRIPT_START_TIME
137
- ) {
138
- /**
139
- * Even if the cache is still valid, since we are checking for validity
140
- * with an explicit expiration period, if the period has past, return
141
- * `false` as if the cache is invalid.
142
- *
143
- * @since 1.2.2.7
144
- */
145
- $is_valid = false;
146
- }
147
-
148
- return $is_valid;
149
- }
150
-
151
- /**
152
- * @author Vova Feldman (@svovaf)
153
- * @since 1.1.6
154
- *
155
- * @param string $key
156
- * @param mixed $default
157
- *
158
- * @return mixed
159
- */
160
- function get( $key, $default = null ) {
161
- $this->_logger->entrance( 'key = ' . $key );
162
-
163
- $cache_entry = $this->_options->get_option( $key, false );
164
-
165
- if ( is_object( $cache_entry ) &&
166
- isset( $cache_entry->timestamp ) &&
167
- is_numeric( $cache_entry->timestamp )
168
- ) {
169
- return $cache_entry->result;
170
- }
171
-
172
- return is_object($default) ? clone $default : $default;
173
- }
174
-
175
- /**
176
- * @author Vova Feldman (@svovaf)
177
- * @since 1.1.6
178
- *
179
- * @param string $key
180
- * @param mixed $default
181
- *
182
- * @return mixed
183
- */
184
- function get_valid( $key, $default = null ) {
185
- $this->_logger->entrance( 'key = ' . $key );
186
-
187
- $cache_entry = $this->_options->get_option( $key, false );
188
-
189
- if ( is_object( $cache_entry ) &&
190
- isset( $cache_entry->timestamp ) &&
191
- is_numeric( $cache_entry->timestamp ) &&
192
- $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME
193
- ) {
194
- return $cache_entry->result;
195
- }
196
-
197
- return is_object($default) ? clone $default : $default;
198
- }
199
-
200
- /**
201
- * @author Vova Feldman (@svovaf)
202
- * @since 1.1.6
203
- *
204
- * @param string $key
205
- * @param mixed $value
206
- * @param int $expiration
207
- */
208
- function set( $key, $value, $expiration = WP_FS__TIME_24_HOURS_IN_SEC ) {
209
- $this->_logger->entrance( 'key = ' . $key );
210
-
211
- $cache_entry = new stdClass();
212
-
213
- $cache_entry->result = $value;
214
- $cache_entry->created = WP_FS__SCRIPT_START_TIME;
215
- $cache_entry->timestamp = WP_FS__SCRIPT_START_TIME + $expiration;
216
- $this->_options->set_option( $key, $cache_entry, true );
217
- }
218
-
219
- /**
220
- * Get cached record expiration, or false if not cached or expired.
221
- *
222
- * @author Vova Feldman (@svovaf)
223
- * @since 1.1.7.3
224
- *
225
- * @param string $key
226
- *
227
- * @return bool|int
228
- */
229
- function get_record_expiration( $key ) {
230
- $this->_logger->entrance( 'key = ' . $key );
231
-
232
- $cache_entry = $this->_options->get_option( $key, false );
233
-
234
- if ( is_object( $cache_entry ) &&
235
- isset( $cache_entry->timestamp ) &&
236
- is_numeric( $cache_entry->timestamp ) &&
237
- $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME
238
- ) {
239
- return $cache_entry->timestamp;
240
- }
241
-
242
- return false;
243
- }
244
-
245
- /**
246
- * Purge cached item.
247
- *
248
- * @author Vova Feldman (@svovaf)
249
- * @since 1.1.6
250
- *
251
- * @param string $key
252
- */
253
- function purge( $key ) {
254
- $this->_logger->entrance( 'key = ' . $key );
255
-
256
- $this->_options->unset_option( $key, true );
257
- }
258
-
259
- /**
260
- * Set cached item as expired.
261
- *
262
- * @author Vova Feldman (@svovaf)
263
- * @since 1.2.2.7
264
- *
265
- * @param string $key
266
- */
267
- function expire( $key ) {
268
- $this->_logger->entrance( 'key = ' . $key );
269
-
270
- $cache_entry = $this->_options->get_option( $key, false );
271
-
272
- if ( is_object( $cache_entry ) &&
273
- isset( $cache_entry->timestamp ) &&
274
- is_numeric( $cache_entry->timestamp ))
275
- {
276
- // Set to expired.
277
- $cache_entry->timestamp = WP_FS__SCRIPT_START_TIME;
278
- $this->_options->set_option( $key, $cache_entry, true );
279
- }
280
- }
281
  }
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.1.6
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ class FS_Cache_Manager {
14
+ /**
15
+ * @var FS_Option_Manager
16
+ */
17
+ private $_options;
18
+ /**
19
+ * @var FS_Logger
20
+ */
21
+ private $_logger;
22
+
23
+ /**
24
+ * @var FS_Cache_Manager[]
25
+ */
26
+ private static $_MANAGERS = array();
27
+
28
+ /**
29
+ * @author Vova Feldman (@svovaf)
30
+ * @since 1.1.3
31
+ *
32
+ * @param string $id
33
+ */
34
+ private function __construct( $id ) {
35
+ $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_cach_mngr_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
36
+
37
+ $this->_logger->entrance();
38
+ $this->_logger->log( 'id = ' . $id );
39
+
40
+ $this->_options = FS_Option_Manager::get_manager( $id, true );
41
+ }
42
+
43
+ /**
44
+ * @author Vova Feldman (@svovaf)
45
+ * @since 1.1.6
46
+ *
47
+ * @param $id
48
+ *
49
+ * @return FS_Cache_Manager
50
+ */
51
+ static function get_manager( $id ) {
52
+ $id = strtolower( $id );
53
+
54
+ if ( ! isset( self::$_MANAGERS[ $id ] ) ) {
55
+ self::$_MANAGERS[ $id ] = new FS_Cache_Manager( $id );
56
+ }
57
+
58
+ return self::$_MANAGERS[ $id ];
59
+ }
60
+
61
+ /**
62
+ * @author Vova Feldman (@svovaf)
63
+ * @since 1.1.6
64
+ *
65
+ * @return bool
66
+ */
67
+ function is_empty() {
68
+ $this->_logger->entrance();
69
+
70
+ return $this->_options->is_empty();
71
+ }
72
+
73
+ /**
74
+ * @author Vova Feldman (@svovaf)
75
+ * @since 1.1.6
76
+ */
77
+ function clear() {
78
+ $this->_logger->entrance();
79
+
80
+ $this->_options->clear( true );
81
+ }
82
+
83
+ /**
84
+ * Delete cache manager from DB.
85
+ *
86
+ * @author Vova Feldman (@svovaf)
87
+ * @since 1.0.9
88
+ */
89
+ function delete() {
90
+ $this->_options->delete();
91
+ }
92
+
93
+ /**
94
+ * Check if there's a cached item.
95
+ *
96
+ * @author Vova Feldman (@svovaf)
97
+ * @since 1.1.6
98
+ *
99
+ * @param string $key
100
+ *
101
+ * @return bool
102
+ */
103
+ function has( $key ) {
104
+ $cache_entry = $this->_options->get_option( $key, false );
105
+
106
+ return ( is_object( $cache_entry ) &&
107
+ isset( $cache_entry->timestamp ) &&
108
+ is_numeric( $cache_entry->timestamp )
109
+ );
110
+ }
111
+
112
+ /**
113
+ * Check if there's a valid cached item.
114
+ *
115
+ * @author Vova Feldman (@svovaf)
116
+ * @since 1.1.6
117
+ *
118
+ * @param string $key
119
+ * @param null|int $expiration Since 1.2.2.7
120
+ *
121
+ * @return bool
122
+ */
123
+ function has_valid( $key, $expiration = null ) {
124
+ $cache_entry = $this->_options->get_option( $key, false );
125
+
126
+ $is_valid = ( is_object( $cache_entry ) &&
127
+ isset( $cache_entry->timestamp ) &&
128
+ is_numeric( $cache_entry->timestamp ) &&
129
+ $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME
130
+ );
131
+
132
+ if ( $is_valid &&
133
+ is_numeric( $expiration ) &&
134
+ isset( $cache_entry->created ) &&
135
+ is_numeric( $cache_entry->created ) &&
136
+ $cache_entry->created + $expiration < WP_FS__SCRIPT_START_TIME
137
+ ) {
138
+ /**
139
+ * Even if the cache is still valid, since we are checking for validity
140
+ * with an explicit expiration period, if the period has past, return
141
+ * `false` as if the cache is invalid.
142
+ *
143
+ * @since 1.2.2.7
144
+ */
145
+ $is_valid = false;
146
+ }
147
+
148
+ return $is_valid;
149
+ }
150
+
151
+ /**
152
+ * @author Vova Feldman (@svovaf)
153
+ * @since 1.1.6
154
+ *
155
+ * @param string $key
156
+ * @param mixed $default
157
+ *
158
+ * @return mixed
159
+ */
160
+ function get( $key, $default = null ) {
161
+ $this->_logger->entrance( 'key = ' . $key );
162
+
163
+ $cache_entry = $this->_options->get_option( $key, false );
164
+
165
+ if ( is_object( $cache_entry ) &&
166
+ isset( $cache_entry->timestamp ) &&
167
+ is_numeric( $cache_entry->timestamp )
168
+ ) {
169
+ return $cache_entry->result;
170
+ }
171
+
172
+ return is_object($default) ? clone $default : $default;
173
+ }
174
+
175
+ /**
176
+ * @author Vova Feldman (@svovaf)
177
+ * @since 1.1.6
178
+ *
179
+ * @param string $key
180
+ * @param mixed $default
181
+ *
182
+ * @return mixed
183
+ */
184
+ function get_valid( $key, $default = null ) {
185
+ $this->_logger->entrance( 'key = ' . $key );
186
+
187
+ $cache_entry = $this->_options->get_option( $key, false );
188
+
189
+ if ( is_object( $cache_entry ) &&
190
+ isset( $cache_entry->timestamp ) &&
191
+ is_numeric( $cache_entry->timestamp ) &&
192
+ $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME
193
+ ) {
194
+ return $cache_entry->result;
195
+ }
196
+
197
+ return is_object($default) ? clone $default : $default;
198
+ }
199
+
200
+ /**
201
+ * @author Vova Feldman (@svovaf)
202
+ * @since 1.1.6
203
+ *
204
+ * @param string $key
205
+ * @param mixed $value
206
+ * @param int $expiration
207
+ */
208
+ function set( $key, $value, $expiration = WP_FS__TIME_24_HOURS_IN_SEC ) {
209
+ $this->_logger->entrance( 'key = ' . $key );
210
+
211
+ $cache_entry = new stdClass();
212
+
213
+ $cache_entry->result = $value;
214
+ $cache_entry->created = WP_FS__SCRIPT_START_TIME;
215
+ $cache_entry->timestamp = WP_FS__SCRIPT_START_TIME + $expiration;
216
+ $this->_options->set_option( $key, $cache_entry, true );
217
+ }
218
+
219
+ /**
220
+ * Get cached record expiration, or false if not cached or expired.
221
+ *
222
+ * @author Vova Feldman (@svovaf)
223
+ * @since 1.1.7.3
224
+ *
225
+ * @param string $key
226
+ *
227
+ * @return bool|int
228
+ */
229
+ function get_record_expiration( $key ) {
230
+ $this->_logger->entrance( 'key = ' . $key );
231
+
232
+ $cache_entry = $this->_options->get_option( $key, false );
233
+
234
+ if ( is_object( $cache_entry ) &&
235
+ isset( $cache_entry->timestamp ) &&
236
+ is_numeric( $cache_entry->timestamp ) &&
237
+ $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME
238
+ ) {
239
+ return $cache_entry->timestamp;
240
+ }
241
+
242
+ return false;
243
+ }
244
+
245
+ /**
246
+ * Purge cached item.
247
+ *
248
+ * @author Vova Feldman (@svovaf)
249
+ * @since 1.1.6
250
+ *
251
+ * @param string $key
252
+ */
253
+ function purge( $key ) {
254
+ $this->_logger->entrance( 'key = ' . $key );
255
+
256
+ $this->_options->unset_option( $key, true );
257
+ }
258
+
259
+ /**
260
+ * Set cached item as expired.
261
+ *
262
+ * @author Vova Feldman (@svovaf)
263
+ * @since 1.2.2.7
264
+ *
265
+ * @param string $key
266
+ */
267
+ function expire( $key ) {
268
+ $this->_logger->entrance( 'key = ' . $key );
269
+
270
+ $cache_entry = $this->_options->get_option( $key, false );
271
+
272
+ if ( is_object( $cache_entry ) &&
273
+ isset( $cache_entry->timestamp ) &&
274
+ is_numeric( $cache_entry->timestamp ))
275
+ {
276
+ // Set to expired.
277
+ $cache_entry->timestamp = WP_FS__SCRIPT_START_TIME;
278
+ $this->_options->set_option( $key, $cache_entry, true );
279
+ }
280
+ }
281
  }
freemius/includes/managers/class-fs-key-value-storage.php CHANGED
@@ -1,328 +1,328 @@
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.7
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * Class FS_Key_Value_Storage
15
- *
16
- * @property int $install_timestamp
17
- * @property int $activation_timestamp
18
- * @property int $sync_timestamp
19
- * @property object $sync_cron
20
- * @property int $install_sync_timestamp
21
- * @property array $connectivity_test
22
- * @property array $is_on
23
- * @property object $trial_plan
24
- * @property bool $has_trial_plan
25
- * @property bool $trial_promotion_shown
26
- * @property string $sdk_version
27
- * @property string $sdk_last_version
28
- * @property bool $sdk_upgrade_mode
29
- * @property bool $sdk_downgrade_mode
30
- * @property bool $plugin_upgrade_mode
31
- * @property bool $plugin_downgrade_mode
32
- * @property string $plugin_version
33
- * @property string $plugin_last_version
34
- * @property bool $is_plugin_new_install
35
- * @property bool $was_plugin_loaded
36
- * @property object $plugin_main_file
37
- * @property bool $prev_is_premium
38
- * @property array $is_anonymous
39
- * @property bool $is_pending_activation
40
- * @property bool $sticky_optin_added
41
- * @property object $uninstall_reason
42
- * @property object $subscription
43
- */
44
- class FS_Key_Value_Storage implements ArrayAccess, Iterator, Countable {
45
- /**
46
- * @var string
47
- */
48
- protected $_id;
49
- /**
50
- * @since 1.2.2
51
- *
52
- * @var string
53
- */
54
- protected $_secondary_id;
55
- /**
56
- * @var array
57
- */
58
- protected $_data;
59
-
60
- /**
61
- * @var FS_Plugin_Manager[]
62
- */
63
- private static $_instances = array();
64
- /**
65
- * @var FS_Logger
66
- */
67
- protected $_logger;
68
-
69
- /**
70
- * @param string $id
71
- * @param string $secondary_id
72
- *
73
- * @return FS_Key_Value_Storage
74
- */
75
- static function instance( $id, $secondary_id ) {
76
- $key = $id . ':' . $secondary_id;
77
- if ( ! isset( self::$_instances[ $key ] ) ) {
78
- self::$_instances[ $key ] = new FS_Key_Value_Storage( $id, $secondary_id );
79
- }
80
-
81
- return self::$_instances[ $key ];
82
- }
83
-
84
- protected function __construct( $id, $secondary_id ) {
85
- $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $secondary_id . '_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
86
-
87
- $this->_secondary_id = $secondary_id;
88
- $this->_id = $id;
89
- $this->load();
90
- }
91
-
92
- protected function get_option_manager() {
93
- return FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true );
94
- }
95
-
96
- protected function get_all_data() {
97
- return $this->get_option_manager()->get_option( $this->_id, array() );
98
- }
99
-
100
- /**
101
- * Load plugin data from local DB.
102
- *
103
- * @author Vova Feldman (@svovaf)
104
- * @since 1.0.7
105
- */
106
- function load() {
107
- $all_plugins_data = $this->get_all_data();
108
- $this->_data = isset( $all_plugins_data[ $this->_secondary_id ] ) ?
109
- $all_plugins_data[ $this->_secondary_id ] :
110
- array();
111
- }
112
-
113
- /**
114
- * @author Vova Feldman (@svovaf)
115
- * @since 1.0.7
116
- *
117
- * @param string $key
118
- * @param mixed $value
119
- * @param bool $flush
120
- */
121
- function store( $key, $value, $flush = true ) {
122
- if ( $this->_logger->is_on() ) {
123
- $this->_logger->entrance( $key . ' = ' . var_export( $value, true ) );
124
- }
125
-
126
- if ( array_key_exists( $key, $this->_data ) && $value === $this->_data[ $key ] ) {
127
- // No need to store data if the value wasn't changed.
128
- return;
129
- }
130
-
131
- $all_data = $this->get_all_data();
132
-
133
- $this->_data[ $key ] = $value;
134
-
135
- $all_data[ $this->_secondary_id ] = $this->_data;
136
-
137
- $options_manager = $this->get_option_manager();
138
- $options_manager->set_option( $this->_id, $all_data, $flush );
139
- }
140
-
141
- /**
142
- * @author Vova Feldman (@svovaf)
143
- * @since 1.0.7
144
- *
145
- * @param bool $store
146
- * @param string[] $exceptions Set of keys to keep and not clear.
147
- */
148
- function clear_all( $store = true, $exceptions = array() ) {
149
- $new_data = array();
150
- foreach ( $exceptions as $key ) {
151
- if ( isset( $this->_data[ $key ] ) ) {
152
- $new_data[ $key ] = $this->_data[ $key ];
153
- }
154
- }
155
-
156
- $this->_data = $new_data;
157
-
158
- if ( $store ) {
159
- $all_data = $this->get_all_data();
160
- $all_data[ $this->_secondary_id ] = $this->_data;
161
- $options_manager = $this->get_option_manager();
162
- $options_manager->set_option( $this->_id, $all_data, true );
163
- }
164
- }
165
-
166
- /**
167
- * Delete key-value storage.
168
- *
169
- * @author Vova Feldman (@svovaf)
170
- * @since 1.0.9
171
- */
172
- function delete() {
173
- $this->_data = array();
174
-
175
- $all_data = $this->get_all_data();
176
- unset( $all_data[ $this->_secondary_id ] );
177
- $options_manager = $this->get_option_manager();
178
- $options_manager->set_option( $this->_id, $all_data, true );
179
- }
180
-
181
- /**
182
- * @author Vova Feldman (@svovaf)
183
- * @since 1.0.7
184
- *
185
- * @param string $key
186
- * @param bool $store
187
- */
188
- function remove( $key, $store = true ) {
189
- if ( ! array_key_exists( $key, $this->_data ) ) {
190
- return;
191
- }
192
-
193
- unset( $this->_data[ $key ] );
194
-
195
- if ( $store ) {
196
- $all_data = $this->get_all_data();
197
- $all_data[ $this->_secondary_id ] = $this->_data;
198
- $options_manager = $this->get_option_manager();
199
- $options_manager->set_option( $this->_id, $all_data, true );
200
- }
201
- }
202
-
203
- /**
204
- * @author Vova Feldman (@svovaf)
205
- * @since 1.0.7
206
- *
207
- * @param string $key
208
- * @param mixed $default
209
- *
210
- * @return bool|\FS_Plugin
211
- */
212
- function get( $key, $default = false ) {
213
- return array_key_exists( $key, $this->_data ) ?
214
- $this->_data[ $key ] :
215
- $default;
216
- }
217
-
218
-
219
- /* ArrayAccess + Magic Access (better for refactoring)
220
- -----------------------------------------------------------------------------------*/
221
- function __set( $k, $v ) {
222
- $this->store( $k, $v );
223
- }
224
-
225
- function __isset( $k ) {
226
- return array_key_exists( $k, $this->_data );
227
- }
228
-
229
- function __unset( $k ) {
230
- $this->remove( $k );
231
- }
232
-
233
- function __get( $k ) {
234
- return $this->get( $k, null );
235
- }
236
-
237
- function offsetSet( $k, $v ) {
238
- if ( is_null( $k ) ) {
239
- throw new Exception( 'Can\'t append value to request params.' );
240
- } else {
241
- $this->{$k} = $v;
242
- }
243
- }
244
-
245
- function offsetExists( $k ) {
246
- return array_key_exists( $k, $this->_data );
247
- }
248
-
249
- function offsetUnset( $k ) {
250
- unset( $this->$k );
251
- }
252
-
253
- function offsetGet( $k ) {
254
- return $this->get( $k, null );
255
- }
256
-
257
- /**
258
- * (PHP 5 &gt;= 5.0.0)<br/>
259
- * Return the current element
260
- *
261
- * @link http://php.net/manual/en/iterator.current.php
262
- * @return mixed Can return any type.
263
- */
264
- public function current() {
265
- return current( $this->_data );
266
- }
267
-
268
- /**
269
- * (PHP 5 &gt;= 5.0.0)<br/>
270
- * Move forward to next element
271
- *
272
- * @link http://php.net/manual/en/iterator.next.php
273
- * @return void Any returned value is ignored.
274
- */
275
- public function next() {
276
- next( $this->_data );
277
- }
278
-
279
- /**
280
- * (PHP 5 &gt;= 5.0.0)<br/>
281
- * Return the key of the current element
282
- *
283
- * @link http://php.net/manual/en/iterator.key.php
284
- * @return mixed scalar on success, or null on failure.
285
- */
286
- public function key() {
287
- return key( $this->_data );
288
- }
289
-
290
- /**
291
- * (PHP 5 &gt;= 5.0.0)<br/>
292
- * Checks if current position is valid
293
- *
294
- * @link http://php.net/manual/en/iterator.valid.php
295
- * @return boolean The return value will be casted to boolean and then evaluated.
296
- * Returns true on success or false on failure.
297
- */
298
- public function valid() {
299
- $key = key( $this->_data );
300
-
301
- return ( $key !== null && $key !== false );
302
- }
303
-
304
- /**
305
- * (PHP 5 &gt;= 5.0.0)<br/>
306
- * Rewind the Iterator to the first element
307
- *
308
- * @link http://php.net/manual/en/iterator.rewind.php
309
- * @return void Any returned value is ignored.
310
- */
311
- public function rewind() {
312
- reset( $this->_data );
313
- }
314
-
315
- /**
316
- * (PHP 5 &gt;= 5.1.0)<br/>
317
- * Count elements of an object
318
- *
319
- * @link http://php.net/manual/en/countable.count.php
320
- * @return int The custom count as an integer.
321
- * </p>
322
- * <p>
323
- * The return value is cast to an integer.
324
- */
325
- public function count() {
326
- return count( $this->_data );
327
- }
328
  }
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.7
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * Class FS_Key_Value_Storage
15
+ *
16
+ * @property int $install_timestamp
17
+ * @property int $activation_timestamp
18
+ * @property int $sync_timestamp
19
+ * @property object $sync_cron
20
+ * @property int $install_sync_timestamp
21
+ * @property array $connectivity_test
22
+ * @property array $is_on
23
+ * @property object $trial_plan
24
+ * @property bool $has_trial_plan
25
+ * @property bool $trial_promotion_shown
26
+ * @property string $sdk_version
27
+ * @property string $sdk_last_version
28
+ * @property bool $sdk_upgrade_mode
29
+ * @property bool $sdk_downgrade_mode
30
+ * @property bool $plugin_upgrade_mode
31
+ * @property bool $plugin_downgrade_mode
32
+ * @property string $plugin_version
33
+ * @property string $plugin_last_version
34
+ * @property bool $is_plugin_new_install
35
+ * @property bool $was_plugin_loaded
36
+ * @property object $plugin_main_file
37
+ * @property bool $prev_is_premium
38
+ * @property array $is_anonymous
39
+ * @property bool $is_pending_activation
40
+ * @property bool $sticky_optin_added
41
+ * @property object $uninstall_reason
42
+ * @property object $subscription
43
+ */
44
+ class FS_Key_Value_Storage implements ArrayAccess, Iterator, Countable {
45
+ /**
46
+ * @var string
47
+ */
48
+ protected $_id;
49
+ /**
50
+ * @since 1.2.2
51
+ *
52
+ * @var string
53
+ */
54
+ protected $_secondary_id;
55
+ /**
56
+ * @var array
57
+ */
58
+ protected $_data;
59
+
60
+ /**
61
+ * @var FS_Plugin_Manager[]
62
+ */
63
+ private static $_instances = array();
64
+ /**
65
+ * @var FS_Logger
66
+ */
67
+ protected $_logger;
68
+
69
+ /**
70
+ * @param string $id
71
+ * @param string $secondary_id
72
+ *
73
+ * @return FS_Key_Value_Storage
74
+ */
75
+ static function instance( $id, $secondary_id ) {
76
+ $key = $id . ':' . $secondary_id;
77
+ if ( ! isset( self::$_instances[ $key ] ) ) {
78
+ self::$_instances[ $key ] = new FS_Key_Value_Storage( $id, $secondary_id );
79
+ }
80
+
81
+ return self::$_instances[ $key ];
82
+ }
83
+
84
+ protected function __construct( $id, $secondary_id ) {
85
+ $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $secondary_id . '_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
86
+
87
+ $this->_secondary_id = $secondary_id;
88
+ $this->_id = $id;
89
+ $this->load();
90
+ }
91
+
92
+ protected function get_option_manager() {
93
+ return FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true );
94
+ }
95
+
96
+ protected function get_all_data() {
97
+ return $this->get_option_manager()->get_option( $this->_id, array() );
98
+ }
99
+
100
+ /**
101
+ * Load plugin data from local DB.
102
+ *
103
+ * @author Vova Feldman (@svovaf)
104
+ * @since 1.0.7
105
+ */
106
+ function load() {
107
+ $all_plugins_data = $this->get_all_data();
108
+ $this->_data = isset( $all_plugins_data[ $this->_secondary_id ] ) ?
109
+ $all_plugins_data[ $this->_secondary_id ] :
110
+ array();
111
+ }
112
+
113
+ /**
114
+ * @author Vova Feldman (@svovaf)
115
+ * @since 1.0.7
116
+ *
117
+ * @param string $key
118
+ * @param mixed $value
119
+ * @param bool $flush
120
+ */
121
+ function store( $key, $value, $flush = true ) {
122
+ if ( $this->_logger->is_on() ) {
123
+ $this->_logger->entrance( $key . ' = ' . var_export( $value, true ) );
124
+ }
125
+
126
+ if ( array_key_exists( $key, $this->_data ) && $value === $this->_data[ $key ] ) {
127
+ // No need to store data if the value wasn't changed.
128
+ return;
129
+ }
130
+
131
+ $all_data = $this->get_all_data();
132
+
133
+ $this->_data[ $key ] = $value;
134
+
135
+ $all_data[ $this->_secondary_id ] = $this->_data;
136
+
137
+ $options_manager = $this->get_option_manager();
138
+ $options_manager->set_option( $this->_id, $all_data, $flush );
139
+ }
140
+
141
+ /**
142
+ * @author Vova Feldman (@svovaf)
143
+ * @since 1.0.7
144
+ *
145
+ * @param bool $store
146
+ * @param string[] $exceptions Set of keys to keep and not clear.
147
+ */
148
+ function clear_all( $store = true, $exceptions = array() ) {
149
+ $new_data = array();
150
+ foreach ( $exceptions as $key ) {
151
+ if ( isset( $this->_data[ $key ] ) ) {
152
+ $new_data[ $key ] = $this->_data[ $key ];
153
+ }
154
+ }
155
+
156
+ $this->_data = $new_data;
157
+
158
+ if ( $store ) {
159
+ $all_data = $this->get_all_data();
160
+ $all_data[ $this->_secondary_id ] = $this->_data;
161
+ $options_manager = $this->get_option_manager();
162
+ $options_manager->set_option( $this->_id, $all_data, true );
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Delete key-value storage.
168
+ *
169
+ * @author Vova Feldman (@svovaf)
170
+ * @since 1.0.9
171
+ */
172
+ function delete() {
173
+ $this->_data = array();
174
+
175
+ $all_data = $this->get_all_data();
176
+ unset( $all_data[ $this->_secondary_id ] );
177
+ $options_manager = $this->get_option_manager();
178
+ $options_manager->set_option( $this->_id, $all_data, true );
179
+ }
180
+
181
+ /**
182
+ * @author Vova Feldman (@svovaf)
183
+ * @since 1.0.7
184
+ *
185
+ * @param string $key
186
+ * @param bool $store
187
+ */
188
+ function remove( $key, $store = true ) {
189
+ if ( ! array_key_exists( $key, $this->_data ) ) {
190
+ return;
191
+ }
192
+
193
+ unset( $this->_data[ $key ] );
194
+
195
+ if ( $store ) {
196
+ $all_data = $this->get_all_data();
197
+ $all_data[ $this->_secondary_id ] = $this->_data;
198
+ $options_manager = $this->get_option_manager();
199
+ $options_manager->set_option( $this->_id, $all_data, true );
200
+ }
201
+ }
202
+
203
+ /**
204
+ * @author Vova Feldman (@svovaf)
205
+ * @since 1.0.7
206
+ *
207
+ * @param string $key
208
+ * @param mixed $default
209
+ *
210
+ * @return bool|\FS_Plugin
211
+ */
212
+ function get( $key, $default = false ) {
213
+ return array_key_exists( $key, $this->_data ) ?
214
+ $this->_data[ $key ] :
215
+ $default;
216
+ }
217
+
218
+
219
+ /* ArrayAccess + Magic Access (better for refactoring)
220
+ -----------------------------------------------------------------------------------*/
221
+ function __set( $k, $v ) {
222
+ $this->store( $k, $v );
223
+ }
224
+
225
+ function __isset( $k ) {
226
+ return array_key_exists( $k, $this->_data );
227
+ }
228
+
229
+ function __unset( $k ) {
230
+ $this->remove( $k );
231
+ }
232
+
233
+ function __get( $k ) {
234
+ return $this->get( $k, null );
235
+ }
236
+
237
+ function offsetSet( $k, $v ) {
238
+ if ( is_null( $k ) ) {
239
+ throw new Exception( 'Can\'t append value to request params.' );
240
+ } else {
241
+ $this->{$k} = $v;
242
+ }
243
+ }
244
+
245
+ function offsetExists( $k ) {
246
+ return array_key_exists( $k, $this->_data );
247
+ }
248
+
249
+ function offsetUnset( $k ) {
250
+ unset( $this->$k );
251
+ }
252
+
253
+ function offsetGet( $k ) {
254
+ return $this->get( $k, null );
255
+ }
256
+
257
+ /**
258
+ * (PHP 5 &gt;= 5.0.0)<br/>
259
+ * Return the current element
260
+ *
261
+ * @link http://php.net/manual/en/iterator.current.php
262
+ * @return mixed Can return any type.
263
+ */
264
+ public function current() {
265
+ return current( $this->_data );
266
+ }
267
+
268
+ /**
269
+ * (PHP 5 &gt;= 5.0.0)<br/>
270
+ * Move forward to next element
271
+ *
272
+ * @link http://php.net/manual/en/iterator.next.php
273
+ * @return void Any returned value is ignored.
274
+ */
275
+ public function next() {
276
+ next( $this->_data );
277
+ }
278
+
279
+ /**
280
+ * (PHP 5 &gt;= 5.0.0)<br/>
281
+ * Return the key of the current element
282
+ *
283
+ * @link http://php.net/manual/en/iterator.key.php
284
+ * @return mixed scalar on success, or null on failure.
285
+ */
286
+ public function key() {
287
+ return key( $this->_data );
288
+ }
289
+
290
+ /**
291
+ * (PHP 5 &gt;= 5.0.0)<br/>
292
+ * Checks if current position is valid
293
+ *
294
+ * @link http://php.net/manual/en/iterator.valid.php
295
+ * @return boolean The return value will be casted to boolean and then evaluated.
296
+ * Returns true on success or false on failure.
297
+ */
298
+ public function valid() {
299
+ $key = key( $this->_data );
300
+
301
+ return ( $key !== null && $key !== false );
302
+ }
303
+
304
+ /**
305
+ * (PHP 5 &gt;= 5.0.0)<br/>
306
+ * Rewind the Iterator to the first element
307
+ *
308
+ * @link http://php.net/manual/en/iterator.rewind.php
309
+ * @return void Any returned value is ignored.
310
+ */
311
+ public function rewind() {
312
+ reset( $this->_data );
313
+ }
314
+
315
+ /**
316
+ * (PHP 5 &gt;= 5.1.0)<br/>
317
+ * Count elements of an object
318
+ *
319
+ * @link http://php.net/manual/en/countable.count.php
320
+ * @return int The custom count as an integer.
321
+ * </p>
322
+ * <p>
323
+ * The return value is cast to an integer.
324
+ */
325
+ public function count() {
326
+ return count( $this->_data );
327
+ }
328
  }
freemius/includes/managers/class-fs-option-manager.php CHANGED
@@ -1,353 +1,353 @@
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
- /**
14
- * 3-layer lazy options manager.
15
- * layer 3: Memory
16
- * layer 2: Cache (if there's any caching plugin and if WP_FS__DEBUG_SDK is FALSE)
17
- * layer 1: Database (options table). All options stored as one option record in the DB to reduce number of DB
18
- * queries.
19
- *
20
- * If load() is not explicitly called, starts as empty manager. Same thing about saving the data - you have to
21
- * explicitly call store().
22
- *
23
- * Class Freemius_Option_Manager
24
- */
25
- class FS_Option_Manager {
26
- /**
27
- * @var string
28
- */
29
- private $_id;
30
- /**
31
- * @var array
32
- */
33
- private $_options;
34
- /**
35
- * @var FS_Logger
36
- */
37
- private $_logger;
38
-
39
- /**
40
- * @var FS_Option_Manager[]
41
- */
42
- private static $_MANAGERS = array();
43
-
44
- /**
45
- * @author Vova Feldman (@svovaf)
46
- * @since 1.0.3
47
- *
48
- * @param string $id
49
- * @param bool $load
50
- */
51
- private function __construct( $id, $load = false ) {
52
- $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_opt_mngr_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
53
-
54
- $this->_logger->entrance();
55
- $this->_logger->log( 'id = ' . $id );
56
-
57
- $this->_id = $id;
58
-
59
- if ( $load ) {
60
- $this->load();
61
- }
62
- }
63
-
64
- /**
65
- * @author Vova Feldman (@svovaf)
66
- * @since 1.0.3
67
- *
68
- * @param $id
69
- * @param $load
70
- *
71
- * @return FS_Option_Manager
72
- */
73
- static function get_manager( $id, $load = false ) {
74
- $id = strtolower( $id );
75
-
76
- if ( ! isset( self::$_MANAGERS[ $id ] ) ) {
77
- self::$_MANAGERS[ $id ] = new FS_Option_Manager( $id, $load );
78
- } // If load required but not yet loaded, load.
79
- else if ( $load && ! self::$_MANAGERS[ $id ]->is_loaded() ) {
80
- self::$_MANAGERS[ $id ]->load();
81
- }
82
-
83
- return self::$_MANAGERS[ $id ];
84
- }
85
-
86
- private function _get_option_manager_name() {
87
- // return WP_FS__SLUG . '_' . $this->_id;
88
- return $this->_id;
89
- }
90
-
91
- /**
92
- * @author Vova Feldman (@svovaf)
93
- * @since 1.0.3
94
- *
95
- * @param bool $flush
96
- */
97
- function load( $flush = false ) {
98
- $this->_logger->entrance();
99
-
100
- $option_name = $this->_get_option_manager_name();
101
-
102
- if ( $flush || ! isset( $this->_options ) ) {
103
- if ( isset( $this->_options ) ) {
104
- // Clear prev options.
105
- $this->clear();
106
- }
107
-
108
- if ( ! WP_FS__DEBUG_SDK ) {
109
- $this->_options = wp_cache_get( $option_name, WP_FS__SLUG );
110
- }
111
-
112
- // $this->_logger->info('wp_cache_get = ' . var_export($this->_options, true));
113
-
114
- // if ( is_array( $this->_options ) ) {
115
- // $this->clear();
116
- // }
117
-
118
- $cached = true;
119
-
120
- if ( empty( $this->_options ) ) {
121
- $this->_options = get_option( $option_name );
122
-
123
- if ( is_string( $this->_options ) ) {
124
- $this->_options = json_decode( $this->_options );
125
- }
126
-
127
- // $this->_logger->info('get_option = ' . var_export($this->_options, true));
128
-
129
- if ( false === $this->_options ) {
130
- $this->clear();
131
- }
132
-
133
- $cached = false;
134
- }
135
-
136
- if ( ! WP_FS__DEBUG_SDK && ! $cached ) // Set non encoded cache.
137
- {
138
- wp_cache_set( $option_name, $this->_options, WP_FS__SLUG );
139
- }
140
- }
141
- }
142
-
143
- /**
144
- * @author Vova Feldman (@svovaf)
145
- * @since 1.0.3
146
- *
147
- * @return bool
148
- */
149
- function is_loaded() {
150
- return isset( $this->_options );
151
- }
152
-
153
- /**
154
- * @author Vova Feldman (@svovaf)
155
- * @since 1.0.3
156
- *
157
- * @return bool
158
- */
159
- function is_empty() {
160
- return ( $this->is_loaded() && false === $this->_options );
161
- }
162
-
163
- /**
164
- * @author Vova Feldman (@svovaf)
165
- * @since 1.0.6
166
- *
167
- * @param bool $flush
168
- */
169
- function clear( $flush = false ) {
170
- $this->_logger->entrance();
171
-
172
- $this->_options = array();
173
-
174
- if ( $flush ) {
175
- $this->store();
176
- }
177
- }
178
-
179
- /**
180
- * Delete options manager from DB.
181
- *
182
- * @author Vova Feldman (@svovaf)
183
- * @since 1.0.9
184
- */
185
- function delete() {
186
- delete_option( $this->_get_option_manager_name() );
187
- }
188
-
189
- /**
190
- * @author Vova Feldman (@svovaf)
191
- * @since 1.0.6
192
- *
193
- * @param string $option
194
- *
195
- * @return bool
196
- */
197
- function has_option( $option ) {
198
- return array_key_exists( $option, $this->_options );
199
- }
200
-
201
- /**
202
- * @author Vova Feldman (@svovaf)
203
- * @since 1.0.3
204
- *
205
- * @param string $option
206
- * @param mixed $default
207
- *
208
- * @return mixed
209
- */
210
- function get_option( $option, $default = null ) {
211
- $this->_logger->entrance( 'option = ' . $option );
212
-
213
- if ( is_array( $this->_options ) ) {
214
- $value = isset( $this->_options[ $option ] ) ?
215
- $this->_options[ $option ] :
216
- $default;
217
- } else if ( is_object( $this->_options ) ) {
218
- $value = isset( $this->_options->{$option} ) ?
219
- $this->_options->{$option} :
220
- $default;
221
- } else {
222
- $value = $default;
223
- }
224
-
225
- /**
226
- * If it's an object, return a clone of the object, otherwise,
227
- * external changes of the object will actually change the value
228
- * of the object in the options manager which may lead to an unexpected
229
- * behaviour and data integrity when a store() call is triggered.
230
- *
231
- * Example:
232
- * $object1 = $options->get_option( 'object1' );
233
- * $object1->x = 123;
234
- *
235
- * $object2 = $options->get_option( 'object2' );
236
- * $object2->y = 'dummy';
237
- *
238
- * $options->set_option( 'object2', $object2, true );
239
- *
240
- * If we don't return a clone of option 'object1', setting 'object2'
241
- * will also store the updated value of 'object1' which is quite not
242
- * an expected behaviour.
243
- *
244
- * @author Vova Feldman
245
- */
246
- return is_object($value) ? clone $value : $value;
247
- }
248
-
249
- /**
250
- * @author Vova Feldman (@svovaf)
251
- * @since 1.0.3
252
- *
253
- * @param string $option
254
- * @param mixed $value
255
- * @param bool $flush
256
- */
257
- function set_option( $option, $value, $flush = false ) {
258
- $this->_logger->entrance( 'option = ' . $option );
259
-
260
- if ( ! $this->is_loaded() ) {
261
- $this->clear();
262
- }
263
-
264
- /**
265
- * If it's an object, store a clone of the object, otherwise,
266
- * external changes of the object will actually change the value
267
- * of the object in the options manager which may lead to an unexpected
268
- * behaviour and data integrity when a store() call is triggered.
269
- *
270
- * Example:
271
- * $object1 = new stdClass();
272
- * $object1->x = 123;
273
- *
274
- * $options->set_option( 'object1', $object1 );
275
- *
276
- * $object1->x = 456;
277
- *
278
- * $options->set_option( 'object2', $object2, true );
279
- *
280
- * If we don't set the option as a clone of option 'object1', setting 'object2'
281
- * will also store the updated value of 'object1' ($object1->x = 456 instead of
282
- * $object1->x = 123) which is quite not an expected behaviour.
283
- *
284
- * @author Vova Feldman
285
- */
286
- $copy = is_object($value) ? clone $value : $value;
287
-
288
- if ( is_array( $this->_options ) ) {
289
- $this->_options[ $option ] = $copy;
290
- } else if ( is_object( $this->_options ) ) {
291
- $this->_options->{$option} = $copy;
292
- }
293
-
294
- if ( $flush ) {
295
- $this->store();
296
- }
297
- }
298
-
299
- /**
300
- * Unset option.
301
- *
302
- * @author Vova Feldman (@svovaf)
303
- * @since 1.0.3
304
- *
305
- * @param string $option
306
- * @param bool $flush
307
- */
308
- function unset_option( $option, $flush = false ) {
309
- $this->_logger->entrance( 'option = ' . $option );
310
-
311
- if ( is_array( $this->_options ) ) {
312
- if ( ! isset( $this->_options[ $option ] ) ) {
313
- return;
314
- }
315
-
316
- unset( $this->_options[ $option ] );
317
-
318
- } else if ( is_object( $this->_options ) ) {
319
- if ( ! isset( $this->_options->{$option} ) ) {
320
- return;
321
- }
322
-
323
- unset( $this->_options->{$option} );
324
- }
325
-
326
- if ( $flush ) {
327
- $this->store();
328
- }
329
- }
330
-
331
- /**
332
- * Dump options to database.
333
- *
334
- * @author Vova Feldman (@svovaf)
335
- * @since 1.0.3
336
- */
337
- function store() {
338
- $this->_logger->entrance();
339
-
340
- $option_name = $this->_get_option_manager_name();
341
-
342
- if ( $this->_logger->is_on() ) {
343
- $this->_logger->info( $option_name . ' = ' . var_export( $this->_options, true ) );
344
- }
345
-
346
- // Update DB.
347
- update_option( $option_name, $this->_options );
348
-
349
- if ( ! WP_FS__DEBUG_SDK ) {
350
- wp_cache_set( $option_name, $this->_options, WP_FS__SLUG );
351
- }
352
- }
353
  }
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
+ /**
14
+ * 3-layer lazy options manager.
15
+ * layer 3: Memory
16
+ * layer 2: Cache (if there's any caching plugin and if WP_FS__DEBUG_SDK is FALSE)
17
+ * layer 1: Database (options table). All options stored as one option record in the DB to reduce number of DB
18
+ * queries.
19
+ *
20
+ * If load() is not explicitly called, starts as empty manager. Same thing about saving the data - you have to
21
+ * explicitly call store().
22
+ *
23
+ * Class Freemius_Option_Manager
24
+ */
25
+ class FS_Option_Manager {
26
+ /**
27
+ * @var string
28
+ */
29
+ private $_id;
30
+ /**
31
+ * @var array
32
+ */
33
+ private $_options;
34
+ /**
35
+ * @var FS_Logger
36
+ */
37
+ private $_logger;
38
+
39
+ /**
40
+ * @var FS_Option_Manager[]
41
+ */
42
+ private static $_MANAGERS = array();
43
+
44
+ /**
45
+ * @author Vova Feldman (@svovaf)
46
+ * @since 1.0.3
47
+ *
48
+ * @param string $id
49
+ * @param bool $load
50
+ */
51
+ private function __construct( $id, $load = false ) {
52
+ $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_opt_mngr_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
53
+
54
+ $this->_logger->entrance();
55
+ $this->_logger->log( 'id = ' . $id );
56
+
57
+ $this->_id = $id;
58
+
59
+ if ( $load ) {
60
+ $this->load();
61
+ }
62
+ }
63
+
64
+ /**
65
+ * @author Vova Feldman (@svovaf)
66
+ * @since 1.0.3
67
+ *
68
+ * @param $id
69
+ * @param $load
70
+ *
71
+ * @return FS_Option_Manager
72
+ */
73
+ static function get_manager( $id, $load = false ) {
74
+ $id = strtolower( $id );
75
+
76
+ if ( ! isset( self::$_MANAGERS[ $id ] ) ) {
77
+ self::$_MANAGERS[ $id ] = new FS_Option_Manager( $id, $load );
78
+ } // If load required but not yet loaded, load.
79
+ else if ( $load && ! self::$_MANAGERS[ $id ]->is_loaded() ) {
80
+ self::$_MANAGERS[ $id ]->load();
81
+ }
82
+
83
+ return self::$_MANAGERS[ $id ];
84
+ }
85
+
86
+ private function _get_option_manager_name() {
87
+ // return WP_FS__SLUG . '_' . $this->_id;
88
+ return $this->_id;
89
+ }
90
+
91
+ /**
92
+ * @author Vova Feldman (@svovaf)
93
+ * @since 1.0.3
94
+ *
95
+ * @param bool $flush
96
+ */
97
+ function load( $flush = false ) {
98
+ $this->_logger->entrance();
99
+
100
+ $option_name = $this->_get_option_manager_name();
101
+
102
+ if ( $flush || ! isset( $this->_options ) ) {
103
+ if ( isset( $this->_options ) ) {
104
+ // Clear prev options.
105
+ $this->clear();
106
+ }
107
+
108
+ if ( ! WP_FS__DEBUG_SDK ) {
109
+ $this->_options = wp_cache_get( $option_name, WP_FS__SLUG );
110
+ }
111
+
112
+ // $this->_logger->info('wp_cache_get = ' . var_export($this->_options, true));
113
+
114
+ // if ( is_array( $this->_options ) ) {
115
+ // $this->clear();
116
+ // }
117
+
118
+ $cached = true;
119
+
120
+ if ( empty( $this->_options ) ) {
121
+ $this->_options = get_option( $option_name );
122
+
123
+ if ( is_string( $this->_options ) ) {
124
+ $this->_options = json_decode( $this->_options );
125
+ }
126
+
127
+ // $this->_logger->info('get_option = ' . var_export($this->_options, true));
128
+
129
+ if ( false === $this->_options ) {
130
+ $this->clear();
131
+ }
132
+
133
+ $cached = false;
134
+ }
135
+
136
+ if ( ! WP_FS__DEBUG_SDK && ! $cached ) // Set non encoded cache.
137
+ {
138
+ wp_cache_set( $option_name, $this->_options, WP_FS__SLUG );
139
+ }
140
+ }
141
+ }
142
+
143
+ /**
144
+ * @author Vova Feldman (@svovaf)
145
+ * @since 1.0.3
146
+ *
147
+ * @return bool
148
+ */
149
+ function is_loaded() {
150
+ return isset( $this->_options );
151
+ }
152
+
153
+ /**
154
+ * @author Vova Feldman (@svovaf)
155
+ * @since 1.0.3
156
+ *
157
+ * @return bool
158
+ */
159
+ function is_empty() {
160
+ return ( $this->is_loaded() && false === $this->_options );
161
+ }
162
+
163
+ /**
164
+ * @author Vova Feldman (@svovaf)
165
+ * @since 1.0.6
166
+ *
167
+ * @param bool $flush
168
+ */
169
+ function clear( $flush = false ) {
170
+ $this->_logger->entrance();
171
+
172
+ $this->_options = array();
173
+
174
+ if ( $flush ) {
175
+ $this->store();
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Delete options manager from DB.
181
+ *
182
+ * @author Vova Feldman (@svovaf)
183
+ * @since 1.0.9
184
+ */
185
+ function delete() {
186
+ delete_option( $this->_get_option_manager_name() );
187
+ }
188
+
189
+ /**
190
+ * @author Vova Feldman (@svovaf)
191
+ * @since 1.0.6
192
+ *
193
+ * @param string $option
194
+ *
195
+ * @return bool
196
+ */
197
+ function has_option( $option ) {
198
+ return array_key_exists( $option, $this->_options );
199
+ }
200
+
201
+ /**
202
+ * @author Vova Feldman (@svovaf)
203
+ * @since 1.0.3
204
+ *
205
+ * @param string $option
206
+ * @param mixed $default
207
+ *
208
+ * @return mixed
209
+ */
210
+ function get_option( $option, $default = null ) {
211
+ $this->_logger->entrance( 'option = ' . $option );
212
+
213
+ if ( is_array( $this->_options ) ) {
214
+ $value = isset( $this->_options[ $option ] ) ?
215
+ $this->_options[ $option ] :
216
+ $default;
217
+ } else if ( is_object( $this->_options ) ) {
218
+ $value = isset( $this->_options->{$option} ) ?
219
+ $this->_options->{$option} :
220
+ $default;
221
+ } else {
222
+ $value = $default;
223
+ }
224
+
225
+ /**
226
+ * If it's an object, return a clone of the object, otherwise,
227
+ * external changes of the object will actually change the value
228
+ * of the object in the options manager which may lead to an unexpected
229
+ * behaviour and data integrity when a store() call is triggered.
230
+ *
231
+ * Example:
232
+ * $object1 = $options->get_option( 'object1' );
233
+ * $object1->x = 123;
234
+ *
235
+ * $object2 = $options->get_option( 'object2' );
236
+ * $object2->y = 'dummy';
237
+ *
238
+ * $options->set_option( 'object2', $object2, true );
239
+ *
240
+ * If we don't return a clone of option 'object1', setting 'object2'
241
+ * will also store the updated value of 'object1' which is quite not
242
+ * an expected behaviour.
243
+ *
244
+ * @author Vova Feldman
245
+ */
246
+ return is_object($value) ? clone $value : $value;
247
+ }
248
+
249
+ /**
250
+ * @author Vova Feldman (@svovaf)
251
+ * @since 1.0.3
252
+ *
253
+ * @param string $option
254
+ * @param mixed $value
255
+ * @param bool $flush
256
+ */
257
+ function set_option( $option, $value, $flush = false ) {
258
+ $this->_logger->entrance( 'option = ' . $option );
259
+
260
+ if ( ! $this->is_loaded() ) {
261
+ $this->clear();
262
+ }
263
+
264
+ /**
265
+ * If it's an object, store a clone of the object, otherwise,
266
+ * external changes of the object will actually change the value
267
+ * of the object in the options manager which may lead to an unexpected
268
+ * behaviour and data integrity when a store() call is triggered.
269
+ *
270
+ * Example:
271
+ * $object1 = new stdClass();
272
+ * $object1->x = 123;
273
+ *
274
+ * $options->set_option( 'object1', $object1 );
275
+ *
276
+ * $object1->x = 456;
277
+ *
278
+ * $options->set_option( 'object2', $object2, true );
279
+ *
280
+ * If we don't set the option as a clone of option 'object1', setting 'object2'
281
+ * will also store the updated value of 'object1' ($object1->x = 456 instead of
282
+ * $object1->x = 123) which is quite not an expected behaviour.
283
+ *
284
+ * @author Vova Feldman
285
+ */
286
+ $copy = is_object($value) ? clone $value : $value;
287
+
288
+ if ( is_array( $this->_options ) ) {
289
+ $this->_options[ $option ] = $copy;
290
+ } else if ( is_object( $this->_options ) ) {
291
+ $this->_options->{$option} = $copy;
292
+ }
293
+
294
+ if ( $flush ) {
295
+ $this->store();
296
+ }
297
+ }
298
+
299
+ /**
300
+ * Unset option.
301
+ *
302
+ * @author Vova Feldman (@svovaf)
303
+ * @since 1.0.3
304
+ *
305
+ * @param string $option
306
+ * @param bool $flush
307
+ */
308
+ function unset_option( $option, $flush = false ) {
309
+ $this->_logger->entrance( 'option = ' . $option );
310
+
311
+ if ( is_array( $this->_options ) ) {
312
+ if ( ! isset( $this->_options[ $option ] ) ) {
313
+ return;
314
+ }
315
+
316
+ unset( $this->_options[ $option ] );
317
+
318
+ } else if ( is_object( $this->_options ) ) {
319
+ if ( ! isset( $this->_options->{$option} ) ) {
320
+ return;
321
+ }
322
+
323
+ unset( $this->_options->{$option} );
324
+ }
325
+
326
+ if ( $flush ) {
327
+ $this->store();
328
+ }
329
+ }
330
+
331
+ /**
332
+ * Dump options to database.
333
+ *
334
+ * @author Vova Feldman (@svovaf)
335
+ * @since 1.0.3
336
+ */
337
+ function store() {
338
+ $this->_logger->entrance();
339
+
340
+ $option_name = $this->_get_option_manager_name();
341
+
342
+ if ( $this->_logger->is_on() ) {
343
+ $this->_logger->info( $option_name . ' = ' . var_export( $this->_options, true ) );
344
+ }
345
+
346
+ // Update DB.
347
+ update_option( $option_name, $this->_options );
348
+
349
+ if ( ! WP_FS__DEBUG_SDK ) {
350
+ wp_cache_set( $option_name, $this->_options, WP_FS__SLUG );
351
+ }
352
+ }
353
  }
freemius/includes/managers/class-fs-plugin-manager.php CHANGED
@@ -1,220 +1,220 @@
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.6
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- class FS_Plugin_Manager {
14
- /**
15
- * @since 1.2.2
16
- *
17
- * @var string|number
18
- */
19
- protected $_module_id;
20
- /**
21
- * @since 1.2.2
22
- *
23
- * @var FS_Plugin
24
- */
25
- protected $_module;
26
-
27
- /**
28
- * @var FS_Plugin_Manager[]
29
- */
30
- private static $_instances = array();
31
- /**
32
- * @var FS_Logger
33
- */
34
- protected $_logger;
35
-
36
- /**
37
- * Option names
38
- *
39
- * @author Leo Fajardo (@leorw)
40
- * @since 1.2.2
41
- */
42
- const OPTION_NAME_PLUGINS = 'plugins';
43
- const OPTION_NAME_THEMES = 'themes';
44
-
45
- /**
46
- * @param string|number $module_id
47
- *
48
- * @return FS_Plugin_Manager
49
- */
50
- static function instance( $module_id ) {
51
- $key = 'm_' . $module_id;
52
-
53
- if ( ! isset( self::$_instances[ $key ] ) ) {
54
- self::$_instances[ $key ] = new FS_Plugin_Manager( $module_id );
55
- }
56
-
57
- return self::$_instances[ $key ];
58
- }
59
-
60
- /**
61
- * @param string|number $module_id
62
- */
63
- protected function __construct( $module_id ) {
64
- $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $module_id . '_' . 'plugins', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
65
- $this->_module_id = $module_id;
66
-
67
- $this->load();
68
- }
69
-
70
- protected function get_option_manager() {
71
- return FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true );
72
- }
73
-
74
- /**
75
- * @author Leo Fajardo (@leorw)
76
- * @since 1.2.2
77
- *
78
- * @param string|false $module_type "plugin", "theme", or "false" for all modules.
79
- *
80
- * @return array
81
- */
82
- protected function get_all_modules( $module_type = false ) {
83
- $option_manager = $this->get_option_manager();
84
-
85
- if ( false !== $module_type ) {
86
- return $option_manager->get_option( $module_type . 's', array() );
87
- }
88
-
89
- return array(
90
- self::OPTION_NAME_PLUGINS => $option_manager->get_option( self::OPTION_NAME_PLUGINS, array() ),
91
- self::OPTION_NAME_THEMES => $option_manager->get_option( self::OPTION_NAME_THEMES, array() ),
92
- );
93
- }
94
-
95
- /**
96
- * Load plugin data from local DB.
97
- *
98
- * @author Vova Feldman (@svovaf)
99
- * @since 1.0.6
100
- */
101
- function load() {
102
- $all_modules = $this->get_all_modules();
103
-
104
- if ( ! is_numeric( $this->_module_id ) ) {
105
- unset( $all_modules[ self::OPTION_NAME_THEMES ] );
106
- }
107
-
108
- foreach ( $all_modules as $modules ) {
109
- /**
110
- * @since 1.2.2
111
- *
112
- * @var $modules FS_Plugin[]
113
- */
114
- foreach ( $modules as $module ) {
115
- $found_module = false;
116
-
117
- /**
118
- * If module ID is not numeric, it must be a plugin's slug.
119
- *
120
- * @author Leo Fajardo (@leorw)
121
- * @since 1.2.2
122
- */
123
- if ( ! is_numeric( $this->_module_id ) ) {
124
- if ( $this->_module_id === $module->slug ) {
125
- $this->_module_id = $module->id;
126
- $found_module = true;
127
- }
128
- } else if ( $this->_module_id == $module->id ) {
129
- $found_module = true;
130
- }
131
-
132
- if ( $found_module ) {
133
- $this->_module = $module;
134
- break;
135
- }
136
- }
137
- }
138
- }
139
-
140
- /**
141
- * Store plugin on local DB.
142
- *
143
- * @author Vova Feldman (@svovaf)
144
- * @since 1.0.6
145
- *
146
- * @param bool|FS_Plugin $module
147
- * @param bool $flush
148
- *
149
- * @return bool|\FS_Plugin
150
- */
151
- function store( $module = false, $flush = true ) {
152
- if ( false !== $module ) {
153
- $this->_module = $module;
154
- }
155
-
156
- $all_modules = $this->get_all_modules( $this->_module->type );
157
- $all_modules[ $this->_module->slug ] = $this->_module;
158
-
159
- $options_manager = $this->get_option_manager();
160
- $options_manager->set_option( $this->_module->type . 's', $all_modules, $flush );
161
-
162
- return $this->_module;
163
- }
164
-
165
- /**
166
- * Update local plugin data if different.
167
- *
168
- * @author Vova Feldman (@svovaf)
169
- * @since 1.0.6
170
- *
171
- * @param \FS_Plugin $plugin
172
- * @param bool $store
173
- *
174
- * @return bool True if plugin was updated.
175
- */
176
- function update( FS_Plugin $plugin, $store = true ) {
177
- if ( ! ($this->_module instanceof FS_Plugin ) ||
178
- $this->_module->slug != $plugin->slug ||
179
- $this->_module->public_key != $plugin->public_key ||
180
- $this->_module->secret_key != $plugin->secret_key ||
181
- $this->_module->parent_plugin_id != $plugin->parent_plugin_id ||
182
- $this->_module->title != $plugin->title
183
- ) {
184
- $this->store( $plugin, $store );
185
-
186
- return true;
187
- }
188
-
189
- return false;
190
- }
191
-
192
- /**
193
- * @author Vova Feldman (@svovaf)
194
- * @since 1.0.6
195
- *
196
- * @param FS_Plugin $plugin
197
- * @param bool $store
198
- */
199
- function set( FS_Plugin $plugin, $store = false ) {
200
- $this->_module = $plugin;
201
-
202
- if ( $store ) {
203
- $this->store();
204
- }
205
- }
206
-
207
- /**
208
- * @author Vova Feldman (@svovaf)
209
- * @since 1.0.6
210
- *
211
- * @return bool|\FS_Plugin
212
- */
213
- function get() {
214
- return isset( $this->_module ) ?
215
- $this->_module :
216
- false;
217
- }
218
-
219
-
220
  }
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.6
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ class FS_Plugin_Manager {
14
+ /**
15
+ * @since 1.2.2
16
+ *
17
+ * @var string|number
18
+ */
19
+ protected $_module_id;
20
+ /**
21
+ * @since 1.2.2
22
+ *
23
+ * @var FS_Plugin
24
+ */
25
+ protected $_module;
26
+
27
+ /**
28
+ * @var FS_Plugin_Manager[]
29
+ */
30
+ private static $_instances = array();
31
+ /**
32
+ * @var FS_Logger
33
+ */
34
+ protected $_logger;
35
+
36
+ /**
37
+ * Option names
38
+ *
39
+ * @author Leo Fajardo (@leorw)
40
+ * @since 1.2.2
41
+ */
42
+ const OPTION_NAME_PLUGINS = 'plugins';
43
+ const OPTION_NAME_THEMES = 'themes';
44
+
45
+ /**
46
+ * @param string|number $module_id
47
+ *
48
+ * @return FS_Plugin_Manager
49
+ */
50
+ static function instance( $module_id ) {
51
+ $key = 'm_' . $module_id;
52
+
53
+ if ( ! isset( self::$_instances[ $key ] ) ) {
54
+ self::$_instances[ $key ] = new FS_Plugin_Manager( $module_id );
55
+ }
56
+
57
+ return self::$_instances[ $key ];
58
+ }
59
+
60
+ /**
61
+ * @param string|number $module_id
62
+ */
63
+ protected function __construct( $module_id ) {
64
+ $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $module_id . '_' . 'plugins', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
65
+ $this->_module_id = $module_id;
66
+
67
+ $this->load();
68
+ }
69
+
70
+ protected function get_option_manager() {
71
+ return FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true );
72
+ }
73
+
74
+ /**
75
+ * @author Leo Fajardo (@leorw)
76
+ * @since 1.2.2
77
+ *
78
+ * @param string|false $module_type "plugin", "theme", or "false" for all modules.
79
+ *
80
+ * @return array
81
+ */
82
+ protected function get_all_modules( $module_type = false ) {
83
+ $option_manager = $this->get_option_manager();
84
+
85
+ if ( false !== $module_type ) {
86
+ return $option_manager->get_option( $module_type . 's', array() );
87
+ }
88
+
89
+ return array(
90
+ self::OPTION_NAME_PLUGINS => $option_manager->get_option( self::OPTION_NAME_PLUGINS, array() ),
91
+ self::OPTION_NAME_THEMES => $option_manager->get_option( self::OPTION_NAME_THEMES, array() ),
92
+ );
93
+ }
94
+
95
+ /**
96
+ * Load plugin data from local DB.
97
+ *
98
+ * @author Vova Feldman (@svovaf)
99
+ * @since 1.0.6
100
+ */
101
+ function load() {
102
+ $all_modules = $this->get_all_modules();
103
+
104
+ if ( ! is_numeric( $this->_module_id ) ) {
105
+ unset( $all_modules[ self::OPTION_NAME_THEMES ] );
106
+ }
107
+
108
+ foreach ( $all_modules as $modules ) {
109
+ /**
110
+ * @since 1.2.2
111
+ *
112
+ * @var $modules FS_Plugin[]
113
+ */
114
+ foreach ( $modules as $module ) {
115
+ $found_module = false;
116
+
117
+ /**
118
+ * If module ID is not numeric, it must be a plugin's slug.
119
+ *
120
+ * @author Leo Fajardo (@leorw)
121
+ * @since 1.2.2
122
+ */
123
+ if ( ! is_numeric( $this->_module_id ) ) {
124
+ if ( $this->_module_id === $module->slug ) {
125
+ $this->_module_id = $module->id;
126
+ $found_module = true;
127
+ }
128
+ } else if ( $this->_module_id == $module->id ) {
129
+ $found_module = true;
130
+ }
131
+
132
+ if ( $found_module ) {
133
+ $this->_module = $module;
134
+ break;
135
+ }
136
+ }
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Store plugin on local DB.
142
+ *
143
+ * @author Vova Feldman (@svovaf)
144
+ * @since 1.0.6
145
+ *
146
+ * @param bool|FS_Plugin $module
147
+ * @param bool $flush
148
+ *
149
+ * @return bool|\FS_Plugin
150
+ */
151
+ function store( $module = false, $flush = true ) {
152
+ if ( false !== $module ) {
153
+ $this->_module = $module;
154
+ }
155
+
156
+ $all_modules = $this->get_all_modules( $this->_module->type );
157
+ $all_modules[ $this->_module->slug ] = $this->_module;
158
+
159
+ $options_manager = $this->get_option_manager();
160
+ $options_manager->set_option( $this->_module->type . 's', $all_modules, $flush );
161
+
162
+ return $this->_module;
163
+ }
164
+
165
+ /**
166
+ * Update local plugin data if different.
167
+ *
168
+ * @author Vova Feldman (@svovaf)
169
+ * @since 1.0.6
170
+ *
171
+ * @param \FS_Plugin $plugin
172
+ * @param bool $store
173
+ *
174
+ * @return bool True if plugin was updated.
175
+ */
176
+ function update( FS_Plugin $plugin, $store = true ) {
177
+ if ( ! ($this->_module instanceof FS_Plugin ) ||
178
+ $this->_module->slug != $plugin->slug ||
179
+ $this->_module->public_key != $plugin->public_key ||
180
+ $this->_module->secret_key != $plugin->secret_key ||
181
+ $this->_module->parent_plugin_id != $plugin->parent_plugin_id ||
182
+ $this->_module->title != $plugin->title
183
+ ) {
184
+ $this->store( $plugin, $store );
185
+
186
+ return true;
187
+ }
188
+
189
+ return false;
190
+ }
191
+
192
+ /**
193
+ * @author Vova Feldman (@svovaf)
194
+ * @since 1.0.6
195
+ *
196
+ * @param FS_Plugin $plugin
197
+ * @param bool $store
198
+ */
199
+ function set( FS_Plugin $plugin, $store = false ) {
200
+ $this->_module = $plugin;
201
+
202
+ if ( $store ) {
203
+ $this->store();
204
+ }
205
+ }
206
+
207
+ /**
208
+ * @author Vova Feldman (@svovaf)
209
+ * @since 1.0.6
210
+ *
211
+ * @return bool|\FS_Plugin
212
+ */
213
+ function get() {
214
+ return isset( $this->_module ) ?
215
+ $this->_module :
216
+ false;
217
+ }
218
+
219
+
220
  }
freemius/includes/supplements/fs-essential-functions-1.1.7.1.php CHANGED
@@ -1,47 +1,47 @@
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.1.7
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * Find the plugin main file path based on any give file inside the plugin's folder.
15
- *
16
- * @author Vova Feldman (@svovaf)
17
- * @since 1.1.7.1
18
- *
19
- * @param string $file Absolute path to a file inside a plugin's folder.
20
- *
21
- * @return string
22
- */
23
- function fs_find_direct_caller_plugin_file( $file ) {
24
- /**
25
- * All the code below will be executed once on activation.
26
- * If the user changes the main plugin's file name, the file_exists()
27
- * will catch it.
28
- */
29
- if ( ! function_exists( 'get_plugins' ) ) {
30
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
31
- }
32
-
33
- $all_plugins = get_plugins();
34
-
35
- $file_real_path = fs_normalize_path( realpath( $file ) );
36
-
37
- // Get active plugin's main files real full names (might be symlinks).
38
- foreach ( $all_plugins as $relative_path => &$data ) {
39
- if ( 0 === strpos( $file_real_path, fs_normalize_path( dirname( realpath( WP_PLUGIN_DIR . '/' . $relative_path ) ) ) ) ) {
40
- if ( '.' !== dirname( trailingslashit( $relative_path ) ) ) {
41
- return $relative_path;
42
- }
43
- }
44
- }
45
-
46
- return null;
47
- }
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.1.7
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * Find the plugin main file path based on any give file inside the plugin's folder.
15
+ *
16
+ * @author Vova Feldman (@svovaf)
17
+ * @since 1.1.7.1
18
+ *
19
+ * @param string $file Absolute path to a file inside a plugin's folder.
20
+ *
21
+ * @return string
22
+ */
23
+ function fs_find_direct_caller_plugin_file( $file ) {
24
+ /**
25
+ * All the code below will be executed once on activation.
26
+ * If the user changes the main plugin's file name, the file_exists()
27
+ * will catch it.
28
+ */
29
+ if ( ! function_exists( 'get_plugins' ) ) {
30
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
31
+ }
32
+
33
+ $all_plugins = get_plugins();
34
+
35
+ $file_real_path = fs_normalize_path( realpath( $file ) );
36
+
37
+ // Get active plugin's main files real full names (might be symlinks).
38
+ foreach ( $all_plugins as $relative_path => &$data ) {
39
+ if ( 0 === strpos( $file_real_path, fs_normalize_path( dirname( realpath( WP_PLUGIN_DIR . '/' . $relative_path ) ) ) ) ) {
40
+ if ( '.' !== dirname( trailingslashit( $relative_path ) ) ) {
41
+ return $relative_path;
42
+ }
43
+ }
44
+ }
45
+
46
+ return null;
47
+ }
freemius/package.json CHANGED
@@ -1,27 +1,27 @@
1
- {
2
- "name": "freemius-wordpress-sdk",
3
- "description": "Monetization, analytics, and marketing automation platform for plugin & theme developers.",
4
- "author": "Freemius, Inc.",
5
- "license": "GPL-3.0",
6
- "homepage": "https://freemius.com",
7
- "version": "1.2.3",
8
- "main": "gulpfile.js",
9
- "dependencies": {},
10
- "scripts": {
11
- "test": "echo \"Error: no test specified\" && exit 1",
12
- "prune": "rimraf .codeclimate.yml .git .github .gitignore .travis.yml gulpfile.js composer.json"
13
- },
14
- "repository": "Freemius/wordpress-sdk.git",
15
- "devDependencies": {
16
- "gulp": "^3.9.1",
17
- "gulp-clean": "^0.3.2",
18
- "gulp-fs": "0.0.2",
19
- "gulp-gettext": "^0.3.0",
20
- "gulp-path": "^3.0.3",
21
- "gulp-pofill": "^1.0.0",
22
- "gulp-rename": "^1.2.2",
23
- "gulp-sort": "^2.0.0",
24
- "gulp-transifex": "^0.1.17",
25
- "gulp-wp-pot": "^1.3.5"
26
- }
27
- }
1
+ {
2
+ "name": "freemius-wordpress-sdk",
3
+ "description": "Monetization, analytics, and marketing automation platform for plugin & theme developers.",
4
+ "author": "Freemius, Inc.",
5
+ "license": "GPL-3.0",
6
+ "homepage": "https://freemius.com",
7
+ "version": "1.2.3",
8
+ "main": "gulpfile.js",
9
+ "dependencies": {},
10
+ "scripts": {
11
+ "test": "echo \"Error: no test specified\" && exit 1",
12
+ "prune": "rimraf .codeclimate.yml .git .github .gitignore .travis.yml gulpfile.js composer.json"
13
+ },
14
+ "repository": "Freemius/wordpress-sdk.git",
15
+ "devDependencies": {
16
+ "gulp": "^3.9.1",
17
+ "gulp-clean": "^0.3.2",
18
+ "gulp-fs": "0.0.2",
19
+ "gulp-gettext": "^0.3.0",
20
+ "gulp-path": "^3.0.3",
21
+ "gulp-pofill": "^1.0.0",
22
+ "gulp-rename": "^1.2.2",
23
+ "gulp-sort": "^2.0.0",
24
+ "gulp-transifex": "^0.1.17",
25
+ "gulp-wp-pot": "^1.3.5"
26
+ }
27
+ }
freemius/require.php CHANGED
@@ -1,45 +1,45 @@
1
- <?php
2
- /**
3
- * @package Freemius
4
- * @copyright Copyright (c) 2016, Freemius, Inc.
5
- * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
- * @since 1.1.9
7
- */
8
-
9
- // Configuration should be loaded first.
10
- require_once dirname( __FILE__ ) . '/config.php';
11
- require_once WP_FS__DIR_INCLUDES . '/fs-core-functions.php';
12
-
13
- // Logger must be loaded before any other.
14
- require_once WP_FS__DIR_INCLUDES . '/class-fs-logger.php';
15
- require_once WP_FS__DIR_INCLUDES . '/debug/debug-bar-start.php';
16
-
17
- // require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-abstract-manager.php';
18
- require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-option-manager.php';
19
- require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-cache-manager.php';
20
- require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-admin-notice-manager.php';
21
- require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-admin-menu-manager.php';
22
- require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-key-value-storage.php';
23
- require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-license-manager.php';
24
- require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-plan-manager.php';
25
- require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-plugin-manager.php';
26
- require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-entity.php';
27
- require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-scope-entity.php';
28
- require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-user.php';
29
- require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-site.php';
30
- require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin.php';
31
- require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-affiliate.php';
32
- require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-affiliate-terms.php';
33
- require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-info.php';
34
- require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-tag.php';
35
- require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-plan.php';
36
- require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-pricing.php';
37
- require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-payment.php';
38
- require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-license.php';
39
- require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-subscription.php';
40
- require_once WP_FS__DIR_INCLUDES . '/class-fs-api.php';
41
- require_once WP_FS__DIR_INCLUDES . '/class-fs-plugin-updater.php';
42
- require_once WP_FS__DIR_INCLUDES . '/class-fs-security.php';
43
- require_once WP_FS__DIR_INCLUDES . '/class-freemius-abstract.php';
44
- require_once WP_FS__DIR_INCLUDES . '/sdk/Exceptions/Exception.php';
45
  require_once WP_FS__DIR_INCLUDES . '/class-freemius.php';
1
+ <?php
2
+ /**
3
+ * @package Freemius
4
+ * @copyright Copyright (c) 2016, Freemius, Inc.
5
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
+ * @since 1.1.9
7
+ */
8
+
9
+ // Configuration should be loaded first.
10
+ require_once dirname( __FILE__ ) . '/config.php';
11
+ require_once WP_FS__DIR_INCLUDES . '/fs-core-functions.php';
12
+
13
+ // Logger must be loaded before any other.
14
+ require_once WP_FS__DIR_INCLUDES . '/class-fs-logger.php';
15
+ require_once WP_FS__DIR_INCLUDES . '/debug/debug-bar-start.php';
16
+
17
+ // require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-abstract-manager.php';
18
+ require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-option-manager.php';
19
+ require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-cache-manager.php';
20
+ require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-admin-notice-manager.php';
21
+ require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-admin-menu-manager.php';
22
+ require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-key-value-storage.php';
23
+ require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-license-manager.php';
24
+ require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-plan-manager.php';
25
+ require_once WP_FS__DIR_INCLUDES . '/managers/class-fs-plugin-manager.php';
26
+ require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-entity.php';
27
+ require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-scope-entity.php';
28
+ require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-user.php';
29
+ require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-site.php';
30
+ require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin.php';
31
+ require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-affiliate.php';
32
+ require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-affiliate-terms.php';
33
+ require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-info.php';
34
+ require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-tag.php';
35
+ require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-plan.php';
36
+ require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-pricing.php';
37
+ require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-payment.php';
38
+ require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-plugin-license.php';
39
+ require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-subscription.php';
40
+ require_once WP_FS__DIR_INCLUDES . '/class-fs-api.php';
41
+ require_once WP_FS__DIR_INCLUDES . '/class-fs-plugin-updater.php';
42
+ require_once WP_FS__DIR_INCLUDES . '/class-fs-security.php';
43
+ require_once WP_FS__DIR_INCLUDES . '/class-freemius-abstract.php';
44
+ require_once WP_FS__DIR_INCLUDES . '/sdk/Exceptions/Exception.php';
45
  require_once WP_FS__DIR_INCLUDES . '/class-freemius.php';
freemius/templates/account/billing.php CHANGED
@@ -1,431 +1,431 @@
1
- <?php
2
- /**
3
- * @package Freemius
4
- * @copyright Copyright (c) 2016, Freemius, Inc.
5
- * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
- * @since 1.2.0
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
- $payments = $fs->_fetch_payments();
22
-
23
- $show_billing = ( is_array( $payments ) && 0 < count( $payments ) );
24
-
25
- if ( $show_billing ) :
26
-
27
- $edit_text = fs_text_x_inline( 'Edit', 'verb', 'edit', $slug );
28
- $update_text = fs_text_x_inline( 'Update', 'verb', 'update', $slug );
29
-
30
- $billing = $fs->_fetch_billing();
31
- $has_billing = ( $billing instanceof FS_Billing );
32
- if ( ! $has_billing ) {
33
- $billing = new FS_Billing();
34
- }
35
- ?>
36
- <!-- Billing -->
37
- <div class="postbox">
38
- <div id="fs_billing">
39
- <h3><span class="dashicons dashicons-portfolio"></span> <?php fs_esc_html_echo_inline( 'Billing', 'billing', $slug ) ?></h3>
40
- <table id="fs_billing_address"<?php if ( $has_billing ) {
41
- echo ' class="fs-read-mode"';
42
- } ?>>
43
- <tr>
44
- <td><label><span><?php fs_esc_html_echo_inline( 'Business name', 'business-name', $slug ) ?>:</span> <input id="business_name" value="<?php echo $billing->business_name ?>" placeholder="<?php fs_esc_attr_echo_inline( 'Business name', 'business-name', $slug ) ?>"></label></td>
45
- <td><label><span><?php fs_esc_html_echo_inline( 'Tax / VAT ID', 'tax-vat-id', $slug ) ?>:</span> <input id="tax_id" value="<?php echo $billing->tax_id ?>" placeholder="<?php fs_esc_attr_echo_inline( 'Tax / VAT ID', 'tax-vat-id', $slug ) ?>"></label></td>
46
- </tr>
47
- <tr>
48
- <td><label><span><?php printf( fs_esc_html_inline( 'Address Line %d', 'address-line-n', $slug ), 1 ) ?>:</span> <input id="address_street" value="<?php echo $billing->address_street ?>" placeholder="<?php printf( fs_esc_attr_inline( 'Address Line %d', 'address-line-n', $slug ), 1 ) ?>"></label></td>
49
- <td><label><span><?php printf( fs_esc_html_inline( 'Address Line %d', 'address-line-n', $slug ), 2 ) ?>:</span> <input id="address_apt" value="<?php echo $billing->address_apt ?>" placeholder="<?php printf( fs_esc_attr_inline( 'Address Line %d', 'address-line-n', $slug ), 2 ) ?>"></label></td>
50
- </tr>
51
- <tr>
52
- <td><label><span><?php fs_esc_html_echo_inline( 'City', 'city', $slug ) ?> / <?php fs_esc_html_echo_inline( 'Town', 'town', $slug ) ?>:</span> <input id="address_city" value="<?php echo $billing->address_city ?>" placeholder="<?php fs_esc_attr_echo_inline( 'City', 'city', $slug ) ?> / <?php fs_esc_attr_echo_inline( 'Town', 'town', $slug ) ?>"></label></td>
53
- <td><label><span><?php fs_esc_html_echo_inline( 'ZIP / Postal Code', 'zip-postal-code', $slug ) ?>:</span> <input id="address_zip" value="<?php echo $billing->address_zip ?>" placeholder="<?php fs_esc_attr_echo_inline( 'ZIP / Postal Code', 'zip-postal-code', $slug ) ?>"></label></td>
54
- </tr>
55
- <tr>
56
- <?php $countries = array(
57
- 'AF' => 'Afghanistan',
58
- 'AX' => 'Aland Islands',
59
- 'AL' => 'Albania',
60
- 'DZ' => 'Algeria',
61
- 'AS' => 'American Samoa',
62
- 'AD' => 'Andorra',
63
- 'AO' => 'Angola',
64
- 'AI' => 'Anguilla',
65
- 'AQ' => 'Antarctica',
66
- 'AG' => 'Antigua and Barbuda',
67
- 'AR' => 'Argentina',
68
- 'AM' => 'Armenia',
69
- 'AW' => 'Aruba',
70
- 'AU' => 'Australia',
71
- 'AT' => 'Austria',
72
- 'AZ' => 'Azerbaijan',
73
- 'BS' => 'Bahamas',
74
- 'BH' => 'Bahrain',
75
- 'BD' => 'Bangladesh',
76
- 'BB' => 'Barbados',
77
- 'BY' => 'Belarus',
78
- 'BE' => 'Belgium',
79
- 'BZ' => 'Belize',
80
- 'BJ' => 'Benin',
81
- 'BM' => 'Bermuda',
82
- 'BT' => 'Bhutan',
83
- 'BO' => 'Bolivia',
84
- 'BQ' => 'Bonaire, Saint Eustatius and Saba',
85
- 'BA' => 'Bosnia and Herzegovina',
86
- 'BW' => 'Botswana',
87
- 'BV' => 'Bouvet Island',
88
- 'BR' => 'Brazil',
89
- 'IO' => 'British Indian Ocean Territory',
90
- 'VG' => 'British Virgin Islands',
91
- 'BN' => 'Brunei',
92
- 'BG' => 'Bulgaria',
93
- 'BF' => 'Burkina Faso',
94
- 'BI' => 'Burundi',
95
- 'KH' => 'Cambodia',
96
- 'CM' => 'Cameroon',
97
- 'CA' => 'Canada',
98
- 'CV' => 'Cape Verde',
99
- 'KY' => 'Cayman Islands',
100
- 'CF' => 'Central African Republic',
101
- 'TD' => 'Chad',
102
- 'CL' => 'Chile',
103
- 'CN' => 'China',
104
- 'CX' => 'Christmas Island',
105
- 'CC' => 'Cocos Islands',
106
- 'CO' => 'Colombia',
107
- 'KM' => 'Comoros',
108
- 'CK' => 'Cook Islands',
109
- 'CR' => 'Costa Rica',
110
- 'HR' => 'Croatia',
111
- 'CU' => 'Cuba',
112
- 'CW' => 'Curacao',
113
- 'CY' => 'Cyprus',
114
- 'CZ' => 'Czech Republic',
115
- 'CD' => 'Democratic Republic of the Congo',
116
- 'DK' => 'Denmark',
117
- 'DJ' => 'Djibouti',
118
- 'DM' => 'Dominica',
119
- 'DO' => 'Dominican Republic',
120
- 'TL' => 'East Timor',
121
- 'EC' => 'Ecuador',
122
- 'EG' => 'Egypt',
123
- 'SV' => 'El Salvador',
124
- 'GQ' => 'Equatorial Guinea',
125
- 'ER' => 'Eritrea',
126
- 'EE' => 'Estonia',
127
- 'ET' => 'Ethiopia',
128
- 'FK' => 'Falkland Islands',
129
- 'FO' => 'Faroe Islands',
130
- 'FJ' => 'Fiji',
131
- 'FI' => 'Finland',
132
- 'FR' => 'France',
133
- 'GF' => 'French Guiana',
134
- 'PF' => 'French Polynesia',
135
- 'TF' => 'French Southern Territories',
136
- 'GA' => 'Gabon',
137
- 'GM' => 'Gambia',
138
- 'GE' => 'Georgia',
139
- 'DE' => 'Germany',
140
- 'GH' => 'Ghana',
141
- 'GI' => 'Gibraltar',
142
- 'GR' => 'Greece',
143
- 'GL' => 'Greenland',
144
- 'GD' => 'Grenada',
145
- 'GP' => 'Guadeloupe',
146
- 'GU' => 'Guam',
147
- 'GT' => 'Guatemala',
148
- 'GG' => 'Guernsey',
149
- 'GN' => 'Guinea',
150
- 'GW' => 'Guinea-Bissau',
151
- 'GY' => 'Guyana',
152
- 'HT' => 'Haiti',
153
- 'HM' => 'Heard Island and McDonald Islands',
154
- 'HN' => 'Honduras',
155
- 'HK' => 'Hong Kong',
156
- 'HU' => 'Hungary',
157
- 'IS' => 'Iceland',
158
- 'IN' => 'India',
159
- 'ID' => 'Indonesia',
160
- 'IR' => 'Iran',
161
- 'IQ' => 'Iraq',
162
- 'IE' => 'Ireland',
163
- 'IM' => 'Isle of Man',
164
- 'IL' => 'Israel',
165
- 'IT' => 'Italy',
166
- 'CI' => 'Ivory Coast',
167
- 'JM' => 'Jamaica',
168
- 'JP' => 'Japan',
169
- 'JE' => 'Jersey',
170
- 'JO' => 'Jordan',
171
- 'KZ' => 'Kazakhstan',
172
- 'KE' => 'Kenya',
173
- 'KI' => 'Kiribati',
174
- 'XK' => 'Kosovo',
175
- 'KW' => 'Kuwait',
176
- 'KG' => 'Kyrgyzstan',
177
- 'LA' => 'Laos',
178
- 'LV' => 'Latvia',
179
- 'LB' => 'Lebanon',
180
- 'LS' => 'Lesotho',
181
- 'LR' => 'Liberia',
182
- 'LY' => 'Libya',
183
- 'LI' => 'Liechtenstein',
184
- 'LT' => 'Lithuania',
185
- 'LU' => 'Luxembourg',
186
- 'MO' => 'Macao',
187
- 'MK' => 'Macedonia',
188
- 'MG' => 'Madagascar',
189
- 'MW' => 'Malawi',
190
- 'MY' => 'Malaysia',
191
- 'MV' => 'Maldives',
192
- 'ML' => 'Mali',
193
- 'MT' => 'Malta',
194
- 'MH' => 'Marshall Islands',
195
- 'MQ' => 'Martinique',
196
- 'MR' => 'Mauritania',
197
- 'MU' => 'Mauritius',
198
- 'YT' => 'Mayotte',
199
- 'MX' => 'Mexico',
200
- 'FM' => 'Micronesia',
201
- 'MD' => 'Moldova',
202
- 'MC' => 'Monaco',
203
- 'MN' => 'Mongolia',
204
- 'ME' => 'Montenegro',
205
- 'MS' => 'Montserrat',
206
- 'MA' => 'Morocco',
207
- 'MZ' => 'Mozambique',
208
- 'MM' => 'Myanmar',
209
- 'NA' => 'Namibia',
210
- 'NR' => 'Nauru',
211
- 'NP' => 'Nepal',
212
- 'NL' => 'Netherlands',
213
- 'NC' => 'New Caledonia',
214
- 'NZ' => 'New Zealand',
215
- 'NI' => 'Nicaragua',
216
- 'NE' => 'Niger',
217
- 'NG' => 'Nigeria',
218
- 'NU' => 'Niue',
219
- 'NF' => 'Norfolk Island',
220
- 'KP' => 'North Korea',
221
- 'MP' => 'Northern Mariana Islands',
222
- 'NO' => 'Norway',
223
- 'OM' => 'Oman',
224
- 'PK' => 'Pakistan',
225
- 'PW' => 'Palau',
226
- 'PS' => 'Palestinian Territory',
227
- 'PA' => 'Panama',
228
- 'PG' => 'Papua New Guinea',
229
- 'PY' => 'Paraguay',
230
- 'PE' => 'Peru',
231
- 'PH' => 'Philippines',
232
- 'PN' => 'Pitcairn',
233
- 'PL' => 'Poland',
234
- 'PT' => 'Portugal',
235
- 'PR' => 'Puerto Rico',
236
- 'QA' => 'Qatar',
237
- 'CG' => 'Republic of the Congo',
238
- 'RE' => 'Reunion',
239
- 'RO' => 'Romania',
240
- 'RU' => 'Russia',
241
- 'RW' => 'Rwanda',
242
- 'BL' => 'Saint Barthelemy',
243
- 'SH' => 'Saint Helena',
244
- 'KN' => 'Saint Kitts and Nevis',
245
- 'LC' => 'Saint Lucia',
246
- 'MF' => 'Saint Martin',
247
- 'PM' => 'Saint Pierre and Miquelon',
248
- 'VC' => 'Saint Vincent and the Grenadines',
249
- 'WS' => 'Samoa',
250
- 'SM' => 'San Marino',
251
- 'ST' => 'Sao Tome and Principe',
252
- 'SA' => 'Saudi Arabia',
253
- 'SN' => 'Senegal',
254
- 'RS' => 'Serbia',
255
- 'SC' => 'Seychelles',
256
- 'SL' => 'Sierra Leone',
257
- 'SG' => 'Singapore',
258
- 'SX' => 'Sint Maarten',
259
- 'SK' => 'Slovakia',
260
- 'SI' => 'Slovenia',
261
- 'SB' => 'Solomon Islands',
262
- 'SO' => 'Somalia',
263
- 'ZA' => 'South Africa',
264
- 'GS' => 'South Georgia and the South Sandwich Islands',
265
- 'KR' => 'South Korea',
266
- 'SS' => 'South Sudan',
267
- 'ES' => 'Spain',
268
- 'LK' => 'Sri Lanka',
269
- 'SD' => 'Sudan',
270
- 'SR' => 'Suriname',
271
- 'SJ' => 'Svalbard and Jan Mayen',
272
- 'SZ' => 'Swaziland',
273
- 'SE' => 'Sweden',
274
- 'CH' => 'Switzerland',
275
- 'SY' => 'Syria',
276
- 'TW' => 'Taiwan',
277
- 'TJ' => 'Tajikistan',
278
- 'TZ' => 'Tanzania',
279
- 'TH' => 'Thailand',
280
- 'TG' => 'Togo',
281
- 'TK' => 'Tokelau',
282
- 'TO' => 'Tonga',
283
- 'TT' => 'Trinidad and Tobago',
284
- 'TN' => 'Tunisia',
285
- 'TR' => 'Turkey',
286
- 'TM' => 'Turkmenistan',
287
- 'TC' => 'Turks and Caicos Islands',
288
- 'TV' => 'Tuvalu',
289
- 'VI' => 'U.S. Virgin Islands',
290
- 'UG' => 'Uganda',
291
- 'UA' => 'Ukraine',
292
- 'AE' => 'United Arab Emirates',
293
- 'GB' => 'United Kingdom',
294
- 'US' => 'United States',
295
- 'UM' => 'United States Minor Outlying Islands',
296
- 'UY' => 'Uruguay',
297
- 'UZ' => 'Uzbekistan',
298
- 'VU' => 'Vanuatu',
299
- 'VA' => 'Vatican',
300
- 'VE' => 'Venezuela',
301
- 'VN' => 'Vietnam',
302
- 'WF' => 'Wallis and Futuna',
303
- 'EH' => 'Western Sahara',
304
- 'YE' => 'Yemen',
305
- 'ZM' => 'Zambia',
306
- 'ZW' => 'Zimbabwe',
307
- ) ?>
308
- <td><label><span><?php fs_esc_html_echo_inline( 'Country', 'country', $slug ) ?>:</span> <select id="address_country_code">
309
- <?php if ( empty( $billing->address_country_code ) ) : ?>
310
- <option value="" selected><?php fs_esc_html_echo_inline( 'Select Country', 'select-country', $slug ) ?></option>
311
- <?php endif ?>
312
- <?php foreach ( $countries as $code => $country ) : ?>
313
- <option
314
- value="<?php echo $code ?>" <?php selected( $billing->address_country_code, $code ) ?>><?php echo $country ?></option>
315
- <?php endforeach ?>
316
- </select></label></td>
317
- <td><label><span><?php fs_esc_html_echo_inline( 'State', 'state', $slug ) ?> / <?php fs_esc_html_echo_inline( 'Province', 'province', $slug ) ?>:</span>
318
- <input id="address_state" value="<?php echo $billing->address_state ?>" placeholder="<?php fs_esc_html_echo_inline( 'State', 'state', $slug ) ?> / <?php fs_esc_html_echo_inline( 'Province', 'province', $slug ) ?>"></label></td>
319
- </tr>
320
- <tr>
321
- <td colspan="2">
322
- <button
323
- class="button"><?php echo esc_html( $has_billing ?
324
- $edit_text :
325
- $update_text
326
- ) ?></button>
327
- </td>
328
- </tr>
329
- </table>
330
- </div>
331
- </div>
332
- <!--/ Billing -->
333
- <script type="text/javascript">
334
- (function($){
335
- var $billingAddress = $('#fs_billing_address'),
336
- $billingInputs = $billingAddress.find('input, select');
337
-
338
- var setPrevValues = function () {
339
- $billingInputs.each(function () {
340
- $(this).attr('data-val', $(this).val());
341
- });
342
- };
343
-
344
- setPrevValues();
345
-
346
- var hasBillingChanged = function () {
347
- for (var i = 0, len = $billingInputs.length; i < len; i++){
348
- var $this = $($billingInputs[i]);
349
- if ($this.attr('data-val') !== $this.val()) {
350
- return true;
351
- }
352
- }
353
-
354
- return false;
355
- };
356
-
357
- var isEditAllFieldsMode = false;
358
-
359
- $billingAddress.find('.button').click(function(){
360
- $billingAddress.toggleClass('fs-read-mode');
361
-
362
- var isEditMode = !$billingAddress.hasClass('fs-read-mode');
363
-
364
- $(this)
365
- .html(isEditMode ? '<?php echo esc_js( $update_text ) ?>' : '<?php echo esc_js( $edit_text ) ?>')
366
- .toggleClass('button-primary');
367
-
368
- if (isEditMode) {
369
- $('#business_name').focus().select();
370
- isEditAllFieldsMode = true;
371
- } else {
372
- isEditAllFieldsMode = false;
373
-
374
- if (!hasBillingChanged())
375
- return;
376
-
377
- var billing = {};
378
-
379
- $billingInputs.each(function(){
380
- if ($(this).attr('data-val') !== $(this).val()) {
381
- billing[$(this).attr('id')] = $(this).val();
382
- }
383
- });
384
-
385
- $.ajax({
386
- url : ajaxurl,
387
- method : 'POST',
388
- data : {
389
- action : '<?php echo $fs->get_ajax_action( 'update_billing' ) ?>',
390
- security : '<?php echo $fs->get_ajax_security( 'update_billing' ) ?>',
391
- module_id: '<?php echo $fs->get_id() ?>',
392
- billing : billing
393
- },
394
- success: function (resultObj) {
395
- if (resultObj.success) {
396
- setPrevValues();
397
- } else {
398
- alert(resultObj.error);
399
- }
400
- }
401
- });
402
- }
403
- });
404
-
405
- $billingInputs
406
- // Get into edit mode upon selection.
407
- .focus(function () {
408
- var isEditMode = !$billingAddress.hasClass('fs-read-mode');
409
-
410
- if (isEditMode) {
411
- return;
412
- }
413
-
414
- $billingAddress.toggleClass('fs-read-mode');
415
- $billingAddress.find('.button')
416
- .html('<?php echo esc_js( $update_text ) ?>')
417
- .toggleClass('button-primary');
418
- })
419
- // If blured after editing only one field without changes, exit edit mode.
420
- .blur(function () {
421
- if (!isEditAllFieldsMode && !hasBillingChanged()) {
422
- $billingAddress.toggleClass('fs-read-mode');
423
- $billingAddress.find('.button')
424
- .html('<?php echo esc_js( $edit_text ) ?>')
425
- .toggleClass('button-primary');
426
- }
427
- });
428
- })(jQuery);
429
- </script>
430
- <?php
431
  endif;
1
+ <?php
2
+ /**
3
+ * @package Freemius
4
+ * @copyright Copyright (c) 2016, Freemius, Inc.
5
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
+ * @since 1.2.0
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
+ $payments = $fs->_fetch_payments();
22
+
23
+ $show_billing = ( is_array( $payments ) && 0 < count( $payments ) );
24
+
25
+ if ( $show_billing ) :
26
+
27
+ $edit_text = fs_text_x_inline( 'Edit', 'verb', 'edit', $slug );
28
+ $update_text = fs_text_x_inline( 'Update', 'verb', 'update', $slug );
29
+
30
+ $billing = $fs->_fetch_billing();
31
+ $has_billing = ( $billing instanceof FS_Billing );
32
+ if ( ! $has_billing ) {
33
+ $billing = new FS_Billing();
34
+ }
35
+ ?>
36
+ <!-- Billing -->
37
+ <div class="postbox">
38
+ <div id="fs_billing">
39
+ <h3><span class="dashicons dashicons-portfolio"></span> <?php fs_esc_html_echo_inline( 'Billing', 'billing', $slug ) ?></h3>
40
+ <table id="fs_billing_address"<?php if ( $has_billing ) {
41
+ echo ' class="fs-read-mode"';
42
+ } ?>>
43
+ <tr>
44
+ <td><label><span><?php fs_esc_html_echo_inline( 'Business name', 'business-name', $slug ) ?>:</span> <input id="business_name" value="<?php echo $billing->business_name ?>" placeholder="<?php fs_esc_attr_echo_inline( 'Business name', 'business-name', $slug ) ?>"></label></td>
45
+ <td><label><span><?php fs_esc_html_echo_inline( 'Tax / VAT ID', 'tax-vat-id', $slug ) ?>:</span> <input id="tax_id" value="<?php echo $billing->tax_id ?>" placeholder="<?php fs_esc_attr_echo_inline( 'Tax / VAT ID', 'tax-vat-id', $slug ) ?>"></label></td>
46
+ </tr>
47
+ <tr>
48
+ <td><label><span><?php printf( fs_esc_html_inline( 'Address Line %d', 'address-line-n', $slug ), 1 ) ?>:</span> <input id="address_street" value="<?php echo $billing->address_street ?>" placeholder="<?php printf( fs_esc_attr_inline( 'Address Line %d', 'address-line-n', $slug ), 1 ) ?>"></label></td>
49
+ <td><label><span><?php printf( fs_esc_html_inline( 'Address Line %d', 'address-line-n', $slug ), 2 ) ?>:</span> <input id="address_apt" value="<?php echo $billing->address_apt ?>" placeholder="<?php printf( fs_esc_attr_inline( 'Address Line %d', 'address-line-n', $slug ), 2 ) ?>"></label></td>
50
+ </tr>
51
+ <tr>
52
+ <td><label><span><?php fs_esc_html_echo_inline( 'City', 'city', $slug ) ?> / <?php fs_esc_html_echo_inline( 'Town', 'town', $slug ) ?>:</span> <input id="address_city" value="<?php echo $billing->address_city ?>" placeholder="<?php fs_esc_attr_echo_inline( 'City', 'city', $slug ) ?> / <?php fs_esc_attr_echo_inline( 'Town', 'town', $slug ) ?>"></label></td>
53
+ <td><label><span><?php fs_esc_html_echo_inline( 'ZIP / Postal Code', 'zip-postal-code', $slug ) ?>:</span> <input id="address_zip" value="<?php echo $billing->address_zip ?>" placeholder="<?php fs_esc_attr_echo_inline( 'ZIP / Postal Code', 'zip-postal-code', $slug ) ?>"></label></td>
54
+ </tr>
55
+ <tr>
56
+ <?php $countries = array(
57
+ 'AF' => 'Afghanistan',
58
+ 'AX' => 'Aland Islands',
59
+ 'AL' => 'Albania',
60
+ 'DZ' => 'Algeria',
61
+ 'AS' => 'American Samoa',
62
+ 'AD' => 'Andorra',
63
+ 'AO' => 'Angola',
64
+ 'AI' => 'Anguilla',
65
+ 'AQ' => 'Antarctica',
66
+ 'AG' => 'Antigua and Barbuda',
67
+ 'AR' => 'Argentina',
68
+ 'AM' => 'Armenia',
69
+ 'AW' => 'Aruba',
70
+ 'AU' => 'Australia',
71
+ 'AT' => 'Austria',
72
+ 'AZ' => 'Azerbaijan',
73
+ 'BS' => 'Bahamas',
74
+ 'BH' => 'Bahrain',
75
+ 'BD' => 'Bangladesh',
76
+ 'BB' => 'Barbados',
77
+ 'BY' => 'Belarus',
78
+ 'BE' => 'Belgium',
79
+ 'BZ' => 'Belize',
80
+ 'BJ' => 'Benin',
81
+ 'BM' => 'Bermuda',
82
+ 'BT' => 'Bhutan',
83
+ 'BO' => 'Bolivia',
84
+ 'BQ' => 'Bonaire, Saint Eustatius and Saba',
85
+ 'BA' => 'Bosnia and Herzegovina',
86
+ 'BW' => 'Botswana',
87
+ 'BV' => 'Bouvet Island',
88
+ 'BR' => 'Brazil',
89
+ 'IO' => 'British Indian Ocean Territory',
90
+ 'VG' => 'British Virgin Islands',
91
+ 'BN' => 'Brunei',
92
+ 'BG' => 'Bulgaria',
93
+ 'BF' => 'Burkina Faso',
94
+ 'BI' => 'Burundi',
95
+ 'KH' => 'Cambodia',
96
+ 'CM' => 'Cameroon',
97
+ 'CA' => 'Canada',
98
+ 'CV' => 'Cape Verde',
99
+ 'KY' => 'Cayman Islands',
100
+ 'CF' => 'Central African Republic',
101
+ 'TD' => 'Chad',
102
+ 'CL' => 'Chile',
103
+ 'CN' => 'China',
104
+ 'CX' => 'Christmas Island',
105
+ 'CC' => 'Cocos Islands',
106
+ 'CO' => 'Colombia',
107
+ 'KM' => 'Comoros',
108
+ 'CK' => 'Cook Islands',
109
+ 'CR' => 'Costa Rica',
110
+ 'HR' => 'Croatia',
111
+ 'CU' => 'Cuba',
112
+ 'CW' => 'Curacao',
113
+ 'CY' => 'Cyprus',
114
+ 'CZ' => 'Czech Republic',
115
+ 'CD' => 'Democratic Republic of the Congo',
116
+ 'DK' => 'Denmark',
117
+ 'DJ' => 'Djibouti',
118
+ 'DM' => 'Dominica',
119
+ 'DO' => 'Dominican Republic',
120
+ 'TL' => 'East Timor',
121
+ 'EC' => 'Ecuador',
122
+ 'EG' => 'Egypt',
123
+ 'SV' => 'El Salvador',
124
+ 'GQ' => 'Equatorial Guinea',
125
+ 'ER' => 'Eritrea',
126
+ 'EE' => 'Estonia',
127
+ 'ET' => 'Ethiopia',
128
+ 'FK' => 'Falkland Islands',
129
+ 'FO' => 'Faroe Islands',
130
+ 'FJ' => 'Fiji',
131
+ 'FI' => 'Finland',
132
+ 'FR' => 'France',
133
+ 'GF' => 'French Guiana',
134
+ 'PF' => 'French Polynesia',
135
+ 'TF' => 'French Southern Territories',
136
+ 'GA' => 'Gabon',
137
+ 'GM' => 'Gambia',
138
+ 'GE' => 'Georgia',
139
+ 'DE' => 'Germany',
140
+ 'GH' => 'Ghana',
141
+ 'GI' => 'Gibraltar',
142
+ 'GR' => 'Greece',
143
+ 'GL' => 'Greenland',
144
+ 'GD' => 'Grenada',
145
+ 'GP' => 'Guadeloupe',
146
+ 'GU' => 'Guam',
147
+ 'GT' => 'Guatemala',
148
+ 'GG' => 'Guernsey',
149
+ 'GN' => 'Guinea',
150
+ 'GW' => 'Guinea-Bissau',
151
+ 'GY' => 'Guyana',
152
+ 'HT' => 'Haiti',
153
+ 'HM' => 'Heard Island and McDonald Islands',
154
+ 'HN' => 'Honduras',
155
+ 'HK' => 'Hong Kong',
156
+ 'HU' => 'Hungary',
157
+ 'IS' => 'Iceland',
158
+ 'IN' => 'India',
159
+ 'ID' => 'Indonesia',
160
+ 'IR' => 'Iran',
161
+ 'IQ' => 'Iraq',
162
+ 'IE' => 'Ireland',
163
+ 'IM' => 'Isle of Man',
164
+ 'IL' => 'Israel',
165
+ 'IT' => 'Italy',
166
+ 'CI' => 'Ivory Coast',
167
+ 'JM' => 'Jamaica',
168
+ 'JP' => 'Japan',
169
+ 'JE' => 'Jersey',
170
+ 'JO' => 'Jordan',
171
+ 'KZ' => 'Kazakhstan',
172
+ 'KE' => 'Kenya',
173
+ 'KI' => 'Kiribati',
174
+ 'XK' => 'Kosovo',
175
+ 'KW' => 'Kuwait',
176
+ 'KG' => 'Kyrgyzstan',
177
+ 'LA' => 'Laos',
178
+ 'LV' => 'Latvia',
179
+ 'LB' => 'Lebanon',
180
+ 'LS' => 'Lesotho',
181
+ 'LR' => 'Liberia',
182
+ 'LY' => 'Libya',
183
+ 'LI' => 'Liechtenstein',
184
+ 'LT' => 'Lithuania',
185
+ 'LU' => 'Luxembourg',
186
+ 'MO' => 'Macao',
187
+ 'MK' => 'Macedonia',
188
+ 'MG' => 'Madagascar',
189
+ 'MW' => 'Malawi',
190
+ 'MY' => 'Malaysia',
191
+ 'MV' => 'Maldives',
192
+ 'ML' => 'Mali',
193
+ 'MT' => 'Malta',
194
+ 'MH' => 'Marshall Islands',
195
+ 'MQ' => 'Martinique',
196
+ 'MR' => 'Mauritania',
197
+ 'MU' => 'Mauritius',
198
+ 'YT' => 'Mayotte',
199
+ 'MX' => 'Mexico',
200
+ 'FM' => 'Micronesia',
201
+ 'MD' => 'Moldova',
202
+ 'MC' => 'Monaco',
203
+ 'MN' => 'Mongolia',
204
+ 'ME' => 'Montenegro',
205
+ 'MS' => 'Montserrat',
206
+ 'MA' => 'Morocco',
207
+ 'MZ' => 'Mozambique',
208
+ 'MM' => 'Myanmar',
209
+ 'NA' => 'Namibia',
210
+ 'NR' => 'Nauru',
211
+ 'NP' => 'Nepal',
212
+ 'NL' => 'Netherlands',
213
+ 'NC' => 'New Caledonia',
214
+ 'NZ' => 'New Zealand',
215
+ 'NI' => 'Nicaragua',
216
+ 'NE' => 'Niger',
217
+ 'NG' => 'Nigeria',
218
+ 'NU' => 'Niue',
219
+ 'NF' => 'Norfolk Island',
220
+ 'KP' => 'North Korea',
221
+ 'MP' => 'Northern Mariana Islands',
222
+ 'NO' => 'Norway',
223
+ 'OM' => 'Oman',
224
+ 'PK' => 'Pakistan',
225
+ 'PW' => 'Palau',
226
+ 'PS' => 'Palestinian Territory',
227
+ 'PA' => 'Panama',
228
+ 'PG' => 'Papua New Guinea',
229
+ 'PY' => 'Paraguay',
230
+ 'PE' => 'Peru',
231
+ 'PH' => 'Philippines',
232
+ 'PN' => 'Pitcairn',
233
+ 'PL' => 'Poland',
234
+ 'PT' => 'Portugal',
235
+ 'PR' => 'Puerto Rico',
236
+ 'QA' => 'Qatar',
237
+ 'CG' => 'Republic of the Congo',
238
+ 'RE' => 'Reunion',
239
+ 'RO' => 'Romania',
240
+ 'RU' => 'Russia',
241
+ 'RW' => 'Rwanda',
242
+ 'BL' => 'Saint Barthelemy',
243
+ 'SH' => 'Saint Helena',
244
+ 'KN' => 'Saint Kitts and Nevis',
245
+ 'LC' => 'Saint Lucia',
246
+ 'MF' => 'Saint Martin',
247
+ 'PM' => 'Saint Pierre and Miquelon',
248
+ 'VC' => 'Saint Vincent and the Grenadines',
249
+ 'WS' => 'Samoa',
250
+ 'SM' => 'San Marino',
251
+ 'ST' => 'Sao Tome and Principe',
252
+ 'SA' => 'Saudi Arabia',
253
+ 'SN' => 'Senegal',
254
+ 'RS' => 'Serbia',
255
+ 'SC' => 'Seychelles',
256
+ 'SL' => 'Sierra Leone',
257
+ 'SG' => 'Singapore',
258
+ 'SX' => 'Sint Maarten',
259
+ 'SK' => 'Slovakia',
260
+ 'SI' => 'Slovenia',
261
+ 'SB' => 'Solomon Islands',
262
+ 'SO' => 'Somalia',
263
+ 'ZA' => 'South Africa',
264
+ 'GS' => 'South Georgia and the South Sandwich Islands',
265
+ 'KR' => 'South Korea',
266
+ 'SS' => 'South Sudan',
267
+ 'ES' => 'Spain',
268
+ 'LK' => 'Sri Lanka',
269
+ 'SD' => 'Sudan',
270
+ 'SR' => 'Suriname',
271
+ 'SJ' => 'Svalbard and Jan Mayen',
272
+ 'SZ' => 'Swaziland',
273
+ 'SE' => 'Sweden',
274
+ 'CH' => 'Switzerland',
275
+ 'SY' => 'Syria',
276
+ 'TW' => 'Taiwan',
277
+ 'TJ' => 'Tajikistan',
278
+ 'TZ' => 'Tanzania',
279
+ 'TH' => 'Thailand',
280
+ 'TG' => 'Togo',
281
+ 'TK' => 'Tokelau',
282
+ 'TO' => 'Tonga',
283
+ 'TT' => 'Trinidad and Tobago',
284
+ 'TN' => 'Tunisia',
285
+ 'TR' => 'Turkey',
286
+ 'TM' => 'Turkmenistan',
287
+ 'TC' => 'Turks and Caicos Islands',
288
+ 'TV' => 'Tuvalu',
289
+ 'VI' => 'U.S. Virgin Islands',
290
+ 'UG' => 'Uganda',
291
+ 'UA' => 'Ukraine',
292
+ 'AE' => 'United Arab Emirates',
293
+ 'GB' => 'United Kingdom',
294
+ 'US' => 'United States',
295
+ 'UM' => 'United States Minor Outlying Islands',
296
+ 'UY' => 'Uruguay',
297
+ 'UZ' => 'Uzbekistan',
298
+ 'VU' => 'Vanuatu',
299
+ 'VA' => 'Vatican',
300
+ 'VE' => 'Venezuela',
301
+ 'VN' => 'Vietnam',
302
+ 'WF' => 'Wallis and Futuna',
303
+ 'EH' => 'Western Sahara',
304
+ 'YE' => 'Yemen',
305
+ 'ZM' => 'Zambia',
306
+ 'ZW' => 'Zimbabwe',
307
+ ) ?>
308
+ <td><label><span><?php fs_esc_html_echo_inline( 'Country', 'country', $slug ) ?>:</span> <select id="address_country_code">
309
+ <?php if ( empty( $billing->address_country_code ) ) : ?>
310
+ <option value="" selected><?php fs_esc_html_echo_inline( 'Select Country', 'select-country', $slug ) ?></option>
311
+ <?php endif ?>
312
+ <?php foreach ( $countries as $code => $country ) : ?>
313
+ <option
314
+ value="<?php echo $code ?>" <?php selected( $billing->address_country_code, $code ) ?>><?php echo $country ?></option>
315
+ <?php endforeach ?>
316
+ </select></label></td>
317
+ <td><label><span><?php fs_esc_html_echo_inline( 'State', 'state', $slug ) ?> / <?php fs_esc_html_echo_inline( 'Province', 'province', $slug ) ?>:</span>
318
+ <input id="address_state" value="<?php echo $billing->address_state ?>" placeholder="<?php fs_esc_html_echo_inline( 'State', 'state', $slug ) ?> / <?php fs_esc_html_echo_inline( 'Province', 'province', $slug ) ?>"></label></td>
319
+ </tr>
320
+ <tr>
321
+ <td colspan="2">
322
+ <button
323
+ class="button"><?php echo esc_html( $has_billing ?
324
+ $edit_text :
325
+ $update_text
326
+ ) ?></button>
327
+ </td>
328
+ </tr>
329
+ </table>
330
+ </div>
331
+ </div>
332
+ <!--/ Billing -->
333
+ <script type="text/javascript">
334
+ (function($){
335
+ var $billingAddress = $('#fs_billing_address'),
336
+ $billingInputs = $billingAddress.find('input, select');
337
+
338
+ var setPrevValues = function () {
339
+ $billingInputs.each(function () {
340
+ $(this).attr('data-val', $(this).val());
341
+ });
342
+ };
343
+
344
+ setPrevValues();
345
+
346
+ var hasBillingChanged = function () {
347
+ for (var i = 0, len = $billingInputs.length; i < len; i++){
348
+ var $this = $($billingInputs[i]);
349
+ if ($this.attr('data-val') !== $this.val()) {
350
+ return true;
351
+ }
352
+ }
353
+
354
+ return false;
355
+ };
356
+
357
+ var isEditAllFieldsMode = false;
358
+
359
+ $billingAddress.find('.button').click(function(){
360
+ $billingAddress.toggleClass('fs-read-mode');
361
+
362
+ var isEditMode = !$billingAddress.hasClass('fs-read-mode');
363
+
364
+ $(this)
365
+ .html(isEditMode ? '<?php echo esc_js( $update_text ) ?>' : '<?php echo esc_js( $edit_text ) ?>')
366
+ .toggleClass('button-primary');
367
+
368
+ if (isEditMode) {
369
+ $('#business_name').focus().select();
370
+ isEditAllFieldsMode = true;
371
+ } else {
372
+ isEditAllFieldsMode = false;
373
+
374
+ if (!hasBillingChanged())
375
+ return;
376
+
377
+ var billing = {};
378
+
379
+ $billingInputs.each(function(){
380
+ if ($(this).attr('data-val') !== $(this).val()) {
381
+ billing[$(this).attr('id')] = $(this).val();
382
+ }
383
+ });
384
+
385
+ $.ajax({
386
+ url : ajaxurl,
387
+ method : 'POST',
388
+ data : {
389
+ action : '<?php echo $fs->get_ajax_action( 'update_billing' ) ?>',
390
+ security : '<?php echo $fs->get_ajax_security( 'update_billing' ) ?>',
391
+ module_id: '<?php echo $fs->get_id() ?>',
392
+ billing : billing
393
+ },
394
+ success: function (resultObj) {
395
+ if (resultObj.success) {
396
+ setPrevValues();
397
+ } else {
398
+ alert(resultObj.error);
399
+ }
400
+ }
401
+ });
402
+ }
403
+ });
404
+
405
+ $billingInputs
406
+ // Get into edit mode upon selection.
407
+ .focus(function () {
408
+ var isEditMode = !$billingAddress.hasClass('fs-read-mode');
409
+
410
+ if (isEditMode) {
411
+ return;
412
+ }
413
+
414
+ $billingAddress.toggleClass('fs-read-mode');
415
+ $billingAddress.find('.button')
416
+ .html('<?php echo esc_js( $update_text ) ?>')
417
+ .toggleClass('button-primary');
418
+ })
419
+ // If blured after editing only one field without changes, exit edit mode.
420
+ .blur(function () {
421
+ if (!isEditAllFieldsMode && !hasBillingChanged()) {
422
+ $billingAddress.toggleClass('fs-read-mode');
423
+ $billingAddress.find('.button')
424
+ .html('<?php echo esc_js( $edit_text ) ?>')
425
+ .toggleClass('button-primary');
426
+ }
427
+ });
428
+ })(jQuery);
429
+ </script>
430
+ <?php
431
  endif;
freemius/templates/account/payments.php CHANGED
@@ -1,59 +1,59 @@
1
- <?php
2
- /**
3
- * @package Freemius
4
- * @copyright Copyright (c) 2016, Freemius, Inc.
5
- * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
- * @since 1.2.0
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
- $payments = $fs->_fetch_payments();
22
-
23
- $show_payments = ( is_array( $payments ) && 0 < count( $payments ) );
24
-
25
- if ( $show_payments ) :
26
- ?>
27
- <div class="postbox">
28
- <div id="fs_payments">
29
- <h3><span class="dashicons dashicons-paperclip"></span> <?php fs_esc_html_echo_inline( 'Payments', 'payments', $slug ) ?></h3>
30
-
31
- <div class="inside">
32
- <table class="widefat">
33
- <thead>
34
- <tr>
35
- <th><?php fs_esc_html_echo_inline( 'ID', 'id', $slug ) ?></th>
36
- <th><?php fs_esc_html_echo_inline( 'Date', 'date', $slug ) ?></th>
37
- <th><?php fs_esc_html_echo_inline( 'Amount', 'amount', $slug ) ?></th>
38
- <th><?php fs_esc_html_echo_inline( 'Invoice', 'invoice', $slug ) ?></th>
39
- </tr>
40
- </thead>
41
- <tbody>
42
- <?php $odd = true ?>
43
- <?php foreach ( $payments as $payment ) : ?>
44
- <tr<?php echo $odd ? ' class="alternate"' : '' ?>>
45
- <td><?php echo $payment->id ?></td>
46
- <td><?php echo date( 'M j, Y', strtotime( $payment->created ) ) ?></td>
47
- <td>$<?php echo $payment->gross ?></td>
48
- <td><a href="<?php echo $fs->_get_invoice_api_url( $payment->id ) ?>"
49
- class="button button-small"
50
- target="_blank"><?php fs_esc_html_echo_inline( 'Invoice', 'invoice', $slug ) ?></a></td>
51
- </tr>
52
- <?php $odd = ! $odd; endforeach ?>
53
- </tbody>
54
- </table>
55
- </div>
56
- </div>
57
- </div>
58
- <?php
59
  endif;
1
+ <?php
2
+ /**
3
+ * @package Freemius
4
+ * @copyright Copyright (c) 2016, Freemius, Inc.
5
+ * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
+ * @since 1.2.0
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
+ $payments = $fs->_fetch_payments();
22
+
23
+ $show_payments = ( is_array( $payments ) && 0 < count( $payments ) );
24
+
25
+ if ( $show_payments ) :
26
+ ?>
27
+ <div class="postbox">
28
+ <div id="fs_payments">
29
+ <h3><span class="dashicons dashicons-paperclip"></span> <?php fs_esc_html_echo_inline( 'Payments', 'payments', $slug ) ?></h3>
30
+
31
+ <div class="inside">
32
+ <table class="widefat">
33
+ <thead>
34
+ <tr>
35
+ <th><?php fs_esc_html_echo_inline( 'ID', 'id', $slug ) ?></th>
36
+ <th><?php fs_esc_html_echo_inline( 'Date', 'date', $slug ) ?></th>
37
+ <th><?php fs_esc_html_echo_inline( 'Amount', 'amount', $slug ) ?></th>
38
+ <th><?php fs_esc_html_echo_inline( 'Invoice', 'invoice', $slug ) ?></th>
39
+ </tr>
40
+ </thead>
41
+ <tbody>
42
+ <?php $odd = true ?>
43
+ <?php foreach ( $payments as $payment ) : ?>
44
+ <tr<?php echo $odd ? ' class="alternate"' : '' ?>>
45
+ <td><?php echo $payment->id ?></td>
46
+ <td><?php echo date( 'M j, Y', strtotime( $payment->created ) ) ?></td>
47
+ <td>$<?php echo $payment->gross ?></td>
48
+ <td><a href="<?php echo $fs->_get_invoice_api_url( $payment->id ) ?>"
49
+ class="button button-small"
50
+ target="_blank"><?php fs_esc_html_echo_inline( 'Invoice', 'invoice', $slug ) ?></a></td>
51
+ </tr>
52
+ <?php $odd = ! $odd; endforeach ?>
53
+ </tbody>
54
+ </table>
55
+ </div>
56
+ </div>
57
+ </div>
58
+ <?php
59
  endif;
freemius/templates/add-ons.php CHANGED
@@ -1,193 +1,193 @@
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
- /**
14
- * @var array $VARS
15
- * @var Freemius
16
- */
17
- $fs = freemius( $VARS['id'] );
18
-
19
- $slug = $fs->get_slug();
20
-
21
- $open_addon_slug = fs_request_get( 'slug' );
22
-
23
- $open_addon = false;
24
-
25
- /**
26
- * @var FS_Plugin[]
27
- */
28
- $addons = $fs->get_addons();
29
-
30
- $has_addons = ( is_array( $addons ) && 0 < count( $addons ) );
31
-
32
- $has_tabs = $fs->_add_tabs_before_content();
33
- ?>
34
- <div id="fs_addons" class="wrap fs-section">
35
- <?php if ( ! $has_tabs ) : ?>
36
- <h2><?php echo esc_html( sprintf( fs_text_inline( 'Add Ons for %s', 'add-ons-for-x', $slug ), $fs->get_plugin_name() ) ) ?></h2>
37
- <?php endif ?>
38
-
39
- <div id="poststuff">
40
- <?php if ( ! $has_addons ) : ?>
41
- <h3><?php echo esc_html( sprintf(
42
- '%s... %s',
43
- fs_text_x_inline( 'Oops', 'exclamation', 'oops', $slug ),
44
- fs_text_inline( 'We could\'nt load the add-ons list. It\'s probably an issue on our side, please try to come back in few minutes.', 'add-ons-missing', $slug )
45
- ) ) ?></h3>
46
- <?php endif ?>
47
- <ul class="fs-cards-list">
48
- <?php if ( $has_addons ) : ?>
49
- <?php foreach ( $addons as $addon ) : ?>
50
- <?php
51
- $open_addon = ( $open_addon || ( $open_addon_slug === $addon->slug ) );
52
-
53
- $price = 0;
54
- $has_trial = false;
55
- $has_free_plan = false;
56
- $has_paid_plan = false;
57
-
58
- $result = $fs->get_api_plugin_scope()->get( "/addons/{$addon->id}/pricing.json?type=visible" );
59
- if ( ! isset( $result->error ) ) {
60
- $plans = $result->plans;
61
-
62
- if ( is_array( $plans ) && 0 < count( $plans ) ) {
63
- foreach ( $plans as $plan ) {
64
- if ( ! isset( $plan->pricing ) ||
65
- ! is_array( $plan->pricing ) ||
66
- 0 == count( $plan->pricing )
67
- ) {
68
- // No pricing means a free plan.
69
- $has_free_plan = true;
70
- continue;
71
- }
72
-
73
-
74
- $has_paid_plan = true;
75
- $has_trial = $has_trial || ( is_numeric( $plan->trial_period ) && ( $plan->trial_period > 0 ) );
76
-
77
- $min_price = 999999;
78
- foreach ( $plan->pricing as $pricing ) {
79
- if ( ! is_null( $pricing->annual_price ) && $pricing->annual_price > 0 ) {
80
- $min_price = min( $min_price, $pricing->annual_price );
81
- } else if ( ! is_null( $pricing->monthly_price ) && $pricing->monthly_price > 0 ) {
82
- $min_price = min( $min_price, 12 * $pricing->monthly_price );
83
- }
84
- }
85
-
86
- if ( $min_price < 999999 ) {
87
- $price = $min_price;
88
- }
89
-
90
- }
91
- }
92
- }
93
- ?>
94
- <li class="fs-card fs-addon" data-slug="<?php echo $addon->slug ?>">
95
- <?php
96
- echo sprintf( '<a href="%s" class="thickbox fs-overlay" aria-label="%s" data-title="%s"></a>',
97
- esc_url( network_admin_url( 'plugin-install.php?tab=plugin-information&parent_plugin_id=' . $fs->get_id() . '&plugin=' . $addon->slug .
98
- '&TB_iframe=true&width=600&height=550' ) ),
99
- esc_attr( sprintf( fs_text_inline( 'More information about %s', 'more-information-about-x', $slug ), $addon->title ) ),
100
- esc_attr( $addon->title )
101
- );
102
- ?>
103
- <?php
104
- if ( is_null( $addon->info ) ) {
105
- $addon->info = new stdClass();
106
- }
107
- if ( ! isset( $addon->info->card_banner_url ) ) {
108
- $addon->info->card_banner_url = '//dashboard.freemius.com/assets/img/marketing/blueprint-300x100.jpg';
109
- }
110
- if ( ! isset( $addon->info->short_description ) ) {
111
- $addon->info->short_description = 'What\'s the one thing your add-on does really, really well?';
112
- }
113
- ?>
114
- <div class="fs-inner">
115
- <ul>
116
- <li class="fs-card-banner"
117
- style="background-image: url('<?php echo $addon->info->card_banner_url ?>');"></li>
118
- <!-- <li class="fs-tag"></li> -->
119
- <li class="fs-title"><?php echo $addon->title ?></li>
120
- <li class="fs-offer">
121
- <span
122
- class="fs-price"><?php
123
- $descriptors = array();
124
-
125
- if ($has_free_plan)
126
- $descriptors[] = fs_text_inline( 'Free', 'free', $slug );
127
- if ($has_paid_plan && $price > 0)
128
- $descriptors[] = '$' . number_format( $price, 2 );
129
- if ($has_trial)
130
- $descriptors[] = fs_text_x_inline( 'Trial', 'trial period', 'trial', $slug );
131
-
132
- echo implode(' - ', $descriptors) ?></span>
133
- </li>
134
- <li class="fs-description"><?php echo ! empty( $addon->info->short_description ) ? $addon->info->short_description : 'SHORT DESCRIPTION' ?></li>
135
- <li class="fs-cta"><a class="button"><?php fs_esc_html_echo_inline( 'View details', 'view-details', $slug ) ?></a></li>
136
- </ul>
137
- </div>
138
- </li>
139
- <?php endforeach ?>
140
- <?php endif ?>
141
- </ul>
142
- </div>
143
- </div>
144
- <script type="text/javascript">
145
- (function ($) {
146
- <?php if ( $open_addon ) : ?>
147
-
148
- var interval = setInterval(function () {
149
- // Open add-on information page.
150
- <?php
151
- /**
152
- * @author Vova Feldman
153
- *
154
- * This code does NOT expose an XSS vulnerability because:
155
- * 1. This page only renders for admins, so if an attacker manage to get
156
- * admin access, they can do more harm.
157
- * 2. This code won't be rendered unless $open_addon_slug matches any of
158
- * the plugin's add-ons slugs.
159
- */
160
- ?>
161
- $('.fs-card[data-slug=<?php echo $open_addon_slug ?>] a').click();
162
- if ($('#TB_iframeContent').length > 0) {
163
- clearInterval(interval);
164
- interval = null;
165
- }
166
- }, 200);
167
-
168
- <?php else : ?>
169
-
170
-
171
- $('.fs-card.fs-addon')
172
- .mouseover(function () {
173
- $(this).find('.fs-cta .button').addClass('button-primary');
174
- }).mouseout(function () {
175
- $(this).find('.fs-cta .button').removeClass('button-primary');
176
- });
177
-
178
- <?php endif ?>
179
- })(jQuery);
180
- </script>
181
- <?php
182
- if ( $has_tabs ) {
183
- $fs->_add_tabs_after_content();
184
- }
185
-
186
- $params = array(
187
- 'page' => 'addons',
188
- 'module_id' => $fs->get_id(),
189
- 'module_type' => $fs->get_module_type(),
190
- 'module_slug' => $slug,
191
- 'module_version' => $fs->get_plugin_version(),
192
- );
193
  fs_require_template( 'powered-by.php', $params );
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
+ /**
14
+ * @var array $VARS
15
+ * @var Freemius
16
+ */
17
+ $fs = freemius( $VARS['id'] );
18
+
19
+ $slug = $fs->get_slug();
20
+
21
+ $open_addon_slug = fs_request_get( 'slug' );
22
+
23
+ $open_addon = false;
24
+
25
+ /**
26
+ * @var FS_Plugin[]
27
+ */
28
+ $addons = $fs->get_addons();
29
+
30
+ $has_addons = ( is_array( $addons ) && 0 < count( $addons ) );
31
+
32
+ $has_tabs = $fs->_add_tabs_before_content();
33
+ ?>
34
+ <div id="fs_addons" class="wrap fs-section">
35
+ <?php if ( ! $has_tabs ) : ?>
36
+ <h2><?php echo esc_html( sprintf( fs_text_inline( 'Add Ons for %s', 'add-ons-for-x', $slug ), $fs->get_plugin_name() ) ) ?></h2>
37
+ <?php endif ?>
38
+
39
+ <div id="poststuff">
40
+ <?php if ( ! $has_addons ) : ?>
41
+ <h3><?php echo esc_html( sprintf(
42
+ '%s... %s',
43
+ fs_text_x_inline( 'Oops', 'exclamation', 'oops', $slug ),
44
+ fs_text_inline( 'We could\'nt load the add-ons list. It\'s probably an issue on our side, please try to come back in few minutes.', 'add-ons-missing', $slug )
45
+ ) ) ?></h3>
46
+ <?php endif ?>
47
+ <ul class="fs-cards-list">
48
+ <?php if ( $has_addons ) : ?>
49
+ <?php foreach ( $addons as $addon ) : ?>
50
+ <?php
51
+ $open_addon = ( $open_addon || ( $open_addon_slug === $addon->slug ) );
52
+
53
+ $price = 0;
54
+ $has_trial = false;
55
+ $has_free_plan = false;
56
+ $has_paid_plan = false;
57
+
58
+ $result = $fs->get_api_plugin_scope()->get( "/addons/{$addon->id}/pricing.json?type=visible" );
59
+ if ( ! isset( $result->error ) ) {
60
+ $plans = $result->plans;
61
+
62
+ if ( is_array( $plans ) && 0 < count( $plans ) ) {
63
+ foreach ( $plans as $plan ) {
64
+ if ( ! isset( $plan->pricing ) ||
65
+ ! is_array( $plan->pricing ) ||
66
+ 0 == count( $plan->pricing )
67
+ ) {
68
+ // No pricing means a free plan.
69
+ $has_free_plan = true;
70
+ continue;
71
+ }
72
+
73
+
74
+ $has_paid_plan = true;
75
+ $has_trial = $has_trial || ( is_numeric( $plan->trial_period ) && ( $plan->trial_period > 0 ) );
76
+
77
+ $min_price = 999999;
78
+ foreach ( $plan->pricing as $pricing ) {
79
+ if ( ! is_null( $pricing->annual_price ) && $pricing->annual_price > 0 ) {
80
+ $min_price = min( $min_price, $pricing->annual_price );
81
+ } else if ( ! is_null( $pricing->monthly_price ) && $pricing->monthly_price > 0 ) {
82
+ $min_price = min( $min_price, 12 * $pricing->monthly_price );
83
+ }
84
+ }
85
+
86
+ if ( $min_price < 999999 ) {
87
+ $price = $min_price;
88
+ }
89
+
90
+ }
91
+ }
92
+ }
93
+ ?>
94
+ <li class="fs-card fs-addon" data-slug="<?php echo $addon->slug ?>">
95
+ <?php
96
+ echo sprintf( '<a href="%s" class="thickbox fs-overlay" aria-label="%s" data-title="%s"></a>',
97
+ esc_url( network_admin_url( 'plugin-install.php?tab=plugin-information&parent_plugin_id=' . $fs->get_id() . '&plugin=' . $addon->slug .
98
+ '&TB_iframe=true&width=600&height=550' ) ),
99
+ esc_attr( sprintf( fs_text_inline( 'More information about %s', 'more-information-about-x', $slug ), $addon->title ) ),
100
+ esc_attr( $addon->title )
101
+ );
102
+ ?>
103
+ <?php
104
+ if ( is_null( $addon->info ) ) {
105
+ $addon->info = new stdClass();
106
+ }
107
+ if ( ! isset( $addon->info->card_banner_url ) ) {
108
+ $addon->info->card_banner_url = '//dashboard.freemius.com/assets/img/marketing/blueprint-300x100.jpg';
109
+ }
110
+ if ( ! isset( $addon->info->short_description ) ) {
111
+ $addon->info->short_description = 'What\'s the one thing your add-on does really, really well?';
112
+ }
113
+ ?>
114
+ <div class="fs-inner">
115
+ <ul>
116
+ <li class="fs-card-banner"
117
+ style="background-image: url('<?php echo $addon->info->card_banner_url ?>');"></li>
118
+ <!-- <li class="fs-tag"></li> -->
119
+ <li class="fs-title"><?php echo $addon->title ?></li>
120
+ <li class="fs-offer">
121
+ <span
122
+ class="fs-price"><?php
123
+ $descriptors = array();
124
+
125
+ if ($has_free_plan)
126
+ $descriptors[] = fs_text_inline( 'Free', 'free', $slug );
127
+ if ($has_paid_plan && $price > 0)
128
+ $descriptors[] = '$' . number_format( $price, 2 );
129
+ if ($has_trial)
130
+ $descriptors[] = fs_text_x_inline( 'Trial', 'trial period', 'trial', $slug );
131
+
132
+ echo implode(' - ', $descriptors) ?></span>
133
+ </li>
134
+ <li class="fs-description"><?php echo ! empty( $addon->info->short_description ) ? $addon->info->short_description : 'SHORT DESCRIPTION' ?></li>
135
+ <li class="fs-cta"><a class="button"><?php fs_esc_html_echo_inline( 'View details', 'view-details', $slug ) ?></a></li>
136
+ </ul>
137
+ </div>
138
+ </li>
139
+ <?php endforeach ?>
140
+ <?php endif ?>
141
+ </ul>
142
+ </div>
143
+ </div>
144
+ <script type="text/javascript">
145
+ (function ($) {
146
+ <?php if ( $open_addon ) : ?>
147
+
148
+ var interval = setInterval(function () {
149
+ // Open add-on information page.
150
+ <?php
151
+ /**
152
+ * @author Vova Feldman
153
+ *
154
+ * This code does NOT expose an XSS vulnerability because:
155
+ * 1. This page only renders for admins, so if an attacker manage to get
156
+ * admin access, they can do more harm.
157
+ * 2. This code won't be rendered unless $open_addon_slug matches any of
158
+ * the plugin's add-ons slugs.
159
+ */
160
+ ?>
161
+ $('.fs-card[data-slug=<?php echo $open_addon_slug ?>] a').click();
162
+ if ($('#TB_iframeContent').length > 0) {
163
+ clearInterval(interval);
164
+ interval = null;
165
+ }
166
+ }, 200);
167
+
168
+ <?php else : ?>
169
+
170
+
171
+ $('.fs-card.fs-addon')
172
+ .mouseover(function () {
173
+ $(this).find('.fs-cta .button').addClass('button-primary');
174
+ }).mouseout(function () {
175
+ $(this).find('.fs-cta .button').removeClass('button-primary');
176
+ });
177
+
178
+ <?php endif ?>
179
+ })(jQuery);
180
+ </script>
181
+ <?php
182
+ if ( $has_tabs ) {
183
+ $fs->_add_tabs_after_content();
184
+ }
185
+
186
+ $params = array(
187
+ 'page' => 'addons',
188
+ 'module_id' => $fs->get_id(),
189
+ 'module_type' => $fs->get_module_type(),
190
+ 'module_slug' => $slug,
191
+ 'module_version' => $fs->get_plugin_version(),
192
+ );
193
  fs_require_template( 'powered-by.php', $params );
freemius/templates/admin-notice.php CHANGED
@@ -1,48 +1,48 @@
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
- $dismiss_text = fs_text_x_inline( 'Dismiss', 'as close a window', 'dismiss' );
14
- ?>
15
- <div<?php if ( ! empty( $VARS['id'] ) ) : ?> data-id="<?php echo $VARS['id'] ?>"<?php endif ?><?php if ( ! empty( $VARS['manager_id'] ) ) : ?> data-manager-id="<?php echo $VARS['manager_id'] ?>"<?php endif ?>
16
- class="<?php
17
- switch ( $VARS['type'] ) {
18
- case 'error':
19
- echo 'error form-invalid';
20
- break;
21
- case 'promotion':
22
- echo 'updated promotion';
23
- break;
24
- case 'update':
25
- // echo 'update-nag update';
26
- // break;
27
- case 'success':
28
- default:
29
- echo 'updated success';
30
- break;
31
- }
32
- ?> fs-notice<?php if ( ! empty( $VARS['sticky'] ) ) {
33
- echo ' fs-sticky';
34
- } ?><?php if ( ! empty( $VARS['plugin'] ) ) {
35
- echo ' fs-has-title';
36
- } ?>"><?php if ( ! empty( $VARS['plugin'] ) ) : ?>
37
- <label class="fs-plugin-title"><?php echo $VARS['plugin'] ?></label>
38
- <?php endif ?>
39
- <?php if ( ! empty( $VARS['sticky'] ) ) : ?>
40
- <div class="fs-close"><i class="dashicons dashicons-no"
41
- title="<?php echo esc_attr( $dismiss_text ) ?>"></i> <span><?php echo esc_html( $dismiss_text ) ?></span>
42
- </div>
43
- <?php endif ?>
44
- <div class="fs-notice-body">
45
- <?php if ( ! empty( $VARS['title'] ) ) : ?><b><?php echo $VARS['title'] ?></b> <?php endif ?>
46
- <?php echo $VARS['message'] ?>
47
- </div>
48
- </div>
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
+ $dismiss_text = fs_text_x_inline( 'Dismiss', 'as close a window', 'dismiss' );
14
+ ?>
15
+ <div<?php if ( ! empty( $VARS['id'] ) ) : ?> data-id="<?php echo $VARS['id'] ?>"<?php endif ?><?php if ( ! empty( $VARS['manager_id'] ) ) : ?> data-manager-id="<?php echo $VARS['manager_id'] ?>"<?php endif ?>
16
+ class="<?php
17
+ switch ( $VARS['type'] ) {
18
+ case 'error':
19
+ echo 'error form-invalid';
20
+ break;
21
+ case 'promotion':
22
+ echo 'updated promotion';
23
+ break;
24
+ case 'update':
25
+ // echo 'update-nag update';
26
+ // break;
27
+ case 'success':
28
+ default:
29
+ echo 'updated success';
30
+ break;
31
+ }
32
+ ?> fs-notice<?php if ( ! empty( $VARS['sticky'] ) ) {
33
+ echo ' fs-sticky';
34
+ } ?><?php if ( ! empty( $VARS['plugin'] ) ) {
35
+ echo ' fs-has-title';
36
+ } ?>"><?php if ( ! empty( $VARS['plugin'] ) ) : ?>
37
+ <label class="fs-plugin-title"><?php echo $VARS['plugin'] ?></label>
38
+ <?php endif ?>
39
+ <?php if ( ! empty( $VARS['sticky'] ) ) : ?>
40
+ <div class="fs-close"><i class="dashicons dashicons-no"
41
+ title="<?php echo esc_attr( $dismiss_text ) ?>"></i> <span><?php echo esc_html( $dismiss_text ) ?></span>
42
+ </div>
43
+ <?php endif ?>
44
+ <div class="fs-notice-body">
45
+ <?php if ( ! empty( $VARS['title'] ) ) : ?><b><?php echo $VARS['title'] ?></b> <?php endif ?>
46
+ <?php echo $VARS['message'] ?>
47
+ </div>
48
+ </div>
freemius/templates/all-admin-notice.php CHANGED
@@ -1,39 +1,39 @@
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
- /**
14
- * @var array $VARS
15
- */
16
- ?>
17
- <div class="<?php
18
- switch ($VARS['type']) {
19
- case 'error':
20
- echo 'error form-invalid';
21
- break;
22
- case 'update-nag':
23
- echo 'update-nag ';
24
- break;
25
- case 'update':
26
- case 'success':
27
- default:
28
- echo 'updated success';
29
- break;
30
- }
31
- ?> fs-notice">
32
- <?php if ('update-nag' !== $VARS['type']) : ?><p><?php endif ?>
33
- <?php if (!empty($VARS['title'])) : ?>
34
- <b><?php echo $VARS['title'] ?></b>
35
- <?php endif ?>
36
- <?php echo $VARS['message'] ?>
37
- <?php if ('update-nag' !== $VARS['type']) : ?></p><?php endif ?>
38
- <?php if ($VARS['sticky']) : ?><i class="dashicons dashicons-no"></i><?php endif ?>
39
  </div>
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
+ /**
14
+ * @var array $VARS
15
+ */
16
+ ?>
17
+ <div class="<?php
18
+ switch ($VARS['type']) {
19
+ case 'error':
20
+ echo 'error form-invalid';
21
+ break;
22
+ case 'update-nag':
23
+ echo 'update-nag ';
24
+ break;
25
+ case 'update':
26
+ case 'success':
27
+ default:
28
+ echo 'updated success';
29
+ break;
30
+ }
31
+ ?> fs-notice">
32
+ <?php if ('update-nag' !== $VARS['type']) : ?><p><?php endif ?>
33
+ <?php if (!empty($VARS['title'])) : ?>
34
+ <b><?php echo $VARS['title'] ?></b>
35
+ <?php endif ?>
36
+ <?php echo $VARS['message'] ?>
37
+ <?php if ('update-nag' !== $VARS['type']) : ?></p><?php endif ?>
38
+ <?php if ($VARS['sticky']) : ?><i class="dashicons dashicons-no"></i><?php endif ?>
39
  </div>
freemius/templates/checkout-legacy.php CHANGED
@@ -1,242 +1,242 @@
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
- wp_enqueue_script( 'jquery' );
14
- wp_enqueue_script( 'json2' );
15
- fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' );
16
- fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' );
17
- fs_enqueue_local_style( 'fs_common', '/admin/common.css' );
18
-
19
- /**
20
- * @var array $VARS
21
- */
22
- $slug = $VARS['slug'];
23
- $fs = freemius( $slug );
24
-
25
- $timestamp = time();
26
-
27
- $context_params = array(
28
- 'plugin_id' => $fs->get_id(),
29
- 'plugin_public_key' => $fs->get_public_key(),
30
- 'plugin_version' => $fs->get_plugin_version(),
31
- );
32
-
33
- // Get site context secure params.
34
- if ( $fs->is_registered() ) {
35
- $site = $fs->get_site();
36
- $plugin_id = fs_request_get( 'plugin_id', $fs->get_id() );
37
-
38
- if ( $plugin_id != $fs->get_id() ) {
39
- if ( $fs->is_addon_activated( $plugin_id ) ) {
40
- $fs_addon = Freemius::get_instance_by_id( $plugin_id );
41
- $site = $fs_addon->get_site();
42
- }
43
- }
44
-
45
- $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params(
46
- $site,
47
- $timestamp,
48
- 'checkout'
49
- ) );
50
- } else {
51
- $current_user = Freemius::_get_current_wp_user();
52
-
53
- // Add site and user info to the request, this information
54
- // is NOT being stored unless the user complete the purchase
55
- // and agrees to the TOS.
56
- $context_params = array_merge( $context_params, array(
57
- 'user_firstname' => $current_user->user_firstname,
58
- 'user_lastname' => $current_user->user_lastname,
59
- 'user_email' => $current_user->user_email,
60
- 'home_url' => home_url(),
61
- ) );
62
-
63
- $fs_user = Freemius::_get_user_by_email( $current_user->user_email );
64
-
65
- if ( is_object( $fs_user ) ) {
66
- $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params(
67
- $fs_user,
68
- $timestamp,
69
- 'checkout'
70
- ) );
71
- }
72
- }
73
-
74
- if ( $fs->is_payments_sandbox() ) {
75
- // Append plugin secure token for sandbox mode authentication.
76
- $context_params['sandbox'] = FS_Security::instance()->get_secure_token(
77
- $fs->get_plugin(),
78
- $timestamp,
79
- 'checkout'
80
- );
81
-
82
- /**
83
- * @since 1.1.7.3 Add security timestamp for sandbox even for anonymous user.
84
- */
85
- if ( empty( $context_params['s_ctx_ts'] ) ) {
86
- $context_params['s_ctx_ts'] = $timestamp;
87
- }
88
- }
89
-
90
- $return_url = $fs->_get_sync_license_url( isset( $_GET['plugin_id'] ) ? $_GET['plugin_id'] : $fs->get_id() );
91
-
92
- $query_params = array_merge( $context_params, $_GET, array(
93
- // Current plugin version.
94
- 'plugin_version' => $fs->get_plugin_version(),
95
- 'sdk_version' => WP_FS__SDK_VERSION,
96
- 'return_url' => $return_url,
97
- // Admin CSS URL for style/design competability.
98
- // 'wp_admin_css' => get_bloginfo('wpurl') . "/wp-admin/load-styles.php?c=1&load=buttons,wp-admin,dashicons",
99
- ) );
100
- ?>
101
- <div id="fs_checkout" class="wrap" style="margin: 0 0 -65px -20px;">
102
- <div id="iframe"></div>
103
- <script type="text/javascript">
104
- // http://stackoverflow.com/questions/4583703/jquery-post-request-not-ajax
105
- jQuery(function ($) {
106
- $.extend({
107
- form: function (url, data, method) {
108
- if (method == null) method = 'POST';
109
- if (data == null) data = {};
110
-
111
- var form = $('<form>').attr({
112
- method: method,
113
- action: url
114
- }).css({
115
- display: 'none'
116
- });
117
-
118
- var addData = function (name, data) {
119
- if ($.isArray(data)) {
120
- for (var i = 0; i < data.length; i++) {
121
- var value = data[i];
122
- addData(name + '[]', value);
123
- }
124
- } else if (typeof data === 'object') {
125
- for (var key in data) {
126
- if (data.hasOwnProperty(key)) {
127
- addData(name + '[' + key + ']', data[key]);
128
- }
129
- }
130
- } else if (data != null) {
131
- form.append($('<input>').attr({
132
- type : 'hidden',
133
- name : String(name),
134
- value: String(data)
135
- }));
136
- }
137
- };
138
-
139
- for (var key in data) {
140
- if (data.hasOwnProperty(key)) {
141
- addData(key, data[key]);
142
- }
143
- }
144
-
145
- return form.appendTo('body');
146
- }
147
- });
148
- });
149
-
150
- (function ($) {
151
- $(function () {
152
-
153
- var
154
- // Keep track of the iframe height.
155
- iframe_height = 800,
156
- base_url = '<?php echo WP_FS__ADDRESS ?>',
157
- // Pass the parent page URL into the Iframe in a meaningful way (this URL could be
158
- // passed via query string or hard coded into the child page, it depends on your needs).
159
- src = base_url + '/checkout/?<?php echo ( isset( $_REQUEST['XDEBUG_SESSION'] ) ? 'XDEBUG_SESSION=' . $_REQUEST['XDEBUG_SESSION'] . '&' : '' ) . http_build_query( $query_params ) ?>#' + encodeURIComponent(document.location.href),
160
-
161
- // Append the Iframe into the DOM.
162
- iframe = $('<iframe " src="' + src + '" width="100%" height="' + iframe_height + 'px" scrolling="no" frameborder="0" style="background: transparent;"><\/iframe>')
163
- .appendTo('#iframe');
164
-
165
- FS.PostMessage.init(base_url, [iframe[0]]);
166
- FS.PostMessage.receiveOnce('height', function (data) {
167
- var h = data.height;
168
- if (!isNaN(h) && h > 0 && h != iframe_height) {
169
- iframe_height = h;
170
- iframe.height(iframe_height + 'px');
171
-
172
- FS.PostMessage.postScroll(iframe[0]);
173
- }
174
- });
175
-
176
- FS.PostMessage.receiveOnce('install', function (data) {
177
- // Post data to activation URL.
178
- $.form('<?php echo fs_nonce_url( $fs->_get_admin_page_url( 'account', array(
179
- 'fs_action' => $slug . '_activate_new',
180
- 'plugin_id' => isset( $_GET['plugin_id'] ) ? $_GET['plugin_id'] : $fs->get_id()
181
- ) ), $slug . '_activate_new' ) ?>', {
182
- user_id : data.user.id,
183
- user_secret_key : data.user.secret_key,
184
- user_public_key : data.user.public_key,
185
- install_id : data.install.id,
186
- install_secret_key: data.install.secret_key,
187
- install_public_key: data.install.public_key
188
- }).submit();
189
- });
190
-
191
- FS.PostMessage.receiveOnce('pending_activation', function (data) {
192
- $.form('<?php echo fs_nonce_url( $fs->_get_admin_page_url( 'account', array(
193
- 'fs_action' => $slug . '_activate_new',
194
- 'plugin_id' => fs_request_get( 'plugin_id', $fs->get_id() ),
195
- 'pending_activation' => true,
196
- ) ), $slug . '_activate_new' ) ?>', {
197
- user_email: data.user_email
198
- }).submit();
199
- });
200
-
201
- FS.PostMessage.receiveOnce('get_context', function () {
202
- console.debug('receiveOnce', 'get_context');
203
-
204
- // If the user didn't connect his account with Freemius,
205
- // once he accepts the Terms of Service and Privacy Policy,
206
- // and then click the purchase button, the context information
207
- // of the user will be shared with Freemius in order to complete the
208
- // purchase workflow and activate the license for the right user.
209
- <?php $install_data = array_merge( $fs->get_opt_in_params(),
210
- array(
211
- 'activation_url' => fs_nonce_url( $fs->_get_admin_page_url( '',
212
- array(
213
- 'fs_action' => $slug . '_activate_new',
214
- 'plugin_id' => fs_request_get( 'plugin_id', $fs->get_id() ),
215
-
216
- ) ),
217
- $slug . '_activate_new' )
218
- ) ) ?>
219
- FS.PostMessage.post('context', <?php echo json_encode( $install_data ) ?>, iframe[0]);
220
- });
221
-
222
- FS.PostMessage.receiveOnce('get_dimensions', function (data) {
223
- console.debug('receiveOnce', 'get_dimensions');
224
-
225
- FS.PostMessage.post('dimensions', {
226
- height : $(document.body).height(),
227
- scrollTop: $(document).scrollTop()
228
- }, iframe[0]);
229
- });
230
- });
231
- })(jQuery);
232
- </script>
233
- </div>
234
- <?php
235
- $params = array(
236
- 'page' => 'checkout',
237
- 'module_id' => $fs->get_id(),
238
- 'module_slug' => $slug,
239
- 'module_version' => $fs->get_plugin_version(),
240
- );
241
- fs_require_template( 'powered-by.php', $params );
242
- ?>
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
+ wp_enqueue_script( 'jquery' );
14
+ wp_enqueue_script( 'json2' );
15
+ fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' );
16
+ fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' );
17
+ fs_enqueue_local_style( 'fs_common', '/admin/common.css' );
18
+
19
+ /**
20
+ * @var array $VARS
21
+ */
22
+ $slug = $VARS['slug'];
23
+ $fs = freemius( $slug );
24
+
25
+ $timestamp = time();
26
+
27
+ $context_params = array(
28
+ 'plugin_id' => $fs->get_id(),
29
+ 'plugin_public_key' => $fs->get_public_key(),
30
+ 'plugin_version' => $fs->get_plugin_version(),
31
+ );
32
+
33
+ // Get site context secure params.
34
+ if ( $fs->is_registered() ) {
35
+ $site = $fs->get_site();
36
+ $plugin_id = fs_request_get( 'plugin_id', $fs->get_id() );
37
+
38
+ if ( $plugin_id != $fs->get_id() ) {
39
+ if ( $fs->is_addon_activated( $plugin_id ) ) {
40
+ $fs_addon = Freemius::get_instance_by_id( $plugin_id );
41
+ $site = $fs_addon->get_site();
42
+ }
43
+ }
44
+
45
+ $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params(
46
+ $site,
47
+ $timestamp,
48
+ 'checkout'
49
+ ) );
50
+ } else {
51
+ $current_user = Freemius::_get_current_wp_user();
52
+
53
+ // Add site and user info to the request, this information
54
+ // is NOT being stored unless the user complete the purchase
55
+ // and agrees to the TOS.
56
+ $context_params = array_merge( $context_params, array(
57
+ 'user_firstname' => $current_user->user_firstname,
58
+ 'user_lastname' => $current_user->user_lastname,
59
+ 'user_email' => $current_user->user_email,
60
+ 'home_url' => home_url(),
61
+ ) );
62
+
63
+ $fs_user = Freemius::_get_user_by_email( $current_user->user_email );
64
+
65
+ if ( is_object( $fs_user ) ) {
66
+ $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params(
67
+ $fs_user,
68
+ $timestamp,
69
+ 'checkout'
70
+ ) );
71
+ }
72
+ }
73
+
74
+ if ( $fs->is_payments_sandbox() ) {
75
+ // Append plugin secure token for sandbox mode authentication.
76
+ $context_params['sandbox'] = FS_Security::instance()->get_secure_token(
77
+ $fs->get_plugin(),
78
+ $timestamp,
79
+ 'checkout'
80
+ );
81
+
82
+ /**
83
+ * @since 1.1.7.3 Add security timestamp for sandbox even for anonymous user.
84
+ */
85
+ if ( empty( $context_params['s_ctx_ts'] ) ) {
86
+ $context_params['s_ctx_ts'] = $timestamp;
87
+ }
88
+ }
89
+
90
+ $return_url = $fs->_get_sync_license_url( isset( $_GET['plugin_id'] ) ? $_GET['plugin_id'] : $fs->get_id() );
91
+
92
+ $query_params = array_merge( $context_params, $_GET, array(
93
+ // Current plugin version.
94
+ 'plugin_version' => $fs->get_plugin_version(),
95
+ 'sdk_version' => WP_FS__SDK_VERSION,
96
+ 'return_url' => $return_url,
97
+ // Admin CSS URL for style/design competability.
98
+ // 'wp_admin_css' => get_bloginfo('wpurl') . "/wp-admin/load-styles.php?c=1&load=buttons,wp-admin,dashicons",
99
+ ) );
100
+ ?>
101
+ <div id="fs_checkout" class="wrap" style="margin: 0 0 -65px -20px;">
102
+ <div id="iframe"></div>
103
+ <script type="text/javascript">
104
+ // http://stackoverflow.com/questions/4583703/jquery-post-request-not-ajax
105
+ jQuery(function ($) {
106
+ $.extend({
107
+ form: function (url, data, method) {
108
+ if (method == null) method = 'POST';
109
+ if (data == null) data = {};
110
+
111
+ var form = $('<form>').attr({
112
+ method: method,
113
+ action: url
114
+ }).css({
115
+ display: 'none'
116
+ });
117
+
118
+ var addData = function (name, data) {
119
+ if ($.isArray(data)) {
120
+ for (var i = 0; i < data.length; i++) {
121
+ var value = data[i];
122
+ addData(name + '[]', value);
123
+ }
124
+ } else if (typeof data === 'object') {
125
+ for (var key in data) {
126
+ if (data.hasOwnProperty(key)) {
127
+ addData(name + '[' + key + ']', data[key]);
128
+ }
129
+ }
130
+ } else if (data != null) {
131
+ form.append($('<input>').attr({
132
+ type : 'hidden',
133
+ name : String(name),
134
+ value: String(data)
135
+ }));
136
+ }
137
+ };
138
+
139
+ for (var key in data) {
140
+ if (data.hasOwnProperty(key)) {
141
+ addData(key, data[key]);
142
+ }
143
+ }
144
+
145
+ return form.appendTo('body');
146
+ }
147
+ });
148
+ });
149
+
150
+ (function ($) {
151
+ $(function () {
152
+
153
+ var
154
+ // Keep track of the iframe height.
155
+ iframe_height = 800,
156
+ base_url = '<?php echo WP_FS__ADDRESS ?>',
157
+ // Pass the parent page URL into the Iframe in a meaningful way (this URL could be
158
+ // passed via query string or hard coded into the child page, it depends on your needs).
159
+ src = base_url + '/checkout/?<?php echo ( isset( $_REQUEST['XDEBUG_SESSION'] ) ? 'XDEBUG_SESSION=' . $_REQUEST['XDEBUG_SESSION'] . '&' : '' ) . http_build_query( $query_params ) ?>#' + encodeURIComponent(document.location.href),
160
+
161
+ // Append the Iframe into the DOM.
162
+ iframe = $('<iframe " src="' + src + '" width="100%" height="' + iframe_height + 'px" scrolling="no" frameborder="0" style="background: transparent;"><\/iframe>')
163
+ .appendTo('#iframe');
164
+
165
+ FS.PostMessage.init(base_url, [iframe[0]]);
166
+ FS.PostMessage.receiveOnce('height', function (data) {
167
+ var h = data.height;
168
+ if (!isNaN(h) && h > 0 && h != iframe_height) {
169
+ iframe_height = h;
170
+ iframe.height(iframe_height + 'px');
171
+
172
+ FS.PostMessage.postScroll(iframe[0]);
173
+ }
174
+ });
175
+
176
+ FS.PostMessage.receiveOnce('install', function (data) {
177
+ // Post data to activation URL.
178
+ $.form('<?php echo fs_nonce_url( $fs->_get_admin_page_url( 'account', array(
179
+ 'fs_action' => $slug . '_activate_new',
180
+ 'plugin_id' => isset( $_GET['plugin_id'] ) ? $_GET['plugin_id'] : $fs->get_id()
181
+ ) ), $slug . '_activate_new' ) ?>', {
182
+ user_id : data.user.id,
183
+ user_secret_key : data.user.secret_key,
184
+ user_public_key : data.user.public_key,
185
+ install_id : data.install.id,
186
+ install_secret_key: data.install.secret_key,
187
+ install_public_key: data.install.public_key
188
+ }).submit();
189
+ });
190
+
191
+ FS.PostMessage.receiveOnce('pending_activation', function (data) {
192
+ $.form('<?php echo fs_nonce_url( $fs->_get_admin_page_url( 'account', array(
193
+ 'fs_action' => $slug . '_activate_new',
194
+ 'plugin_id' => fs_request_get( 'plugin_id', $fs->get_id() ),
195
+ 'pending_activation' => true,
196
+ ) ), $slug . '_activate_new' ) ?>', {
197
+ user_email: data.user_email
198
+ }).submit();
199
+ });
200
+
201
+ FS.PostMessage.receiveOnce('get_context', function () {
202
+ console.debug('receiveOnce', 'get_context');
203
+
204
+ // If the user didn't connect his account with Freemius,
205
+ // once he accepts the Terms of Service and Privacy Policy,
206
+ // and then click the purchase button, the context information
207
+ // of the user will be shared with Freemius in order to complete the
208
+ // purchase workflow and activate the license for the right user.
209
+ <?php $install_data = array_merge( $fs->get_opt_in_params(),
210
+ array(
211
+ 'activation_url' => fs_nonce_url( $fs->_get_admin_page_url( '',
212
+ array(
213
+ 'fs_action' => $slug . '_activate_new',
214
+ 'plugin_id' => fs_request_get( 'plugin_id', $fs->get_id() ),
215
+
216
+ ) ),
217
+ $slug . '_activate_new' )
218
+ ) ) ?>
219
+ FS.PostMessage.post('context', <?php echo json_encode( $install_data ) ?>, iframe[0]);
220
+ });
221
+
222
+ FS.PostMessage.receiveOnce('get_dimensions', function (data) {
223
+ console.debug('receiveOnce', 'get_dimensions');
224
+
225
+ FS.PostMessage.post('dimensions', {
226
+ height : $(document.body).height(),
227
+ scrollTop: $(document).scrollTop()
228
+ }, iframe[0]);
229
+ });
230
+ });
231
+ })(jQuery);
232
+ </script>
233
+ </div>
234
+ <?php
235
+ $params = array(
236
+ 'page' => 'checkout',
237
+ 'module_id' => $fs->get_id(),
238
+ 'module_slug' => $slug,
239
+ 'module_version' => $fs->get_plugin_version(),
240
+ );
241
+ fs_require_template( 'powered-by.php', $params );
242
+ ?>
freemius/templates/debug/api-calls.php CHANGED
@@ -1,155 +1,155 @@
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.1.7.3
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- if ( class_exists( 'Freemius_Api_WordPress' ) ) {
14
- $logger = Freemius_Api_WordPress::GetLogger();
15
- } else {
16
- $logger = array();
17
- }
18
-
19
- $counters = array(
20
- 'GET' => 0,
21
- 'POST' => 0,
22
- 'PUT' => 0,
23
- 'DELETE' => 0
24
- );
25
-
26
- $show_body = false;
27
- foreach ( $logger as $log ) {
28
- $counters[ $log['method'] ] ++;
29
-
30
- if ( ! is_null( $log['body'] ) ) {
31
- $show_body = true;
32
- }
33
- }
34
-
35
- $pretty_print = $show_body && defined( 'JSON_PRETTY_PRINT' ) && version_compare( phpversion(), '5.3', '>=' );
36
-
37
- /**
38
- * This template is used for debugging, therefore, when possible
39
- * we'd like to prettify the output of a JSON encoded variable.
40
- * This will only be executed when $pretty_print is `true`, and
41
- * the var is `true` only for PHP 5.3 and higher. Due to the
42
- * limitations of the current Theme Check, it throws an error
43
- * that using the "options" parameter (the 2nd param) is not
44
- * supported in PHP 5.2 and lower. Thus, we added this alias
45
- * variable to work around that false-positive.
46
- *
47
- * @author Vova Feldman (@svovaf)
48
- * @since 1.2.2.7
49
- */
50
- $encode = 'json_encode';
51
-
52
- $root_path_len = strlen( ABSPATH );
53
-
54
- $ms_text = fs_text_x_inline( 'ms', 'milliseconds' );
55
- ?>
56
- <h1><?php fs_echo_inline( 'API' ) ?></h1>
57
-
58
- <h2><span>Total Time:</span><?php echo Freemius_Debug_Bar_Panel::total_time() ?></h2>
59
-
60
- <h2><span>Total Requests:</span><?php echo Freemius_Debug_Bar_Panel::requests_count() ?></h2>
61
- <?php foreach ( $counters as $method => $count ) : ?>
62
- <h2><span><?php echo $method ?>:</span><?php echo number_format( $count ) ?></h2>
63
- <?php endforeach ?>
64
- <table class="widefat">
65
- <thead>
66
- <tr>
67
- <th>#</th>
68
- <th><?php fs_esc_html_echo_inline( 'Method' ) ?></th>
69
- <th><?php fs_esc_html_echo_inline( 'Code' ) ?></th>
70
- <th><?php fs_esc_html_echo_inline( 'Length' ) ?></th>
71
- <th><?php fs_esc_html_echo_x_inline( 'Path', 'as file/folder path' ) ?></th>
72
- <?php if ( $show_body ) : ?>
73
- <th><?php fs_esc_html_echo_inline( 'Body' ) ?></th>
74
- <?php endif ?>
75
- <th><?php fs_esc_html_echo_inline( 'Result' ) ?></th>
76
- <th><?php fs_esc_html_echo_inline( 'Start' ) ?></th>
77
- <th><?php fs_esc_html_echo_inline( 'End' ) ?></th>
78
- </tr>
79
- </thead>
80
- <tbody>
81
- <?php foreach ( $logger as $log ) : ?>
82
- <tr>
83
- <td><?php echo $log['id'] ?>.</td>
84
- <td><?php echo $log['method'] ?></td>
85
- <td><?php echo $log['code'] ?></td>
86
- <td><?php echo number_format( 100 * $log['total'], 2 ) . ' ' . $ms_text ?></td>
87
- <td>
88
- <?php
89
- printf( '<a href="#" onclick="jQuery(this).parent().find(\'table\').toggle(); return false;">%s</a>',
90
- $log['path']
91
- );
92
- ?>
93
- <table class="widefat" style="display: none">
94
- <tbody>
95
- <?php for ( $i = 0, $bt = $log['backtrace'], $len = count( $bt ); $i < $len; $i ++ ) : ?>
96
- <tr>
97
- <td><?php echo( $len - $i ) ?></td>
98
- <td><?php if ( isset( $bt[ $i ]['function'] ) ) {
99
- echo ( isset( $bt[ $i ]['class'] ) ? $bt[ $i ]['class'] . $bt[ $i ]['type'] : '' ) . $bt[ $i ]['function'];
100
- } ?></td>
101
- <td><?php if ( isset( $bt[ $i ]['file'] ) ) {
102
- echo substr( $bt[ $i ]['file'], $root_path_len ) . ':' . $bt[ $i ]['line'];
103
- } ?></td>
104
- </tr>
105
- <?php endfor ?>
106
- </tbody>
107
- </table>
108
- </td>
109
- <?php if ( $show_body ) : ?>
110
- <td>
111
- <?php if ( 'GET' !== $log['method'] ) : ?>
112
- <?php
113
- $body = $log['body'];
114
- printf(
115
- '<a href="#" onclick="jQuery(this).parent().find(\'pre\').toggle(); return false;">%s</a>',
116
- substr( $body, 0, 32 ) . ( 32 < strlen( $body ) ? '...' : '' )
117
- );
118
- if ( $pretty_print ) {
119
- $body = $encode( json_decode( $log['body'] ), JSON_PRETTY_PRINT );
120
- }
121
- ?>
122
- <pre style="display: none"><code><?php echo esc_html( $body ) ?></code></pre>
123
- <?php endif ?>
124
- </td>
125
- <?php endif ?>
126
- <td>
127
- <?php
128
- $result = $log['result'];
129
-
130
- $is_not_empty_result = ( is_string( $result ) && ! empty( $result ) );
131
-
132
- if ( $is_not_empty_result ) {
133
- printf(
134
- '<a href="#" onclick="jQuery(this).parent().find(\'pre\').toggle(); return false;">%s</a>',
135
- substr( $result, 0, 32 ) . ( 32 < strlen( $result ) ? '...' : '' )
136
- );
137
- }
138
-
139
- if ( $is_not_empty_result && $pretty_print ) {
140
- $decoded = json_decode( $result );
141
- if ( ! is_null( $decoded ) ) {
142
- $result = $encode( $decoded, JSON_PRETTY_PRINT );
143
- }
144
- } else {
145
- $result = is_string( $result ) ? $result : json_encode( $result );
146
- }
147
- ?>
148
- <pre<?php if ( $is_not_empty_result ) : ?> style="display: none"<?php endif ?>><code><?php echo esc_html( $result ) ?></code></pre>
149
- </td>
150
- <td><?php echo number_format( 100 * ( $log['start'] - WP_FS__SCRIPT_START_TIME ), 2 ) . ' ' . $ms_text ?></td>
151
- <td><?php echo number_format( 100 * ( $log['end'] - WP_FS__SCRIPT_START_TIME ), 2 ) . ' ' . $ms_text ?></td>
152
- </tr>
153
- <?php endforeach ?>
154
- </tbody>
155
  </table>
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.1.7.3
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ if ( class_exists( 'Freemius_Api_WordPress' ) ) {
14
+ $logger = Freemius_Api_WordPress::GetLogger();
15
+ } else {
16
+ $logger = array();
17
+ }
18
+
19
+ $counters = array(
20
+ 'GET' => 0,
21
+ 'POST' => 0,
22
+ 'PUT' => 0,
23
+ 'DELETE' => 0
24
+ );
25
+
26
+ $show_body = false;
27
+ foreach ( $logger as $log ) {
28
+ $counters[ $log['method'] ] ++;
29
+
30
+ if ( ! is_null( $log['body'] ) ) {
31
+ $show_body = true;
32
+ }
33
+ }
34
+
35
+ $pretty_print = $show_body && defined( 'JSON_PRETTY_PRINT' ) && version_compare( phpversion(), '5.3', '>=' );
36
+
37
+ /**
38
+ * This template is used for debugging, therefore, when possible
39
+ * we'd like to prettify the output of a JSON encoded variable.
40
+ * This will only be executed when $pretty_print is `true`, and
41
+ * the var is `true` only for PHP 5.3 and higher. Due to the
42
+ * limitations of the current Theme Check, it throws an error
43
+ * that using the "options" parameter (the 2nd param) is not
44
+ * supported in PHP 5.2 and lower. Thus, we added this alias
45
+ * variable to work around that false-positive.
46
+ *
47
+ * @author Vova Feldman (@svovaf)
48
+ * @since 1.2.2.7
49
+ */
50
+ $encode = 'json_encode';
51
+
52
+ $root_path_len = strlen( ABSPATH );
53
+
54
+ $ms_text = fs_text_x_inline( 'ms', 'milliseconds' );
55
+ ?>
56
+ <h1><?php fs_echo_inline( 'API' ) ?></h1>
57
+
58
+ <h2><span>Total Time:</span><?php echo Freemius_Debug_Bar_Panel::total_time() ?></h2>
59
+
60
+ <h2><span>Total Requests:</span><?php echo Freemius_Debug_Bar_Panel::requests_count() ?></h2>
61
+ <?php foreach ( $counters as $method => $count ) : ?>
62
+ <h2><span><?php echo $method ?>:</span><?php echo number_format( $count ) ?></h2>
63
+ <?php endforeach ?>
64
+ <table class="widefat">
65
+ <thead>
66
+ <tr>
67
+ <th>#</th>
68
+ <th><?php fs_esc_html_echo_inline( 'Method' ) ?></th>
69
+ <th><?php fs_esc_html_echo_inline( 'Code' ) ?></th>
70
+ <th><?php fs_esc_html_echo_inline( 'Length' ) ?></th>
71
+ <th><?php fs_esc_html_echo_x_inline( 'Path', 'as file/folder path' ) ?></th>
72
+ <?php if ( $show_body ) : ?>
73
+ <th><?php fs_esc_html_echo_inline( 'Body' ) ?></th>
74
+ <?php endif ?>
75
+ <th><?php fs_esc_html_echo_inline( 'Result' ) ?></th>
76
+ <th><?php fs_esc_html_echo_inline( 'Start' ) ?></th>
77
+ <th><?php fs_esc_html_echo_inline( 'End' ) ?></th>
78
+ </tr>
79
+ </thead>
80
+ <tbody>
81
+ <?php foreach ( $logger as $log ) : ?>
82
+ <tr>
83
+ <td><?php echo $log['id'] ?>.</td>
84
+ <td><?php echo $log['method'] ?></td>
85
+ <td><?php echo $log['code'] ?></td>
86
+ <td><?php echo number_format( 100 * $log['total'], 2 ) . ' ' . $ms_text ?></td>
87
+ <td>
88
+ <?php
89
+ printf( '<a href="#" onclick="jQuery(this).parent().find(\'table\').toggle(); return false;">%s</a>',
90
+ $log['path']
91
+ );
92
+ ?>
93
+ <table class="widefat" style="display: none">
94
+ <tbody>
95
+ <?php for ( $i = 0, $bt = $log['backtrace'], $len = count( $bt ); $i < $len; $i ++ ) : ?>
96
+ <tr>
97
+ <td><?php echo( $len - $i ) ?></td>
98
+ <td><?php if ( isset( $bt[ $i ]['function'] ) ) {
99
+ echo ( isset( $bt[ $i ]['class'] ) ? $bt[ $i ]['class'] . $bt[ $i ]['type'] : '' ) . $bt[ $i ]['function'];
100
+ } ?></td>
101
+ <td><?php if ( isset( $bt[ $i ]['file'] ) ) {
102
+ echo substr( $bt[ $i ]['file'], $root_path_len ) . ':' . $bt[ $i ]['line'];
103
+ } ?></td>
104
+ </tr>
105
+ <?php endfor ?>
106
+ </tbody>
107
+ </table>
108
+ </td>
109
+ <?php if ( $show_body ) : ?>
110
+ <td>
111
+ <?php if ( 'GET' !== $log['method'] ) : ?>
112
+ <?php
113
+ $body = $log['body'];
114
+ printf(
115
+ '<a href="#" onclick="jQuery(this).parent().find(\'pre\').toggle(); return false;">%s</a>',
116
+ substr( $body, 0, 32 ) . ( 32 < strlen( $body ) ? '...' : '' )
117
+ );
118
+ if ( $pretty_print ) {
119
+ $body = $encode( json_decode( $log['body'] ), JSON_PRETTY_PRINT );
120
+ }
121
+ ?>
122
+ <pre style="display: none"><code><?php echo esc_html( $body ) ?></code></pre>
123
+ <?php endif ?>
124
+ </td>
125
+ <?php endif ?>
126
+ <td>
127
+ <?php
128
+ $result = $log['result'];
129
+
130
+ $is_not_empty_result = ( is_string( $result ) && ! empty( $result ) );
131
+
132
+ if ( $is_not_empty_result ) {
133
+ printf(
134
+ '<a href="#" onclick="jQuery(this).parent().find(\'pre\').toggle(); return false;">%s</a>',
135
+ substr( $result, 0, 32 ) . ( 32 < strlen( $result ) ? '...' : '' )
136
+ );
137
+ }
138
+
139
+ if ( $is_not_empty_result && $pretty_print ) {
140
+ $decoded = json_decode( $result );
141
+ if ( ! is_null( $decoded ) ) {
142
+ $result = $encode( $decoded, JSON_PRETTY_PRINT );
143
+ }
144
+ } else {
145
+ $result = is_string( $result ) ? $result : json_encode( $result );
146
+ }
147
+ ?>
148
+ <pre<?php if ( $is_not_empty_result ) : ?> style="display: none"<?php endif ?>><code><?php echo esc_html( $result ) ?></code></pre>
149
+ </td>
150
+ <td><?php echo number_format( 100 * ( $log['start'] - WP_FS__SCRIPT_START_TIME ), 2 ) . ' ' . $ms_text ?></td>
151
+ <td><?php echo number_format( 100 * ( $log['end'] - WP_FS__SCRIPT_START_TIME ), 2 ) . ' ' . $ms_text ?></td>
152
+ </tr>
153
+ <?php endforeach ?>
154
+ </tbody>
155
  </table>
freemius/templates/debug/logger.php CHANGED
@@ -1,66 +1,66 @@
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.1.7.3
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- $log_book = FS_Logger::get_log();
14
- ?>
15
- <h1><?php fs_echo_inline( 'Log' ) ?></h1>
16
-
17
- <table class="widefat" style="font-size: 11px;">
18
- <thead>
19
- <tr>
20
- <th>#</th>
21
- <th><?php fs_esc_html_echo_inline( 'ID', 'id' ) ?></th>
22
- <th><?php fs_esc_html_echo_inline( 'Type' ) ?></th>
23
- <th><?php fs_esc_html_echo_inline( 'Function' ) ?></th>
24
- <th><?php fs_esc_html_echo_inline( 'Message' ) ?></th>
25
- <th><?php fs_esc_html_echo_inline( 'File' ) ?></th>
26
- <th><?php fs_esc_html_echo_inline( 'Timestamp' ) ?></th>
27
- </tr>
28
- </thead>
29
- <tbody>
30
-
31
- <?php $i = 0;
32
- foreach ( $log_book as $log ) : ?>
33
- <?php
34
- /**
35
- * @var FS_Logger $logger
36
- */
37
- $logger = $log['logger'];
38
- ?>
39
- <tr<?php if ( $i % 2 ) {
40
- echo ' class="alternate"';
41
- } ?>>
42
- <td><?php echo $log['cnt'] ?>.</td>
43
- <td><?php echo $logger->get_id() ?></td>
44
- <td><?php echo $log['log_type'] ?></td>
45
- <td><b><code style="color: blue;"><?php echo ( ! empty( $log['class'] ) ? $log['class'] . $log['type'] : '' ) . $log['function'] ?></code></b></td>
46
- <td>
47
- <?php
48
- printf(
49
- '<a href="#" style="color: darkorange !important;" onclick="jQuery(this).parent().find(\'div\').toggle(); return false;"><nobr>%s</nobr></a>',
50
- esc_html( substr( $log['msg'], 0, 32 ) ) . ( 32 < strlen( $log['msg'] ) ? '...' : '' )
51
- );
52
- ?>
53
- <div style="display: none;">
54
- <b style="color: darkorange;"><?php echo esc_html( $log['msg'] ) ?></b>
55
- </div>
56
- </td>
57
- <td><?php
58
- if ( isset( $log['file'] ) ) {
59
- echo substr( $log['file'], $logger->get_file() ) . ':' . $log['line'];
60
- }
61
- ?></td>
62
- <td><?php echo number_format( 100 * ( $log['timestamp'] - WP_FS__SCRIPT_START_TIME ), 2 ) . ' ' . fs_text_x_inline( 'ms', 'milliseconds' ) ?></td>
63
- </tr>
64
- <?php $i ++; endforeach ?>
65
- </tbody>
66
  </table>
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.1.7.3
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ $log_book = FS_Logger::get_log();
14
+ ?>
15
+ <h1><?php fs_echo_inline( 'Log' ) ?></h1>
16
+
17
+ <table class="widefat" style="font-size: 11px;">
18
+ <thead>
19
+ <tr>
20
+ <th>#</th>
21
+ <th><?php fs_esc_html_echo_inline( 'ID', 'id' ) ?></th>
22
+ <th><?php fs_esc_html_echo_inline( 'Type' ) ?></th>
23
+ <th><?php fs_esc_html_echo_inline( 'Function' ) ?></th>
24
+ <th><?php fs_esc_html_echo_inline( 'Message' ) ?></th>
25
+ <th><?php fs_esc_html_echo_inline( 'File' ) ?></th>
26
+ <th><?php fs_esc_html_echo_inline( 'Timestamp' ) ?></th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+
31
+ <?php $i = 0;
32
+ foreach ( $log_book as $log ) : ?>
33
+ <?php
34
+ /**
35
+ * @var FS_Logger $logger
36
+ */
37
+ $logger = $log['logger'];
38
+ ?>
39
+ <tr<?php if ( $i % 2 ) {
40
+ echo ' class="alternate"';
41
+ } ?>>
42
+ <td><?php echo $log['cnt'] ?>.</td>
43
+ <td><?php echo $logger->get_id() ?></td>
44
+ <td><?php echo $log['log_type'] ?></td>
45
+ <td><b><code style="color: blue;"><?php echo ( ! empty( $log['class'] ) ? $log['class'] . $log['type'] : '' ) . $log['function'] ?></code></b></td>
46
+ <td>
47
+ <?php
48
+ printf(
49
+ '<a href="#" style="color: darkorange !important;" onclick="jQuery(this).parent().find(\'div\').toggle(); return false;"><nobr>%s</nobr></a>',
50
+ esc_html( substr( $log['msg'], 0, 32 ) ) . ( 32 < strlen( $log['msg'] ) ? '...' : '' )
51
+ );
52
+ ?>
53
+ <div style="display: none;">
54
+ <b style="color: darkorange;"><?php echo esc_html( $log['msg'] ) ?></b>
55
+ </div>
56
+ </td>
57
+ <td><?php
58
+ if ( isset( $log['file'] ) ) {
59
+ echo substr( $log['file'], $logger->get_file() ) . ':' . $log['line'];
60
+ }
61
+ ?></td>
62
+ <td><?php echo number_format( 100 * ( $log['timestamp'] - WP_FS__SCRIPT_START_TIME ), 2 ) . ' ' . fs_text_x_inline( 'ms', 'milliseconds' ) ?></td>
63
+ </tr>
64
+ <?php $i ++; endforeach ?>
65
+ </tbody>
66
  </table>
freemius/templates/forms/deactivation/contact.php CHANGED
@@ -1,23 +1,23 @@
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.0
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * @var array $VARS
15
- */
16
- $fs = freemius( $VARS['id'] );
17
- $slug = $fs->get_slug();
18
-
19
- echo fs_text_inline( 'Sorry for the inconvenience and we are here to help if you give us a chance.', 'contact-support-before-deactivation', $slug )
20
- . sprintf(" <a href='%s' class='button button-small button-primary'>%s</a>",
21
- $fs->contact_url( 'technical_support' ),
22
- fs_text_inline( 'Contact Support', 'contact-support', $slug )
23
- );
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.0
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * @var array $VARS
15
+ */
16
+ $fs = freemius( $VARS['id'] );
17
+ $slug = $fs->get_slug();
18
+
19
+ echo fs_text_inline( 'Sorry for the inconvenience and we are here to help if you give us a chance.', 'contact-support-before-deactivation', $slug )
20
+ . sprintf(" <a href='%s' class='button button-small button-primary'>%s</a>",
21
+ $fs->contact_url( 'technical_support' ),
22
+ fs_text_inline( 'Contact Support', 'contact-support', $slug )
23
+ );
freemius/templates/forms/deactivation/form.php CHANGED
@@ -1,409 +1,409 @@
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.1.2
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- $fs = freemius( $VARS['id'] );
14
- $slug = $fs->get_slug();
15
-
16
- $confirmation_message = $fs->apply_filters( 'uninstall_confirmation_message', '' );
17
-
18
- $reasons = $VARS['reasons'];
19
-
20
- $reasons_list_items_html = '';
21
-
22
- foreach ( $reasons as $reason ) {
23
- $list_item_classes = 'reason' . ( ! empty( $reason['input_type'] ) ? ' has-input' : '' );
24
-
25
- if ( isset( $reason['internal_message'] ) && ! empty( $reason['internal_message'] ) ) {
26
- $list_item_classes .= ' has-internal-message';
27
- $reason_internal_message = $reason['internal_message'];
28
- } else {
29
- $reason_internal_message = '';
30
- }
31
-
32
- $reason_input_type = ( ! empty( $reason['input_type'] ) ? $reason['input_type'] : '' );
33
- $reason_input_placeholder = ( ! empty( $reason['input_placeholder'] ) ? $reason['input_placeholder'] : '' );
34
-
35
- $reason_list_item_html = <<< HTML
36
- <li class="{$list_item_classes}"
37
- data-input-type="{$reason_input_type}"
38
- data-input-placeholder="{$reason_input_placeholder}">
39
- <label>
40
- <span>
41
- <input type="radio" name="selected-reason" value="{$reason['id']}"/>
42
- </span>
43
- <span>{$reason['text']}</span>
44
- </label>
45
- <div class="internal-message">{$reason_internal_message}</div>
46
- </li>
47
- HTML;
48
-
49
- $reasons_list_items_html .= $reason_list_item_html;
50
- }
51
-
52
- $is_anonymous = ( ! $fs->is_registered() );
53
- if ( $is_anonymous ) {
54
- $anonymous_feedback_checkbox_html = sprintf(
55
- '<label class="anonymous-feedback-label"><input type="checkbox" class="anonymous-feedback-checkbox"> %s</label>',
56
- fs_esc_html_inline( 'Anonymous feedback', 'anonymous-feedback', $slug )
57
- );
58
- } else {
59
- $anonymous_feedback_checkbox_html = '';
60
- }
61
-
62
- // Aliases.
63
- $deactivate_text = fs_text_inline( 'Deactivate', 'deactivate', $slug );
64
- $theme_text = fs_text_inline( 'Theme', 'theme', $slug );
65
- $activate_x_text = fs_text_inline( 'Activate %s', 'activate-x', $slug );
66
-
67
- fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
68
- ?>
69
- <script type="text/javascript">
70
- (function ($) {
71
- var reasonsHtml = <?php echo json_encode( $reasons_list_items_html ); ?>,
72
- modalHtml =
73
- '<div class="fs-modal fs-modal-deactivation-feedback<?php echo empty( $confirmation_message ) ? ' no-confirmation-message' : ''; ?>">'
74
- + ' <div class="fs-modal-dialog">'
75
- + ' <div class="fs-modal-header">'
76
- + ' <h4><?php fs_esc_attr_echo_inline( 'Quick feedback', 'quick-feedback' , $slug ) ?></h4>'
77
- + ' </div>'
78
- + ' <div class="fs-modal-body">'
79
- + ' <div class="fs-modal-panel" data-panel-id="confirm"><p><?php echo $confirmation_message; ?></p></div>'
80
- + ' <div class="fs-modal-panel active" data-panel-id="reasons"><h3><strong><?php echo esc_js( sprintf( fs_text_inline( 'If you have a moment, please let us know why you are %s', 'deactivation-share-reason' , $slug ), ( $fs->is_plugin() ? fs_text_inline( 'deactivating', 'deactivating', $slug ) : fs_text_inline( 'switching', 'switching', $slug ) ) ) ) ?>:</strong></h3><ul id="reasons-list">' + reasonsHtml + '</ul></div>'
81
- + ' </div>'
82
- + ' <div class="fs-modal-footer">'
83
- + ' <?php echo $anonymous_feedback_checkbox_html ?>'
84
- + ' <a href="#" class="button button-secondary button-deactivate"></a>'
85
- + ' <a href="#" class="button button-primary button-close"><?php fs_esc_js_echo_inline( 'Cancel', 'cancel' , $slug ) ?></a>'
86
- + ' </div>'
87
- + ' </div>'
88
- + '</div>',
89
- $modal = $(modalHtml),
90
- $deactivateLink = $('#the-list .deactivate > [data-module-id=<?php echo $fs->get_id() ?>].fs-module-id').prev(),
91
- selectedReasonID = false,
92
- redirectLink = '',
93
- $anonymousFeedback = $modal.find( '.anonymous-feedback-label' ),
94
- isAnonymous = <?php echo ( $is_anonymous ? 'true' : 'false' ); ?>,
95
- otherReasonID = <?php echo Freemius::REASON_OTHER; ?>,
96
- dontShareDataReasonID = <?php echo Freemius::REASON_DONT_LIKE_TO_SHARE_MY_INFORMATION; ?>;
97
-
98
- $modal.appendTo($('body'));
99
-
100
- registerEventHandlers();
101
-
102
- function registerEventHandlers() {
103
- <?php
104
- if ( $fs->is_plugin() ) { ?>
105
- $deactivateLink.click(function (evt) {
106
- evt.preventDefault();
107
-
108
- redirectLink = $(this).attr('href');
109
-
110
- showModal();
111
- });
112
- <?php
113
- /**
114
- * For "theme" module type, the modal is shown when the current user clicks on
115
- * the "Activate" button of any other theme. The "Activate" button is actually
116
- * a link to the "Themes" page (/wp-admin/themes.php) containing query params
117
- * that tell WordPress to deactivate the current theme and activate a different theme.
118
- *
119
- * @author Leo Fajardo (@leorw)
120
- * @since 1.2.2
121
- *
122
- * @since 1.2.2.7 Don't trigger the deactivation feedback form if activating the premium version of the theme.
123
- */
124
- } else { ?>
125
- $('body').on('click', '.theme-browser .theme:not([data-slug=<?php echo $slug ?>-premium]) .theme-actions .button.activate', function (evt) {
126
- evt.preventDefault();
127
-
128
- redirectLink = $(this).attr('href');
129
-
130
- showModal();
131
- });
132
- <?php
133
- } ?>
134
-
135
- $modal.on('input propertychange', '.reason-input input', function () {
136
- if (!isOtherReasonSelected()) {
137
- return;
138
- }
139
-
140
- var reason = $(this).val().trim();
141
-
142
- /**
143
- * If reason is not empty, remove the error-message class of the message container
144
- * to change the message color back to default.
145
- */
146
- if (reason.length > 0) {
147
- $('.message').removeClass('error-message');
148
- enableDeactivateButton();
149
- }
150
- });
151
-
152
- $modal.on('blur', '.reason-input input', function () {
153
- var $userReason = $(this);
154
-
155
- setTimeout(function () {
156
- if (!isOtherReasonSelected()) {
157
- return;
158
- }
159
-
160
- /**
161
- * If reason is empty, add the error-message class to the message container
162
- * to change the message color to red.
163
- */
164
- if (0 === $userReason.val().trim().length) {
165
- $('.message').addClass('error-message');
166
- disableDeactivateButton();
167
- }
168
- }, 150);
169
- });
170
-
171
- $modal.on('click', '.fs-modal-footer .button', function (evt) {
172
- evt.preventDefault();
173
-
174
- if ($(this).hasClass('disabled')) {
175
- return;
176
- }
177
-
178
- var _parent = $(this).parents('.fs-modal:first');
179
- var _this = $(this);
180
-
181
- if (_this.hasClass('allow-deactivate')) {
182
- var $radio = $('input[type="radio"]:checked');
183
-
184
- if (0 === $radio.length) {
185
- // If no selected reason, just deactivate the plugin.
186
- window.location.href = redirectLink;
187
- return;
188
- }
189
-
190
- var $selected_reason = $radio.parents('li:first'),
191
- $input = $selected_reason.find('textarea, input[type="text"]'),
192
- userReason = ( 0 !== $input.length ) ? $input.val().trim() : '';
193
-
194
- if (isOtherReasonSelected() && ( '' === userReason )) {
195
- return;
196
- }
197
-
198
- $.ajax({
199
- url : ajaxurl,
200
- method : 'POST',
201
- data : {
202
- action : '<?php echo $fs->get_ajax_action( 'submit_uninstall_reason' ) ?>',
203
- security : '<?php echo $fs->get_ajax_security( 'submit_uninstall_reason' ) ?>',
204
- module_id : '<?php echo $fs->get_id() ?>',
205
- reason_id : $radio.val(),
206
- reason_info : userReason,
207
- is_anonymous: isAnonymousFeedback()
208
- },
209
- beforeSend: function () {
210
- _parent.find('.fs-modal-footer .button').addClass('disabled');
211
- _parent.find('.fs-modal-footer .button-secondary').text('Processing...');
212
- },
213
- complete : function () {
214
- // Do not show the dialog box, deactivate the plugin.
215
- window.location.href = redirectLink;
216
- }
217
- });
218
- } else if (_this.hasClass('button-deactivate')) {
219
- // Change the Deactivate button's text and show the reasons panel.
220
- _parent.find('.button-deactivate').addClass('allow-deactivate');
221
-
222
- showPanel('reasons');
223
- }
224
- });
225
-
226
- $modal.on('click', 'input[type="radio"]', function () {
227
- var $selectedReasonOption = $(this);
228
-
229
- // If the selection has not changed, do not proceed.
230
- if (selectedReasonID === $selectedReasonOption.val())
231
- return;
232
-
233
- selectedReasonID = $selectedReasonOption.val();
234
-
235
- if ( isAnonymous ) {
236
- if ( isReasonSelected( dontShareDataReasonID ) ) {
237
- $anonymousFeedback.hide();
238
- } else {
239
- $anonymousFeedback.show();
240
- }
241
- }
242
-
243
- var _parent = $(this).parents('li:first');
244
-
245
- $modal.find('.reason-input').remove();
246
- $modal.find( '.internal-message' ).hide();
247
- $modal.find('.button-deactivate').html('<?php echo esc_js( sprintf(
248
- fs_text_inline( 'Submit & %s', 'deactivation-modal-button-submit' , $slug ),
249
- $fs->is_plugin() ?
250
- $deactivate_text :
251
- sprintf( $activate_x_text, $theme_text )
252
- ) ) ?>');
253
-
254
- enableDeactivateButton();
255
-
256
- if ( _parent.hasClass( 'has-internal-message' ) ) {
257
- _parent.find( '.internal-message' ).show();
258
- }
259
-
260
- if (_parent.hasClass('has-input')) {
261
- var inputType = _parent.data('input-type'),
262
- inputPlaceholder = _parent.data('input-placeholder'),
263
- reasonInputHtml = '<div class="reason-input"><span class="message"></span>' + ( ( 'textfield' === inputType ) ? '<input type="text" />' : '<textarea rows="5"></textarea>' ) + '</div>';
264
-
265
- _parent.append($(reasonInputHtml));
266
- _parent.find('input, textarea').attr('placeholder', inputPlaceholder).focus();
267
-
268
- if (isOtherReasonSelected()) {
269
- showMessage('<?php echo esc_js( fs_text_inline( 'Kindly tell us the reason so we can improve.', 'ask-for-reason-message' , $slug ) ); ?>');
270
- disableDeactivateButton();
271
- }
272
- }
273
- });
274
-
275
- // If the user has clicked outside the window, cancel it.
276
- $modal.on('click', function (evt) {
277
- var $target = $(evt.target);
278
-
279
- // If the user has clicked anywhere in the modal dialog, just return.
280
- if ($target.hasClass('fs-modal-body') || $target.hasClass('fs-modal-footer')) {
281
- return;
282
- }
283
-
284
- // If the user has not clicked the close button and the clicked element is inside the modal dialog, just return.
285
- if (!$target.hasClass('button-close') && ( $target.parents('.fs-modal-body').length > 0 || $target.parents('.fs-modal-footer').length > 0 )) {
286
- return;
287
- }
288
-
289
- closeModal();
290
- return false;
291
- });
292
- }
293
-
294
- function isAnonymousFeedback() {
295
- if ( ! isAnonymous ) {
296
- return false;
297
- }
298
-
299
- return ( isReasonSelected( dontShareDataReasonID ) || $anonymousFeedback.find( 'input' ).prop( 'checked' ) );
300
- }
301
-
302
- function isReasonSelected( reasonID ) {
303
- // Get the selected radio input element.
304
- var $selectedReasonOption = $modal.find('input[type="radio"]:checked');
305
-
306
- return ( reasonID == $selectedReasonOption.val() );
307
- }
308
-
309
- function isOtherReasonSelected() {
310
- return isReasonSelected( otherReasonID );
311
- }
312
-
313
- function showModal() {
314
- resetModal();
315
-
316
- // Display the dialog box.
317
- $modal.addClass('active');
318
-
319
- $('body').addClass('has-fs-modal');
320
- }
321
-
322
- function closeModal() {
323
- $modal.removeClass('active');
324
-
325
- $('body').removeClass('has-fs-modal');
326
- }
327
-
328
- function resetModal() {
329
- selectedReasonID = false;
330
-
331
- enableDeactivateButton();
332
-
333
- // Uncheck all radio buttons.
334
- $modal.find('input[type="radio"]').prop('checked', false);
335
-
336
- // Remove all input fields ( textfield, textarea ).
337
- $modal.find('.reason-input').remove();
338
-
339
- $modal.find('.message').hide();
340
-
341
- if ( isAnonymous ) {
342
- $anonymousFeedback.find( 'input' ).prop( 'checked', false );
343
-
344
- // Hide, since by default there is no selected reason.
345
- $anonymousFeedback.hide();
346
- }
347
-
348
- var $deactivateButton = $modal.find('.button-deactivate');
349
-
350
- /*
351
- * If the modal dialog has no confirmation message, that is, it has only one panel, then ensure
352
- * that clicking the deactivate button will actually deactivate the plugin.
353
- */
354
- if ($modal.hasClass('no-confirmation-message')) {
355
- $deactivateButton.addClass('allow-deactivate');
356
-
357
- showPanel('reasons');
358
- } else {
359
- $deactivateButton.removeClass('allow-deactivate');
360
-
361
- showPanel('confirm');
362
- }
363
- }
364
-
365
- function showMessage(message) {
366
- $modal.find('.message').text(message).show();
367
- }
368
-
369
- function enableDeactivateButton() {
370
- $modal.find('.button-deactivate').removeClass('disabled');
371
- }
372
-
373
- function disableDeactivateButton() {
374
- $modal.find('.button-deactivate').addClass('disabled');
375
- }
376
-
377
- function showPanel(panelType) {
378
- $modal.find('.fs-modal-panel').removeClass('active ');
379
- $modal.find('[data-panel-id="' + panelType + '"]').addClass('active');
380
-
381
- updateButtonLabels();
382
- }
383
-
384
- function updateButtonLabels() {
385
- var $deactivateButton = $modal.find('.button-deactivate');
386
-
387
- // Reset the deactivate button's text.
388
- if ('confirm' === getCurrentPanel()) {
389
- $deactivateButton.text('<?php echo esc_js( sprintf(
390
- fs_text_inline( 'Yes - %s', 'deactivation-modal-button-confirm' , $slug ),
391
- $fs->is_plugin() ?
392
- $deactivate_text :
393
- sprintf( $activate_x_text, $theme_text )
394
- ) ) ?>');
395
- } else {
396
- $deactivateButton.html('<?php echo esc_js( sprintf(
397
- fs_text_inline('Skip & %s', 'skip-and-x', $slug ),
398
- $fs->is_plugin() ?
399
- $deactivate_text :
400
- sprintf( $activate_x_text, $theme_text )
401
- ) ) ?>');
402
- }
403
- }
404
-
405
- function getCurrentPanel() {
406
- return $modal.find('.fs-modal-panel.active').attr('data-panel-id');
407
- }
408
- })(jQuery);
409
- </script>
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.1.2
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ $fs = freemius( $VARS['id'] );
14
+ $slug = $fs->get_slug();
15
+
16
+ $confirmation_message = $fs->apply_filters( 'uninstall_confirmation_message', '' );
17
+
18
+ $reasons = $VARS['reasons'];
19
+
20
+ $reasons_list_items_html = '';
21
+
22
+ foreach ( $reasons as $reason ) {
23
+ $list_item_classes = 'reason' . ( ! empty( $reason['input_type'] ) ? ' has-input' : '' );
24
+
25
+ if ( isset( $reason['internal_message'] ) && ! empty( $reason['internal_message'] ) ) {
26
+ $list_item_classes .= ' has-internal-message';
27
+ $reason_internal_message = $reason['internal_message'];
28
+ } else {
29
+ $reason_internal_message = '';
30
+ }
31
+
32
+ $reason_input_type = ( ! empty( $reason['input_type'] ) ? $reason['input_type'] : '' );
33
+ $reason_input_placeholder = ( ! empty( $reason['input_placeholder'] ) ? $reason['input_placeholder'] : '' );
34
+
35
+ $reason_list_item_html = <<< HTML
36
+ <li class="{$list_item_classes}"
37
+ data-input-type="{$reason_input_type}"
38
+ data-input-placeholder="{$reason_input_placeholder}">
39
+ <label>
40
+ <span>
41
+ <input type="radio" name="selected-reason" value="{$reason['id']}"/>
42
+ </span>
43
+ <span>{$reason['text']}</span>
44
+ </label>
45
+ <div class="internal-message">{$reason_internal_message}</div>
46
+ </li>
47
+ HTML;
48
+
49
+ $reasons_list_items_html .= $reason_list_item_html;
50
+ }
51
+
52
+ $is_anonymous = ( ! $fs->is_registered() );
53
+ if ( $is_anonymous ) {
54
+ $anonymous_feedback_checkbox_html = sprintf(
55
+ '<label class="anonymous-feedback-label"><input type="checkbox" class="anonymous-feedback-checkbox"> %s</label>',
56
+ fs_esc_html_inline( 'Anonymous feedback', 'anonymous-feedback', $slug )
57
+ );
58
+ } else {
59
+ $anonymous_feedback_checkbox_html = '';
60
+ }
61
+
62
+ // Aliases.
63
+ $deactivate_text = fs_text_inline( 'Deactivate', 'deactivate', $slug );
64
+ $theme_text = fs_text_inline( 'Theme', 'theme', $slug );
65
+ $activate_x_text = fs_text_inline( 'Activate %s', 'activate-x', $slug );
66
+
67
+ fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
68
+ ?>
69
+ <script type="text/javascript">
70
+ (function ($) {
71
+ var reasonsHtml = <?php echo json_encode( $reasons_list_items_html ); ?>,
72
+ modalHtml =
73
+ '<div class="fs-modal fs-modal-deactivation-feedback<?php echo empty( $confirmation_message ) ? ' no-confirmation-message' : ''; ?>">'
74
+ + ' <div class="fs-modal-dialog">'
75
+ + ' <div class="fs-modal-header">'
76
+ + ' <h4><?php fs_esc_attr_echo_inline( 'Quick feedback', 'quick-feedback' , $slug ) ?></h4>'
77
+ + ' </div>'
78
+ + ' <div class="fs-modal-body">'
79
+ + ' <div class="fs-modal-panel" data-panel-id="confirm"><p><?php echo $confirmation_message; ?></p></div>'
80
+ + ' <div class="fs-modal-panel active" data-panel-id="reasons"><h3><strong><?php echo esc_js( sprintf( fs_text_inline( 'If you have a moment, please let us know why you are %s', 'deactivation-share-reason' , $slug ), ( $fs->is_plugin() ? fs_text_inline( 'deactivating', 'deactivating', $slug ) : fs_text_inline( 'switching', 'switching', $slug ) ) ) ) ?>:</strong></h3><ul id="reasons-list">' + reasonsHtml + '</ul></div>'
81
+ + ' </div>'
82
+ + ' <div class="fs-modal-footer">'
83
+ + ' <?php echo $anonymous_feedback_checkbox_html ?>'
84
+ + ' <a href="#" class="button button-secondary button-deactivate"></a>'
85
+ + ' <a href="#" class="button button-primary button-close"><?php fs_esc_js_echo_inline( 'Cancel', 'cancel' , $slug ) ?></a>'
86
+ + ' </div>'
87
+ + ' </div>'
88
+ + '</div>',
89
+ $modal = $(modalHtml),
90
+ $deactivateLink = $('#the-list .deactivate > [data-module-id=<?php echo $fs->get_id() ?>].fs-module-id').prev(),
91
+ selectedReasonID = false,
92
+ redirectLink = '',
93
+ $anonymousFeedback = $modal.find( '.anonymous-feedback-label' ),
94
+ isAnonymous = <?php echo ( $is_anonymous ? 'true' : 'false' ); ?>,
95
+ otherReasonID = <?php echo Freemius::REASON_OTHER; ?>,
96
+ dontShareDataReasonID = <?php echo Freemius::REASON_DONT_LIKE_TO_SHARE_MY_INFORMATION; ?>;
97
+
98
+ $modal.appendTo($('body'));
99
+
100
+ registerEventHandlers();
101
+
102
+ function registerEventHandlers() {
103
+ <?php
104
+ if ( $fs->is_plugin() ) { ?>
105
+ $deactivateLink.click(function (evt) {
106
+ evt.preventDefault();
107
+
108
+ redirectLink = $(this).attr('href');
109
+
110
+ showModal();
111
+ });
112
+ <?php
113
+ /**
114
+ * For "theme" module type, the modal is shown when the current user clicks on
115
+ * the "Activate" button of any other theme. The "Activate" button is actually
116
+ * a link to the "Themes" page (/wp-admin/themes.php) containing query params
117
+ * that tell WordPress to deactivate the current theme and activate a different theme.
118
+ *
119
+ * @author Leo Fajardo (@leorw)
120
+ * @since 1.2.2
121
+ *
122
+ * @since 1.2.2.7 Don't trigger the deactivation feedback form if activating the premium version of the theme.
123
+ */
124
+ } else { ?>
125
+ $('body').on('click', '.theme-browser .theme:not([data-slug=<?php echo $slug ?>-premium]) .theme-actions .button.activate', function (evt) {
126
+ evt.preventDefault();
127
+
128
+ redirectLink = $(this).attr('href');
129
+
130
+ showModal();
131
+ });
132
+ <?php
133
+ } ?>
134
+
135
+ $modal.on('input propertychange', '.reason-input input', function () {
136
+ if (!isOtherReasonSelected()) {
137
+ return;
138
+ }
139
+
140
+ var reason = $(this).val().trim();
141
+
142
+ /**
143
+ * If reason is not empty, remove the error-message class of the message container
144
+ * to change the message color back to default.
145
+ */
146
+ if (reason.length > 0) {
147
+ $('.message').removeClass('error-message');
148
+ enableDeactivateButton();
149
+ }
150
+ });
151
+
152
+ $modal.on('blur', '.reason-input input', function () {
153
+ var $userReason = $(this);
154
+
155
+ setTimeout(function () {
156
+ if (!isOtherReasonSelected()) {
157
+ return;
158
+ }
159
+
160
+ /**
161
+ * If reason is empty, add the error-message class to the message container
162
+ * to change the message color to red.
163
+ */
164
+ if (0 === $userReason.val().trim().length) {
165
+ $('.message').addClass('error-message');
166
+ disableDeactivateButton();
167
+ }
168
+ }, 150);
169
+ });
170
+
171
+ $modal.on('click', '.fs-modal-footer .button', function (evt) {
172
+ evt.preventDefault();
173
+
174
+ if ($(this).hasClass('disabled')) {
175
+ return;
176
+ }
177
+
178
+ var _parent = $(this).parents('.fs-modal:first');
179
+ var _this = $(this);
180
+
181
+ if (_this.hasClass('allow-deactivate')) {
182
+ var $radio = $('input[type="radio"]:checked');
183
+
184
+ if (0 === $radio.length) {
185
+ // If no selected reason, just deactivate the plugin.
186
+ window.location.href = redirectLink;
187
+ return;
188
+ }
189
+
190
+ var $selected_reason = $radio.parents('li:first'),
191
+ $input = $selected_reason.find('textarea, input[type="text"]'),
192
+ userReason = ( 0 !== $input.length ) ? $input.val().trim() : '';
193
+
194
+ if (isOtherReasonSelected() && ( '' === userReason )) {
195
+ return;
196
+ }
197
+
198
+ $.ajax({
199
+ url : ajaxurl,
200
+ method : 'POST',
201
+ data : {
202
+ action : '<?php echo $fs->get_ajax_action( 'submit_uninstall_reason' ) ?>',
203
+ security : '<?php echo $fs->get_ajax_security( 'submit_uninstall_reason' ) ?>',
204
+ module_id : '<?php echo $fs->get_id() ?>',
205
+ reason_id : $radio.val(),
206
+ reason_info : userReason,
207
+ is_anonymous: isAnonymousFeedback()
208
+ },
209
+ beforeSend: function () {
210
+ _parent.find('.fs-modal-footer .button').addClass('disabled');
211
+ _parent.find('.fs-modal-footer .button-secondary').text('Processing...');
212
+ },
213
+ complete : function () {
214
+ // Do not show the dialog box, deactivate the plugin.
215
+ window.location.href = redirectLink;
216
+ }
217
+ });
218
+ } else if (_this.hasClass('button-deactivate')) {
219
+ // Change the Deactivate button's text and show the reasons panel.
220
+ _parent.find('.button-deactivate').addClass('allow-deactivate');
221
+
222
+ showPanel('reasons');
223
+ }
224
+ });
225
+
226
+ $modal.on('click', 'input[type="radio"]', function () {
227
+ var $selectedReasonOption = $(this);
228
+
229
+ // If the selection has not changed, do not proceed.
230
+ if (selectedReasonID === $selectedReasonOption.val())
231
+ return;
232
+
233
+ selectedReasonID = $selectedReasonOption.val();
234
+
235
+ if ( isAnonymous ) {
236
+ if ( isReasonSelected( dontShareDataReasonID ) ) {
237
+ $anonymousFeedback.hide();
238
+ } else {
239
+ $anonymousFeedback.show();
240
+ }
241
+ }
242
+
243
+ var _parent = $(this).parents('li:first');
244
+
245
+ $modal.find('.reason-input').remove();
246
+ $modal.find( '.internal-message' ).hide();
247
+ $modal.find('.button-deactivate').html('<?php echo esc_js( sprintf(
248
+ fs_text_inline( 'Submit & %s', 'deactivation-modal-button-submit' , $slug ),
249
+ $fs->is_plugin() ?
250
+ $deactivate_text :
251
+ sprintf( $activate_x_text, $theme_text )
252
+ ) ) ?>');
253
+
254
+ enableDeactivateButton();
255
+
256
+ if ( _parent.hasClass( 'has-internal-message' ) ) {
257
+ _parent.find( '.internal-message' ).show();
258
+ }
259
+
260
+ if (_parent.hasClass('has-input')) {
261
+ var inputType = _parent.data('input-type'),
262
+ inputPlaceholder = _parent.data('input-placeholder'),
263
+ reasonInputHtml = '<div class="reason-input"><span class="message"></span>' + ( ( 'textfield' === inputType ) ? '<input type="text" />' : '<textarea rows="5"></textarea>' ) + '</div>';
264
+
265
+ _parent.append($(reasonInputHtml));
266
+ _parent.find('input, textarea').attr('placeholder', inputPlaceholder).focus();
267
+
268
+ if (isOtherReasonSelected()) {
269
+ showMessage('<?php echo esc_js( fs_text_inline( 'Kindly tell us the reason so we can improve.', 'ask-for-reason-message' , $slug ) ); ?>');
270
+ disableDeactivateButton();
271
+ }
272
+ }
273
+ });
274
+
275
+ // If the user has clicked outside the window, cancel it.
276
+ $modal.on('click', function (evt) {
277
+ var $target = $(evt.target);
278
+
279
+ // If the user has clicked anywhere in the modal dialog, just return.
280
+ if ($target.hasClass('fs-modal-body') || $target.hasClass('fs-modal-footer')) {
281
+ return;
282
+ }
283
+
284
+ // If the user has not clicked the close button and the clicked element is inside the modal dialog, just return.
285
+ if (!$target.hasClass('button-close') && ( $target.parents('.fs-modal-body').length > 0 || $target.parents('.fs-modal-footer').length > 0 )) {
286
+ return;
287
+ }
288
+
289
+ closeModal();
290
+ return false;
291
+ });
292
+ }
293
+
294
+ function isAnonymousFeedback() {
295
+ if ( ! isAnonymous ) {
296
+ return false;
297
+ }
298
+
299
+ return ( isReasonSelected( dontShareDataReasonID ) || $anonymousFeedback.find( 'input' ).prop( 'checked' ) );
300
+ }
301
+
302
+ function isReasonSelected( reasonID ) {
303
+ // Get the selected radio input element.
304
+ var $selectedReasonOption = $modal.find('input[type="radio"]:checked');
305
+
306
+ return ( reasonID == $selectedReasonOption.val() );
307
+ }
308
+
309
+ function isOtherReasonSelected() {
310
+ return isReasonSelected( otherReasonID );
311
+ }
312
+
313
+ function showModal() {
314
+ resetModal();
315
+
316
+ // Display the dialog box.
317
+ $modal.addClass('active');
318
+
319
+ $('body').addClass('has-fs-modal');
320
+ }
321
+
322
+ function closeModal() {
323
+ $modal.removeClass('active');
324
+
325
+ $('body').removeClass('has-fs-modal');
326
+ }
327
+
328
+ function resetModal() {
329
+ selectedReasonID = false;
330
+
331
+ enableDeactivateButton();
332
+
333
+ // Uncheck all radio buttons.
334
+ $modal.find('input[type="radio"]').prop('checked', false);
335
+
336
+ // Remove all input fields ( textfield, textarea ).
337
+ $modal.find('.reason-input').remove();
338
+
339
+ $modal.find('.message').hide();
340
+
341
+ if ( isAnonymous ) {
342
+ $anonymousFeedback.find( 'input' ).prop( 'checked', false );
343
+
344
+ // Hide, since by default there is no selected reason.
345
+ $anonymousFeedback.hide();
346
+ }
347
+
348
+ var $deactivateButton = $modal.find('.button-deactivate');
349
+
350
+ /*
351
+ * If the modal dialog has no confirmation message, that is, it has only one panel, then ensure
352
+ * that clicking the deactivate button will actually deactivate the plugin.
353
+ */
354
+ if ($modal.hasClass('no-confirmation-message')) {
355
+ $deactivateButton.addClass('allow-deactivate');
356
+
357
+ showPanel('reasons');
358
+ } else {
359
+ $deactivateButton.removeClass('allow-deactivate');
360
+
361
+ showPanel('confirm');
362
+ }
363
+ }
364
+
365
+ function showMessage(message) {
366
+ $modal.find('.message').text(message).show();
367
+ }
368
+
369
+ function enableDeactivateButton() {
370
+ $modal.find('.button-deactivate').removeClass('disabled');
371
+ }
372
+
373
+ function disableDeactivateButton() {
374
+ $modal.find('.button-deactivate').addClass('disabled');
375
+ }
376
+
377
+ function showPanel(panelType) {
378
+ $modal.find('.fs-modal-panel').removeClass('active ');
379
+ $modal.find('[data-panel-id="' + panelType + '"]').addClass('active');
380
+
381
+ updateButtonLabels();
382
+ }
383
+
384
+ function updateButtonLabels() {
385
+ var $deactivateButton = $modal.find('.button-deactivate');
386
+
387
+ // Reset the deactivate button's text.
388
+ if ('confirm' === getCurrentPanel()) {
389
+ $deactivateButton.text('<?php echo esc_js( sprintf(
390
+ fs_text_inline( 'Yes - %s', 'deactivation-modal-button-confirm' , $slug ),
391
+ $fs->is_plugin() ?
392
+ $deactivate_text :
393
+ sprintf( $activate_x_text, $theme_text )
394
+ ) ) ?>');
395
+ } else {
396
+ $deactivateButton.html('<?php echo esc_js( sprintf(
397
+ fs_text_inline('Skip & %s', 'skip-and-x', $slug ),
398
+ $fs->is_plugin() ?
399
+ $deactivate_text :
400
+ sprintf( $activate_x_text, $theme_text )
401
+ ) ) ?>');
402
+ }
403
+ }
404
+
405
+ function getCurrentPanel() {
406
+ return $modal.find('.fs-modal-panel.active').attr('data-panel-id');
407
+ }
408
+ })(jQuery);
409
+ </script>
freemius/templates/forms/deactivation/retry-skip.php CHANGED
@@ -1,24 +1,24 @@
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.0
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * @var array $VARS
15
- */
16
- $fs = freemius( $VARS['id'] );
17
- $slug = $fs->get_slug();
18
-
19
- $skip_url = fs_nonce_url( $fs->_get_admin_page_url( '', array( 'fs_action' => $fs->get_unique_affix() . '_skip_activation' ) ), $fs->get_unique_affix() . '_skip_activation' );
20
- $skip_text = strtolower( fs_text_x_inline( 'Skip', 'verb', 'skip', $slug ) );
21
- $use_plugin_anonymously_text = fs_text_inline( 'Click here to use the plugin anonymously', 'click-here-to-use-plugin-anonymously', $slug );
22
-
23
- echo sprintf( fs_text_inline( "You might have missed it, but you don't have to share any data and can just %s the opt-in.", 'dont-have-to-share-any-data', $slug ), "<a href='{$skip_url}'>{$skip_text}</a>" )
24
  . " <a href='{$skip_url}' class='button button-small button-secondary'>{$use_plugin_anonymously_text}</a>";
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.0
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * @var array $VARS
15
+ */
16
+ $fs = freemius( $VARS['id'] );
17
+ $slug = $fs->get_slug();
18
+
19
+ $skip_url = fs_nonce_url( $fs->_get_admin_page_url( '', array( 'fs_action' => $fs->get_unique_affix() . '_skip_activation' ) ), $fs->get_unique_affix() . '_skip_activation' );
20
+ $skip_text = strtolower( fs_text_x_inline( 'Skip', 'verb', 'skip', $slug ) );
21
+ $use_plugin_anonymously_text = fs_text_inline( 'Click here to use the plugin anonymously', 'click-here-to-use-plugin-anonymously', $slug );
22
+
23
+ echo sprintf( fs_text_inline( "You might have missed it, but you don't have to share any data and can just %s the opt-in.", 'dont-have-to-share-any-data', $slug ), "<a href='{$skip_url}'>{$skip_text}</a>" )
24
  . " <a href='{$skip_url}' class='button button-small button-secondary'>{$use_plugin_anonymously_text}</a>";
freemius/templates/forms/optout.php CHANGED
@@ -1,267 +1,267 @@
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.1.5
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
- $slug = $fs->get_slug();
19
-
20
- $action = $fs->is_tracking_allowed() ?
21
- 'stop_tracking' :
22
- 'allow_tracking';
23
-
24
- $reconnect_url = $fs->get_activation_url( array(
25
- 'nonce' => wp_create_nonce( $fs->get_unique_affix() . '_reconnect' ),
26
- 'fs_action' => ( $fs->get_unique_affix() . '_reconnect' ),
27
- ) );
28
-
29
- $plugin_title = "<strong>{$fs->get_plugin()->title}</strong>";
30
- $opt_out_text = fs_text_x_inline( 'Opt Out', 'verb', 'opt-out', $slug );
31
- $opt_in_text = fs_text_x_inline( 'Opt In', 'verb', 'opt-in', $slug );
32
- $opt_out_message_appreciation = sprintf( fs_text_inline( 'We appreciate your help in making the %s better by letting us track some usage data.', 'opt-out-message-appreciation', $slug ), $fs->get_module_type() );
33
- $opt_out_message_usage_tracking = sprintf( fs_text_inline( "Usage tracking is done in the name of making %s better. Making a better user experience, prioritizing new features, and more good things. We'd really appreciate if you'll reconsider letting us continue with the tracking.", 'opt-out-message-usage-tracking', $slug ), $plugin_title );
34
- $opt_out_message_clicking_opt_out = sprintf(
35
- fs_text_inline( 'By clicking "Opt Out", we will no longer be sending any data from %s to %s.', 'opt-out-message-clicking-opt-out', $slug ),
36
- $plugin_title,
37
- sprintf(
38
- '<a href="%s" target="_blank">%s</a>',
39
- 'https://freemius.com',
40
- 'freemius.com'
41
- )
42
- );
43
-
44
- $admin_notice_params = array(
45
- 'id' => '',
46
- 'slug' => $fs->get_id(),
47
- 'type' => 'success',
48
- 'sticky' => false,
49
- 'plugin' => $fs->get_plugin()->title,
50
- 'message' => $opt_out_message_appreciation
51
- );
52
-
53
- $admin_notice_html = fs_get_template( 'admin-notice.php', $admin_notice_params );
54
-
55
- $modal_content_html = <<< HTML
56
- <h2>{$opt_out_message_appreciation}</h2>
57
- <div class="notice notice-error inline opt-out-error-message"><p></p></div>
58
- <p>{$opt_out_message_usage_tracking}</p>
59
- <p>{$opt_out_message_clicking_opt_out}</p>
60
- HTML;
61
-
62
- fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
63
- fs_enqueue_local_style( 'fs_common', '/admin/common.css' );
64
- ?>
65
- <script type="text/javascript">
66
- (function( $ ) {
67
- $( document ).ready(function() {
68
- var modalContentHtml = <?php echo json_encode( $modal_content_html ) ?>,
69
- modalHtml =
70
- '<div class="fs-modal fs-modal-opt-out">'
71
- + ' <div class="fs-modal-dialog">'
72
- + ' <div class="fs-modal-header">'
73
- + ' <h4><?php echo esc_js( $opt_out_text ) ?></h4>'
74
- + ' </div>'
75
- + ' <div class="fs-modal-body">'
76
- + ' <div class="fs-modal-panel active">' + modalContentHtml + '</div>'
77
- + ' </div>'
78
- + ' <div class="fs-modal-footer">'
79
- + ' <button class="button button-secondary button-opt-out" tabindex="1"><?php echo esc_js( $opt_out_text ) ?></button>'
80
- + ' <button class="button button-primary button-close" tabindex="2"><?php fs_esc_js_echo_inline( 'On second thought - I want to continue helping', 'opt-out-cancel', $slug ) ?></button>'
81
- + ' </div>'
82
- + ' </div>'
83
- + '</div>',
84
- $modal = $( modalHtml ),
85
- $adminNotice = $( <?php echo json_encode( $admin_notice_html ) ?> ),
86
- action = '<?php echo $action ?>',
87
- $actionLink = $( 'span.opt-in-or-opt-out.<?php echo $slug ?> a' ),
88
- $optOutButton = $modal.find( '.button-opt-out' ),
89
- $optOutErrorMessage = $modal.find( '.opt-out-error-message' ),
90
- moduleID = '<?php echo $fs->get_id() ?>';
91
-
92
- $actionLink.attr( 'data-action', action );
93
- $modal.appendTo( $( 'body' ) );
94
-
95
- function registerActionLinkClick() {
96
- $actionLink.click(function( evt ) {
97
- evt.preventDefault();
98
-
99
- if ( 'stop_tracking' == $actionLink.attr( 'data-action' ) ) {
100
- showModal();
101
- } else {
102
- optIn();
103
- }
104
-
105
- return false;
106
- });
107
- }
108
-
109
- function registerEventHandlers() {
110
- registerActionLinkClick();
111
-
112
- $modal.on( 'click', '.button-opt-out', function( evt ) {
113
- evt.preventDefault();
114
-
115
- if ( $( this ).hasClass( 'disabled' ) ) {
116
- return;
117
- }
118
-
119
- disableOptOutButton();
120
- optOut();
121
- });
122
-
123
- // If the user has clicked outside the window, close the modal.
124
- $modal.on( 'click', '.fs-close, .button-close', function() {
125
- closeModal();
126
- return false;
127
- });
128
- }
129
-
130
- registerEventHandlers();
131
-
132
- function showModal() {
133
- resetModal();
134
-
135
- // Display the dialog box.
136
- $modal.addClass( 'active' );
137
- $( 'body' ).addClass( 'has-fs-modal' );
138
- }
139
-
140
- function closeModal() {
141
- $modal.removeClass( 'active' );
142
- $( 'body' ).removeClass( 'has-fs-modal' );
143
- }
144
-
145
- function resetOptOutButton() {
146
- enableOptOutButton();
147
- $optOutButton.text( <?php echo json_encode( $opt_out_text ) ?> );
148
- }
149
-
150
- function resetModal() {
151
- hideError();
152
- resetOptOutButton();
153
- }
154
-
155
- function optIn() {
156
- sendRequest();
157
- }
158
-
159
- function optOut() {
160
- sendRequest();
161
- }
162
-
163
- function sendRequest() {
164
- $.ajax({
165
- url: ajaxurl,
166
- method: 'POST',
167
- data: {
168
- action : ( 'stop_tracking' == action ?
169
- '<?php echo $fs->get_ajax_action( 'stop_tracking' ) ?>' :
170
- '<?php echo $fs->get_ajax_action( 'allow_tracking' ) ?>'
171
- ),
172
- security : ( 'stop_tracking' == action ?
173
- '<?php echo $fs->get_ajax_security( 'stop_tracking' ) ?>' :
174
- '<?php echo $fs->get_ajax_security( 'allow_tracking' ) ?>'
175
- ),
176
- module_id: moduleID
177
- },
178
- beforeSend: function() {
179
- if ( 'opt-in' == action ) {
180
- $actionLink.text( '<?php fs_esc_js_echo_inline( 'Opting in', 'opting-in', $slug ) ?>...' );
181
- } else {
182
- $optOutButton.text( '<?php fs_esc_js_echo_inline( 'Opting out', 'opting-out', $slug ) ?>...' );
183
- }
184
- },
185
- success: function( resultObj ) {
186
- if ( resultObj.success ) {
187
- if ( 'allow_tracking' == action ) {
188
- action = 'stop_tracking';
189
- $actionLink.text( '<?php echo esc_js( $opt_out_text ) ?>' );
190
- showOptInAppreciationMessageAndScrollToTop();
191
- } else {
192
- action = 'allow_tracking';
193
- $actionLink.text( '<?php echo esc_js( $opt_in_text ) ?>' );
194
- closeModal();
195
-
196
- if ( $adminNotice.length > 0 ) {
197
- $adminNotice.remove();
198
- }
199
- }
200
-
201
- $actionLink.attr( 'data-action', action );
202
- } else {
203
- showError( resultObj.error );
204
- resetOptOutButton();
205
- }
206
- }
207
- });
208
- }
209
-
210
- function enableOptOutButton() {
211
- $optOutButton.removeClass( 'disabled' );
212
- }
213
-
214
- function disableOptOutButton() {
215
- $optOutButton.addClass( 'disabled' );
216
- }
217
-
218
- function hideError() {
219
- $optOutErrorMessage.hide();
220
- }
221
-
222
- function showOptInAppreciationMessageAndScrollToTop() {
223
- $adminNotice.insertAfter( $( '#wpbody-content' ).find( ' > .wrap > h1' ) );
224
- window.scrollTo(0, 0);
225
- }
226
-
227
- function showError( msg ) {
228
- $optOutErrorMessage.find( ' > p' ).html( msg );
229
- $optOutErrorMessage.show();
230
- }
231
-
232
- <?php if ( $fs->is_theme() ) : ?>
233
- /**
234
- * Add opt-in/out button to the active theme's buttons collection
235
- * in the theme's extended details overlay.
236
- *
237
- * @author Vova Feldman (@svovaf)
238
- * @since 1.2.2.7
239
- */
240
- $('.theme-overlay').contentChange(function () {
241
- if (!$(this).find('.theme-overlay').hasClass('active')) {
242
- // Add opt-in/out button only to the currently active theme.
243
- return;
244
- }
245
-
246
- if ($('#fs_theme_opt_in_out').length > 0){
247
- // Button already there.
248
- return;
249
- }
250
-
251
- var label = (('stop_tracking' == action) ?
252
- '<?php echo esc_js( $opt_out_text ) ?>' :
253
- '<?php echo esc_js( $opt_in_text ) ?>'),
254
- href = (('stop_tracking' != action) ?
255
- '<?php echo esc_js( $reconnect_url ) ?>' :
256
- '');
257
-
258
- $actionLink = $('<a id="fs_theme_opt_in_out" href="' + encodeURI(href) + '" class="button" data-action="' + action + '">' + label + '</a>');
259
-
260
- $('.theme-wrap .theme-actions .active-theme').append($actionLink);
261
-
262
- registerActionLinkClick();
263
- });
264
- <?php endif ?>
265
- });
266
- })( jQuery );
267
- </script>
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.1.5
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
+ $slug = $fs->get_slug();
19
+
20
+ $action = $fs->is_tracking_allowed() ?
21
+ 'stop_tracking' :
22
+ 'allow_tracking';
23
+
24
+ $reconnect_url = $fs->get_activation_url( array(
25
+ 'nonce' => wp_create_nonce( $fs->get_unique_affix() . '_reconnect' ),
26
+ 'fs_action' => ( $fs->get_unique_affix() . '_reconnect' ),
27
+ ) );
28
+
29
+ $plugin_title = "<strong>{$fs->get_plugin()->title}</strong>";
30
+ $opt_out_text = fs_text_x_inline( 'Opt Out', 'verb', 'opt-out', $slug );
31
+ $opt_in_text = fs_text_x_inline( 'Opt In', 'verb', 'opt-in', $slug );
32
+ $opt_out_message_appreciation = sprintf( fs_text_inline( 'We appreciate your help in making the %s better by letting us track some usage data.', 'opt-out-message-appreciation', $slug ), $fs->get_module_type() );
33
+ $opt_out_message_usage_tracking = sprintf( fs_text_inline( "Usage tracking is done in the name of making %s better. Making a better user experience, prioritizing new features, and more good things. We'd really appreciate if you'll reconsider letting us continue with the tracking.", 'opt-out-message-usage-tracking', $slug ), $plugin_title );
34
+ $opt_out_message_clicking_opt_out = sprintf(
35
+ fs_text_inline( 'By clicking "Opt Out", we will no longer be sending any data from %s to %s.', 'opt-out-message-clicking-opt-out', $slug ),
36
+ $plugin_title,
37
+ sprintf(
38
+ '<a href="%s" target="_blank">%s</a>',
39
+ 'https://freemius.com',
40
+ 'freemius.com'
41
+ )
42
+ );
43
+
44
+ $admin_notice_params = array(
45
+ 'id' => '',
46
+ 'slug' => $fs->get_id(),
47
+ 'type' => 'success',
48
+ 'sticky' => false,
49
+ 'plugin' => $fs->get_plugin()->title,
50
+ 'message' => $opt_out_message_appreciation
51
+ );
52
+
53
+ $admin_notice_html = fs_get_template( 'admin-notice.php', $admin_notice_params );
54
+
55
+ $modal_content_html = <<< HTML
56
+ <h2>{$opt_out_message_appreciation}</h2>
57
+ <div class="notice notice-error inline opt-out-error-message"><p></p></div>
58
+ <p>{$opt_out_message_usage_tracking}</p>
59
+ <p>{$opt_out_message_clicking_opt_out}</p>
60
+ HTML;
61
+
62
+ fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
63
+ fs_enqueue_local_style( 'fs_common', '/admin/common.css' );
64
+ ?>
65
+ <script type="text/javascript">
66
+ (function( $ ) {
67
+ $( document ).ready(function() {
68
+ var modalContentHtml = <?php echo json_encode( $modal_content_html ) ?>,
69
+ modalHtml =
70
+ '<div class="fs-modal fs-modal-opt-out">'
71
+ + ' <div class="fs-modal-dialog">'
72
+ + ' <div class="fs-modal-header">'
73
+ + ' <h4><?php echo esc_js( $opt_out_text ) ?></h4>'
74
+ + ' </div>'
75
+ + ' <div class="fs-modal-body">'
76
+ + ' <div class="fs-modal-panel active">' + modalContentHtml + '</div>'
77
+ + ' </div>'
78
+ + ' <div class="fs-modal-footer">'
79
+ + ' <button class="button button-secondary button-opt-out" tabindex="1"><?php echo esc_js( $opt_out_text ) ?></button>'
80
+ + ' <button class="button button-primary button-close" tabindex="2"><?php fs_esc_js_echo_inline( 'On second thought - I want to continue helping', 'opt-out-cancel', $slug ) ?></button>'
81
+ + ' </div>'
82
+ + ' </div>'
83
+ + '</div>',
84
+ $modal = $( modalHtml ),
85
+ $adminNotice = $( <?php echo json_encode( $admin_notice_html ) ?> ),
86
+ action = '<?php echo $action ?>',
87
+ $actionLink = $( 'span.opt-in-or-opt-out.<?php echo $slug ?> a' ),
88
+ $optOutButton = $modal.find( '.button-opt-out' ),
89
+ $optOutErrorMessage = $modal.find( '.opt-out-error-message' ),
90
+ moduleID = '<?php echo $fs->get_id() ?>';
91
+
92
+ $actionLink.attr( 'data-action', action );
93
+ $modal.appendTo( $( 'body' ) );
94
+
95
+ function registerActionLinkClick() {
96
+ $actionLink.click(function( evt ) {
97
+ evt.preventDefault();
98
+
99
+ if ( 'stop_tracking' == $actionLink.attr( 'data-action' ) ) {
100
+ showModal();
101
+ } else {
102
+ optIn();
103
+ }
104
+
105
+ return false;
106
+ });
107
+ }
108
+
109
+ function registerEventHandlers() {
110
+ registerActionLinkClick();
111
+
112
+ $modal.on( 'click', '.button-opt-out', function( evt ) {
113
+ evt.preventDefault();
114
+
115
+ if ( $( this ).hasClass( 'disabled' ) ) {
116
+ return;
117
+ }
118
+
119
+ disableOptOutButton();
120
+ optOut();
121
+ });
122
+
123
+ // If the user has clicked outside the window, close the modal.
124
+ $modal.on( 'click', '.fs-close, .button-close', function() {
125
+ closeModal();
126
+ return false;
127
+ });
128
+ }
129
+
130
+ registerEventHandlers();
131
+
132
+ function showModal() {
133
+ resetModal();
134
+
135
+ // Display the dialog box.
136
+ $modal.addClass( 'active' );
137
+ $( 'body' ).addClass( 'has-fs-modal' );
138
+ }
139
+
140
+ function closeModal() {
141
+ $modal.removeClass( 'active' );
142
+ $( 'body' ).removeClass( 'has-fs-modal' );
143
+ }
144
+
145
+ function resetOptOutButton() {
146
+ enableOptOutButton();
147
+ $optOutButton.text( <?php echo json_encode( $opt_out_text ) ?> );
148
+ }
149
+
150
+ function resetModal() {
151
+ hideError();
152
+ resetOptOutButton();
153
+ }
154
+
155
+ function optIn() {
156
+ sendRequest();
157
+ }
158
+
159
+ function optOut() {
160
+ sendRequest();
161
+ }
162
+
163
+ function sendRequest() {
164
+ $.ajax({
165
+ url: ajaxurl,
166
+ method: 'POST',
167
+ data: {
168
+ action : ( 'stop_tracking' == action ?
169
+ '<?php echo $fs->get_ajax_action( 'stop_tracking' ) ?>' :
170
+ '<?php echo $fs->get_ajax_action( 'allow_tracking' ) ?>'
171
+ ),
172
+ security : ( 'stop_tracking' == action ?
173
+ '<?php echo $fs->get_ajax_security( 'stop_tracking' ) ?>' :
174
+ '<?php echo $fs->get_ajax_security( 'allow_tracking' ) ?>'
175
+ ),
176
+ module_id: moduleID
177
+ },
178
+ beforeSend: function() {
179
+ if ( 'opt-in' == action ) {
180
+ $actionLink.text( '<?php fs_esc_js_echo_inline( 'Opting in', 'opting-in', $slug ) ?>...' );
181
+ } else {
182
+ $optOutButton.text( '<?php fs_esc_js_echo_inline( 'Opting out', 'opting-out', $slug ) ?>...' );
183
+ }
184
+ },
185
+ success: function( resultObj ) {
186
+ if ( resultObj.success ) {
187
+ if ( 'allow_tracking' == action ) {
188
+ action = 'stop_tracking';
189
+ $actionLink.text( '<?php echo esc_js( $opt_out_text ) ?>' );
190
+ showOptInAppreciationMessageAndScrollToTop();
191
+ } else {
192
+ action = 'allow_tracking';
193
+ $actionLink.text( '<?php echo esc_js( $opt_in_text ) ?>' );
194
+ closeModal();
195
+
196
+ if ( $adminNotice.length > 0 ) {
197
+ $adminNotice.remove();
198
+ }
199
+ }
200
+
201
+ $actionLink.attr( 'data-action', action );
202
+ } else {
203
+ showError( resultObj.error );
204
+ resetOptOutButton();
205
+ }
206
+ }
207
+ });
208
+ }
209
+
210
+ function enableOptOutButton() {
211
+ $optOutButton.removeClass( 'disabled' );
212
+ }
213
+
214
+ function disableOptOutButton() {
215
+ $optOutButton.addClass( 'disabled' );
216
+ }
217
+
218
+ function hideError() {
219
+ $optOutErrorMessage.hide();
220
+ }
221
+
222
+ function showOptInAppreciationMessageAndScrollToTop() {
223
+ $adminNotice.insertAfter( $( '#wpbody-content' ).find( ' > .wrap > h1' ) );
224
+ window.scrollTo(0, 0);
225
+ }
226
+
227
+ function showError( msg ) {
228
+ $optOutErrorMessage.find( ' > p' ).html( msg );
229
+ $optOutErrorMessage.show();
230
+ }
231
+
232
+ <?php if ( $fs->is_theme() ) : ?>
233
+ /**
234
+ * Add opt-in/out button to the active theme's buttons collection
235
+ * in the theme's extended details overlay.
236
+ *
237
+ * @author Vova Feldman (@svovaf)
238
+ * @since 1.2.2.7
239
+ */
240
+ $('.theme-overlay').contentChange(function () {
241
+ if (!$(this).find('.theme-overlay').hasClass('active')) {
242
+ // Add opt-in/out button only to the currently active theme.
243
+ return;
244
+ }
245
+
246
+ if ($('#fs_theme_opt_in_out').length > 0){
247
+ // Button already there.
248
+ return;
249
+ }
250
+
251
+ var label = (('stop_tracking' == action) ?
252
+ '<?php echo esc_js( $opt_out_text ) ?>' :
253
+ '<?php echo esc_js( $opt_in_text ) ?>'),
254
+ href = (('stop_tracking' != action) ?
255
+ '<?php echo esc_js( $reconnect_url ) ?>' :
256
+ '');
257
+
258
+ $actionLink = $('<a id="fs_theme_opt_in_out" href="' + encodeURI(href) + '" class="button" data-action="' + action + '">' + label + '</a>');
259
+
260
+ $('.theme-wrap .theme-actions .active-theme').append($actionLink);
261
+
262
+ registerActionLinkClick();
263
+ });
264
+ <?php endif ?>
265
+ });
266
+ })( jQuery );
267
+ </script>
freemius/templates/forms/resend-key.php CHANGED
@@ -1,247 +1,247 @@
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.0
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
- $send_button_text = fs_text_inline( 'Send License Key', 'send-license-key', $slug );
22
- $cancel_button_text = fs_text_inline( 'Cancel', 'cancel', $slug );
23
- $email_address_placeholder = fs_esc_attr_inline( 'Email address', 'email-address', $slug );
24
- $other_text = fs_text_inline( 'Other', 'other', $slug );
25
-
26
- $is_freemium = $fs->is_freemium();
27
-
28
- $send_button_text_html = esc_html($send_button_text);
29
-
30
- $button_html = <<< HTML
31
- <div class="button-container">
32
- <a href="#" class="button button-primary button-send-license-key" tabindex="2">{$send_button_text_html}</a>
33
- </div>
34
- HTML;
35
-
36
- if ( $is_freemium ) {
37
- $current_user = Freemius::_get_current_wp_user();
38
- $email = $current_user->user_email;
39
- $esc_email = esc_attr( $email );
40
- $form_html = <<< HTML
41
- <div class="email-address-container">
42
- <label><input name="email-address" type="radio" checked="checked" tabindex="1" value="{$esc_email}"> {$email}</label>
43
- <label><input name="email-address" type="radio" tabindex="1" value="other">{$other_text}: <input class="email-address" type="text" placeholder="{$email_address_placeholder}"></label>
44
- </div>
45
- {$button_html}
46
- HTML;
47
- } else {
48
- $email = '';
49
- $form_html = <<< HTML
50
- {$button_html}
51
- <div class="email-address-container">
52
- <input class="email-address" type="text" placeholder="{$email_address_placeholder}" tabindex="1">
53
- </div>
54
- HTML;
55
- }
56
-
57
- $message_above_input_field = fs_esc_html_inline( "Enter the email address you've used for the upgrade below and we will resend you the license key.", 'ask-for-upgrade-email-address', $slug );
58
- $modal_content_html = <<< HTML
59
- <div class="notice notice-error inline license-resend-message"><p></p></div>
60
- <p>{$message_above_input_field}</p>
61
- <div class="input-container">
62
- {$form_html}
63
- </div>
64
- HTML;
65
-
66
- fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
67
- ?>
68
- <script type="text/javascript">
69
- (function ($) {
70
- $(document).ready(function () {
71
- var contentHtml = <?php echo json_encode( $modal_content_html ); ?>,
72
- modalHtml =
73
- '<div class="fs-modal fs-modal-license-key-resend <?php echo $is_freemium ? 'fs-freemium' : 'fs-premium' ?>">'
74
- + ' <div class="fs-modal-dialog">'
75
- + ' <div class="fs-modal-header">'
76
- + ' <h4><?php echo esc_js( $send_button_text ) ?></h4>'
77
- + ' <a href="#!" class="fs-close" tabindex="3" title="Close"><i class="dashicons dashicons-no" title="<?php echo esc_js( fs_text_x_inline( 'Dismiss', 'as close a window', 'dismiss', $slug ) ) ?>"></i></a>'
78
- + ' </div>'
79
- + ' <div class="fs-modal-body">'
80
- + ' <div class="fs-modal-panel active">' + contentHtml + '</div>'
81
- + ' </div>'
82
- + ' </div>'
83
- + '</div>',
84
- $modal = $(modalHtml),
85
- $sendButton = $modal.find('.button-send-license-key'),
86
- $emailInput = $modal.find('input.email-address'),
87
- $feedbackMessage = $modal.find('.license-resend-message'),
88
- isFreemium = <?php echo json_encode( $is_freemium ) ?>,
89
- userEmail = <?php echo json_encode( $email ) ?>,
90
- moduleID = '<?php echo $fs->get_id() ?>',
91
- isChild = false;
92
-
93
-
94
- $modal.appendTo($('body'));
95
-
96
- function registerEventHandlers() {
97
- $('a.show-license-resend-modal-<?php echo $fs->get_unique_affix() ?>').click(function (evt) {
98
- evt.preventDefault();
99
-
100
- showModal();
101
- });
102
-
103
- if (isFreemium) {
104
- $modal.on('change', 'input[type=radio][name=email-address]', function () {
105
- updateButtonState();
106
- });
107
-
108
- $modal.on('focus', 'input.email-address', function () {
109
- // Check custom email radio button on email input focus.
110
- $($modal.find('input[type=radio]')[1]).prop('checked', true);
111
-
112
- updateButtonState();
113
- });
114
- }
115
-
116
- $modal.on('input propertychange', 'input.email-address', function () {
117
- updateButtonState();
118
- });
119
-
120
- $modal.on('blur', 'input.email-address', function () {
121
- updateButtonState();
122
- });
123
-
124
- $modal.on('click', '.fs-close', function (){
125
- closeModal();
126
- return false;
127
- });
128
-
129
- $modal.on('click', '.button', function (evt) {
130
- evt.preventDefault();
131
-
132
- if ($(this).hasClass('disabled')) {
133
- return;
134
- }
135
-
136
- var email = getEmail();
137
-
138
- disableButton();
139
-
140
- if (!(-1 < email.indexOf('@'))) {
141
- return;
142
- }
143
-
144
- $.ajax({
145
- url : ajaxurl,
146
- method : 'POST',
147
- data : {
148
- action : '<?php echo $fs->get_ajax_action( 'resend_license_key' ) ?>',
149
- security : '<?php echo $fs->get_ajax_security( 'resend_license_key' ) ?>',
150
- module_id : moduleID,
151
- email : email
152
- },
153
- beforeSend: function () {
154
- $sendButton.text('<?php fs_esc_js_echo_inline( 'Sending license key', 'sending-license-key', $slug ) ?>...');
155
- },
156
- success : function (result) {
157
- var resultObj = $.parseJSON(result);
158
- if (resultObj.success) {
159
- closeModal();
160
- } else {
161
- showError(resultObj.error);
162
- resetButton();
163
- }
164
- }
165
- });
166
- });
167
- }
168
-
169
- registerEventHandlers();
170
-
171
- resetButton();
172
-
173
- function showModal() {
174
- resetModal();
175
-
176
- // Display the dialog box.
177
- $modal.addClass('active');
178
-
179
- if (!isFreemium)
180
- $emailInput.focus();
181
-
182
- var $body = $('body');
183
-
184
- isChild = $body.hasClass('has-fs-modal');
185
- if (isChild) {
186
- return;
187
- }
188
-
189
- $body.addClass('has-fs-modal');
190
- }
191
-
192
- function closeModal() {
193
- $modal.removeClass('active');
194
-
195
- // If child modal, do not remove the "has-fs-modal" class of the <body> element to keep its scrollbars hidden.
196
- if (isChild) {
197
- return;
198
- }
199
-
200
- $('body').removeClass('has-fs-modal');
201
- }
202
-
203
- function resetButton() {
204
- updateButtonState();
205
- $sendButton.text(<?php echo json_encode($send_button_text) ?>);
206
- }
207
-
208
- function resetModal() {
209
- hideError();
210
- resetButton();
211
- $emailInput.val('');
212
- }
213
-
214
- function getEmail() {
215
- var email = $emailInput.val().trim();
216
-
217
- if (isFreemium) {
218
- if ('other' != $modal.find('input[type=radio][name=email-address]:checked').val()) {
219
- email = userEmail;
220
- }
221
- }
222
-
223
- return email;
224
- }
225
-
226
- function updateButtonState() {
227
- /**
228
- * If email address is not empty, enable the send license key button.
229
- */
230
- $sendButton.toggleClass('disabled', !( -1 < getEmail().indexOf('@') ));
231
- }
232
-
233
- function disableButton() {
234
- $sendButton.addClass('disabled');
235
- }
236
-
237
- function hideError() {
238
- $feedbackMessage.hide();
239
- }
240
-
241
- function showError(msg) {
242
- $feedbackMessage.find(' > p').html(msg);
243
- $feedbackMessage.show();
244
- }
245
- });
246
- })(jQuery);
247
- </script>
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.0
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
+ $send_button_text = fs_text_inline( 'Send License Key', 'send-license-key', $slug );
22
+ $cancel_button_text = fs_text_inline( 'Cancel', 'cancel', $slug );
23
+ $email_address_placeholder = fs_esc_attr_inline( 'Email address', 'email-address', $slug );
24
+ $other_text = fs_text_inline( 'Other', 'other', $slug );
25
+
26
+ $is_freemium = $fs->is_freemium();
27
+
28
+ $send_button_text_html = esc_html($send_button_text);
29
+
30
+ $button_html = <<< HTML
31
+ <div class="button-container">
32
+ <a href="#" class="button button-primary button-send-license-key" tabindex="2">{$send_button_text_html}</a>
33
+ </div>
34
+ HTML;
35
+
36
+ if ( $is_freemium ) {
37
+ $current_user = Freemius::_get_current_wp_user();
38
+ $email = $current_user->user_email;
39
+ $esc_email = esc_attr( $email );
40
+ $form_html = <<< HTML
41
+ <div class="email-address-container">
42
+ <label><input name="email-address" type="radio" checked="checked" tabindex="1" value="{$esc_email}"> {$email}</label>
43
+ <label><input name="email-address" type="radio" tabindex="1" value="other">{$other_text}: <input class="email-address" type="text" placeholder="{$email_address_placeholder}"></label>
44
+ </div>
45
+ {$button_html}
46
+ HTML;
47
+ } else {
48
+ $email = '';
49
+ $form_html = <<< HTML
50
+ {$button_html}
51
+ <div class="email-address-container">
52
+ <input class="email-address" type="text" placeholder="{$email_address_placeholder}" tabindex="1">
53
+ </div>
54
+ HTML;
55
+ }
56
+
57
+ $message_above_input_field = fs_esc_html_inline( "Enter the email address you've used for the upgrade below and we will resend you the license key.", 'ask-for-upgrade-email-address', $slug );
58
+ $modal_content_html = <<< HTML
59
+ <div class="notice notice-error inline license-resend-message"><p></p></div>
60
+ <p>{$message_above_input_field}</p>
61
+ <div class="input-container">
62
+ {$form_html}
63
+ </div>
64
+ HTML;
65
+
66
+ fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
67
+ ?>
68
+ <script type="text/javascript">
69
+ (function ($) {
70
+ $(document).ready(function () {
71
+ var contentHtml = <?php echo json_encode( $modal_content_html ); ?>,
72
+ modalHtml =
73
+ '<div class="fs-modal fs-modal-license-key-resend <?php echo $is_freemium ? 'fs-freemium' : 'fs-premium' ?>">'
74
+ + ' <div class="fs-modal-dialog">'
75
+ + ' <div class="fs-modal-header">'
76
+ + ' <h4><?php echo esc_js( $send_button_text ) ?></h4>'
77
+ + ' <a href="#!" class="fs-close" tabindex="3" title="Close"><i class="dashicons dashicons-no" title="<?php echo esc_js( fs_text_x_inline( 'Dismiss', 'as close a window', 'dismiss', $slug ) ) ?>"></i></a>'
78
+ + ' </div>'
79
+ + ' <div class="fs-modal-body">'
80
+ + ' <div class="fs-modal-panel active">' + contentHtml + '</div>'
81
+ + ' </div>'
82
+ + ' </div>'
83
+ + '</div>',
84
+ $modal = $(modalHtml),
85
+ $sendButton = $modal.find('.button-send-license-key'),
86
+ $emailInput = $modal.find('input.email-address'),
87
+ $feedbackMessage = $modal.find('.license-resend-message'),
88
+ isFreemium = <?php echo json_encode( $is_freemium ) ?>,
89
+ userEmail = <?php echo json_encode( $email ) ?>,
90
+ moduleID = '<?php echo $fs->get_id() ?>',
91
+ isChild = false;
92
+
93
+
94
+ $modal.appendTo($('body'));
95
+
96
+ function registerEventHandlers() {
97
+ $('a.show-license-resend-modal-<?php echo $fs->get_unique_affix() ?>').click(function (evt) {
98
+ evt.preventDefault();
99
+
100
+ showModal();
101
+ });
102
+
103
+ if (isFreemium) {
104
+ $modal.on('change', 'input[type=radio][name=email-address]', function () {
105
+ updateButtonState();
106
+ });
107
+
108
+ $modal.on('focus', 'input.email-address', function () {
109
+ // Check custom email radio button on email input focus.
110
+ $($modal.find('input[type=radio]')[1]).prop('checked', true);
111
+
112
+ updateButtonState();
113
+ });
114
+ }
115
+
116
+ $modal.on('input propertychange', 'input.email-address', function () {
117
+ updateButtonState();
118
+ });
119
+
120
+ $modal.on('blur', 'input.email-address', function () {
121
+ updateButtonState();
122
+ });
123
+
124
+ $modal.on('click', '.fs-close', function (){
125
+ closeModal();
126
+ return false;
127
+ });
128
+
129
+ $modal.on('click', '.button', function (evt) {
130
+ evt.preventDefault();
131
+
132
+ if ($(this).hasClass('disabled')) {
133
+ return;
134
+ }
135
+
136
+ var email = getEmail();
137
+
138
+ disableButton();
139
+
140
+ if (!(-1 < email.indexOf('@'))) {
141
+ return;
142
+ }
143
+
144
+ $.ajax({
145
+ url : ajaxurl,
146
+ method : 'POST',
147
+ data : {
148
+ action : '<?php echo $fs->get_ajax_action( 'resend_license_key' ) ?>',
149
+ security : '<?php echo $fs->get_ajax_security( 'resend_license_key' ) ?>',
150
+ module_id : moduleID,
151
+ email : email
152
+ },
153
+ beforeSend: function () {
154
+ $sendButton.text('<?php fs_esc_js_echo_inline( 'Sending license key', 'sending-license-key', $slug ) ?>...');
155
+ },
156
+ success : function (result) {
157
+ var resultObj = $.parseJSON(result);
158
+ if (resultObj.success) {
159
+ closeModal();
160
+ } else {
161
+ showError(resultObj.error);
162
+ resetButton();
163
+ }
164
+ }
165
+ });
166
+ });
167
+ }
168
+
169
+ registerEventHandlers();
170
+
171
+ resetButton();
172
+
173
+ function showModal() {
174
+ resetModal();
175
+
176
+ // Display the dialog box.
177
+ $modal.addClass('active');
178
+
179
+ if (!isFreemium)
180
+ $emailInput.focus();
181
+
182
+ var $body = $('body');
183
+
184
+ isChild = $body.hasClass('has-fs-modal');
185
+ if (isChild) {
186
+ return;
187
+ }
188
+
189
+ $body.addClass('has-fs-modal');
190
+ }
191
+
192
+ function closeModal() {
193
+ $modal.removeClass('active');
194
+
195
+ // If child modal, do not remove the "has-fs-modal" class of the <body> element to keep its scrollbars hidden.
196
+ if (isChild) {
197
+ return;
198
+ }
199
+
200
+ $('body').removeClass('has-fs-modal');
201
+ }
202
+
203
+ function resetButton() {
204
+ updateButtonState();
205
+ $sendButton.text(<?php echo json_encode($send_button_text) ?>);
206
+ }
207
+
208
+ function resetModal() {
209
+ hideError();
210
+ resetButton();
211
+ $emailInput.val('');
212
+ }
213
+
214
+ function getEmail() {
215
+ var email = $emailInput.val().trim();
216
+
217
+ if (isFreemium) {
218
+ if ('other' != $modal.find('input[type=radio][name=email-address]:checked').val()) {
219
+ email = userEmail;
220
+ }
221
+ }
222
+
223
+ return email;
224
+ }
225
+
226
+ function updateButtonState() {
227
+ /**
228
+ * If email address is not empty, enable the send license key button.
229
+ */
230
+ $sendButton.toggleClass('disabled', !( -1 < getEmail().indexOf('@') ));
231
+ }
232
+
233
+ function disableButton() {
234
+ $sendButton.addClass('disabled');
235
+ }
236
+
237
+ function hideError() {
238
+ $feedbackMessage.hide();
239
+ }
240
+
241
+ function showError(msg) {
242
+ $feedbackMessage.find(' > p').html(msg);
243
+ $feedbackMessage.show();
244
+ }
245
+ });
246
+ })(jQuery);
247
+ </script>
freemius/templates/forms/trial-start.php CHANGED
@@ -1,181 +1,181 @@
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.0
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
- $slug = $fs->get_slug();
19
-
20
- $message_header = sprintf(
21
- /* translators: %1$s: Number of trial days; %2$s: Plan name; */
22
- fs_text_inline( 'You are 1-click away from starting your %1$s-day free trial of the %2$s plan.', 'start-trial-prompt-header', $slug ),
23
- '<span class="var-trial_period"></span>',
24
- '<span class="var-plan_title"></span>'
25
- );
26
- $message_content = sprintf(
27
- /* translators: %s: Link to freemius.com */
28
- fs_text_inline( 'For compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.', 'start-trial-prompt-message', $slug ),
29
- $fs->get_module_type(),
30
- sprintf(
31
- '<a href="%s" target="_blank">%s</a>',
32
- 'https://freemius.com',
33
- 'freemius.com'
34
- )
35
- );
36
-
37
- $modal_content_html = <<< HTML
38
- <div class="notice notice-error inline"><p></p></div>
39
- <h3>{$message_header}</h3>
40
- <p>{$message_content}</p>
41
- HTML;
42
-
43
- fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
44
- ?>
45
- <script type="text/javascript">
46
- (function ($) {
47
- $(document).ready(function () {
48
- var modalContentHtml = <?php echo json_encode( $modal_content_html ); ?>,
49
- modalHtml =
50
- '<div class="fs-modal fs-modal-license-key-resend">'
51
- + ' <div class="fs-modal-dialog">'
52
- + ' <div class="fs-modal-header">'
53
- + ' <h4><?php echo esc_js( fs_text_x_inline( 'Start free trial', 'call to action', 'start-free-trial', $slug ) ) ?></h4>'
54
- + ' </div>'
55
- + ' <div class="fs-modal-body">' + modalContentHtml + '</div>'
56
- + ' <div class="fs-modal-footer">'
57
- + ' <button class="button button-secondary button-close">' + <?php fs_json_encode_echo_inline( 'Cancel', 'cancel', $slug ) ?> +'</button>'
58
- + ' <button class="button button-primary button-connect">' + <?php fs_json_encode_echo_inline( 'Approve & Start Trial', 'approve-start-trial', $slug ) ?> +'</button>'
59
- + ' </div>'
60
- + ' </div>'
61
- + '</div>',
62
- $modal = $( modalHtml ),
63
- trialData;
64
-
65
- $modal.appendTo($('body'));
66
-
67
- var $errorNotice = $modal.find('.notice-error');
68
-
69
- registerEventHandlers();
70
-
71
- function registerEventHandlers() {
72
- $modal.on('click', '.button-close', function () {
73
- closeModal();
74
- return false;
75
- });
76
-
77
- $modal.on('click', '.button-connect', function (evt) {
78
- evt.preventDefault();
79
-
80
- var $button = $(this);
81
-
82
- $.ajax({
83
- url : ajaxurl,
84
- method : 'POST',
85
- data : {
86
- action : '<?php echo $fs->get_ajax_action( 'start_trial' ) ?>',
87
- security : '<?php echo $fs->get_ajax_security( 'start_trial' ) ?>',
88
- module_id: '<?php echo $fs->get_id() ?>',
89
- trial : trialData
90
- },
91
- beforeSend: function () {
92
- // Disable all buttons during trial activation.
93
- $modal.find('.button').prop('disabled', true);
94
-
95
- $button.text(<?php fs_json_encode_echo_inline( 'Starting trial', 'starting-trial', $slug ) ?> + '...');
96
-
97
- setLoadingMode();
98
- },
99
- success : function (resultObj) {
100
- if (resultObj.success) {
101
- $button.text(<?php fs_json_encode_echo_inline( 'Please wait', 'please-wait', $slug ) ?> + '...');
102
-
103
- // Redirect to the "Account" page and sync the license.
104
- window.location.href = resultObj.data.next_page;
105
- } else {
106
- $button.text(<?php fs_json_encode_echo( 'approve-start-trial', $slug ) ?>);
107
-
108
- resetLoadingMode();
109
- showError(resultObj.error);
110
- }
111
- }
112
- });
113
- });
114
- }
115
-
116
- window.openTrialConfirmationModal = function showModal(data) {
117
- resetModal();
118
-
119
- // Display the dialog box.
120
- $modal.addClass('active');
121
-
122
- trialData = data;
123
-
124
- var $modalBody = $modal.find('.fs-modal-body'),
125
- $var;
126
-
127
- for (var key in data) {
128
- if (data.hasOwnProperty(key)) {
129
- $var = $modalBody.find('.var-' + key);
130
-
131
- if ($var.length > 0)
132
- $var.html(data[key]);
133
- }
134
- }
135
-
136
- $('body').addClass('has-fs-modal');
137
- };
138
-
139
- function closeModal() {
140
- $modal.removeClass('active');
141
-
142
- $('body').removeClass('has-fs-modal');
143
- }
144
-
145
- function resetModal() {
146
- hideError();
147
- }
148
-
149
- function hideError() {
150
- $errorNotice.hide();
151
- }
152
-
153
- function setLoadingMode() {
154
- $modal.find('.button')
155
- // Re-enable all buttons.
156
- .prop('disabled', trialData)
157
- // Stop loading cursor.
158
- .css({'cursor': 'wait'});
159
-
160
- // Stop loading cursor.
161
- $(document.body).css({'cursor': 'wait'});
162
- }
163
-
164
- function resetLoadingMode() {
165
- $modal.find('.button')
166
- // Re-enable all buttons.
167
- .prop('disabled', false)
168
- // Stop loading cursor.
169
- .css({'cursor': 'initial'});
170
-
171
- // Stop loading cursor.
172
- $(document.body).css({'cursor': 'initial'});
173
- }
174
-
175
- function showError(msg) {
176
- $errorNotice.find(' > p').html(msg);
177
- $errorNotice.show();
178
- }
179
- });
180
- })(jQuery);
181
- </script>
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.0
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
+ $slug = $fs->get_slug();
19
+
20
+ $message_header = sprintf(
21
+ /* translators: %1$s: Number of trial days; %2$s: Plan name; */
22
+ fs_text_inline( 'You are 1-click away from starting your %1$s-day free trial of the %2$s plan.', 'start-trial-prompt-header', $slug ),
23
+ '<span class="var-trial_period"></span>',
24
+ '<span class="var-plan_title"></span>'
25
+ );
26
+ $message_content = sprintf(
27
+ /* translators: %s: Link to freemius.com */
28
+ fs_text_inline( 'For compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.', 'start-trial-prompt-message', $slug ),
29
+ $fs->get_module_type(),
30
+ sprintf(
31
+ '<a href="%s" target="_blank">%s</a>',
32
+ 'https://freemius.com',
33
+ 'freemius.com'
34
+ )
35
+ );
36
+
37
+ $modal_content_html = <<< HTML
38
+ <div class="notice notice-error inline"><p></p></div>
39
+ <h3>{$message_header}</h3>
40
+ <p>{$message_content}</p>
41
+ HTML;
42
+
43
+ fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' );
44
+ ?>
45
+ <script type="text/javascript">
46
+ (function ($) {
47
+ $(document).ready(function () {
48
+ var modalContentHtml = <?php echo json_encode( $modal_content_html ); ?>,
49
+ modalHtml =
50
+ '<div class="fs-modal fs-modal-license-key-resend">'
51
+ + ' <div class="fs-modal-dialog">'
52
+ + ' <div class="fs-modal-header">'
53
+ + ' <h4><?php echo esc_js( fs_text_x_inline( 'Start free trial', 'call to action', 'start-free-trial', $slug ) ) ?></h4>'
54
+ + ' </div>'
55
+ + ' <div class="fs-modal-body">' + modalContentHtml + '</div>'
56
+ + ' <div class="fs-modal-footer">'
57
+ + ' <button class="button button-secondary button-close">' + <?php fs_json_encode_echo_inline( 'Cancel', 'cancel', $slug ) ?> +'</button>'
58
+ + ' <button class="button button-primary button-connect">' + <?php fs_json_encode_echo_inline( 'Approve & Start Trial', 'approve-start-trial', $slug ) ?> +'</button>'
59
+ + ' </div>'
60
+ + ' </div>'
61
+ + '</div>',
62
+ $modal = $( modalHtml ),
63
+ trialData;
64
+
65
+ $modal.appendTo($('body'));
66
+
67
+ var $errorNotice = $modal.find('.notice-error');
68
+
69
+ registerEventHandlers();
70
+
71
+ function registerEventHandlers() {
72
+ $modal.on('click', '.button-close', function () {
73
+ closeModal();
74
+ return false;
75
+ });
76
+
77
+ $modal.on('click', '.button-connect', function (evt) {
78
+ evt.preventDefault();
79
+
80
+ var $button = $(this);
81
+
82
+ $.ajax({
83
+ url : ajaxurl,
84
+ method : 'POST',
85
+ data : {
86
+ action : '<?php echo $fs->get_ajax_action( 'start_trial' ) ?>',
87
+ security : '<?php echo $fs->get_ajax_security( 'start_trial' ) ?>',
88
+ module_id: '<?php echo $fs->get_id() ?>',
89
+ trial : trialData
90
+ },
91
+ beforeSend: function () {
92
+ // Disable all buttons during trial activation.
93
+ $modal.find('.button').prop('disabled', true);
94
+
95
+ $button.text(<?php fs_json_encode_echo_inline( 'Starting trial', 'starting-trial', $slug ) ?> + '...');
96
+
97
+ setLoadingMode();
98
+ },
99
+ success : function (resultObj) {
100
+ if (resultObj.success) {
101
+ $button.text(<?php fs_json_encode_echo_inline( 'Please wait', 'please-wait', $slug ) ?> + '...');
102
+
103
+ // Redirect to the "Account" page and sync the license.
104
+ window.location.href = resultObj.data.next_page;
105
+ } else {
106
+ $button.text(<?php fs_json_encode_echo( 'approve-start-trial', $slug ) ?>);
107
+
108
+ resetLoadingMode();
109
+ showError(resultObj.error);
110
+ }
111
+ }
112
+ });
113
+ });
114
+ }
115
+
116
+ window.openTrialConfirmationModal = function showModal(data) {
117
+ resetModal();
118
+
119
+ // Display the dialog box.
120
+ $modal.addClass('active');
121
+
122
+ trialData = data;
123
+
124
+ var $modalBody = $modal.find('.fs-modal-body'),
125
+ $var;
126
+
127
+ for (var key in data) {
128
+ if (data.hasOwnProperty(key)) {
129
+ $var = $modalBody.find('.var-' + key);
130
+
131
+ if ($var.length > 0)
132
+ $var.html(data[key]);
133
+ }
134
+ }
135
+
136
+ $('body').addClass('has-fs-modal');
137
+ };
138
+
139
+ function closeModal() {
140
+ $modal.removeClass('active');
141
+
142
+ $('body').removeClass('has-fs-modal');
143
+ }
144
+
145
+ function resetModal() {
146
+ hideError();
147
+ }
148
+
149
+ function hideError() {
150
+ $errorNotice.hide();
151
+ }
152
+
153
+ function setLoadingMode() {
154
+ $modal.find('.button')
155
+ // Re-enable all buttons.
156
+ .prop('disabled', trialData)
157
+ // Stop loading cursor.
158
+ .css({'cursor': 'wait'});
159
+
160
+ // Stop loading cursor.
161
+ $(document.body).css({'cursor': 'wait'});
162
+ }
163
+
164
+ function resetLoadingMode() {
165
+ $modal.find('.button')
166
+ // Re-enable all buttons.
167
+ .prop('disabled', false)
168
+ // Stop loading cursor.
169
+ .css({'cursor': 'initial'});
170
+
171
+ // Stop loading cursor.
172
+ $(document.body).css({'cursor': 'initial'});
173
+ }
174
+
175
+ function showError(msg) {
176
+ $errorNotice.find(' > p').html(msg);
177
+ $errorNotice.show();
178
+ }
179
+ });
180
+ })(jQuery);
181
+ </script>
freemius/templates/js/style-premium-theme.php CHANGED
@@ -1,45 +1,45 @@
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.2.7
7
- *
8
- */
9
-
10
- if ( ! defined( 'ABSPATH' ) ) {
11
- exit;
12
- }
13
-
14
- /**
15
- * @var array $VARS
16
- * @var Freemius $fs
17
- */
18
- $fs = freemius( $VARS['id'] );
19
-
20
- $slug = $fs->get_slug();
21
-
22
- ?>
23
- <script type="text/javascript">
24
- (function ($) {
25
- // Select the premium theme version.
26
- var $theme = $('#<?php echo $slug ?>-premium-name').parents('.theme'),
27
- addPremiumMetadata = function (firstCall) {
28
- if (!firstCall) {
29
- // Seems like the original theme element is removed from the DOM,
30
- // so we need to reselect the updated one.
31
- $theme = $('#<?php echo $slug ?>-premium-name').parents('.theme');
32
- }
33
-
34
- if (0 === $theme.find('.fs-premium-theme-badge').length) {
35
- $theme.addClass('fs-premium');
36
-
37
- $theme.append('<span class="fs-premium-theme-badge">' + <?php echo json_encode( $fs->get_text_inline( 'Premium', 'premium' ) ) ?> +'</span>');
38
- }
39
- };
40
-
41
- addPremiumMetadata(true);
42
-
43
- $theme.contentChange(addPremiumMetadata);
44
- })(jQuery);
45
  </script>
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.2.7
7
+ *
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
+
14
+ /**
15
+ * @var array $VARS
16
+ * @var Freemius $fs
17
+ */
18
+ $fs = freemius( $VARS['id'] );
19
+
20
+ $slug = $fs->get_slug();
21
+
22
+ ?>
23
+ <script type="text/javascript">
24
+ (function ($) {
25
+ // Select the premium theme version.
26
+ var $theme = $('#<?php echo $slug ?>-premium-name').parents('.theme'),
27
+ addPremiumMetadata = function (firstCall) {
28
+ if (!firstCall) {
29
+ // Seems like the original theme element is removed from the DOM,
30
+ // so we need to reselect the updated one.
31
+ $theme = $('#<?php echo $slug ?>-premium-name').parents('.theme');
32
+ }
33
+
34
+ if (0 === $theme.find('.fs-premium-theme-badge').length) {
35
+ $theme.addClass('fs-premium');
36
+
37
+ $theme.append('<span class="fs-premium-theme-badge">' + <?php echo json_encode( $fs->get_text_inline( 'Premium', 'premium' ) ) ?> +'</span>');
38
+ }
39
+ };
40
+
41
+ addPremiumMetadata(true);
42
+
43
+ $theme.contentChange(addPremiumMetadata);
44
+ })(jQuery);
45
  </script>
freemius/templates/plugin-icon.php CHANGED
@@ -1,130 +1,130 @@
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.1.4
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- $fs = freemius( $VARS['id'] );
14
- $slug = $fs->get_slug();
15
-
16
- /**
17
- * @since 1.1.7.5
18
- */
19
- $local_path = $fs->apply_filters( 'plugin_icon', false );
20
-
21
- if ( is_string( $local_path ) ) {
22
- $icons = array( $local_path );
23
- } else {
24
- global $fs_active_plugins;
25
-
26
- $img_dir = WP_FS__DIR_IMG;
27
-
28
- if ( 1 < count( $fs_active_plugins->plugins ) ) {
29
- $plugin_or_theme_img_dir = ( $fs->is_plugin() ? WP_PLUGIN_DIR : get_theme_root() );
30
-
31
- foreach ( $fs_active_plugins->plugins as $sdk_path => &$data ) {
32
- if ( $data->plugin_path == $fs->get_plugin_basename() ) {
33
- $img_dir = $plugin_or_theme_img_dir
34
- . '/'
35
- . str_replace( '../themes/', '', $sdk_path )
36
- . '/assets/img';
37
-
38
- break;
39
- }
40
- }
41
- }
42
-
43
- if ( $fs->is_theme() ) {
44
- $icons = array(
45
- fs_normalize_path( $img_dir . '/theme-icon.png' )
46
- );
47
- } else {
48
- $icons = glob( fs_normalize_path( $img_dir . '/' . $slug . '.*' ) );
49
- if ( ! is_array( $icons ) || 0 === count( $icons ) ) {
50
- $icon_found = false;
51
- $local_path = fs_normalize_path( $img_dir . '/' . $slug . '.png' );
52
-
53
- $have_write_permissions = ( 'direct' === get_filesystem_method( array(), fs_normalize_path( $img_dir ) ) );
54
-
55
- if ( WP_FS__IS_LOCALHOST && $fs->is_org_repo_compliant() && $have_write_permissions ) {
56
- /**
57
- * IMPORTANT: THIS CODE WILL NEVER RUN AFTER THE PLUGIN IS IN THE REPO.
58
- *
59
- * This code will only be executed once during the testing
60
- * of the plugin in a local environment. The plugin icon file WILL
61
- * already exist in the assets folder when the plugin is deployed to
62
- * the repository.
63
- */
64
- if ( ! function_exists( 'plugins_api' ) ) {
65
- require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
66
- }
67
-
68
- $plugin_information = plugins_api( 'plugin_information', array(
69
- 'slug' => $slug,
70
- 'fields' => array(
71
- 'sections' => false,
72
- 'tags' => false,
73
- 'icons' => true
74
- )
75
- ) );
76
-
77
- if (
78
- ! is_wp_error( $plugin_information )
79
- && isset( $plugin_information->icons )
80
- && ! empty( $plugin_information->icons )
81
- ) {
82
- /**
83
- * Get the smallest icon.
84
- *
85
- * @author Leo Fajardo (@leorw)
86
- * @since 1.2.2
87
- */
88
- $icon = end( $plugin_information->icons );
89
-
90
- if ( 0 !== strpos( $icon, 'http' ) ) {
91
- $icon = 'http:' . $icon;
92
- }
93
-
94
- /**
95
- * Get a clean file extension, e.g.: "jpg" and not "jpg?rev=1305765".
96
- *
97
- * @author Leo Fajardo (@leorw)
98
- * @since 1.2.2
99
- */
100
- $ext = pathinfo( strtok( $icon, '?' ), PATHINFO_EXTENSION );
101
-
102
- $local_path = fs_normalize_path( $img_dir . '/' . $slug . '.' . $ext );
103
-
104
- // Try to download the icon.
105
- $icon_found = fs_download_image( $icon, $local_path );
106
- }
107
- }
108
-
109
- if ( ! $icon_found ) {
110
- // No icons found, fallback to default icon.
111
- if ( $have_write_permissions ) {
112
- // If have write permissions, copy default icon.
113
- copy( fs_normalize_path( $img_dir . '/plugin-icon.png' ), $local_path );
114
- } else {
115
- // If doesn't have write permissions, use default icon path.
116
- $local_path = fs_normalize_path( $img_dir . '/plugin-icon.png' );
117
- }
118
- }
119
-
120
- $icons = array( $local_path );
121
- }
122
- }
123
- }
124
-
125
- $icon_dir = dirname( $icons[0] );
126
- $relative_url = fs_img_url( substr( $icons[0], strlen( $icon_dir ) ), $icon_dir );
127
- ?>
128
- <div class="fs-plugin-icon">
129
- <img src="<?php echo $relative_url ?>" width="80" height="80"/>
130
  </div>
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.1.4
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ $fs = freemius( $VARS['id'] );
14
+ $slug = $fs->get_slug();
15
+
16
+ /**
17
+ * @since 1.1.7.5
18
+ */
19
+ $local_path = $fs->apply_filters( 'plugin_icon', false );
20
+
21
+ if ( is_string( $local_path ) ) {
22
+ $icons = array( $local_path );
23
+ } else {
24
+ global $fs_active_plugins;
25
+
26
+ $img_dir = WP_FS__DIR_IMG;
27
+
28
+ if ( 1 < count( $fs_active_plugins->plugins ) ) {
29
+ $plugin_or_theme_img_dir = ( $fs->is_plugin() ? WP_PLUGIN_DIR : get_theme_root() );
30
+
31
+ foreach ( $fs_active_plugins->plugins as $sdk_path => &$data ) {
32
+ if ( $data->plugin_path == $fs->get_plugin_basename() ) {
33
+ $img_dir = $plugin_or_theme_img_dir
34
+ . '/'
35
+ . str_replace( '../themes/', '', $sdk_path )
36
+ . '/assets/img';
37
+
38
+ break;
39
+ }
40
+ }
41
+ }
42
+
43
+ if ( $fs->is_theme() ) {
44
+ $icons = array(
45
+ fs_normalize_path( $img_dir . '/theme-icon.png' )
46
+ );
47
+ } else {
48
+ $icons = glob( fs_normalize_path( $img_dir . '/' . $slug . '.*' ) );
49
+ if ( ! is_array( $icons ) || 0 === count( $icons ) ) {
50
+ $icon_found = false;
51
+ $local_path = fs_normalize_path( $img_dir . '/' . $slug . '.png' );
52
+
53
+ $have_write_permissions = ( 'direct' === get_filesystem_method( array(), fs_normalize_path( $img_dir ) ) );
54
+
55
+ if ( WP_FS__IS_LOCALHOST && $fs->is_org_repo_compliant() && $have_write_permissions ) {
56
+ /**
57
+ * IMPORTANT: THIS CODE WILL NEVER RUN AFTER THE PLUGIN IS IN THE REPO.
58
+ *
59
+ * This code will only be executed once during the testing
60
+ * of the plugin in a local environment. The plugin icon file WILL
61
+ * already exist in the assets folder when the plugin is deployed to
62
+ * the repository.
63
+ */
64
+ if ( ! function_exists( 'plugins_api' ) ) {
65
+ require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
66
+ }
67
+
68
+ $plugin_information = plugins_api( 'plugin_information', array(
69
+ 'slug' => $slug,
70
+ 'fields' => array(
71
+ 'sections' => false,
72
+ 'tags' => false,
73
+ 'icons' => true
74
+ )
75
+ ) );
76
+
77
+ if (
78
+ ! is_wp_error( $plugin_information )
79
+ && isset( $plugin_information->icons )
80
+ && ! empty( $plugin_information->icons )
81
+ ) {
82
+ /**
83
+ * Get the smallest icon.
84
+ *
85
+ * @author Leo Fajardo (@leorw)
86
+ * @since 1.2.2
87
+ */
88
+ $icon = end( $plugin_information->icons );
89
+
90
+ if ( 0 !== strpos( $icon, 'http' ) ) {
91
+ $icon = 'http:' . $icon;
92
+ }
93
+
94
+ /**
95
+ * Get a clean file extension, e.g.: "jpg" and not "jpg?rev=1305765".
96
+ *
97
+ * @author Leo Fajardo (@leorw)
98
+ * @since 1.2.2
99
+ */
100
+ $ext = pathinfo( strtok( $icon, '?' ), PATHINFO_EXTENSION );
101
+
102
+ $local_path = fs_normalize_path( $img_dir . '/' . $slug . '.' . $ext );
103
+
104
+ // Try to download the icon.
105
+ $icon_found = fs_download_image( $icon, $local_path );
106
+ }
107
+ }
108
+
109
+ if ( ! $icon_found ) {
110
+ // No icons found, fallback to default icon.
111
+ if ( $have_write_permissions ) {
112
+ // If have write permissions, copy default icon.
113
+ copy( fs_normalize_path( $img_dir . '/plugin-icon.png' ), $local_path );
114
+ } else {
115
+ // If doesn't have write permissions, use default icon path.
116
+ $local_path = fs_normalize_path( $img_dir . '/plugin-icon.png' );
117
+ }
118
+ }
119
+
120
+ $icons = array( $local_path );
121
+ }
122
+ }
123
+ }
124
+
125
+ $icon_dir = dirname( $icons[0] );
126
+ $relative_url = fs_img_url( substr( $icons[0], strlen( $icon_dir ) ), $icon_dir );
127
+ ?>
128
+ <div class="fs-plugin-icon">
129
+ <img src="<?php echo $relative_url ?>" width="80" height="80"/>
130
  </div>
freemius/templates/plugin-info/description.php CHANGED
@@ -1,78 +1,78 @@
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.6
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * @var array $VARS
15
- *
16
- * @var FS_Plugin $plugin
17
- */
18
- $plugin = $VARS['plugin'];
19
-
20
- if ( ! empty( $plugin->info->selling_point_0 ) ||
21
- ! empty( $plugin->info->selling_point_1 ) ||
22
- ! empty( $plugin->info->selling_point_2 )
23
- ) : ?>
24
- <div class="fs-selling-points">
25
- <ul>
26
- <?php for ( $i = 0; $i < 3; $i ++ ) : ?>
27
- <?php if ( ! empty( $plugin->info->{'selling_point_' . $i} ) ) : ?>
28
- <li><i class="dashicons dashicons-yes"></i>
29
-
30
- <h3><?php echo esc_html( $plugin->info->{'selling_point_' . $i} ) ?></h3></li>
31
- <?php endif ?>
32
- <?php endfor ?>
33
- </ul>
34
- </div>
35
- <?php endif ?>
36
- <div>
37
- <?php
38
- echo wp_kses( $plugin->info->description, array(
39
- 'a' => array( 'href' => array(), 'title' => array(), 'target' => array() ),
40
- 'b' => array(),
41
- 'i' => array(),
42
- 'p' => array(),
43
- 'blockquote' => array(),
44
- 'h2' => array(),
45
- 'h3' => array(),
46
- 'ul' => array(),
47
- 'ol' => array(),
48
- 'li' => array()
49
- ) );
50
- ?>
51
- </div>
52
- <?php if ( ! empty( $plugin->info->screenshots ) ) : ?>
53
- <?php $screenshots = $plugin->info->screenshots ?>
54
- <div class="fs-screenshots clearfix">
55
- <h2><?php fs_esc_html_echo_inline( 'Screenshots', 'screenshots', $plugin->slug ) ?></h2>
56
- <ul>
57
- <?php $i = 0;
58
- foreach ( $screenshots as $s => $url ) : ?>
59
- <?php
60
- // Relative URLs are replaced with WordPress.org base URL
61
- // therefore we need to set absolute URLs.
62
- $url = 'http' . ( WP_FS__IS_HTTPS ? 's' : '' ) . ':' . $url;
63
- ?>
64
- <li class="<?php echo ( 0 === $i % 2 ) ? 'odd' : 'even' ?>">
65
- <style>
66
- #section-description .fs-screenshots <?php echo ".fs-screenshot-{$i}" ?>
67
- {
68
- background-image: url('<?php echo $url ?>');
69
- }
70
- </style>
71
- <a href="<?php echo $url ?>"
72
- title="<?php echo esc_attr( sprintf( fs_text_inline( 'Click to view full-size screenshot %d', 'view-full-size-x', $plugin->slug ), $i ) ) ?>"
73
- class="fs-screenshot-<?php echo $i ?>"></a>
74
- </li>
75
- <?php $i ++; endforeach ?>
76
- </ul>
77
- </div>
78
  <?php endif ?>
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.6
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * @var array $VARS
15
+ *
16
+ * @var FS_Plugin $plugin
17
+ */
18
+ $plugin = $VARS['plugin'];
19
+
20
+ if ( ! empty( $plugin->info->selling_point_0 ) ||
21
+ ! empty( $plugin->info->selling_point_1 ) ||
22
+ ! empty( $plugin->info->selling_point_2 )
23
+ ) : ?>
24
+ <div class="fs-selling-points">
25
+ <ul>
26
+ <?php for ( $i = 0; $i < 3; $i ++ ) : ?>
27
+ <?php if ( ! empty( $plugin->info->{'selling_point_' . $i} ) ) : ?>
28
+ <li><i class="dashicons dashicons-yes"></i>
29
+
30
+ <h3><?php echo esc_html( $plugin->info->{'selling_point_' . $i} ) ?></h3></li>
31
+ <?php endif ?>
32
+ <?php endfor ?>
33
+ </ul>
34
+ </div>
35
+ <?php endif ?>
36
+ <div>
37
+ <?php
38
+ echo wp_kses( $plugin->info->description, array(
39
+ 'a' => array( 'href' => array(), 'title' => array(), 'target' => array() ),
40
+ 'b' => array(),
41
+ 'i' => array(),
42
+ 'p' => array(),
43
+ 'blockquote' => array(),
44
+ 'h2' => array(),
45
+ 'h3' => array(),
46
+ 'ul' => array(),
47
+ 'ol' => array(),
48
+ 'li' => array()
49
+ ) );
50
+ ?>
51
+ </div>
52
+ <?php if ( ! empty( $plugin->info->screenshots ) ) : ?>
53
+ <?php $screenshots = $plugin->info->screenshots ?>
54
+ <div class="fs-screenshots clearfix">
55
+ <h2><?php fs_esc_html_echo_inline( 'Screenshots', 'screenshots', $plugin->slug ) ?></h2>
56
+ <ul>
57
+ <?php $i = 0;
58
+ foreach ( $screenshots as $s => $url ) : ?>
59
+ <?php
60
+ // Relative URLs are replaced with WordPress.org base URL
61
+ // therefore we need to set absolute URLs.
62
+ $url = 'http' . ( WP_FS__IS_HTTPS ? 's' : '' ) . ':' . $url;
63
+ ?>
64
+ <li class="<?php echo ( 0 === $i % 2 ) ? 'odd' : 'even' ?>">
65
+ <style>
66
+ #section-description .fs-screenshots <?php echo ".fs-screenshot-{$i}" ?>
67
+ {
68
+ background-image: url('<?php echo $url ?>');
69
+ }
70
+ </style>
71
+ <a href="<?php echo $url ?>"
72
+ title="<?php echo esc_attr( sprintf( fs_text_inline( 'Click to view full-size screenshot %d', 'view-full-size-x', $plugin->slug ), $i ) ) ?>"
73
+ class="fs-screenshot-<?php echo $i ?>"></a>
74
+ </li>
75
+ <?php $i ++; endforeach ?>
76
+ </ul>
77
+ </div>
78
  <?php endif ?>
freemius/templates/plugin-info/features.php CHANGED
@@ -1,114 +1,114 @@
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.6
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * @var array $VARS
15
- *
16
- * @var FS_Plugin $plugin
17
- */
18
- $plugin = $VARS['plugin'];
19
-
20
- $plans = $VARS['plans'];
21
-
22
- $features_plan_map = array();
23
- foreach ( $plans as $plan ) {
24
- if (!empty($plan->features) && is_array($plan->features)) {
25
- foreach ( $plan->features as $feature ) {
26
- if ( ! isset( $features_plan_map[ $feature->id ] ) ) {
27
- $features_plan_map[ $feature->id ] = array( 'feature' => $feature, 'plans' => array() );
28
- }
29
-
30
- $features_plan_map[ $feature->id ]['plans'][ $plan->id ] = $feature;
31
- }
32
- }
33
-
34
- // Add support as a feature.
35
- if ( ! empty( $plan->support_email ) ||
36
- ! empty( $plan->support_skype ) ||
37
- ! empty( $plan->support_phone ) ||
38
- true === $plan->is_success_manager
39
- ) {
40
- if ( ! isset( $features_plan_map['support'] ) ) {
41
- $support_feature = new stdClass();
42
- $support_feature->id = 'support';
43
- $support_feature->title = fs_text_inline( 'Support', $plugin->slug );
44
- $features_plan_map[ $support_feature->id ] = array( 'feature' => $support_feature, 'plans' => array() );
45
- } else {
46
- $support_feature = $features_plan_map['support'];
47
- }
48
-
49
- $features_plan_map[ $support_feature->id ]['plans'][ $plan->id ] = $support_feature;
50
- }
51
- }
52
-
53
- // Add updates as a feature for all plans.
54
- $updates_feature = new stdClass();
55
- $updates_feature->id = 'updates';
56
- $updates_feature->title = fs_text_inline( 'Unlimited Updates', 'unlimited-updates', $plugin->slug );
57
- $features_plan_map[ $updates_feature->id ] = array( 'feature' => $updates_feature, 'plans' => array() );
58
- foreach ( $plans as $plan ) {
59
- $features_plan_map[ $updates_feature->id ]['plans'][ $plan->id ] = $updates_feature;
60
- }
61
- ?>
62
- <div class="fs-features">
63
- <table>
64
- <thead>
65
- <tr>
66
- <th></th>
67
- <?php foreach ( $plans as $plan ) : ?>
68
- <th>
69
- <?php echo $plan->title ?>
70
- <span class="fs-price"><?php
71
- if ( empty( $plan->pricing ) ) {
72
- fs_esc_html_echo_inline( 'Free', 'free', $plugin->slug );
73
- } else {
74
- foreach ( $plan->pricing as $pricing ) {
75
- /**
76
- * @var FS_Pricing $pricing
77
- */
78
- if ( 1 == $pricing->licenses ) {
79
- if ( $pricing->has_annual() ) {
80
- echo "\${$pricing->annual_price} / " . fs_esc_html_x_inline( 'year', 'as annual period', 'year', $plugin->slug );
81
- } else if ( $pricing->has_monthly() ) {
82
- echo "\${$pricing->monthly_price} / " . fs_esc_html_x_inline( 'mo', 'as monthly period', 'mo', $plugin->slug );
83
- } else {
84
- echo "\${$pricing->lifetime_price}";
85
- }
86
- }
87
- }
88
- }
89
- ?></span>
90
- </th>
91
- <?php endforeach ?>
92
- </tr>
93
- </thead>
94
- <tbody>
95
- <?php $odd = true;
96
- foreach ( $features_plan_map as $feature_id => $data ) : ?>
97
- <tr class="fs-<?php echo $odd ? 'odd' : 'even' ?>">
98
- <td><?php echo esc_html( ucfirst( $data['feature']->title ) ) ?></td>
99
- <?php foreach ( $plans as $plan ) : ?>
100
- <td>
101
- <?php if ( isset( $data['plans'][ $plan->id ] ) ) : ?>
102
- <?php if ( ! empty( $data['plans'][ $plan->id ]->value ) ) : ?>
103
- <b><?php echo esc_html( $data['plans'][ $plan->id ]->value ) ?></b>
104
- <?php else : ?>
105
- <i class="dashicons dashicons-yes"></i>
106
- <?php endif ?>
107
- <?php endif ?>
108
- </td>
109
- <?php endforeach ?>
110
- </tr>
111
- <?php $odd = ! $odd; endforeach ?>
112
- </tbody>
113
- </table>
114
  </div>
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.6
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * @var array $VARS
15
+ *
16
+ * @var FS_Plugin $plugin
17
+ */
18
+ $plugin = $VARS['plugin'];
19
+
20
+ $plans = $VARS['plans'];
21
+
22
+ $features_plan_map = array();
23
+ foreach ( $plans as $plan ) {
24
+ if (!empty($plan->features) && is_array($plan->features)) {
25
+ foreach ( $plan->features as $feature ) {
26
+ if ( ! isset( $features_plan_map[ $feature->id ] ) ) {
27
+ $features_plan_map[ $feature->id ] = array( 'feature' => $feature, 'plans' => array() );
28
+ }
29
+
30
+ $features_plan_map[ $feature->id ]['plans'][ $plan->id ] = $feature;
31
+ }
32
+ }
33
+
34
+ // Add support as a feature.
35
+ if ( ! empty( $plan->support_email ) ||
36
+ ! empty( $plan->support_skype ) ||
37
+ ! empty( $plan->support_phone ) ||
38
+ true === $plan->is_success_manager
39
+ ) {
40
+ if ( ! isset( $features_plan_map['support'] ) ) {
41
+ $support_feature = new stdClass();
42
+ $support_feature->id = 'support';
43
+ $support_feature->title = fs_text_inline( 'Support', $plugin->slug );
44
+ $features_plan_map[ $support_feature->id ] = array( 'feature' => $support_feature, 'plans' => array() );
45
+ } else {
46
+ $support_feature = $features_plan_map['support'];
47
+ }
48
+
49
+ $features_plan_map[ $support_feature->id ]['plans'][ $plan->id ] = $support_feature;
50
+ }
51
+ }
52
+
53
+ // Add updates as a feature for all plans.
54
+ $updates_feature = new stdClass();
55
+ $updates_feature->id = 'updates';
56
+ $updates_feature->title = fs_text_inline( 'Unlimited Updates', 'unlimited-updates', $plugin->slug );
57
+ $features_plan_map[ $updates_feature->id ] = array( 'feature' => $updates_feature, 'plans' => array() );
58
+ foreach ( $plans as $plan ) {
59
+ $features_plan_map[ $updates_feature->id ]['plans'][ $plan->id ] = $updates_feature;
60
+ }
61
+ ?>
62
+ <div class="fs-features">
63
+ <table>
64
+ <thead>
65
+ <tr>
66
+ <th></th>
67
+ <?php foreach ( $plans as $plan ) : ?>
68
+ <th>
69
+ <?php echo $plan->title ?>
70
+ <span class="fs-price"><?php
71
+ if ( empty( $plan->pricing ) ) {
72
+ fs_esc_html_echo_inline( 'Free', 'free', $plugin->slug );
73
+ } else {
74
+ foreach ( $plan->pricing as $pricing ) {
75
+ /**
76
+ * @var FS_Pricing $pricing
77
+ */
78
+ if ( 1 == $pricing->licenses ) {
79
+ if ( $pricing->has_annual() ) {
80
+ echo "\${$pricing->annual_price} / " . fs_esc_html_x_inline( 'year', 'as annual period', 'year', $plugin->slug );
81
+ } else if ( $pricing->has_monthly() ) {
82
+ echo "\${$pricing->monthly_price} / " . fs_esc_html_x_inline( 'mo', 'as monthly period', 'mo', $plugin->slug );
83
+ } else {
84
+ echo "\${$pricing->lifetime_price}";
85
+ }
86
+ }
87
+ }
88
+ }
89
+ ?></span>
90
+ </th>
91
+ <?php endforeach ?>
92
+ </tr>
93
+ </thead>
94
+ <tbody>
95
+ <?php $odd = true;
96
+ foreach ( $features_plan_map as $feature_id => $data ) : ?>
97
+ <tr class="fs-<?php echo $odd ? 'odd' : 'even' ?>">
98
+ <td><?php echo esc_html( ucfirst( $data['feature']->title ) ) ?></td>
99
+ <?php foreach ( $plans as $plan ) : ?>
100
+ <td>
101
+ <?php if ( isset( $data['plans'][ $plan->id ] ) ) : ?>
102
+ <?php if ( ! empty( $data['plans'][ $plan->id ]->value ) ) : ?>
103
+ <b><?php echo esc_html( $data['plans'][ $plan->id ]->value ) ?></b>
104
+ <?php else : ?>
105
+ <i class="dashicons dashicons-yes"></i>
106
+ <?php endif ?>
107
+ <?php endif ?>
108
+ </td>
109
+ <?php endforeach ?>
110
+ </tr>
111
+ <?php $odd = ! $odd; endforeach ?>
112
+ </tbody>
113
+ </table>
114
  </div>
freemius/templates/plugin-info/screenshots.php CHANGED
@@ -1,34 +1,34 @@
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.6
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) {
10
- exit;
11
- }
12
-
13
- /**
14
- * @var array $VARS
15
- *
16
- * @var FS_Plugin $plugin
17
- */
18
- $plugin = $VARS['plugin'];
19
-
20
- $screenshots = $VARS['screenshots'];
21
- ?>
22
- <ol>
23
- <?php $i = 0;
24
- foreach ( $screenshots as $s => $url ) : ?>
25
- <?php
26
- // Relative URLs are replaced with WordPress.org base URL
27
- // therefore we need to set absolute URLs.
28
- $url = 'http' . ( WP_FS__IS_HTTPS ? 's' : '' ) . ':' . $url;
29
- ?>
30
- <li>
31
- <a href="<?php echo $url ?>" title="<?php echo esc_attr( sprintf( fs_text_inline( 'Click to view full-size screenshot %d', 'view-full-size-x', $plugin->slug ), $i ) ) ?>"><img src="<?php echo $url ?>"></a>
32
- </li>
33
- <?php $i ++; endforeach ?>
34
- </ol>
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.6
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ exit;
11
+ }
12
+
13
+ /**
14
+ * @var array $VARS
15
+ *
16
+ * @var FS_Plugin $plugin
17
+ */
18
+ $plugin = $VARS['plugin'];
19
+
20
+ $screenshots = $VARS['screenshots'];
21
+ ?>
22
+ <ol>
23
+ <?php $i = 0;
24
+ foreach ( $screenshots as $s => $url ) : ?>
25
+ <?php
26
+ // Relative URLs are replaced with WordPress.org base URL
27
+ // therefore we need to set absolute URLs.
28
+ $url = 'http' . ( WP_FS__IS_HTTPS ? 's' : '' ) . ':' . $url;
29
+ ?>
30
+ <li>
31
+ <a href="<?php echo $url ?>" title="<?php echo esc_attr( sprintf( fs_text_inline( 'Click to view full-size screenshot %d', 'view-full-size-x', $plugin->slug ), $i ) ) ?>"><img src="<?php echo $url ?>"></a>
32
+ </li>
33
+ <?php $i ++; endforeach ?>
34
+ </ol>
freemius/templates/secure-https-header.php CHANGED
@@ -1,39 +1,39 @@
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.1.8
7
- *
8
- * @var array $VARS
9
- */
10
-
11
- if ( ! defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
- ?>
15
- <div class="fs-secure-notice">
16
- <i class="dashicons dashicons-lock"></i>
17
- <span><?php
18
- if ( ! empty( $VARS['message'] ) ) {
19
- echo esc_html( $VARS['message'] );
20
- } else {
21
- /**
22
- * @var Freemius $fs
23
- */
24
- $fs = freemius( $VARS['id'] );
25
-
26
- echo esc_html( sprintf(
27
- /* translators: %s: Page name */
28
- $fs->get_text_inline( 'Secure HTTPS %s page, running from an external domain', 'secure-x-page-header' ),
29
- $VARS['page']
30
- ) ) .
31
- ' - ' .
32
- sprintf(
33
- '<a class="fs-security-proof" href="%s" target="_blank">%s</a>',
34
- 'https://www.mcafeesecure.com/verify?host=' . WP_FS__ROOT_DOMAIN_PRODUCTION,
35
- 'Freemius Inc. [US]'
36
- );
37
- }
38
- ?></span>
39
  </div>
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.1.8
7
+ *
8
+ * @var array $VARS
9
+ */
10
+
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
+ ?>
15
+ <div class="fs-secure-notice">
16
+ <i class="dashicons dashicons-lock"></i>
17
+ <span><?php
18
+ if ( ! empty( $VARS['message'] ) ) {
19
+ echo esc_html( $VARS['message'] );
20
+ } else {
21
+ /**
22
+ * @var Freemius $fs
23
+ */
24
+ $fs = freemius( $VARS['id'] );
25
+
26
+ echo esc_html( sprintf(
27
+ /* translators: %s: Page name */
28
+ $fs->get_text_inline( 'Secure HTTPS %s page, running from an external domain', 'secure-x-page-header' ),
29
+ $VARS['page']
30
+ ) ) .
31
+ ' - ' .
32
+ sprintf(
33
+ '<a class="fs-security-proof" href="%s" target="_blank">%s</a>',
34
+ 'https://www.mcafeesecure.com/verify?host=' . WP_FS__ROOT_DOMAIN_PRODUCTION,
35
+ 'Freemius Inc. [US]'
36
+ );
37
+ }
38
+ ?></span>
39
  </div>
includes/admin/class-settings.php CHANGED
@@ -281,6 +281,14 @@ if ( ! class_exists( 'FooGallery_Admin_Settings' ) ) {
281
  'tab' => 'advanced'
282
  );
283
 
 
 
 
 
 
 
 
 
284
  $settings[] = array(
285
  'id' => 'enable_debugging',
286
  'title' => __( 'Enable Debugging', 'foogallery' ),
281
  'tab' => 'advanced'
282
  );
283
 
284
+ $settings[] = array(
285
+ 'id' => 'enable_legacy_thumb_cropping',
286
+ 'title' => __( 'Enable Legacy Thumb Cropping', 'foogallery' ),
287
+ 'desc' => __( 'For when you want to enable legacy cropping options in certain gallery templates. This is not recommended.', 'foogallery' ),
288
+ 'type' => 'checkbox',
289
+ 'tab' => 'advanced'
290
+ );
291
+
292
  $settings[] = array(
293
  'id' => 'enable_debugging',
294
  'title' => __( 'Enable Debugging', 'foogallery' ),
includes/class-thumbnail-dimensions.php CHANGED
@@ -91,9 +91,21 @@ if ( ! class_exists( 'FooGallery_Thumbnail_Dimensions' ) ) {
91
  $calculated_thumb_width = $thumb_width;
92
  $calculated_thumb_height = $thumb_height;
93
  } else {
94
- $size_array = image_resize_dimensions($attachment->width, $attachment->height, $thumb_width, $thumb_height, $thumb_crop);
95
- $calculated_thumb_width = $size_array[4];
96
- $calculated_thumb_height = $size_array[5];
 
 
 
 
 
 
 
 
 
 
 
 
97
  }
98
 
99
  $attachment->has_thumbnail_dimensions = true;
@@ -105,6 +117,45 @@ if ( ! class_exists( 'FooGallery_Thumbnail_Dimensions' ) ) {
105
  }
106
  }
107
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  /**
109
  * Include the thumb dimension html attributes in the rendered HTML
110
  *
91
  $calculated_thumb_width = $thumb_width;
92
  $calculated_thumb_height = $thumb_height;
93
  } else {
94
+ $size_array = image_resize_dimensions( $attachment->width, $attachment->height, $thumb_width, $thumb_height, $thumb_crop );
95
+ if ( false !== $size_array ) {
96
+ $calculated_thumb_width = $size_array[4];
97
+ $calculated_thumb_height = $size_array[5];
98
+ } else {
99
+ $size_array = $this->calculate_dimensions( $attachment->width, $attachment->height, $thumb_width, $thumb_height );
100
+ if ( false !== $size_array ) {
101
+ $calculated_thumb_width = $size_array[0];
102
+ $calculated_thumb_height = $size_array[1];
103
+ } else {
104
+ //fallback for when we cannot calculate dimensions. Use the originals
105
+ $calculated_thumb_width = $attachment->width;
106
+ $calculated_thumb_height = $attachment->height;
107
+ }
108
+ }
109
  }
110
 
111
  $attachment->has_thumbnail_dimensions = true;
117
  }
118
  }
119
 
120
+ /**
121
+ * Returns a resized width and height value given the original dimensions and then either the new width or height value, one can be 0.
122
+ *
123
+ * @param {int} $orig_width - The original width of the image.
124
+ * @param {int} $orig_height - The original height of the image.
125
+ * @param {int} $new_width - The new width for the image or 0 to calculate it from the supplied new height and original dimensions.
126
+ * @param {int} $new_height - The new height for the image or 0 to calculate it from the supplied new width and original dimensions.
127
+ *
128
+ * @return array|false - Returns an array with the width value at index 0 and the height value at index 1.
129
+ * Returns false if the original dimensions are invalid or if both the new width and height are invalid.
130
+ *
131
+ * @example
132
+ *
133
+ * $size_1 = calculate_dimensions(800, 600, 0, 300); // => [400, 300]
134
+ *
135
+ * $size_2 = calculate_dimensions(800, 600, 400, 0); // => [400, 300]
136
+ */
137
+ function calculate_dimensions($orig_width, $orig_height, $new_width, $new_height){
138
+ // if we have an invalid original size provided exit early and return false
139
+ if (!is_numeric($orig_width) || $orig_width === 0 || !is_numeric($orig_height) || $orig_height === 0){
140
+ return false;
141
+ }
142
+ $needs_width = !is_numeric($new_width) || $new_width === 0;
143
+ $needs_height = !is_numeric($new_height) || $new_height === 0;
144
+ // if we have an invalid new size provided i.e. both new values are not numbers or both are 0 then exit early and return false
145
+ if ($needs_width && $needs_height){
146
+ return false;
147
+ }
148
+ // otherwise get the ratio of the original so we can calculate any missing new values
149
+ $ratio = $orig_width / $orig_height;
150
+ if ($needs_width){
151
+ $new_width = $new_height * $ratio;
152
+ }
153
+ if ($needs_height){
154
+ $new_height = $new_width / $ratio;
155
+ }
156
+ return array($new_width, $new_height);
157
+ }
158
+
159
  /**
160
  * Include the thumb dimension html attributes in the rendered HTML
161
  *
includes/class-thumbnails.php CHANGED
@@ -109,14 +109,31 @@ if ( !class_exists( 'FooGallery_Thumbnails' ) ) {
109
  unset( $args['height'] );
110
  }
111
 
112
- //save the generated thumb url to a global so that we can use it later if needed
113
- $foogallery_last_generated_thumb_url = wpthumb( $original_image_src, $args );
114
-
115
- //TODO : get 'Force HTTPS' setting and replace all occurrences of http:// with https://
 
 
 
116
 
117
  return $foogallery_last_generated_thumb_url;
118
  }
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  function run_thumbnail_generation_tests() {
121
  $test_image_url = foogallery_test_thumb_url();
122
 
109
  unset( $args['height'] );
110
  }
111
 
112
+ //do some checks to see if the image is smaller
113
+ if ( $this->should_resize( $thumbnail_object, $args ) ) {
114
+ //save the generated thumb url to a global so that we can use it later if needed
115
+ $foogallery_last_generated_thumb_url = wpthumb( $original_image_src, $args );
116
+ } else {
117
+ $foogallery_last_generated_thumb_url = $original_image_src;
118
+ }
119
 
120
  return $foogallery_last_generated_thumb_url;
121
  }
122
 
123
+ function should_resize($thumbnail_object, $args) {
124
+ $original_width = $thumbnail_object->width;
125
+ $original_height = $thumbnail_object->height;
126
+ $new_width = isset( $args['width'] ) ? $args['width'] : 0;
127
+ $new_height = isset( $args['height'] ) ? $args['height'] : 0;
128
+
129
+ if ( $new_width > 0 && $new_height > 0 ) {
130
+ return $original_width > $new_width || $original_height > $new_height;
131
+ } else if ( $new_width > 0 ) {
132
+ return $original_width > $new_width;
133
+ }
134
+ return $original_height > $new_height;
135
+ }
136
+
137
  function run_thumbnail_generation_tests() {
138
  $test_image_url = foogallery_test_thumb_url();
139
 
includes/functions.php CHANGED
@@ -629,7 +629,10 @@ function foogallery_caption_title_source() {
629
  */
630
  function foogallery_get_caption_title_for_attachment($attachment_post, $source = false) {
631
  if ( false === $source ) {
632
- $source = foogallery_caption_title_source();
 
 
 
633
  }
634
 
635
  switch ( $source ) {
@@ -674,7 +677,10 @@ function foogallery_caption_desc_source() {
674
  */
675
  function foogallery_get_caption_desc_for_attachment($attachment_post, $source = false) {
676
  if ( false === $source ) {
677
- $source = foogallery_caption_desc_source();
 
 
 
678
  }
679
 
680
  switch ( $source ) {
629
  */
630
  function foogallery_get_caption_title_for_attachment($attachment_post, $source = false) {
631
  if ( false === $source ) {
632
+ $source = foogallery_gallery_template_setting( 'caption_title_source', false );
633
+ if ( false === $source || "none" === $source ) {
634
+ $source = foogallery_caption_title_source();
635
+ }
636
  }
637
 
638
  switch ( $source ) {
677
  */
678
  function foogallery_get_caption_desc_for_attachment($attachment_post, $source = false) {
679
  if ( false === $source ) {
680
+ $source = foogallery_gallery_template_setting( 'caption_desc_source', false );
681
+ if ( false === $source || "none" === $source ) {
682
+ $source = foogallery_caption_desc_source();
683
+ }
684
  }
685
 
686
  switch ( $source ) {
js/foogallery.admin.min.js CHANGED
@@ -1,6 +1,6 @@
1
  /*
2
  * FooGallery - The Most Intuitive and Extensible Gallery Creation and Management Tool Ever Created for WordPress
3
- * @version 1.0.25
4
  * @link
5
  * @copyright Steven Usher & Brad Vincent 2015
6
  * @license Released under the GPLv3 license.
1
  /*
2
  * FooGallery - The Most Intuitive and Extensible Gallery Creation and Management Tool Ever Created for WordPress
3
+ * @version 1.0.26
4
  * @link
5
  * @copyright Steven Usher & Brad Vincent 2015
6
  * @license Released under the GPLv3 license.