Google Maps Plugin by Intergeo - Version 2.3.0

Version Description

  • 2019-03-07
Download this release

Release Info

Developer codeinwp
Plugin Icon 128x128 Google Maps Plugin by Intergeo
Version 2.3.0
Comparing to
See all releases

Code changes from version 2.2.4 to 2.3.0

Files changed (53) hide show
  1. CHANGELOG.md +7 -0
  2. css/frontend.css +1 -1
  3. css/library.css +7 -0
  4. index.php +13 -4
  5. js/rendering.js +34 -0
  6. readme.md +7 -12
  7. readme.txt +7 -12
  8. templates/iframe/directions.php +2 -3
  9. templates/iframe/extra.php +4 -4
  10. templates/iframe/form.php +5 -5
  11. templates/iframe/layers.php +2 -3
  12. templates/iframe/overlays.php +17 -17
  13. templates/iframe/popups.php +2 -2
  14. templates/library/list.php +83 -83
  15. themeisle-hash.json +1 -1
  16. vendor/autoload.php +1 -1
  17. vendor/codeinwp/themeisle-sdk/CHANGELOG.md +42 -0
  18. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-endpoints.php +0 -312
  19. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback-deactivate.php +0 -556
  20. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback-factory.php +0 -50
  21. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback-review.php +0 -209
  22. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback-translate.php +0 -983
  23. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback.php +0 -90
  24. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-licenser.php +0 -686
  25. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-loader.php +0 -96
  26. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-logger.php +0 -227
  27. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-notification-manager.php +0 -105
  28. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-product.php +0 -635
  29. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-rollback.php +0 -223
  30. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-widget-dashboard-blog.php +0 -412
  31. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-widget.php +0 -50
  32. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-widgets-factory.php +0 -37
  33. vendor/codeinwp/themeisle-sdk/composer.json +0 -24
  34. vendor/codeinwp/themeisle-sdk/index.php +2 -4
  35. vendor/codeinwp/themeisle-sdk/load.php +17 -3
  36. vendor/codeinwp/themeisle-sdk/src/Common/Abstract_module.php +66 -0
  37. vendor/codeinwp/themeisle-sdk/src/Common/Module_factory.php +108 -0
  38. vendor/codeinwp/themeisle-sdk/src/Loader.php +126 -0
  39. vendor/codeinwp/themeisle-sdk/src/Modules/Dashboard_widget.php +464 -0
  40. vendor/codeinwp/themeisle-sdk/src/Modules/Endpoint.php +358 -0
  41. vendor/codeinwp/themeisle-sdk/src/Modules/Licenser.php +719 -0
  42. vendor/codeinwp/themeisle-sdk/src/Modules/Logger.php +177 -0
  43. vendor/codeinwp/themeisle-sdk/src/Modules/Notification.php +456 -0
  44. vendor/codeinwp/themeisle-sdk/src/Modules/Recommendation.php +374 -0
  45. vendor/codeinwp/themeisle-sdk/src/Modules/Review.php +117 -0
  46. vendor/codeinwp/themeisle-sdk/src/Modules/Rollback.php +376 -0
  47. vendor/codeinwp/themeisle-sdk/src/Modules/Translate.php +918 -0
  48. vendor/codeinwp/themeisle-sdk/src/Modules/Uninstall_feedback.php +728 -0
  49. vendor/codeinwp/themeisle-sdk/src/Product.php +396 -0
  50. vendor/codeinwp/themeisle-sdk/start.php +32 -21
  51. vendor/composer/autoload_files.php +0 -1
  52. vendor/composer/autoload_real.php +5 -5
  53. vendor/composer/installed.json +12 -12
CHANGELOG.md CHANGED
@@ -1,4 +1,11 @@
1
 
 
 
 
 
 
 
 
2
  ### v2.2.4 - 2018-12-06
3
  **Changes:**
4
  * Fixed problem with Custom Styles option not working
1
 
2
+ ### v2.3.0 - 2019-03-07
3
+ **Changes:**
4
+
5
+ ### v2.3.0 - 2019-03-07
6
+ **Changes:**
7
+ * Develop
8
+
9
  ### v2.2.4 - 2018-12-06
10
  **Changes:**
11
  * Fixed problem with Custom Styles option not working
css/frontend.css CHANGED
@@ -1,5 +1,5 @@
1
  /*
2
- * Version: 2.2.4
3
  */
4
 
5
  .intergeo_map_canvas img {
1
  /*
2
+ * Version: 2.3.0
3
  */
4
 
5
  .intergeo_map_canvas img {
css/library.css CHANGED
@@ -107,7 +107,14 @@
107
  width: 84%;
108
  }
109
 
 
 
 
 
 
 
110
  .intergeo_sidebar_right {
 
111
  float: right;
112
  width: 16%;
113
  }
107
  width: 84%;
108
  }
109
 
110
+ .intergeo_sidebar_right h2{
111
+
112
+ margin: 0px;
113
+ margin-bottom: 30px;
114
+ font-size: 1.5em;
115
+ }
116
  .intergeo_sidebar_right {
117
+
118
  float: right;
119
  width: 16%;
120
  }
index.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
  /**
3
  *
4
- * Plugin Name: Intergeo - Google Maps Plugin - Lite
5
  * Plugin URI: http://themeisle.com/plugins/intergeo-maps-lite/
6
  * Description: A simple, easy and quite powerful Google Map tool to create, manage and embed custom Google Maps into your WordPress posts and pages. The plugin allows you to deeply customize look and feel of a map, add overlays like markers, rectangles, circles, polylines and polygons to your map. It could even be integraded with your Google Adsense account and show ad on your maps.
7
- * Version: 2.2.4
8
  * Author: Themeisle
9
  * Author URI: http://themeisle.com
10
  * License: GPL v2.0 or later
@@ -16,7 +16,8 @@
16
  */
17
 
18
  define( 'INTERGEO_PLUGIN_NAME', 'intergeo' );
19
- define( 'INTERGEO_VERSION', '2.2.4' );
 
20
  define( 'INTERGEO_ABSPATH', dirname( __FILE__ ) );
21
  define( 'INTERGEO_ABSURL', plugins_url( '/', __FILE__ ) );
22
  defined( 'WPLANG' ) || define( 'WPLANG', '' );
@@ -106,7 +107,6 @@ function intergeo_settings() {
106
  <h2>
107
  <div id="intergeo_lbrr_ttl">Inter<span style="color:#4067dc">g</span><span style="color:#e21b31">e</span><span style="color:#fcaa08">o</span>' . __( 'Maps Settings', 'intergeo-maps' ) . '</div> ';
108
  echo '<a href="' . admin_url( 'upload.php?page=' . INTERGEO_PLUGIN_NAME ) . '" class="add-new-h2">' . __( 'Create New Map', 'intergeo-maps' ) . '</a>';
109
- echo '<a target="_blank" href="' . INTERGEO_PRO_URL . '" class="intergeo-pro-btn add-new-h2">' . __( 'Buy PRO version to add more maps', 'intergeo-maps' ) . '</a>';
110
 
111
  echo '<a id="intergeo_lbrr_settings" href="' . admin_url( 'upload.php?page=' . INTERGEO_PLUGIN_NAME ) . '" class="add-new-h2">' . __( 'View Existing Maps', 'intergeo-maps' ) . '</a>
112
  </h2>';
@@ -1477,3 +1477,12 @@ function intergeo_register_parrot( $plugins ) {
1477
  $plugins[] = INTERGEO_PLUGIN_NAME;
1478
  return $plugins;
1479
  }
 
 
 
 
 
 
 
 
 
1
  <?php
2
  /**
3
  *
4
+ * Plugin Name: Intergeo - Google Maps Plugin
5
  * Plugin URI: http://themeisle.com/plugins/intergeo-maps-lite/
6
  * Description: A simple, easy and quite powerful Google Map tool to create, manage and embed custom Google Maps into your WordPress posts and pages. The plugin allows you to deeply customize look and feel of a map, add overlays like markers, rectangles, circles, polylines and polygons to your map. It could even be integraded with your Google Adsense account and show ad on your maps.
7
+ * Version: 2.3.0
8
  * Author: Themeisle
9
  * Author URI: http://themeisle.com
10
  * License: GPL v2.0 or later
16
  */
17
 
18
  define( 'INTERGEO_PLUGIN_NAME', 'intergeo' );
19
+ define( 'TI_INTERGEO_PLUGIN_NAME', 'intergeo_maps' );
20
+ define( 'INTERGEO_VERSION', '2.3.0' );
21
  define( 'INTERGEO_ABSPATH', dirname( __FILE__ ) );
22
  define( 'INTERGEO_ABSURL', plugins_url( '/', __FILE__ ) );
23
  defined( 'WPLANG' ) || define( 'WPLANG', '' );
107
  <h2>
108
  <div id="intergeo_lbrr_ttl">Inter<span style="color:#4067dc">g</span><span style="color:#e21b31">e</span><span style="color:#fcaa08">o</span>' . __( 'Maps Settings', 'intergeo-maps' ) . '</div> ';
109
  echo '<a href="' . admin_url( 'upload.php?page=' . INTERGEO_PLUGIN_NAME ) . '" class="add-new-h2">' . __( 'Create New Map', 'intergeo-maps' ) . '</a>';
 
110
 
111
  echo '<a id="intergeo_lbrr_settings" href="' . admin_url( 'upload.php?page=' . INTERGEO_PLUGIN_NAME ) . '" class="add-new-h2">' . __( 'View Existing Maps', 'intergeo-maps' ) . '</a>
112
  </h2>';
1477
  $plugins[] = INTERGEO_PLUGIN_NAME;
1478
  return $plugins;
1479
  }
1480
+
1481
+
1482
+ add_filter( TI_INTERGEO_PLUGIN_NAME . '_enqueue_recommend', 'intergeo_upsell_plugins', 10, 2 );
1483
+ /**
1484
+ * Validates the correct screen on which the assets for upsell should be loaded.
1485
+ */
1486
+ function intergeo_upsell_plugins( $return, $screen_id ) {
1487
+ return $screen_id === 'media_page_intergeo';
1488
+ }
js/rendering.js CHANGED
@@ -2,6 +2,8 @@
2
  /* global google */
3
  /* global alert */
4
  //noinspection JSUnresolvedVariable
 
 
5
  (function (c, b) {
6
  var a = function (d, f) {
7
  var e = this;
@@ -356,6 +358,33 @@
356
  });
357
  });
358
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
359
  a.prototype.render = function () {
360
  var d = this,
361
  j = d.options.layer || {},
@@ -401,6 +430,11 @@
401
  if (d.options.overlays) {
402
  d._renderOverlays();
403
  }
 
 
 
 
 
404
  if (d.options.directions) {
405
  d._renderDirections();
406
  }
2
  /* global google */
3
  /* global alert */
4
  //noinspection JSUnresolvedVariable
5
+ /* jshint ignore:start */
6
+
7
  (function (c, b) {
8
  var a = function (d, f) {
9
  var e = this;
358
  });
359
  });
360
  };
361
+ a.prototype.drawImportedMarkers = function() {
362
+ var e = this;
363
+ var map = e.map;
364
+ var infoWindow = new b.InfoWindow();
365
+ b.event.addListener(map, 'click', function () {
366
+ infoWindow.close();
367
+ });
368
+
369
+ downloadUrl(e.options.xml, function (data) {
370
+ var markers = data.documentElement.getElementsByTagName("marker");
371
+ for (var i = 0; i < markers.length; i++) {
372
+ var latlng = new b.LatLng(parseFloat(markers[i].getAttribute("lat")),
373
+ parseFloat(markers[i].getAttribute("lng")));
374
+ var name = markers[i].getAttribute("name");
375
+ var icon = markers[i].getAttribute("icon");
376
+ var marker = new b.Marker({ position: latlng, map: map });
377
+ marker.setIcon(icon);
378
+ e.bindInfoWindow(marker, map, infoWindow, name);
379
+ }
380
+ });
381
+ };
382
+ a.prototype.bindInfoWindow = function(marker, map, infowindow, html) {
383
+ b.event.addListener(marker, 'click', function () {
384
+ infowindow.setContent(html);
385
+ infowindow.open(map, marker);
386
+ });
387
+ };
388
  a.prototype.render = function () {
389
  var d = this,
390
  j = d.options.layer || {},
430
  if (d.options.overlays) {
431
  d._renderOverlays();
432
  }
433
+
434
+ if(d.options.layer.importcsv == 1){
435
+ d.drawImportedMarkers();
436
+ }
437
+
438
  if (d.options.directions) {
439
  d._renderDirections();
440
  }
readme.md CHANGED
@@ -2,7 +2,7 @@
2
  **Contributors:** [codeinwp](https://profiles.wordpress.org/codeinwp), [intergeomaps](https://profiles.wordpress.org/intergeomaps), [hardeepasrani](https://profiles.wordpress.org/hardeepasrani), [themeisle](https://profiles.wordpress.org/themeisle), [Madalin_ThemeIsle](https://profiles.wordpress.org/Madalin_ThemeIsle), [uriahs-victor](https://profiles.wordpress.org/uriahs-victor), [contactashish13](https://profiles.wordpress.org/contactashish13)
3
  **Tags:** directions, easy map, google, google map, google map plugin, google maps, latitude, location, longitude, map, map directions, map markers, map plugin, map widget, maps, marker, polygons, polylines, routes, store locator, streetview, wp google map, wp google maps, wp maps,plugin,admin,widget,shortcode,google maps, maps, map, map markers, google, google map, maps api, wp maps, wp google maps, easy map, embed, marker, placemark, icon, geocode, shortcode, custom post type, multisite, marker clustering
4
  **Requires at least:** 3.5
5
- **Tested up to:** 5.0
6
  **Stable tag:** trunk
7
  **License:** GPL v2.0 or later
8
  **License URI:** http://www.opensource.org/licenses/gpl-license.php
@@ -23,17 +23,6 @@ The powerful UI builder allows users to:
23
  * Setup map color styles by using predefined color schemes or by using custom color settings;
24
  * Add markers;
25
 
26
- > **Time-saving features available in the FULL version:**
27
- >
28
- > * Add overlays like rectangles, circles, polylines and polygons using the build or the drawing tools;
29
- > * Create directions routes from A address to B address;
30
- > * Integrate AdSense service into your maps and earn money by displaying ads on maps.
31
- > * Import/Export Markers
32
- > * Custom Layers
33
- > * Support and updates for 12 months
34
- >
35
- > **[Learn more about Intergeo Maps Pro version]( https://themeisle.com/plugins/intergeo-maps/ )**
36
-
37
 
38
  ### Create Google maps with shortcode ###
39
 
@@ -128,6 +117,12 @@ function filter_intergeo_map_settings( $options ) {
128
  }`
129
 
130
  ## Changelog ##
 
 
 
 
 
 
131
  ### 2.2.4 - 2018-12-06 ###
132
 
133
  * Fixed problem with Custom Styles option not working
2
  **Contributors:** [codeinwp](https://profiles.wordpress.org/codeinwp), [intergeomaps](https://profiles.wordpress.org/intergeomaps), [hardeepasrani](https://profiles.wordpress.org/hardeepasrani), [themeisle](https://profiles.wordpress.org/themeisle), [Madalin_ThemeIsle](https://profiles.wordpress.org/Madalin_ThemeIsle), [uriahs-victor](https://profiles.wordpress.org/uriahs-victor), [contactashish13](https://profiles.wordpress.org/contactashish13)
3
  **Tags:** directions, easy map, google, google map, google map plugin, google maps, latitude, location, longitude, map, map directions, map markers, map plugin, map widget, maps, marker, polygons, polylines, routes, store locator, streetview, wp google map, wp google maps, wp maps,plugin,admin,widget,shortcode,google maps, maps, map, map markers, google, google map, maps api, wp maps, wp google maps, easy map, embed, marker, placemark, icon, geocode, shortcode, custom post type, multisite, marker clustering
4
  **Requires at least:** 3.5
5
+ **Tested up to:** 5.1
6
  **Stable tag:** trunk
7
  **License:** GPL v2.0 or later
8
  **License URI:** http://www.opensource.org/licenses/gpl-license.php
23
  * Setup map color styles by using predefined color schemes or by using custom color settings;
24
  * Add markers;
25
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  ### Create Google maps with shortcode ###
28
 
117
  }`
118
 
119
  ## Changelog ##
120
+ ### 2.3.0 - 2019-03-07 ###
121
+
122
+ * Adds compatibility with WordPress 5.1
123
+ * Remove occurrence of the Pro plugin, discontinue support of the Premium addon.
124
+
125
+
126
  ### 2.2.4 - 2018-12-06 ###
127
 
128
  * Fixed problem with Custom Styles option not working
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
  Contributors: codeinwp,intergeomaps,hardeepasrani,themeisle,Madalin_ThemeIsle,uriahs-victor,contactashish13
3
  Tags: directions, easy map, google, google map, google map plugin, google maps, latitude, location, longitude, map, map directions, map markers, map plugin, map widget, maps, marker, polygons, polylines, routes, store locator, streetview, wp google map, wp google maps, wp maps,plugin,admin,widget,shortcode,google maps, maps, map, map markers, google, google map, maps api, wp maps, wp google maps, easy map, embed, marker, placemark, icon, geocode, shortcode, custom post type, multisite, marker clustering
4
  Requires at least: 3.5
5
- Tested up to: 5.0
6
  Stable tag: trunk
7
  License: GPL v2.0 or later
8
  License URI: http://www.opensource.org/licenses/gpl-license.php
@@ -23,17 +23,6 @@ The powerful UI builder allows users to:
23
  * Setup map color styles by using predefined color schemes or by using custom color settings;
24
  * Add markers;
25
 
26
- > **Time-saving features available in the FULL version:**
27
- >
28
- > * Add overlays like rectangles, circles, polylines and polygons using the build or the drawing tools;
29
- > * Create directions routes from A address to B address;
30
- > * Integrate AdSense service into your maps and earn money by displaying ads on maps.
31
- > * Import/Export Markers
32
- > * Custom Layers
33
- > * Support and updates for 12 months
34
- >
35
- > **[Learn more about Intergeo Maps Pro version]( https://themeisle.com/plugins/intergeo-maps/ )**
36
-
37
 
38
  ### Create Google maps with shortcode ###
39
 
@@ -128,6 +117,12 @@ function filter_intergeo_map_settings( $options ) {
128
  }`
129
 
130
  == Changelog ==
 
 
 
 
 
 
131
  = 2.2.4 - 2018-12-06 =
132
 
133
  * Fixed problem with Custom Styles option not working
2
  Contributors: codeinwp,intergeomaps,hardeepasrani,themeisle,Madalin_ThemeIsle,uriahs-victor,contactashish13
3
  Tags: directions, easy map, google, google map, google map plugin, google maps, latitude, location, longitude, map, map directions, map markers, map plugin, map widget, maps, marker, polygons, polylines, routes, store locator, streetview, wp google map, wp google maps, wp maps,plugin,admin,widget,shortcode,google maps, maps, map, map markers, google, google map, maps api, wp maps, wp google maps, easy map, embed, marker, placemark, icon, geocode, shortcode, custom post type, multisite, marker clustering
4
  Requires at least: 3.5
5
+ Tested up to: 5.1
6
  Stable tag: trunk
7
  License: GPL v2.0 or later
8
  License URI: http://www.opensource.org/licenses/gpl-license.php
23
  * Setup map color styles by using predefined color schemes or by using custom color settings;
24
  * Add markers;
25
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  ### Create Google maps with shortcode ###
28
 
117
  }`
118
 
119
  == Changelog ==
120
+ = 2.3.0 - 2019-03-07 =
121
+
122
+ * Adds compatibility with WordPress 5.1
123
+ * Remove occurrence of the Pro plugin, discontinue support of the Premium addon.
124
+
125
+
126
  = 2.2.4 - 2018-12-06 =
127
 
128
  * Fixed problem with Custom Styles option not working
templates/iframe/directions.php CHANGED
@@ -3,10 +3,9 @@
3
  <?php
4
  if ( ! intergeo_is_developer() ) {
5
  ?>
6
- <a target="_blank" href="<?php echo INTERGEO_PRO_URL; ?>" class="intergeo-pro-btn button"><?php _e( 'Available in Developer plan', 'intergeo-maps' ); ?></a>
7
  <?php
8
  } else {
9
- ?>
10
  <li class="intergeo_tlbr_ul_li_ul_li">
11
  <p class="intergeo_tlbr_grp_dsc">
12
  <?php esc_html_e( 'To add a new direction just click the button below', 'intergeo-maps' ); ?>:
@@ -84,7 +83,7 @@
84
  <?php endif; ?>
85
  </div>
86
  </li>
87
- <?php
88
  }
89
  ?>
90
  </ul>
3
  <?php
4
  if ( ! intergeo_is_developer() ) {
5
  ?>
 
6
  <?php
7
  } else {
8
+ ?>
9
  <li class="intergeo_tlbr_ul_li_ul_li">
10
  <p class="intergeo_tlbr_grp_dsc">
11
  <?php esc_html_e( 'To add a new direction just click the button below', 'intergeo-maps' ); ?>:
83
  <?php endif; ?>
84
  </div>
85
  </li>
86
+ <?php
87
  }
88
  ?>
89
  </ul>
templates/iframe/extra.php CHANGED
@@ -1,14 +1,14 @@
1
  <li class="intergeo_tlbr_ul_li">
2
- <h3 class="intergeo_tlbr_ul_li_h3"><?php esc_html_e( 'Import/Export Markers', 'intergeo-maps' ); ?></h3>
3
  <ul class="intergeo_tlbr_ul_li_ul">
4
  <?php
5
  if ( ! intergeo_is_agency() ) {
6
- ?>
7
  <li><a target="_blank" href="<?php echo INTERGEO_PRO_URL; ?>" class="intergeo-pro-btn button"><?php _e( 'Available in Agency plan', 'intergeo-maps' ); ?></a></li>
8
- <?php
9
  } else {
10
  do_action( 'intergeo_add_upload_elements', $json );
11
  }
12
- ?>
13
  </ul>
14
  </li>
1
  <li class="intergeo_tlbr_ul_li">
2
+ <h3 class="intergeo_tlbr_ul_li_h3"><?php esc_html_e( 'Import/Export Markers', 'intergeo-maps' ); ?></h3>
3
  <ul class="intergeo_tlbr_ul_li_ul">
4
  <?php
5
  if ( ! intergeo_is_agency() ) {
6
+ ?>
7
  <li><a target="_blank" href="<?php echo INTERGEO_PRO_URL; ?>" class="intergeo-pro-btn button"><?php _e( 'Available in Agency plan', 'intergeo-maps' ); ?></a></li>
8
+ <?php
9
  } else {
10
  do_action( 'intergeo_add_upload_elements', $json );
11
  }
12
+ ?>
13
  </ul>
14
  </li>
templates/iframe/form.php CHANGED
@@ -1,5 +1,5 @@
1
  <form id="intergeo_frm"
2
- method="post"<?php echo ! $post_id ? ' origtarget="_parent" target="_parent"' : 'origtarget="self"'; ?>>
3
  <input type="hidden" id="intergeo_map_lat" name="lat"
4
  value="<?php echo isset( $json['lat'] ) ? esc_attr( $json['lat'] ) : 48.1366069; ?>">
5
  <input type="hidden" id="intergeo_map_lng" name="lng"
@@ -25,11 +25,11 @@
25
  </li>
26
  <?php
27
  if ( intergeo_is_personal() ) {
28
- ?>
29
  <li class="intergeo_tlbr_ul_li">
30
  <?php include INTERGEO_ABSPATH . '/templates/iframe/directions.php'; ?>
31
  </li>
32
- <?php
33
  }
34
  ?>
35
  <li class="intergeo_tlbr_ul_li">
@@ -37,11 +37,11 @@
37
  </li>
38
  <?php
39
  if ( intergeo_is_personal() ) {
40
- ?>
41
  <li class="intergeo_tlbr_ul_li">
42
  <?php include INTERGEO_ABSPATH . '/templates/iframe/adsense.php'; ?>
43
  </li>
44
- <?php
45
  }
46
  if ( intergeo_is_personal() ) {
47
  include INTERGEO_ABSPATH . '/templates/iframe/extra.php';
1
  <form id="intergeo_frm"
2
+ method="post"<?php echo ! $post_id ? ' origtarget="_parent" target="_parent"' : 'origtarget="self"'; ?>>
3
  <input type="hidden" id="intergeo_map_lat" name="lat"
4
  value="<?php echo isset( $json['lat'] ) ? esc_attr( $json['lat'] ) : 48.1366069; ?>">
5
  <input type="hidden" id="intergeo_map_lng" name="lng"
25
  </li>
26
  <?php
27
  if ( intergeo_is_personal() ) {
28
+ ?>
29
  <li class="intergeo_tlbr_ul_li">
30
  <?php include INTERGEO_ABSPATH . '/templates/iframe/directions.php'; ?>
31
  </li>
32
+ <?php
33
  }
34
  ?>
35
  <li class="intergeo_tlbr_ul_li">
37
  </li>
38
  <?php
39
  if ( intergeo_is_personal() ) {
40
+ ?>
41
  <li class="intergeo_tlbr_ul_li">
42
  <?php include INTERGEO_ABSPATH . '/templates/iframe/adsense.php'; ?>
43
  </li>
44
+ <?php
45
  }
46
  if ( intergeo_is_personal() ) {
47
  include INTERGEO_ABSPATH . '/templates/iframe/extra.php';
templates/iframe/layers.php CHANGED
@@ -3,10 +3,9 @@
3
  <?php
4
  if ( ! intergeo_is_developer() ) {
5
  ?>
6
- <a target="_blank" href="<?php echo INTERGEO_PRO_URL; ?>" class="intergeo-pro-btn button"><?php _e( 'Available in Developer plan', 'intergeo-maps' ); ?></a>
7
  <?php
8
  } else {
9
- ?>
10
 
11
  <li class="intergeo_tlbr_ul_li_ul_li">
12
  <span class="intergeo_tlbr_cntrl_ttl"><?php esc_html_e( 'Traffic layer', 'intergeo-maps' ); ?></span>
@@ -45,5 +44,5 @@
45
  <?php
46
  do_action( 'intergeo_add_layers', 'layers', $json );
47
  }
48
- ?>
49
  </ul>
3
  <?php
4
  if ( ! intergeo_is_developer() ) {
5
  ?>
 
6
  <?php
7
  } else {
8
+ ?>
9
 
10
  <li class="intergeo_tlbr_ul_li_ul_li">
11
  <span class="intergeo_tlbr_cntrl_ttl"><?php esc_html_e( 'Traffic layer', 'intergeo-maps' ); ?></span>
44
  <?php
45
  do_action( 'intergeo_add_layers', 'layers', $json );
46
  }
47
+ ?>
48
  </ul>
templates/iframe/overlays.php CHANGED
@@ -27,7 +27,7 @@
27
  <?php
28
  $markers = 0;
29
  if ( ! empty( $json['overlays']['marker'] ) ) :
30
- ?>
31
  <?php foreach ( $json['overlays']['marker'] as $i => $overlay ) : ?>
32
  <table class="intergeo_tlbr_cntrl_tbl intergeo_tlbr_overlay intergeo_tlbr_marker" border="0" cellspacing="0" cellpadding="0" data-table-num="<?php echo $i + 1; ?>">
33
  <tr>
@@ -36,10 +36,10 @@
36
  #<?php echo $i + 1; ?> <?php esc_html_e( 'marker', 'intergeo-maps' ); ?>
37
  <?php else : ?>
38
  <?php echo esc_html( $overlay['title'] ); ?>
39
- <?php
40
  endif;
41
- $markers ++;
42
- ?>
43
  </td>
44
  <td>
45
  <input type="hidden" class="intergeo_tlbr_marker_location" name="overlays_marker[<?php echo $i; ?>][position]" value="<?php echo esc_attr( implode( ',', $overlay['position'] ) ); ?>" data-position="<?php echo $i; ?>">
@@ -74,7 +74,7 @@ $markers ++;
74
 
75
  <?php
76
  if ( intergeo_is_personal() ) {
77
- ?>
78
  <li class="intergeo_tlbr_ul_li_ul_li">
79
  <script id="intergeo_tlbr_polyline_tmpl" type="text/html">
80
  <table class="intergeo_tlbr_cntrl_tbl intergeo_tlbr_overlay intergeo_tlbr_polyline" border="0" cellspacing="0" cellpadding="0">
@@ -106,14 +106,14 @@ if ( intergeo_is_personal() ) {
106
  </p>
107
 
108
  <div id="intergeo_tlbr_polylines">
109
- <?php
110
- if ( ! empty( $json['overlays']['polyline'] ) ) :
111
- $i = 0;
112
- foreach ( $json['overlays']['polyline'] as $overlay ) :
113
- $path = array();
114
- foreach ( $overlay['path'] as $point ) :
115
- $path[] = implode( ',', $point );
116
- endforeach;
117
  ?>
118
  <table class="intergeo_tlbr_cntrl_tbl intergeo_tlbr_overlay intergeo_tlbr_polyline" border="0" cellspacing="0" cellpadding="0">
119
  <tr>
@@ -204,7 +204,7 @@ if ( ! empty( $json['overlays']['polyline'] ) ) :
204
  foreach ( $overlay['path'] as $point ) :
205
  $path[] = implode( ',', $point );
206
  endforeach;
207
- ?>
208
  <table class="intergeo_tlbr_cntrl_tbl intergeo_tlbr_overlay intergeo_tlbr_rectangle" border="0" cellspacing="0" cellpadding="0">
209
  <tr>
210
  <td>
@@ -298,7 +298,7 @@ if ( ! empty( $json['overlays']['polyline'] ) ) :
298
  foreach ( $overlay['path'] as $point ) :
299
  $path[] = implode( ',', $point );
300
  endforeach;
301
- ?>
302
  <table class="intergeo_tlbr_cntrl_tbl intergeo_tlbr_overlay intergeo_tlbr_circle" border="0" cellspacing="0" cellpadding="0">
303
  <tr>
304
  <td>
@@ -392,7 +392,7 @@ if ( ! empty( $json['overlays']['polyline'] ) ) :
392
  foreach ( $overlay['path'] as $point ) :
393
  $path[] = implode( ',', $point );
394
  endforeach;
395
- ?>
396
  <table class="intergeo_tlbr_cntrl_tbl intergeo_tlbr_overlay intergeo_tlbr_polygon" border="0" cellspacing="0" cellpadding="0">
397
  <tr>
398
  <td>
@@ -431,7 +431,7 @@ if ( ! empty( $json['overlays']['polyline'] ) ) :
431
 
432
  </div>
433
  </li>
434
- <?php
435
  }
436
  ?>
437
  </ul>
27
  <?php
28
  $markers = 0;
29
  if ( ! empty( $json['overlays']['marker'] ) ) :
30
+ ?>
31
  <?php foreach ( $json['overlays']['marker'] as $i => $overlay ) : ?>
32
  <table class="intergeo_tlbr_cntrl_tbl intergeo_tlbr_overlay intergeo_tlbr_marker" border="0" cellspacing="0" cellpadding="0" data-table-num="<?php echo $i + 1; ?>">
33
  <tr>
36
  #<?php echo $i + 1; ?> <?php esc_html_e( 'marker', 'intergeo-maps' ); ?>
37
  <?php else : ?>
38
  <?php echo esc_html( $overlay['title'] ); ?>
39
+ <?php
40
  endif;
41
+ $markers ++;
42
+ ?>
43
  </td>
44
  <td>
45
  <input type="hidden" class="intergeo_tlbr_marker_location" name="overlays_marker[<?php echo $i; ?>][position]" value="<?php echo esc_attr( implode( ',', $overlay['position'] ) ); ?>" data-position="<?php echo $i; ?>">
74
 
75
  <?php
76
  if ( intergeo_is_personal() ) {
77
+ ?>
78
  <li class="intergeo_tlbr_ul_li_ul_li">
79
  <script id="intergeo_tlbr_polyline_tmpl" type="text/html">
80
  <table class="intergeo_tlbr_cntrl_tbl intergeo_tlbr_overlay intergeo_tlbr_polyline" border="0" cellspacing="0" cellpadding="0">
106
  </p>
107
 
108
  <div id="intergeo_tlbr_polylines">
109
+ <?php
110
+ if ( ! empty( $json['overlays']['polyline'] ) ) :
111
+ $i = 0;
112
+ foreach ( $json['overlays']['polyline'] as $overlay ) :
113
+ $path = array();
114
+ foreach ( $overlay['path'] as $point ) :
115
+ $path[] = implode( ',', $point );
116
+ endforeach;
117
  ?>
118
  <table class="intergeo_tlbr_cntrl_tbl intergeo_tlbr_overlay intergeo_tlbr_polyline" border="0" cellspacing="0" cellpadding="0">
119
  <tr>
204
  foreach ( $overlay['path'] as $point ) :
205
  $path[] = implode( ',', $point );
206
  endforeach;
207
+ ?>
208
  <table class="intergeo_tlbr_cntrl_tbl intergeo_tlbr_overlay intergeo_tlbr_rectangle" border="0" cellspacing="0" cellpadding="0">
209
  <tr>
210
  <td>
298
  foreach ( $overlay['path'] as $point ) :
299
  $path[] = implode( ',', $point );
300
  endforeach;
301
+ ?>
302
  <table class="intergeo_tlbr_cntrl_tbl intergeo_tlbr_overlay intergeo_tlbr_circle" border="0" cellspacing="0" cellpadding="0">
303
  <tr>
304
  <td>
392
  foreach ( $overlay['path'] as $point ) :
393
  $path[] = implode( ',', $point );
394
  endforeach;
395
+ ?>
396
  <table class="intergeo_tlbr_cntrl_tbl intergeo_tlbr_overlay intergeo_tlbr_polygon" border="0" cellspacing="0" cellpadding="0">
397
  <tr>
398
  <td>
431
 
432
  </div>
433
  </li>
434
+ <?php
435
  }
436
  ?>
437
  </ul>
templates/iframe/popups.php CHANGED
@@ -51,7 +51,7 @@
51
  <option value="https://maps.google.com/mapfiles/ms/icons/orange-dot.png" data-imagesrc="https://maps.google.com/mapfiles/ms/icons/orange-dot.png"><?php _e( 'Orange', 'intergeo-maps' ); ?></option>
52
  <?php
53
  if ( intergeo_is_personal() ) :
54
- ?>
55
  <option value="custom"><?php _e( 'Custom', 'intergeo-maps' ); ?></option>
56
  <?php endif; ?>
57
  </select>
@@ -75,7 +75,7 @@
75
  'quicktags' => false,
76
  )
77
  );
78
- ?>
79
  </td>
80
  </tr>
81
  <tr>
51
  <option value="https://maps.google.com/mapfiles/ms/icons/orange-dot.png" data-imagesrc="https://maps.google.com/mapfiles/ms/icons/orange-dot.png"><?php _e( 'Orange', 'intergeo-maps' ); ?></option>
52
  <?php
53
  if ( intergeo_is_personal() ) :
54
+ ?>
55
  <option value="custom"><?php _e( 'Custom', 'intergeo-maps' ); ?></option>
56
  <?php endif; ?>
57
  </select>
75
  'quicktags' => false,
76
  )
77
  );
78
+ ?>
79
  </td>
80
  </tr>
81
  <tr>
templates/library/list.php CHANGED
@@ -15,7 +15,6 @@
15
  <a id="intergeo_lbrr_add_new" href="javascript:;"
16
  class="intergeo_lbrr_add_new add-new-h2"><?php _e( 'Add New', 'intergeo-maps' ); ?></a>
17
 
18
-
19
  <a id="intergeo_lbrr_settings"
20
  href="<?php echo admin_url( 'options-general.php?page=' . INTERGEO_PLUGIN_NAME ); ?>"
21
  class="add-new-h2"><?php _e( 'Maps Settings', 'intergeo-maps' ); ?></a>
@@ -30,107 +29,108 @@
30
 
31
  <div id="intergeo_library" class="intergeo_library">
32
  <div id="intergeo_sidebar" class="intergeo_sidebar_right">
 
33
  <?php
34
- if ( ! intergeo_is_personal() ) :
35
- ?>
36
- <div class="intergeo_sidebar_pro">
37
- <h3>Extend your maps power.</h3>
38
- <ul>
39
- <li>Custom layers</li>
40
- <li>Add directions</li>
41
- <li>Adsense integrations</li>
42
- <li>Import/export markers</li>
43
- <li>Support and updates for 12 months</li>
44
- </ul>
45
- <a href="<?php echo INTERGEO_PRO_URL; ?>" target="_blank" class="btn">Upgrade Now</a>
46
- </div>
47
- <?php
48
- endif;
49
  do_action( INTERGEO_PLUGIN_NAME . '_render_subscribe_box' );
 
50
  ?>
51
  </div>
52
 
 
 
53
  <?php if ( $query->have_posts() ) : ?>
54
 
55
- <div id="intergeo_lbrr_items" class="intergeo_sidebar_left">
56
- <?php
57
  $index = 0;
58
- while ( $query->have_posts() ) :
59
- $post = $query->next_post();
60
-
61
- $id = intergeo_encode( $post->ID );
62
- $json = json_decode( $post->post_content, true );
63
-
64
- $delete_url = add_query_arg(
65
- array(
66
- 'map' => $id,
67
- 'do' => 'delete',
68
- 'noheader' => 'true',
69
- 'nonce' => wp_create_nonce( $post->ID . filter_input( INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP ) ),
70
- )
71
- );
72
 
73
- $libraries = intergeo_check_libraries( $json, $libraries );
 
74
 
75
- ?>
76
- <div class="intergeo_lbrr_item"<?php echo $index != 0 && $index % 3 == 0 ? ' style="clear:both"' : ''; ?>>
77
- <div class="intergeo_lbrr_wrapper">
78
- <div class="intergeo_lbrr_map_wrapper">
79
- <div class="intergeo_lbrr_map_loader">
80
- <div id="intergeo_map<?php echo $id; ?>" class="intergeo_lbrr_map"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  </div>
82
  </div>
83
- <table class="intergeo_lbrr_cntrls" cellspacing="0" cellpadding="0" border="0">
84
- <tr>
85
- <td>
86
- <input type="text" class="intergeo_lbrr_code"
87
- value="[intergeo id=&quot;<?php echo $id; ?>&quot;]<?php echo ! empty( $json['address'] ) ? esc_attr( $json['address'] ) : ''; ?>[/intergeo]">
88
- </td>
89
- <td class="intergeo_lbrr_item_actions">
90
- <a class="intergeo_lbrr_item_edit" href="javascript:;"
91
- title="<?php _e( 'Edit', 'intergeo-maps' ); ?>" data-map="<?php echo $id; ?>"></a>
92
- <a class="intergeo_lbrr_item_copy" href="javascript:;"
93
- title="<?php _e( 'Clone', 'intergeo-maps' ); ?>" data-map="<?php echo $id; ?>"></a>
94
- <a class="intergeo_lbrr_item_delete" href="<?php echo esc_attr( $delete_url ); ?>"
95
- title="<?php _e( 'Delete', 'intergeo-maps' ); ?>"
96
- onclick="return showNotice.warn();"></a>
97
- </td>
98
- </tr>
99
- </table>
100
- </div>
101
- </div>
102
- <script type="text/javascript">
103
- /* <![CDATA[ */
104
- window.intergeo_maps.push({
105
- container: 'intergeo_map<?php echo $id; ?>',
106
- options: <?php echo $post->post_content; ?>
107
- });
108
- /* ]]> */
109
- </script>
110
  <?php
111
 
112
  $index ++;
113
  endwhile;
114
 
115
  ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  <div style="clear:both"></div>
117
- </div>
118
- </div>
119
 
120
- <?php if ( ! empty( $pagination ) ) : ?>
121
- <div class="clear">
122
- <ul id="intergeo_lbrr_pgntn">
123
- <?php foreach ( $pagination as $page_item ) : ?>
124
- <li><?php echo $page_item; ?></li>
125
- <?php endforeach; ?>
126
- </ul>
127
- <div style="clear:both"></div>
128
  </div>
129
- <?php endif; ?>
130
-
131
- <?php else : ?>
132
- <p>
133
- <?php esc_html_e( 'You do not have created maps. Start adding it by clicking "Add New" button.', 'intergeo-maps' ); ?>
134
- </p>
135
- <?php endif; ?>
136
  </div>
15
  <a id="intergeo_lbrr_add_new" href="javascript:;"
16
  class="intergeo_lbrr_add_new add-new-h2"><?php _e( 'Add New', 'intergeo-maps' ); ?></a>
17
 
 
18
  <a id="intergeo_lbrr_settings"
19
  href="<?php echo admin_url( 'options-general.php?page=' . INTERGEO_PLUGIN_NAME ); ?>"
20
  class="add-new-h2"><?php _e( 'Maps Settings', 'intergeo-maps' ); ?></a>
29
 
30
  <div id="intergeo_library" class="intergeo_library">
31
  <div id="intergeo_sidebar" class="intergeo_sidebar_right">
32
+ <h2>Intergeo recommends</h2>
33
  <?php
34
+
35
+ do_action(
36
+ TI_INTERGEO_PLUGIN_NAME . '_recommend_products', array(
37
+ 'otter-blocks' => 'Otter',
38
+ 'optimole-wp' => 'OptiMole',
39
+ ), array(
40
+ 'neve' => 'Neve',
41
+ ), array( 'install' => __( 'More details', 'intergeo-maps' ) ), array( 'image' => 'icon' )
42
+ );
43
+
 
 
 
 
 
44
  do_action( INTERGEO_PLUGIN_NAME . '_render_subscribe_box' );
45
+
46
  ?>
47
  </div>
48
 
49
+ <div id="intergeo_lbrr_items" class="intergeo_sidebar_left">
50
+
51
  <?php if ( $query->have_posts() ) : ?>
52
 
53
+ <?php
 
54
  $index = 0;
55
+ while ( $query->have_posts() ) :
56
+ $post = $query->next_post();
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
+ $id = intergeo_encode( $post->ID );
59
+ $json = json_decode( $post->post_content, true );
60
 
61
+ $delete_url = add_query_arg(
62
+ array(
63
+ 'map' => $id,
64
+ 'do' => 'delete',
65
+ 'noheader' => 'true',
66
+ 'nonce' => wp_create_nonce( $post->ID . filter_input( INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP ) ),
67
+ )
68
+ );
69
+
70
+ $libraries = intergeo_check_libraries( $json, $libraries );
71
+
72
+ ?>
73
+ <div class="intergeo_lbrr_item"<?php echo $index != 0 && $index % 3 == 0 ? ' style="clear:both"' : ''; ?>>
74
+ <div class="intergeo_lbrr_wrapper">
75
+ <div class="intergeo_lbrr_map_wrapper">
76
+ <div class="intergeo_lbrr_map_loader">
77
+ <div id="intergeo_map<?php echo $id; ?>" class="intergeo_lbrr_map"></div>
78
+ </div>
79
+ </div>
80
+ <table class="intergeo_lbrr_cntrls" cellspacing="0" cellpadding="0" border="0">
81
+ <tr>
82
+ <td>
83
+ <input type="text" class="intergeo_lbrr_code"
84
+ value="[intergeo id=&quot;<?php echo $id; ?>&quot;]<?php echo ! empty( $json['address'] ) ? esc_attr( $json['address'] ) : ''; ?>[/intergeo]">
85
+ </td>
86
+ <td class="intergeo_lbrr_item_actions">
87
+ <a class="intergeo_lbrr_item_edit" href="javascript:;"
88
+ title="<?php _e( 'Edit', 'intergeo-maps' ); ?>"
89
+ data-map="<?php echo $id; ?>"></a>
90
+ <a class="intergeo_lbrr_item_copy" href="javascript:;"
91
+ title="<?php _e( 'Clone', 'intergeo-maps' ); ?>"
92
+ data-map="<?php echo $id; ?>"></a>
93
+ <a class="intergeo_lbrr_item_delete" href="<?php echo esc_attr( $delete_url ); ?>"
94
+ title="<?php _e( 'Delete', 'intergeo-maps' ); ?>"
95
+ onclick="return showNotice.warn();"></a>
96
+ </td>
97
+ </tr>
98
+ </table>
99
  </div>
100
  </div>
101
+ <script type="text/javascript">
102
+ /* <![CDATA[ */
103
+ window.intergeo_maps.push({
104
+ container: 'intergeo_map<?php echo $id; ?>',
105
+ options: <?php echo $post->post_content; ?>
106
+ });
107
+ /* ]]> */
108
+ </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  <?php
110
 
111
  $index ++;
112
  endwhile;
113
 
114
  ?>
115
+
116
+ <?php if ( ! empty( $pagination ) ) : ?>
117
+ <div class="clear">
118
+ <ul id="intergeo_lbrr_pgntn">
119
+ <?php foreach ( $pagination as $page_item ) : ?>
120
+ <li><?php echo $page_item; ?></li>
121
+ <?php endforeach; ?>
122
+ </ul>
123
+ <div style="clear:both"></div>
124
+ </div>
125
+ <?php endif; ?>
126
+
127
+ <?php else : ?>
128
+ <p>
129
+ <?php esc_html_e( 'You do not have created maps. Start adding it by clicking "Add New" button.', 'intergeo-maps' ); ?>
130
+ </p>
131
+ <?php endif; ?>
132
  <div style="clear:both"></div>
 
 
133
 
134
+ </div>
 
 
 
 
 
 
 
135
  </div>
 
 
 
 
 
 
 
136
  </div>
themeisle-hash.json CHANGED
@@ -1 +1 @@
1
- {"index.php":"67cf27efd3519a39ff86c91c88cf2c40"}
1
+ {"index.php":"abd21d55cf38d6fc2de662c7a8662034"}
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit0df49950d5c45f5a33cc99a042d21267::getLoader();
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit50a5a90c970ef91e5ea0336e536a989f::getLoader();
vendor/codeinwp/themeisle-sdk/CHANGELOG.md ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## [3.0.5](https://github.com/Codeinwp/themeisle-sdk/compare/v3.0.4...v3.0.5) (2019-03-07)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * dashboard widget issues and recommended module inconsistency fix [#50](https://github.com/Codeinwp/themeisle-sdk/issues/50), [#49](https://github.com/Codeinwp/themeisle-sdk/issues/49), [#47](https://github.com/Codeinwp/themeisle-sdk/issues/47) ([757eb02](https://github.com/Codeinwp/themeisle-sdk/commit/757eb02))
7
+
8
+ ## [3.0.4](https://github.com/Codeinwp/themeisle-sdk/compare/v3.0.3...v3.0.4) (2019-01-28)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * uninstall feedback disclosure issues when one of the feedback fields is open ([4631eef](https://github.com/Codeinwp/themeisle-sdk/commit/4631eef))
14
+
15
+ ## [3.0.3](https://github.com/Codeinwp/themeisle-sdk/compare/v3.0.2...v3.0.3) (2019-01-07)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **build:** fix exit code when is running outside wordpress context ([d298bb5](https://github.com/Codeinwp/themeisle-sdk/commit/d298bb5))
21
+
22
+ ## [3.0.2](https://github.com/Codeinwp/themeisle-sdk/compare/v3.0.1...v3.0.2) (2018-12-28)
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * remove composer/installers from package requirements ([a0ad543](https://github.com/Codeinwp/themeisle-sdk/commit/a0ad543))
28
+
29
+ ## [3.0.1](https://github.com/Codeinwp/themeisle-sdk/compare/v3.0.0...v3.0.1) (2018-12-24)
30
+
31
+
32
+ ### Bug Fixes
33
+
34
+ * notifications setup triggers after all products register their n… ([999a944](https://github.com/Codeinwp/themeisle-sdk/commit/999a944))
35
+ * notifications setup triggers after all products register their notices ([ec3cacc](https://github.com/Codeinwp/themeisle-sdk/commit/ec3cacc))
36
+
37
+ # 1.0.0 (2018-12-21)
38
+
39
+
40
+ ### Features
41
+
42
+ * adds uninstall feedback privacy policy info ([ed17943](https://github.com/Codeinwp/themeisle-sdk/commit/ed17943))
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-endpoints.php DELETED
@@ -1,312 +0,0 @@
1
- <?php
2
- /**
3
- * The class that exposes endpoints.
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Endpoints
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- // Exit if accessed directly.
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
- if ( ! class_exists( 'ThemeIsle_SDK_Endpoints' ) ) :
16
- /**
17
- * Expose endpoints for ThemeIsle SDK.
18
- */
19
- final class ThemeIsle_SDK_Endpoints {
20
-
21
- const SDK_ENDPOINT = 'themeisle-sdk';
22
- const SDK_ENDPOINT_VERSION = 1;
23
-
24
- const HASH_FILE = 'themeisle-hash.json';
25
-
26
- // if true, the endpoint will expect a product slug and will return the value only for that.
27
- const PRODUCT_SPECIFIC = false;
28
-
29
- /**
30
- * @var ThemeIsle_SDK_Product $products Array of Themeisle Product.
31
- */
32
- static protected $products = array();
33
-
34
- /**
35
- * ThemeIsle_SDK_Endpoints constructor.
36
- *
37
- * @param ThemeIsle_SDK_Product $product_object Product Object.
38
- */
39
- public function __construct( $product_object ) {
40
- if ( $product_object instanceof ThemeIsle_SDK_Product ) {
41
- self::$products[] = $product_object;
42
- }
43
- $this->setup_endpoints();
44
- }
45
-
46
- /**
47
- * Setup endpoints.
48
- */
49
- private function setup_endpoints() {
50
- global $wp_version;
51
- if ( version_compare( $wp_version, '4.4', '<' ) ) {
52
- // no REST support.
53
- return;
54
- }
55
-
56
- $this->setup_rest();
57
- }
58
-
59
- /**
60
- * Setup REST endpoints.
61
- */
62
- private function setup_rest() {
63
- add_action( 'rest_api_init', array( $this, 'rest_register' ) );
64
- }
65
-
66
- /**
67
- * Registers the endpoints
68
- */
69
- function rest_register() {
70
- register_rest_route(
71
- self::SDK_ENDPOINT . '/v' . self::SDK_ENDPOINT_VERSION,
72
- '/checksum/' . ( self::PRODUCT_SPECIFIC ? '(?P<slug>.*)/' : '' ),
73
- array(
74
- 'methods' => 'GET',
75
- 'callback' => array( $this, 'checksum' ),
76
- )
77
- );
78
- }
79
-
80
- /**
81
- * The checksum endpoint.
82
- *
83
- * @param WP_REST_Request $data the request.
84
- *
85
- * @return WP_REST_Response Response or the error
86
- */
87
- function checksum( WP_REST_Request $data ) {
88
- $products = self::$products;
89
- if ( self::PRODUCT_SPECIFIC ) {
90
- $params = $this->validate_params( $data, array( 'slug' ) );
91
- foreach ( self::$products as $product ) {
92
- if ( $params['slug'] === $product->get_slug() ) {
93
- $products = array( $product );
94
- break;
95
- }
96
- }
97
- }
98
- $response = array();
99
- $custom_css = $this->has_custom_css();
100
- if ( is_bool( $custom_css ) ) {
101
- $response['custom_css'] = $custom_css;
102
- }
103
-
104
- $response['child_theme'] = $this->get_theme_properties();
105
-
106
- foreach ( $products as $product ) {
107
- $files = array();
108
- switch ( $product->get_type() ) {
109
- case 'plugin':
110
- $files = array();
111
- break;
112
- case 'theme':
113
- $files = array( 'style.css', 'functions.php' );
114
- break;
115
- }
116
-
117
- $error = '';
118
-
119
- // if any element in the $files array contains a '/', this would imply recursion is required.
120
- $diff = $this->generate_diff( $product, $files, array_reduce( $files, array( $this, 'is_recursion_required' ), false ) );
121
- if ( is_wp_error( $diff ) ) {
122
- $error = $diff->get_error_message();
123
- $diff = array();
124
- }
125
-
126
- $response['products'][] = array(
127
- 'slug' => $product->get_slug(),
128
- 'version' => $product->get_version(),
129
- 'diffs' => $diff,
130
- 'error' => $error,
131
- );
132
- }
133
-
134
- return new WP_REST_Response( array( 'checksum' => $response ) );
135
- }
136
-
137
- /**
138
- * Get the current theme properties.
139
- *
140
- * @return array Properties of the current theme.
141
- */
142
- function get_theme_properties() {
143
- if ( ! is_child_theme() ) {
144
- return false;
145
- }
146
-
147
- $properties = array();
148
- $theme = wp_get_theme();
149
- // @codingStandardsIgnoreStart
150
- $properties['name'] = $theme->Name;
151
- // @codingStandardsIgnoreEnd
152
-
153
- // get the files in the child theme.
154
- require_once( ABSPATH . 'wp-admin/includes/file.php' );
155
- WP_Filesystem();
156
- global $wp_filesystem;
157
- $path = str_replace( ABSPATH, $wp_filesystem->abspath(), get_stylesheet_directory() );
158
- $list = $wp_filesystem->dirlist( $path, false, false );
159
- if ( $list ) {
160
- $list = array_keys( self::flatten_dirlist( $list ) );
161
- $properties['files'] = $list;
162
- }
163
- return $properties;
164
- }
165
-
166
- /**
167
- * Check if custom css has been added to the theme.
168
- *
169
- * @return bool Whether custom css has been added to the theme.
170
- */
171
- private function has_custom_css() {
172
- $query = new WP_Query(
173
- array(
174
- 'post_type' => 'custom_css',
175
- 'post_status' => 'publish',
176
- 'numberposts' => 1,
177
- 'update_post_meta_cache' => false,
178
- 'update_post_term_cache' => false,
179
- )
180
- );
181
-
182
- if ( $query->have_posts() ) {
183
- $query->the_post();
184
- $content = get_the_content();
185
- // if the content contains a colon, a CSS rule has been added.
186
- return strpos( $content, ':' ) === false ? false : true;
187
- }
188
- return false;
189
- }
190
-
191
- /**
192
- * Check if recursion needs to be enabled on the WP_Filesystem by reducing the array of files to a boolean.
193
- *
194
- * @param string $carry Value of the previous iteration.
195
- * @param string $item Value of the current iteration.
196
- *
197
- * @return bool Whether to recurse or not.
198
- */
199
- function is_recursion_required( $carry, $item ) {
200
- if ( ! $carry ) {
201
- return ( strpos( $item, '/' ) !== false );
202
- }
203
- return $carry;
204
- }
205
-
206
- /**
207
- * Generate the diff of the files.
208
- *
209
- * @param ThemeIsle_SDK_Product $product Themeisle Product.
210
- * @param array $files Array of files.
211
- * @param bool $recurse Whether to recurse or not.
212
- *
213
- * @return string
214
- */
215
- private function generate_diff( $product, $files, $recurse = false ) {
216
- require_once( ABSPATH . 'wp-admin/includes/file.php' );
217
- WP_Filesystem();
218
- global $wp_filesystem;
219
-
220
- $diff = array();
221
- $path = str_replace( ABSPATH, $wp_filesystem->abspath(), plugin_dir_path( $product->get_basefile() ) );
222
- $list = $wp_filesystem->dirlist( $path, false, $recurse );
223
- // nothing found.
224
- if ( ! $list ) {
225
- return $diff;
226
- }
227
- $list = array_keys( self::flatten_dirlist( $list ) );
228
-
229
- // now let's get the valid files that actually exist.
230
- if ( empty( $files ) ) {
231
- $files = $list;
232
- } else {
233
- $files = array_intersect( $files, $list );
234
- }
235
-
236
- // fetch the calculated hashes.
237
- if ( ! $wp_filesystem->is_readable( $path . '/' . self::HASH_FILE ) ) {
238
- return new WP_Error( 'themeisle_sdk_hash_not_found', sprintf( '%s not found', self::HASH_FILE ) );
239
- }
240
-
241
- $hashes = json_decode( $wp_filesystem->get_contents( $path . '/' . self::HASH_FILE ), true );
242
- ksort( $hashes );
243
-
244
- $diff = array();
245
- foreach ( $files as $file ) {
246
- // file does not exist in the hashes.
247
- if ( ! array_key_exists( $file, $hashes ) ) {
248
- continue;
249
- }
250
- $new = md5( $wp_filesystem->get_contents( $path . $file ) );
251
- $old = $hashes[ $file ];
252
-
253
- // same hash, bail.
254
- if ( $new === $old ) {
255
- continue;
256
- }
257
- $diff[] = $file;
258
- }
259
- return $diff;
260
- }
261
-
262
- /**
263
- * Flatten the results of WP_Filesystem::dirlist() for iterating over.
264
- *
265
- * @access private
266
- *
267
- * @param array $nested_files Array of files as returned by WP_Filesystem::dirlist().
268
- * @param string $path Relative path to prepend to child nodes. Optional.
269
- * @return array $files A flattened array of the $nested_files specified.
270
- */
271
- private static function flatten_dirlist( $nested_files, $path = '' ) {
272
- $files = array();
273
- foreach ( $nested_files as $name => $details ) {
274
- $files[ $path . $name ] = $details;
275
- // Append children recursively
276
- if ( ! empty( $details['files'] ) ) {
277
- $children = self::flatten_dirlist( $details['files'], $path . $name . '/' );
278
- // Merge keeping possible numeric keys, which array_merge() will reindex from 0..n
279
- $files = $files + $children;
280
- }
281
- }
282
- return $files;
283
- }
284
-
285
- /**
286
- * Validates the parameters to the API
287
- *
288
- * @param WP_REST_Request $data the request.
289
- * @param array $params the parameters to validate.
290
- *
291
- * @return array of parameter name=>value
292
- */
293
- private function validate_params( WP_REST_Request $data, $params ) {
294
- $collect = array();
295
- foreach ( $params as $param ) {
296
- $value = sanitize_text_field( $data[ $param ] );
297
- if ( empty( $value ) ) {
298
- return new WP_Error(
299
- 'themeisle_' . $param . '_invalid', sprintf( 'Invalid %', $param ), array(
300
- 'status' => 403,
301
- )
302
- );
303
- } else {
304
- $collect[ $param ] = $value;
305
- }
306
- }
307
-
308
- return $collect;
309
- }
310
-
311
- }
312
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback-deactivate.php DELETED
@@ -1,556 +0,0 @@
1
- <?php
2
- /**
3
- * The deactivate feedback model class for ThemeIsle SDK
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Feedback
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- // Exit if accessed directly.
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
- if ( ! class_exists( 'ThemeIsle_SDK_Feedback_Deactivate' ) ) :
16
- /**
17
- * Deactivate feedback model for ThemeIsle SDK.
18
- */
19
- class ThemeIsle_SDK_Feedback_Deactivate extends ThemeIsle_SDK_Feedback {
20
-
21
- /**
22
- * @var array $options_plugin The main options list for plugins.
23
- */
24
- private $options_plugin = array(
25
- 'I found a better plugin' => array(
26
- 'id' => 3,
27
- 'type' => 'text',
28
- 'placeholder' => 'What\'s the plugin\'s name?',
29
- ),
30
- 'I could not get the plugin to work' => array(
31
- 'id' => 4,
32
- ),
33
- 'I no longer need the plugin' => array(
34
- 'id' => 5,
35
- 'type' => 'textarea',
36
- 'placeholder' => 'If you could improve one thing about our product, what would it be?',
37
- ),
38
- 'It\'s a temporary deactivation. I\'m just debugging an issue.' => array(
39
- 'id' => 6,
40
- ),
41
- );
42
-
43
- /**
44
- * @var array $options_theme The main options list for themes.
45
- */
46
- private $options_theme = array(
47
- 'I don\'t know how to make it look like demo' => array(
48
- 'id' => 7,
49
- ),
50
- 'It lacks options' => array(
51
- 'id' => 8,
52
- ),
53
- 'Is not working with a plugin that I need' => array(
54
- 'id' => 9,
55
- 'type' => 'text',
56
- 'placeholder' => 'What is the name of the plugin',
57
- ),
58
- 'I want to try a new design, I don\'t like {theme} style' => array(
59
- 'id' => 10,
60
- ),
61
- );
62
-
63
- /**
64
- * @var array $other The other option
65
- */
66
- private $other = array(
67
- 'Other' => array(
68
- 'id' => 999,
69
- 'type' => 'textarea',
70
- 'placeholder' => 'cmon cmon tell us',
71
- ),
72
- );
73
-
74
- /**
75
- * @var string $heading_plugin The heading of the modal
76
- */
77
- private $heading_plugin = 'Quick Feedback <span>Because we care about our clients, please leave us a feedback.</span>';
78
-
79
- /**
80
- * @var string $heading_theme The heading of the modal
81
- */
82
- private $heading_theme = 'Looking to change {theme} <span> What does not work for you?</span>';
83
-
84
- /**
85
- * @var string $button_submit_before The text of the deactivate button before an option is chosen
86
- */
87
- private $button_submit_before = 'Skip &amp; Deactivate';
88
-
89
- /**
90
- * @var string $button_submit The text of the deactivate button
91
- */
92
- private $button_submit = 'Submit &amp; Deactivate';
93
-
94
- /**
95
- * @var string $button_cancel The text of the cancel button
96
- */
97
- private $button_cancel = 'Skip &amp; Deactivate';
98
-
99
- /**
100
- * @var int how many seconds before the deactivation window is triggered for themes
101
- */
102
- const AUTO_TRIGGER_DEACTIVATE_WINDOW_SECONDS = 3;
103
-
104
- /**
105
- * @var int how many days before the deactivation window pops up again for the theme
106
- */
107
- const PAUSE_DEACTIVATE_WINDOW_DAYS = 100;
108
-
109
- /**
110
- * ThemeIsle_SDK_Feedback_Deactivate constructor.
111
- *
112
- * @param ThemeIsle_SDK_Product $product_object The product object.
113
- */
114
- public function __construct( $product_object ) {
115
- parent::__construct( $product_object );
116
- }
117
-
118
- /**
119
- * Registers the hooks
120
- */
121
- public function setup_hooks_child() {
122
- global $pagenow;
123
-
124
- if ( ( $this->product->get_type() === 'plugin' && $pagenow === 'plugins.php' ) || ( $this->product->get_type() === 'theme' && $pagenow === 'theme-install.php' ) ) {
125
- add_action( 'admin_head', array( $this, 'load_resources' ) );
126
- }
127
- add_action( 'wp_ajax_' . $this->product->get_key() . __CLASS__, array( $this, 'post_deactivate' ) );
128
- }
129
-
130
- /**
131
- * Loads the additional resources
132
- */
133
- function load_resources() {
134
- add_thickbox();
135
-
136
- $id = $this->product->get_key() . '_deactivate';
137
-
138
- $this->add_css( $this->product->get_type(), $this->product->get_key() );
139
- $this->add_js( $this->product->get_type(), $this->product->get_key(), '#TB_inline?' . apply_filters( $this->product->get_key() . '_feedback_deactivate_attributes', 'width=600&height=550' ) . '&inlineId=' . $id );
140
-
141
- echo '<div id="' . $id . '" style="display:none;" class="themeisle-deactivate-box">' . $this->get_html( $this->product->get_type(), $this->product->get_key() ) . '</div>';
142
- }
143
-
144
- /**
145
- * Loads the css
146
- *
147
- * @param string $type The type of product.
148
- * @param string $key The product key.
149
- */
150
- function add_css( $type, $key ) {
151
- $suffix = 'theme' === $type ? 'theme-install-php' : 'plugins-php';
152
- ?>
153
- <style type="text/css" id="<?php echo $key; ?>ti-deactivate-css">
154
- input[name="ti-deactivate-option"] ~ div {
155
- display: none;
156
- }
157
-
158
- input[name="ti-deactivate-option"]:checked ~ div {
159
- display: block;
160
- }
161
-
162
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container #TB_window.thickbox-loading:before {
163
- background: none !important;
164
- }
165
-
166
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container #TB_title {
167
- background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQyIDc5LjE2MDkyNCwgMjAxNy8wNy8xMy0wMTowNjozOSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpDNkVDM0M4RkYxMzMxMUU3OEMyMkQ0NTIxRTVEQ0ZBRiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpDNkVDM0M5MEYxMzMxMUU3OEMyMkQ0NTIxRTVEQ0ZBRiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkM2RUMzQzhERjEzMzExRTc4QzIyRDQ1MjFFNURDRkFGIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkM2RUMzQzhFRjEzMzExRTc4QzIyRDQ1MjFFNURDRkFGIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+KBNOswAAFtFJREFUeNrkWwmUXVWV3W/8Y81zkVAhgUwQg00IAYIRGcRuERDSKqALtVEbxRYcGzWIuhatKCYuUXQtERRtFAccQCDtckCZwpRISEIlIXMqlaGGP///ht7n3vd//YRUUkljN718a53U+++//97d95yzz3BvjDAM8fd02May4YndaZhoDErYeu/laCyN8rN16PuDAPA83mcAjjOxd8jcVypydhrlKspCSidlhPIk5T8p9/+PAP8fTrZJaaQ0UFxKiVKk/CvlU5Rk3b0C+gTKFZRvUa75/wJ4EuVcyimU2RGQdkqCkoOBDExjBoJx3Uwm5OlXt4bFrIPgTXSJK+DY59PEO8a5s0mPiEPyfUrwMieh3ED57qsTsJBhoXAOmps+gd6u85AvGtgxQEOmJcfj+vvxDsvS/hzsB5pkgA9QplJuoux59QD2g1ZUvCXhVe+4pnjxJc5gdx8SxTza1jwDY9ntMDdsBlLJQ4O2CTogRs+vBzydFmLCMm98NWl4OvL5O3Hd+09/9p8/iK/9GOjfRHZKpnHZWy7AlbfPRuK918DYTm3H3PHZWrQbVnHKtUBbh201EvSFvHLX0TLlK3ksRLG4HPPmnL7+0vfiaz8EOkwP+aduwPKbZ+DadyzBnVuPBa4nEQf+/hqW0zKvZcqkJoYmi0DTMXo2+cyltiu8oSi+HQrR3UG5+n9Fw6bFmRYJOVehUf/VAsrPacodOPtM3LcmjmPSwMz4cvzXAJEXt6C89gv49rJTcMk3zkdPL8e9e0iTVNHTTziuGTi9D5jF73oaNVg5RnLAjiywagfwp01ybiJufQOOuYMTdf9hg3s5H83oEQIWhYwOMGySf2KNFTjJchW0EMmPKB1KMx2d2LQFGCKtvPD0A1izbitnitcZbrat+T12Fi8i4C5g6y49kDkk7re/RoNtTmo+DiKmFlPupaZPbAPOp3VceSLwYD/fttrFUPlbSNsL+YgtB48QjGKmje+ceBlKlqsATBywIe82sG9TC5OhONqP2wOnucB0wRY13Cn6qQWPYgEtVNZvf8/J3RhnZAprrtjY81qkxHX3jGrtvn8esHgm0wzek6Vf76Y2Q19ncibBmymeM1Mz+H1IS2ji9XfPAuZzAm5+ajLWDn8JKfvymgprQczHyvbpGEh14f2nX89sLyVsehQmbQewKj5GBxtQzMXQ3DvyWcvxz9rPvFf9Fed+ELjnl8Q07To07FyJ3MATCDouxXmL344pO55nmsFs8avMHE8jmH1/puzmkEsarBo7n2dweCbn06YFxJizWJzFErVW5Kwez8m45VTgM08txqqhu5C0HxyDHNIIDSxedCP6Ozk5Bb6rNHzkpCWQTJqlwQcWcgkUh+NXG2b4sf1uSjDGPvQITh98Bh/5F35s6UXTovvR+eaVuPD6O/DRt8bg/uL7CK+nj75mI7DtD0CefhkUopfYkUZtDdyn75Y2kMz+wvtW6s8yMRmCaCLwG2Za6E5ch4xnoMLPZUo2g3uPPQfr25iNFob3U76BpUMTVK2JBLOmP37hU5hE5yzBvbZz2p6lyXYSiH/AvBVLCI/pRvnmG7Fy8nysYtgVEz+jIYPuu7+NSvIe2OfZMIvh4YuQevIRkxYtx6fxd662hkZOzu9257Fk/esZrlaI2arY+PY70d8yhRNZOWKWPobSS4fPFBx37YaeHkwdGrgCqfDWZGveRHAQI6GWje07EXvfRzB/0XzMn0UfzdBnH/oLwrOogTcfS7BbtSaPxL7kfp+aLayliR+nJytDEz8jnsRpDW/F45kVFTfE0rmXo7+VPOqXjygOn0f5qXgk5QnKc9Ty50MVfozbGjqyVFFwIFWM0XkioXPiB8hct9wGfI15Qmo3gnfSb3MZVW4e1SGmHtL8K1u1G1QYciyCflPqPFRK9ouN0/CJM6+LNBtOKA6Lqy6hfJri1H5jWbFUIX9D75597yM/NSWaiwfG4ZeDlpw4ldLvjXO23zOPeYMPw9/HqY5pRj+qg8/1yebYp0ktzwfNDGdgvnvcKnd6P7yKDmcTzLQE7Oc4SMflty1xA21JEyazng8v/4110uDmrrAphBXzdK47kUNYdS7j94ITEI7uhOkEh56sCefsGQ1cEotkIV3+ePKUm856txCXlKCXqLzgMIDfqEowaqQ1YaCv0URrjJyciGHu9k24+k8PsiB1EW8q6rg40S6GzPbZ3bSnOK1xAJZtHrpwmHDM4HODnDbtcAiPetNnb8x1fBFmebnK+oBHKVeOZ9JMBPEfHKDbTrBdKZMZX4gS3TDvmHjvA79BayGDYSONWKo8ce36BNZGgCd3EmyRRDt8BMw8kaNquhXmLC3vrHhOj2GXqp54POUHUVL0hQM1fBXvOjnlGOgm2Arjrcdn5VwHJ2zZggueXYEc4tSOD8vxxupW4zDAJcuaxBDSmUaQzzKS5HXV87cowWFMgWPElBtSHLPGW1I/L64HzGwB75KTjqShrI3JlBprgbnoPz3xONqZrVRoEKYVQrGzmJSkhgJ6PABGBLiPBBW3SJySXHhjJd8rfhiK/CVtF8X1pk3EdP4iL/x36ZOZtUonxClJ3iQ3lqldscQK70tmczj/mRUoE6z8TqolBboKWDqSVeDjabvZ0n7MxCH0A/ytjqyf5msspTCxTpvDEdCmHtZrKYuqgC8VbTe5ot1QZWjyg6ztYNbmzZi+Y5tkViqlNKhdQ4BVw45Dc3Uj0CIHalvuFfsJyuqrMLReAcI6+DGCHsX+AccZRPSR4JCa40bVtF8no4tJ4a7GxXELWLnRDyUBt7DghReQCop8gHFAmhdGPWd7f007ddqu4hLt+gX6vuTJCX4MXnHvlVRzS2lmrfgQxYVROtDg1sb+D6Zql4Y4PsY6ltasAQfanA3Px4xtWyIXqFZd9EXF0KFuw4h2rQioAu3UmbmpQUtiIKHDFKtoQTlb0t+9YkeFFtmNFUNMJw0ydGjUwErH16VNR6/rkT9zJCSJc8tNnjLnkD5rIp3N44TB7UzHx8KI75mcxGiw5XIENgLp2AdoPLq2Tx6aV1qOt01CcUieUTk8w0848SpjXeFUPDvUQmCBAloFK2IyZzC1jlIy8mnqN2bVlDWPlqnVhlwO7SOj/DymjYCARdRgBbA8yHXHfLhewwJW/GSbaJkaDrKwk0m4bXMwujkLv1JSWaJ6vIyoKvJMSWwM6XuVyXWM374kO8FBJknYKYn1T07hKzxyjPbfsE7qWoEyIsxU8SliNvFdZdJ8sctEIVEq1/xXDCVkdVQpOHAk+ZDYVSCQpubIj0w9SDVoQycnTGIwyAcOcBr7mAp6MSS6ephenonsrrX06wzcRJSLmJoMaYD0FpvjINsZbeQhxvAKx5HfiFR7hWltXV9bUtyB45G6YzPMS0scq1XTcFjT8Jiz26r0k4nlVS9ATUJ+jpVKcFgD1/uwvKY4GkeyI6fnbZQgWlt0fSqrDPJ039DgxfSFmkd5/Uk+9DiadSWrfhZjgRxrWohyIY+glFcmboQmgcdYVzTDdJs4KQ0E18RrBGi5KA3vRqb/e2jsLfKxjp5ctxW4mwnRmgHFlZ7y33BMwxHVBDqSlgVwuxF94YU6u/KV8UtzkjE3Yrux0B4qwGHF4kB4U5GmNkoQba21RoGWqI8soMVzHufnN1CaWc/6jh4N73HTSdJoS9TlqIoVdTwkhPH54u+Bg1hbL7zhhfByD8BtciS7AJa3oXD3Ls73ND7Oh7TpqiYtMELolkBkEFmzuqajTDnyYb/6i4NkRAKYZSdBM5pZUWjas0f/KBar8+U6ApNguJevepD3S1oq5WFYjjqT9GOPbiEpZ00KWgLpcVV0p0OE1uE0dHGiCLSBz3osicqyvchk5V1mzb9rJh2pStrdUSDca0buq8ZbZWgvMt4SycejnRgHKYCkiad8VF5C08fOnWPsXGXsGmh+bqTJ/5Gv+4skeOL/uxWJVTMwMuH+f2vnVcCVKMaWYIiKfsf33pLF8EuuKtsrDv1eIkagDTqo8+OSF1Y1vM6MNF5LOJT/Rg5QJPuWGGfNAzoH8rk4EkdxOKGb8uI8+6i1wUHdxKuxdB14N5J7ONCnKEkBRMuo7NXaRtSDluEoYNXzYIxn42KFW2H8mr/9RoD8YAK5bJqG7yGXSMC3rJqGa2YtU1RbnsJacZS9QlyS45vRzETxB3kOcJQAmlnlAC8v6Ya2NaG7saTSTbUSsX2H1mZ3J99i6BaPYYyJpO5Fyvd8zdxn82Ux+nSZBOinOIBG3cEQkgqicCXEZEvSQlm5De6d62CtcMmPDvYNtCh05GXsaGmlm/Pd5aI230hpokBZoeF8+VXA2yX58ALNxYrMOMNhpYJhFv4bWzswbe+gWp4/0JdL+RiGCbplCrVbbeYx91Ya6u2l9jy9hUHFV1NPgISpMuUXPF8VgZ7O8zSBm6MRUdmatITtZa1pE8H+gdHg90xP88yVYw72bGiHR841VdAMsbp7kn5HqJspSsOGNueK1uJW6cvZ0Yr6BWOa9RnfPSU+zbm/vRMX9P91nGIsxMiuBrXkku6kFXhV0FsYn8mufX3UakL7uBFpu8ri0vXYxGvfpbRR+qQ/ymE2+nqhf4TnWzlhLxLwFko+VGwfsHzd3d+OYjamwIp2C2T21cccq0mwluqHKsUs+DV3FJy7BfCDlE+q7ocCW1Ga0H+BZ6YcC+8xs6b9AwHLRO3a1KxCTLo9r8OQaGcX/ZmlJSZz5pv5vR1qbVc3usgT04a+f4R/VxDg414UNH3USjaJ55KvM8Hw6Q4717eiRP5wIt5leoLdqUb0d3VANe/qxik/r/PfX1cbAOTN8F7RqMkSzvA9DVYYkgnBo32TsT3Vwhf44y4/BjTnLRtbMTSQ1pwvaaGQlmRh617UMjwytvovImvDVUJL8LzBlrKGk0CRxSdh9WaGuTSvxwzkMzG8tJYxl2DdCFKoSj0Pz07qow83wygXUQ1Gmp1R5SQx598qwAZ1bwTBZw2/sgu+NmVEJm0z192VTuGxqceypK1gvCpW6ksh602bmrCV4rGiUhqVBN3k+fAwTZOgX1jDV/PdmYzWpLCqG9XTMgFy7lRragkbJKB8EQMbXWxY08yCy1Wldf3CiVS/D594orIaQ1mo7pULCZfHNsfcSxnU+7Sk7RJiA5/+Sf7gzv1MWkyLL//ZSSfirc8/zzwjPKAuHnt5Ujieyf3OXUkMZ1z09mTR0soUUIBX15IlKxOti7nXJyhG3Sq/76kmurx+eNjFjp2NJPE4Gvn8GIz9Jl2UsLmhDQ/PnKUX2eQdQri81w9q95JR8c0xi4wiMjV9l+GX51C7HzUi4hJN28UAj0yZhGe6e3Dqzu3Iwh23G5siMGmrDBdsrNnYgPSuBDoIurWpzCTMZ4IU+a56pRexeFhXaxsoknn3jiSxZyiGQs5BOrTQRgDmAWCrgH8697UYbOZ00BoNy9HRgn4fmrWGrCwobKgDnNAxTmvu0wQ7jdq9WJk1NW3zb9G1cMcpc3Dab7brimmcJpzyKYLu5PAkaR3OGViXt2EPkNASHhqZbCQI3LGDagRRIMuUfNFGJm+xxONAPQspPqNLadXcr8yrHi45ZWeiEXedOo+2WyJ1cGRq+cZSZaTkBtT0V3jh9v04x3SeQpibxxtGRKPSLriaoNtpWgurmnaLJfxqxhRc8WwfXrd9G0Zgjdt3rA6skeWdLEEXGY4ynLgcZ2AoK9SnSa32+9BQnmhT4jxvJcAUn+9EXYvxmkEpavfW+QuxpZ2ESu2GaoVfp6msukbD0FrCRy57Wa8g9p5f0s+eRzi0AIYnhWmZEc94yPTKi0hkvaJpiw5VJE+v7whx0Ysb4Pr2YZeFor6m0riYZRMhNfJvo3wmoJQ6t9DMJKOV0hY6PLcI+uDmW//cBpTxdFcvPn7hBZxAQ2l3LKMz/0jbvoqgfnawBTvLeRvhpVfDSD3Hp3GWStKkdzJGJfaQEeTONYJyl1FxOePD2HT2UnrALrxx5SSUEE60vVYDL3bhEk6cwJIEFuNfV5X7Ri3OH+6pYsoVMvn7Lv5HvNTWBlfiOlSltJl+chOB/htls+ztODjgxbKKx9fGNsFs+gPM9ntZkrK+tEdGjHz3b81ifD7cHZPDObfAbFmJJ2ZmMXVLA07d2oa8mt8j7i++TCa+ZhgyGnhYsuhM/Oqk6YiXmDeY5mBoWt8kwA9QHmYY9BXYcQDbtWEECf3XGoLR8X2QMSgztgT5rvuQ2ngG0ttglRLw3AAfvfZpdIzE8PrVnRhGpa67ZEZtfh0fxwCadZVW9bpRIz8j+nSo60Jdab7rK/Pm4tvzZiNeLA7CjP2ARHUbtfvShNcmEj9JtEWl0J66TZ6S2b4OZmkx06+FLDSVFdRWP8m07QT8nS/NxzmruzEkoGMBUhcW4E4vo9zvIv/LJIKyLLP6SF2Uh9PnofRXF7n7Eyp0WC28fnEOdpeP4tMMQcvjasKc7gqSb8nDag5QfDSO/J8lswoU2K/PnYUbz16wwTGdH5pm7K7QcjZSFGGFJsWOxIrxL8W0Dgp4drSzzVHNSr3Fty3a0jv+ki9BNzHkfHXpPFzy5CTElg0geWlG0yqDcf7HDdjzuVZ0LtuN+Hl5XWyzasrc3ozh25rQ+d1diJ1WrDWbRm5uRebeNLp/NAB7dinaZ2lg9DOt2Ht3E76+YMajSxfM/QFJ7Sem6exToBTYIwcsfxdR7o7ATsw0JFelVg1iuXXzdFy7uEHFT5BtmQUwQlRQejyO+MKC6lQq77HKCAs+ys/FEDtLth/FdP/KLiEYZhnX7yB2ulyXriSvx3i+r1z6ycfmfehtfed/H+1WOc2iIqiCOgrAJC21sYRFLO6LAM+e6Hq0RQ2ULQ99cwy8OdHNCyIs4o0043ce9hQBm6Tt9PB6g4qehpGFPZlAPH52u/X1MAnDzcCeRAMrs7Jy5DoLkYATksoWEyflbyqY7s7n9/WgUIrBdkNNSgKoKkbd+SFIq/6KOP5llPOjnaq7J7QIz/LOzUlY4ODcTmqL3uB06hXYkpR3BGx31V3nfaVQA3Wi+90u1ZVU99ukEIelnt2uvy+45tSpQ6nvXPgAnrrsDlwxaxUrRwsFz8HRHPYBw1+ktv8CA9FC7oSOuBnuYaLcBrvDqHU7jfU6T5LNKwJA9aaCqKMRRDvsOnV3RJp0og11Pa0nSMrRIK9VUtLLE3M6d+Dui36IM57ehqWr3oD+zGRYTFmtowQcQv9HC9Hy6ye42WCfZeDz81NSxFpfVqZbXVU0qsCk5OvV8xdGSyWmdD9oAW5v1I2sjO3ZkL2V1fv90aoidJzypca2cc3Jf8a7pq/CHS8uwJfXnIvthW7FsbI74Uj3Sz9GOScC/fNqDXmQTRXS87mlFARnzYwnll3U1JZFmR7g7dba9Bjh1F4Ot4IKjSUY0vslKzs0CLle3qZ70GLS5c16c4rBqqL8kloN1PsqX9K9aea7+42gHEfaKeLDJz+MNRd/HjedfB+unPYnloQWg4F52Dh8qO8lHk+Jtv+INWSjpp+MarjAYvvnfVNxSXOrlJWP8pY07BaClRLUl//g8Fma7FJqmfVAU3Q9WMfrzFF9ZkdxQ5GTtGoN40lev4cfblVmbST0xBnmI/xHdhcVDo6A8++UlH0+t28qrlxxPVbnZnBOjYOy9OG2Hm6OZPz9/q6EHNG4eTlHuIQaPY7mzN+Yn1N9JMMq0mQ/icquHmpwLa/LXotHVPEalD5EP23l9VUc+fUc9UoOKQU/9x7OLSndelJfHwesckRqtKyVdnLbOjQ4hUPuATP+3v4r3n8LMAAsR90w+kkNLQAAAABJRU5ErkJggg==') 40px 30px no-repeat;
168
- border: none;
169
- box-sizing: border-box;
170
- color: #373e40;
171
- font-size: 24px;
172
- font-weight: 700;
173
- height: 90px;
174
- padding: 40px 40px 0 120px;
175
- text-transform: uppercase;
176
- width: 100%;
177
- }
178
-
179
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container div.actions {
180
- box-sizing: border-box;
181
- padding: 30px 40px;
182
- background-color: #eaeaea;
183
- }
184
-
185
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button {
186
- background: #ec5d60;
187
- border: none;
188
- box-shadow: none;
189
- color: #ffffff;
190
- font-size: 15px;
191
- font-weight: 700;
192
- height: auto;
193
- line-height: 20px;
194
- padding: 10px 15px;
195
- text-transform: uppercase;
196
- -webkit-transition: 0.3s ease;
197
- -moz-transition: 0.3s ease;
198
- -ms-transition: 0.3s ease;
199
- -o-transition: 0.3s ease;
200
- transition: 0.3s ease;
201
- }
202
-
203
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button.button-primary {
204
- background: transparent;
205
- box-shadow: none;
206
- color: #8d9192;
207
- font-weight: 400;
208
- float: right;
209
- line-height: 40px;
210
- padding: 0;
211
- text-decoration: underline;
212
- text-shadow: none;
213
- text-transform: none;
214
- }
215
-
216
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button:hover {
217
- background: #e83f42;
218
- }
219
-
220
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button.button-primary:hover {
221
- background: transparent;
222
- }
223
-
224
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button:focus {
225
- box-shadow: none;
226
- outline: none;
227
- }
228
-
229
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button:active {
230
- box-shadow: none;
231
- transform: translateY(0);
232
- }
233
-
234
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button:disabled {
235
- cursor: not-allowed;
236
- }
237
-
238
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button.button-primary:hover {
239
- text-decoration: none;
240
- }
241
-
242
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container div.revive_network-container {
243
- background-color: #ffffff;
244
- }
245
-
246
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list {
247
- margin: 0;
248
- }
249
-
250
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list li {
251
- color: #373e40;
252
- font-size: 13px;
253
- margin-bottom: 5px;
254
- }
255
-
256
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list li label {
257
- margin-left: 10px;
258
- line-height: 28px;
259
- font-size: 15px;
260
- }
261
-
262
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list input[type=radio] {
263
- margin-top: 1px;
264
- }
265
-
266
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container #TB_ajaxContent {
267
- box-sizing: border-box;
268
- height: auto !important;
269
- padding: 20px 40px;
270
- width: 100% !important;
271
- }
272
-
273
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container li div textarea {
274
- padding: 10px 15px;
275
- width: 100%;
276
- }
277
-
278
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list li div {
279
- margin: 10px 30px;
280
- }
281
-
282
- .<?php echo $key; ?>-container #TB_title #TB_ajaxWindowTitle {
283
- box-sizing: border-box;
284
- display: block;
285
- float: none;
286
- font-weight: 700;
287
- line-height: 1;
288
- padding: 0;
289
- text-align: left;
290
- width: 100%;
291
- }
292
-
293
- .<?php echo $key; ?>-container #TB_title #TB_ajaxWindowTitle span {
294
- color: #8d9192;
295
- display: block;
296
- font-size: 15px;
297
- font-weight: 400;
298
- margin-top: 5px;
299
- text-transform: none;
300
- }
301
-
302
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container .actions {
303
- width: 100%;
304
- display: block;
305
- position: absolute;
306
- left: 0;
307
- bottom: 0;
308
- }
309
-
310
- .theme-install-php .<?php echo $key; ?>-container #TB_closeWindowButton .tb-close-icon:before {
311
- font-size: 32px;
312
- }
313
-
314
- .<?php echo $key; ?>-container #TB_closeWindowButton .tb-close-icon {
315
- color: #eee;
316
- }
317
-
318
- .<?php echo $key; ?>-container #TB_closeWindowButton {
319
- left: auto;
320
- right: -5px;
321
- top: -35px;
322
- color: #eee;
323
- }
324
-
325
- .<?php echo $key; ?>-container #TB_closeWindowButton .tb-close-icon {
326
- text-align: right;
327
- line-height: 25px;
328
- width: 25px;
329
- height: 25px;
330
- }
331
-
332
- .<?php echo $key; ?>-container #TB_closeWindowButton:focus .tb-close-icon {
333
- box-shadow: none;
334
- outline: none;
335
- }
336
-
337
- .<?php echo $key; ?>-container #TB_closeWindowButton .tb-close-icon:before {
338
- font: normal 25px dashicons;
339
- }
340
-
341
- body.<?php echo $suffix; ?> .<?php echo $key; ?>-container {
342
- margin: auto !important;
343
- height: 500px !important;
344
- top: 0 !important;
345
- left: 0 !important;
346
- bottom: 0 !important;
347
- right: 0 !important;
348
- width: 600px !important;
349
- }
350
- </style>
351
- <?php
352
- }
353
-
354
- /**
355
- * Loads the js
356
- *
357
- * @param string $type The type of product.
358
- * @param string $key The product key.
359
- * @param string $src The url that will hijack the deactivate button url.
360
- */
361
- function add_js( $type, $key, $src ) {
362
- $heading = 'plugin' === $type ? $this->heading_plugin : str_replace( '{theme}', $this->product->get_name(), $this->heading_theme );
363
- $heading = apply_filters( $this->product->get_key() . '_feedback_deactivate_heading', $heading );
364
- ?>
365
- <script type="text/javascript" id="ti-deactivate-js">
366
- (function ($) {
367
- $(document).ready(function () {
368
- var auto_trigger = false;
369
- var target_element = 'tr[data-plugin^="<?php echo $this->product->get_slug(); ?>/"] span.deactivate a';
370
- <?php
371
- if ( 'theme' === $type ) {
372
- ?>
373
- auto_trigger = true;
374
- if ($('a.ti-auto-anchor').length == 0) {
375
- $('body').append($('<a class="ti-auto-anchor" href=""></a>'));
376
- }
377
- target_element = 'a.ti-auto-anchor';
378
- <?php
379
- }
380
- ?>
381
-
382
- if (auto_trigger) {
383
- setTimeout(function () {
384
- $('a.ti-auto-anchor').trigger('click');
385
- }, <?php echo self::AUTO_TRIGGER_DEACTIVATE_WINDOW_SECONDS * 1000; ?> );
386
- }
387
- $(document).on('thickbox:removed', function () {
388
- $.ajax({
389
- url: ajaxurl,
390
- method: 'post',
391
- data: {
392
- 'action': '<?php echo $key . __CLASS__; ?>',
393
- 'nonce': '<?php echo wp_create_nonce( (string) __CLASS__ ); ?>',
394
- 'type': '<?php echo $type; ?>',
395
- 'key': '<?php echo $key; ?>'
396
- },
397
- });
398
- });
399
- var href = $(target_element).attr('href');
400
- $('#<?php echo $key; ?>ti-deactivate-no').attr('data-ti-action', href).on('click', function (e) {
401
- e.preventDefault();
402
- e.stopPropagation();
403
-
404
- $('body').unbind('thickbox:removed');
405
- tb_remove();
406
- var redirect = $(this).attr('data-ti-action');
407
- if (redirect != '') {
408
- location.href = redirect;
409
- }
410
- });
411
-
412
- $('#<?php echo $key; ?> ul.ti-list label, #<?php echo $key; ?> ul.ti-list input[name="ti-deactivate-option"]').on('click', function (e) {
413
- $('#<?php echo $key; ?>ti-deactivate-yes').val($('#<?php echo $key; ?>ti-deactivate-yes').attr('data-after-text'));
414
-
415
- var radio = $(this).prop('tagName') === 'LABEL' ? $(this).parent() : $(this);
416
- if (radio.parent().find('textarea').length > 0 && radio.parent().find('textarea').val().length === 0) {
417
- $('#<?php echo $key; ?>ti-deactivate-yes').attr('disabled', 'disabled');
418
- radio.parent().find('textarea').on('keyup', function (ee) {
419
- if ($(this).val().length === 0) {
420
- $('#<?php echo $key; ?>ti-deactivate-yes').attr('disabled', 'disabled');
421
- } else {
422
- $('#<?php echo $key; ?>ti-deactivate-yes').removeAttr('disabled');
423
- }
424
- });
425
- } else {
426
- $('#<?php echo $key; ?>ti-deactivate-yes').removeAttr('disabled');
427
- }
428
- });
429
-
430
- $('#<?php echo $key; ?>ti-deactivate-yes').attr('data-ti-action', href).on('click', function (e) {
431
- e.preventDefault();
432
- e.stopPropagation();
433
- $.ajax({
434
- url: ajaxurl,
435
- method: 'post',
436
- data: {
437
- 'action': '<?php echo $key . __CLASS__; ?>',
438
- 'nonce': '<?php echo wp_create_nonce( (string) __CLASS__ ); ?>',
439
- 'id': $('#<?php echo $key; ?> input[name="ti-deactivate-option"]:checked').parent().attr('ti-option-id'),
440
- 'msg': $('#<?php echo $key; ?> input[name="ti-deactivate-option"]:checked').parent().find('textarea').val(),
441
- 'type': '<?php echo $type; ?>',
442
- 'key': '<?php echo $key; ?>'
443
- },
444
- });
445
- var redirect = $(this).attr('data-ti-action');
446
- if (redirect != '') {
447
- location.href = redirect;
448
- } else {
449
- $('body').unbind('thickbox:removed');
450
- tb_remove();
451
- }
452
- });
453
-
454
- $(target_element).attr('name', '<?php echo wp_kses( $heading, array( 'span' => array() ) ); ?>').attr('href', '<?php echo $src; ?>').addClass('thickbox');
455
- var thicbox_timer;
456
- $(target_element).on('click', function () {
457
- tiBindThickbox();
458
- });
459
-
460
- function tiBindThickbox() {
461
- var thicbox_timer = setTimeout(function () {
462
- if ($("#<?php echo esc_html( $key ); ?>").is(":visible")) {
463
- $("body").trigger('thickbox:iframe:loaded');
464
- $("#TB_window").addClass("<?php echo $key; ?>-container");
465
- clearTimeout(thicbox_timer);
466
- $('body').unbind('thickbox:removed');
467
- } else {
468
- tiBindThickbox();
469
- }
470
- }, 100);
471
- }
472
- });
473
- })(jQuery);
474
- </script>
475
- <?php
476
- }
477
-
478
- /**
479
- * Generates the HTML
480
- *
481
- * @param string $type The type of product.
482
- * @param string $key The product key.
483
- */
484
- function get_html( $type, $key ) {
485
- $options = 'plugin' === $type ? $this->options_plugin : $this->options_theme;
486
- $button_submit_before = 'plugin' === $type ? $this->button_submit_before : 'Submit';
487
- $button_submit = 'plugin' === $type ? $this->button_submit : 'Submit';
488
- $options = $this->randomize_options( apply_filters( $this->product->get_key() . '_feedback_deactivate_options', $options ) );
489
- $button_submit_before = apply_filters( $this->product->get_key() . '_feedback_deactivate_button_submit_before', $button_submit_before );
490
- $button_submit = apply_filters( $this->product->get_key() . '_feedback_deactivate_button_submit', $button_submit );
491
- $button_cancel = apply_filters( $this->product->get_key() . '_feedback_deactivate_button_cancel', $this->button_cancel );
492
-
493
- $options += $this->other;
494
-
495
- $list = '';
496
- foreach ( $options as $title => $attributes ) {
497
- $id = $attributes['id'];
498
- $list .= '<li ti-option-id="' . $id . '"><input type="radio" name="ti-deactivate-option" id="' . $key . $id . '"><label for="' . $key . $id . '">' . str_replace( '{theme}', $this->product->get_name(), $title ) . '</label>';
499
- if ( array_key_exists( 'type', $attributes ) ) {
500
- $list .= '<div>';
501
- $placeholder = array_key_exists( 'placeholder', $attributes ) ? $attributes['placeholder'] : '';
502
- switch ( $attributes['type'] ) {
503
- case 'text':
504
- $list .= '<textarea style="width: 100%" rows="1" name="comments" placeholder="' . $placeholder . '"></textarea>';
505
- break;
506
- case 'textarea':
507
- $list .= '<textarea style="width: 100%" rows="2" name="comments" placeholder="' . $placeholder . '"></textarea>';
508
- break;
509
- }
510
- $list .= '</div>';
511
- }
512
- $list .= '</li>';
513
- }
514
-
515
- return '<div id="' . $this->product->get_key() . '">'
516
- . '<ul class="ti-list">' . $list . '</ul>'
517
- . '<div class="actions">'
518
- . get_submit_button(
519
- $button_submit, 'secondary', $this->product->get_key() . 'ti-deactivate-yes', false, array(
520
- 'data-after-text' => $button_submit,
521
- 'disabled' => true,
522
- )
523
- )
524
- . get_submit_button( $button_cancel, 'primary', $this->product->get_key() . 'ti-deactivate-no', false )
525
- . '</div></div>';
526
- }
527
-
528
- /**
529
- * Called when the deactivate button is clicked
530
- */
531
- function post_deactivate() {
532
- check_ajax_referer( (string) __CLASS__, 'nonce' );
533
-
534
- if ( ! empty( $_POST['id'] ) ) {
535
- $this->call_api(
536
- array(
537
- 'type' => 'deactivate',
538
- 'id' => $_POST['id'],
539
- 'comment' => isset( $_POST['msg'] ) ? $_POST['msg'] : '',
540
- )
541
- );
542
- }
543
-
544
- $this->post_deactivate_or_cancel();
545
- }
546
-
547
- /**
548
- * Called when the deactivate/cancel button is clicked
549
- */
550
- private function post_deactivate_or_cancel() {
551
- if ( isset( $_POST['type'] ) && isset( $_POST['key'] ) && 'theme' === $_POST['type'] ) {
552
- set_transient( 'ti_sdk_pause_' . $_POST['key'], true, PAUSE_DEACTIVATE_WINDOW_DAYS * DAY_IN_SECONDS );
553
- }
554
- }
555
- }
556
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback-factory.php DELETED
@@ -1,50 +0,0 @@
1
- <?php
2
- /**
3
- * The feedback factory class for ThemeIsle SDK
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Feedback
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- // Exit if accessed directly.
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
- if ( ! class_exists( 'ThemeIsle_SDK_Feedback_Factory' ) ) :
16
- /**
17
- * Feedback model for ThemeIsle SDK.
18
- */
19
- class ThemeIsle_SDK_Feedback_Factory {
20
-
21
- /**
22
- * @var array $instances collection of the instances that are registered with the factory
23
- */
24
- private $_instances = array();
25
-
26
- /**
27
- * ThemeIsle_SDK_Feedback_Factory constructor.
28
- *
29
- * @param ThemeIsle_SDK_Product $product_object Product Object.
30
- * @param array $feedback_types the feedback types.
31
- */
32
- public function __construct( $product_object, $feedback_types ) {
33
- if ( $product_object instanceof ThemeIsle_SDK_Product && $feedback_types && is_array( $feedback_types ) ) {
34
- foreach ( $feedback_types as $type ) {
35
- $class = 'ThemeIsle_SDK_Feedback_' . ucwords( $type );
36
- $instance = new $class( $product_object );
37
- $this->_instances[ $type ] = $instance;
38
- $instance->setup_hooks();
39
- }
40
- }
41
- }
42
-
43
- /**
44
- * Get the registered instances
45
- */
46
- public function get_instances() {
47
- return $this->_instances;
48
- }
49
- }
50
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback-review.php DELETED
@@ -1,209 +0,0 @@
1
- <?php
2
- /**
3
- * The review feedback model class for ThemeIsle SDK
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Feedback
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- // Exit if accessed directly.
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
- if ( ! class_exists( 'ThemeIsle_SDK_Feedback_Review' ) ) :
16
- /**
17
- * Deactivate feedback model for ThemeIsle SDK.
18
- */
19
- class ThemeIsle_SDK_Feedback_Review extends ThemeIsle_SDK_Feedback {
20
-
21
- /**
22
- * @var string $heading The heading of the modal
23
- */
24
- private $heading = 'Hey, it’s great to see you have <b>{product}</b> active for a few days now. How is everything going? If you can spare a few moments to rate it on WordPress.org it would help us a lot (and boost my motivation). Cheers! <br/> <br/>~ {developer}, developer of {product}';
25
-
26
- /**
27
- * @var string $msg The text of the modal
28
- */
29
- private $msg = '';
30
-
31
- /**
32
- * @var string $button_cancel The text of the cancel button
33
- */
34
- private $button_cancel = 'No, thanks.';
35
- /**
36
- * @var array Developers who work for each type of product for review purpose.
37
- */
38
- private $developers = array(
39
- 'plugin' => array( 'Marius', 'Bogdan' ),
40
- 'theme' => array( 'Rodica', 'Andrei', 'Bogdan', 'Cristi' ),
41
- );
42
- /**
43
- * @var string $button_already The text of the already did it button
44
- */
45
- private $button_do = 'Ok, I will gladly help.';
46
-
47
- /**
48
- * ThemeIsle_SDK_Feedback_Deactivate constructor.
49
- *
50
- * @param ThemeIsle_SDK_Product $product_object The product object.
51
- */
52
- public function __construct( $product_object ) {
53
- parent::__construct( $product_object );
54
- }
55
-
56
- /**
57
- * Registers the hooks
58
- */
59
- public function setup_hooks_child() {
60
- add_action( 'wp_ajax_' . $this->product->get_key() . __CLASS__, array( $this, 'dismiss' ) );
61
- }
62
-
63
- /**
64
- * Either we can notify or not.
65
- *
66
- * @return bool Notification available or not.
67
- */
68
- public function can_notify() {
69
- if ( ! $this->product->is_wordpress_available() ) {
70
- $this->disable();
71
-
72
- return false;
73
- }
74
- $show = get_option( $this->product->get_key() . '_review_flag', 'yes' );
75
- if ( 'no' === $show ) {
76
- return false;
77
- }
78
- $finally_show = apply_filters( $this->product->get_key() . '_feedback_review_trigger', true );
79
- if ( false !== $finally_show ) {
80
- if ( is_array( $finally_show ) && ! empty( $finally_show ) ) {
81
- $this->heading = $finally_show['heading'];
82
- $this->msg = $finally_show['msg'];
83
- }
84
- } else {
85
- return false;
86
- }
87
-
88
- return true;
89
- }
90
-
91
- /**
92
- * Shows the notification
93
- */
94
- function show_notification() {
95
- add_action( 'admin_notices', array( $this, 'admin_notices' ) );
96
- }
97
-
98
- /**
99
- * Shows the admin notice
100
- */
101
- function admin_notices() {
102
- $id = $this->product->get_key() . '_review';
103
-
104
- $this->add_css( $this->product->get_key() );
105
- $this->add_js( $this->product->get_key() );
106
-
107
- echo '<div class="notice notice-success is-dismissible" id="' . $id . '" ><div class="themeisle-review-box">' . $this->get_html( $this->product->get_key() ) . '</div></div>';
108
- }
109
-
110
- /**
111
- * Loads the css
112
- *
113
- * @param string $key The product key.
114
- */
115
- function add_css( $key ) {
116
- ?>
117
- <style type="text/css" id="<?php echo $key; ?>ti-review-css">
118
- #<?php echo $key; ?>-review-notification {
119
- padding-bottom: 5px;
120
- }
121
-
122
- #<?php echo $key; ?>-review-notification .review-dismiss {
123
- margin-left: 5px;
124
- }
125
- </style>
126
- <?php
127
- }
128
-
129
- /**
130
- * Loads the js
131
- *
132
- * @param string $key The product key.
133
- */
134
- function add_js( $key ) {
135
- ?>
136
- <script type="text/javascript" id="<?php echo $key; ?>ti-review-js">
137
- (function ($) {
138
- $(document).ready(function () {
139
- $('#<?php echo $key; ?>_review').on('click', '.notice-dismiss, .review-dismiss', function (e) {
140
-
141
- $.ajax({
142
- url: ajaxurl,
143
- method: "post",
144
- data: {
145
- 'nonce': '<?php echo wp_create_nonce( (string) __CLASS__ ); ?>',
146
- 'action': '<?php echo $this->product->get_key() . __CLASS__; ?>'
147
- },
148
- success: function () {
149
- $('#<?php echo $key; ?>_review').html('<p><b>Thanks for your answer.</b></p>');
150
- }
151
- });
152
- });
153
- });
154
- })(jQuery);
155
- </script>
156
- <?php
157
- }
158
-
159
- /**
160
- * Generates the HTML
161
- *
162
- * @param string $key The product key.
163
- */
164
- function get_html( $key ) {
165
- $link = 'https://wordpress.org/support/' . $this->product->get_type() . '/' . $this->product->get_slug() . '/reviews/#wporg-footer';
166
- $heading = apply_filters( $this->product->get_key() . '_feedback_review_heading', $this->heading );
167
- $heading = str_replace(
168
- array( '{product}' ),
169
- $this->product->get_friendly_name(), $heading
170
- );
171
- $heading = str_replace( '{developer}', $this->developers[ $this->product->get_type() ][ rand( 0, ( count( $this->developers[ $this->product->get_type() ] ) - 1 ) ) ], $heading );
172
-
173
- $button_cancel = apply_filters( $this->product->get_key() . '_feedback_review_button_cancel', $this->button_cancel );
174
- $button_do = apply_filters( $this->product->get_key() . '_feedback_review_button_do', $this->button_do );
175
- $msg = apply_filters( $this->product->get_key() . '_feedback_review_message', $this->msg );
176
-
177
- return '<div id="' . $this->product->get_key() . '-review-notification" class="themeisle-sdk-review-box">'
178
- . '<p>' . $heading . '</p>'
179
- . ( $msg ? '<p>' . $msg . '</p>' : '' )
180
- . '<div class="actions">'
181
- . '<a href="' . $link . '" target="_blank" class="button button-primary review-dismiss"> ' . $button_do . '</a>'
182
- . get_submit_button( $button_cancel, 'review-dismiss ' . $this->product->get_key() . '-ti-review', $this->product->get_key() . 'ti-review-no', false )
183
- . '</div></div>';
184
- }
185
-
186
- /**
187
- * Called when the either button is clicked
188
- */
189
- function dismiss() {
190
- check_ajax_referer( (string) __CLASS__, 'nonce' );
191
-
192
- $this->disable();
193
- }
194
-
195
- /**
196
- * Disables the notification
197
- */
198
- protected function disable() {
199
- update_option( $this->product->get_key() . '_review_flag', 'no' );
200
- }
201
-
202
- /**
203
- * Enables the notification
204
- */
205
- protected function enable() {
206
- update_option( $this->product->get_key() . '_review_flag', 'yes' );
207
- }
208
- }
209
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback-translate.php DELETED
@@ -1,983 +0,0 @@
1
- <?php
2
- /**
3
- * The Translate feedback model class for ThemeIsle SDK
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Feedback
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- // Exit if accessed directly.
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
- if ( ! class_exists( 'ThemeIsle_SDK_Feedback_Translate' ) ) :
16
- /**
17
- * Translate feedback model for ThemeIsle SDK.
18
- */
19
- class ThemeIsle_SDK_Feedback_Translate extends ThemeIsle_SDK_Feedback {
20
-
21
- /**
22
- * @var string $heading The heading of the modal
23
- */
24
- private $heading = 'Improve {product}';
25
- /**
26
- * @var string The message.
27
- */
28
- private $msg = 'Translating <b>{product}</b> into as many languages as possible is a huge project. We still need help with a lot of them, so if you are good at translating into <b>{language}</b>, it would be greatly appreciated.
29
- The process is easy, and you can join by following the link below!';
30
- /**
31
- * @var string $button_cancel The text of the cancel button
32
- */
33
- private $button_cancel = 'No, thanks.';
34
- /**
35
- * @var string $button_already The text of the already did it button
36
- */
37
- private $button_do = 'Ok, I will gladly help.';
38
- /**
39
- * @var array Array of available locals.
40
- */
41
- private $locales = array(
42
- 'af' => array(
43
- 'slug' => 'af',
44
- 'name' => 'Afrikaans',
45
- ),
46
- 'ak' => array(
47
- 'slug' => 'ak',
48
- 'name' => 'Akan',
49
- ),
50
- 'am' => array(
51
- 'slug' => 'am',
52
- 'name' => 'Amharic',
53
- ),
54
- 'ar' => array(
55
- 'slug' => 'ar',
56
- 'name' => 'Arabic',
57
- ),
58
- 'arq' => array(
59
- 'slug' => 'arq',
60
- 'name' => 'Algerian Arabic',
61
- ),
62
- 'ary' => array(
63
- 'slug' => 'ary',
64
- 'name' => 'Moroccan Arabic',
65
- ),
66
- 'as' => array(
67
- 'slug' => 'as',
68
- 'name' => 'Assamese',
69
- ),
70
- 'ast' => array(
71
- 'slug' => 'ast',
72
- 'name' => 'Asturian',
73
- ),
74
- 'az' => array(
75
- 'slug' => 'az',
76
- 'name' => 'Azerbaijani',
77
- ),
78
- 'azb' => array(
79
- 'slug' => 'azb',
80
- 'name' => 'South Azerbaijani',
81
- ),
82
- 'az_TR' => array(
83
- 'slug' => 'az-tr',
84
- 'name' => 'Azerbaijani (Turkey)',
85
- ),
86
- 'ba' => array(
87
- 'slug' => 'ba',
88
- 'name' => 'Bashkir',
89
- ),
90
- 'bal' => array(
91
- 'slug' => 'bal',
92
- 'name' => 'Catalan (Balear)',
93
- ),
94
- 'bcc' => array(
95
- 'slug' => 'bcc',
96
- 'name' => 'Balochi Southern',
97
- ),
98
- 'bel' => array(
99
- 'slug' => 'bel',
100
- 'name' => 'Belarusian',
101
- ),
102
- 'bg_BG' => array(
103
- 'slug' => 'bg',
104
- 'name' => 'Bulgarian',
105
- ),
106
- 'bn_BD' => array(
107
- 'slug' => 'bn',
108
- 'name' => 'Bengali',
109
- ),
110
- 'bo' => array(
111
- 'slug' => 'bo',
112
- 'name' => 'Tibetan',
113
- ),
114
- 'bre' => array(
115
- 'slug' => 'br',
116
- 'name' => 'Breton',
117
- ),
118
- 'bs_BA' => array(
119
- 'slug' => 'bs',
120
- 'name' => 'Bosnian',
121
- ),
122
- 'ca' => array(
123
- 'slug' => 'ca',
124
- 'name' => 'Catalan',
125
- ),
126
- 'ceb' => array(
127
- 'slug' => 'ceb',
128
- 'name' => 'Cebuano',
129
- ),
130
- 'ckb' => array(
131
- 'slug' => 'ckb',
132
- 'name' => 'Kurdish (Sorani)',
133
- ),
134
- 'co' => array(
135
- 'slug' => 'co',
136
- 'name' => 'Corsican',
137
- ),
138
- 'cs_CZ' => array(
139
- 'slug' => 'cs',
140
- 'name' => 'Czech',
141
- ),
142
- 'cy' => array(
143
- 'slug' => 'cy',
144
- 'name' => 'Welsh',
145
- ),
146
- 'da_DK' => array(
147
- 'slug' => 'da',
148
- 'name' => 'Danish',
149
- ),
150
- 'de_DE' => array(
151
- 'slug' => 'de',
152
- 'name' => 'German',
153
- ),
154
- 'de_CH' => array(
155
- 'slug' => 'de-ch',
156
- 'name' => 'German (Switzerland)',
157
- ),
158
- 'dv' => array(
159
- 'slug' => 'dv',
160
- 'name' => 'Dhivehi',
161
- ),
162
- 'dzo' => array(
163
- 'slug' => 'dzo',
164
- 'name' => 'Dzongkha',
165
- ),
166
- 'el' => array(
167
- 'slug' => 'el',
168
- 'name' => 'Greek',
169
- ),
170
- 'art_xemoji' => array(
171
- 'slug' => 'art-xemoji',
172
- 'name' => 'Emoji',
173
- ),
174
- 'en_US' => array(
175
- 'slug' => 'en',
176
- 'name' => 'English',
177
- ),
178
- 'en_AU' => array(
179
- 'slug' => 'en-au',
180
- 'name' => 'English (Australia)',
181
- ),
182
- 'en_CA' => array(
183
- 'slug' => 'en-ca',
184
- 'name' => 'English (Canada)',
185
- ),
186
- 'en_GB' => array(
187
- 'slug' => 'en-gb',
188
- 'name' => 'English (UK)',
189
- ),
190
- 'en_NZ' => array(
191
- 'slug' => 'en-nz',
192
- 'name' => 'English (New Zealand)',
193
- ),
194
- 'en_ZA' => array(
195
- 'slug' => 'en-za',
196
- 'name' => 'English (South Africa)',
197
- ),
198
- 'eo' => array(
199
- 'slug' => 'eo',
200
- 'name' => 'Esperanto',
201
- ),
202
- 'es_ES' => array(
203
- 'slug' => 'es',
204
- 'name' => 'Spanish (Spain)',
205
- ),
206
- 'es_AR' => array(
207
- 'slug' => 'es-ar',
208
- 'name' => 'Spanish (Argentina)',
209
- ),
210
- 'es_CL' => array(
211
- 'slug' => 'es-cl',
212
- 'name' => 'Spanish (Chile)',
213
- ),
214
- 'es_CO' => array(
215
- 'slug' => 'es-co',
216
- 'name' => 'Spanish (Colombia)',
217
- ),
218
- 'es_CR' => array(
219
- 'slug' => 'es-cr',
220
- 'name' => 'Spanish (Costa Rica)',
221
- ),
222
- 'es_GT' => array(
223
- 'slug' => 'es-gt',
224
- 'name' => 'Spanish (Guatemala)',
225
- ),
226
- 'es_MX' => array(
227
- 'slug' => 'es-mx',
228
- 'name' => 'Spanish (Mexico)',
229
- ),
230
- 'es_PE' => array(
231
- 'slug' => 'es-pe',
232
- 'name' => 'Spanish (Peru)',
233
- ),
234
- 'es_PR' => array(
235
- 'slug' => 'es-pr',
236
- 'name' => 'Spanish (Puerto Rico)',
237
- ),
238
- 'es_VE' => array(
239
- 'slug' => 'es-ve',
240
- 'name' => 'Spanish (Venezuela)',
241
- ),
242
- 'et' => array(
243
- 'slug' => 'et',
244
- 'name' => 'Estonian',
245
- ),
246
- 'eu' => array(
247
- 'slug' => 'eu',
248
- 'name' => 'Basque',
249
- ),
250
- 'fa_IR' => array(
251
- 'slug' => 'fa',
252
- 'name' => 'Persian',
253
- ),
254
- 'fa_AF' => array(
255
- 'slug' => 'fa-af',
256
- 'name' => 'Persian (Afghanistan)',
257
- ),
258
- 'fuc' => array(
259
- 'slug' => 'fuc',
260
- 'name' => 'Fulah',
261
- ),
262
- 'fi' => array(
263
- 'slug' => 'fi',
264
- 'name' => 'Finnish',
265
- ),
266
- 'fo' => array(
267
- 'slug' => 'fo',
268
- 'name' => 'Faroese',
269
- ),
270
- 'fr_FR' => array(
271
- 'slug' => 'fr',
272
- 'name' => 'French (France)',
273
- ),
274
- 'fr_BE' => array(
275
- 'slug' => 'fr-be',
276
- 'name' => 'French (Belgium)',
277
- ),
278
- 'fr_CA' => array(
279
- 'slug' => 'fr-ca',
280
- 'name' => 'French (Canada)',
281
- ),
282
- 'frp' => array(
283
- 'slug' => 'frp',
284
- 'name' => 'Arpitan',
285
- ),
286
- 'fur' => array(
287
- 'slug' => 'fur',
288
- 'name' => 'Friulian',
289
- ),
290
- 'fy' => array(
291
- 'slug' => 'fy',
292
- 'name' => 'Frisian',
293
- ),
294
- 'ga' => array(
295
- 'slug' => 'ga',
296
- 'name' => 'Irish',
297
- ),
298
- 'gd' => array(
299
- 'slug' => 'gd',
300
- 'name' => 'Scottish Gaelic',
301
- ),
302
- 'gl_ES' => array(
303
- 'slug' => 'gl',
304
- 'name' => 'Galician',
305
- ),
306
- 'gn' => array(
307
- 'slug' => 'gn',
308
- 'name' => 'Guaraní',
309
- ),
310
- 'gsw' => array(
311
- 'slug' => 'gsw',
312
- 'name' => 'Swiss German',
313
- ),
314
- 'gu' => array(
315
- 'slug' => 'gu',
316
- 'name' => 'Gujarati',
317
- ),
318
- 'hat' => array(
319
- 'slug' => 'hat',
320
- 'name' => 'Haitian Creole',
321
- ),
322
- 'hau' => array(
323
- 'slug' => 'hau',
324
- 'name' => 'Hausa',
325
- ),
326
- 'haw_US' => array(
327
- 'slug' => 'haw',
328
- 'name' => 'Hawaiian',
329
- ),
330
- 'haz' => array(
331
- 'slug' => 'haz',
332
- 'name' => 'Hazaragi',
333
- ),
334
- 'he_IL' => array(
335
- 'slug' => 'he',
336
- 'name' => 'Hebrew',
337
- ),
338
- 'hi_IN' => array(
339
- 'slug' => 'hi',
340
- 'name' => 'Hindi',
341
- ),
342
- 'hr' => array(
343
- 'slug' => 'hr',
344
- 'name' => 'Croatian',
345
- ),
346
- 'hu_HU' => array(
347
- 'slug' => 'hu',
348
- 'name' => 'Hungarian',
349
- ),
350
- 'hy' => array(
351
- 'slug' => 'hy',
352
- 'name' => 'Armenian',
353
- ),
354
- 'id_ID' => array(
355
- 'slug' => 'id',
356
- 'name' => 'Indonesian',
357
- ),
358
- 'ido' => array(
359
- 'slug' => 'ido',
360
- 'name' => 'Ido',
361
- ),
362
- 'is_IS' => array(
363
- 'slug' => 'is',
364
- 'name' => 'Icelandic',
365
- ),
366
- 'it_IT' => array(
367
- 'slug' => 'it',
368
- 'name' => 'Italian',
369
- ),
370
- 'ja' => array(
371
- 'slug' => 'ja',
372
- 'name' => 'Japanese',
373
- ),
374
- 'jv_ID' => array(
375
- 'slug' => 'jv',
376
- 'name' => 'Javanese',
377
- ),
378
- 'ka_GE' => array(
379
- 'slug' => 'ka',
380
- 'name' => 'Georgian',
381
- ),
382
- 'kab' => array(
383
- 'slug' => 'kab',
384
- 'name' => 'Kabyle',
385
- ),
386
- 'kal' => array(
387
- 'slug' => 'kal',
388
- 'name' => 'Greenlandic',
389
- ),
390
- 'kin' => array(
391
- 'slug' => 'kin',
392
- 'name' => 'Kinyarwanda',
393
- ),
394
- 'kk' => array(
395
- 'slug' => 'kk',
396
- 'name' => 'Kazakh',
397
- ),
398
- 'km' => array(
399
- 'slug' => 'km',
400
- 'name' => 'Khmer',
401
- ),
402
- 'kn' => array(
403
- 'slug' => 'kn',
404
- 'name' => 'Kannada',
405
- ),
406
- 'ko_KR' => array(
407
- 'slug' => 'ko',
408
- 'name' => 'Korean',
409
- ),
410
- 'kir' => array(
411
- 'slug' => 'kir',
412
- 'name' => 'Kyrgyz',
413
- ),
414
- 'lb_LU' => array(
415
- 'slug' => 'lb',
416
- 'name' => 'Luxembourgish',
417
- ),
418
- 'li' => array(
419
- 'slug' => 'li',
420
- 'name' => 'Limburgish',
421
- ),
422
- 'lin' => array(
423
- 'slug' => 'lin',
424
- 'name' => 'Lingala',
425
- ),
426
- 'lo' => array(
427
- 'slug' => 'lo',
428
- 'name' => 'Lao',
429
- ),
430
- 'lt_LT' => array(
431
- 'slug' => 'lt',
432
- 'name' => 'Lithuanian',
433
- ),
434
- 'lv' => array(
435
- 'slug' => 'lv',
436
- 'name' => 'Latvian',
437
- ),
438
- 'me_ME' => array(
439
- 'slug' => 'me',
440
- 'name' => 'Montenegrin',
441
- ),
442
- 'mg_MG' => array(
443
- 'slug' => 'mg',
444
- 'name' => 'Malagasy',
445
- ),
446
- 'mk_MK' => array(
447
- 'slug' => 'mk',
448
- 'name' => 'Macedonian',
449
- ),
450
- 'ml_IN' => array(
451
- 'slug' => 'ml',
452
- 'name' => 'Malayalam',
453
- ),
454
- 'mlt' => array(
455
- 'slug' => 'mlt',
456
- 'name' => 'Maltese',
457
- ),
458
- 'mn' => array(
459
- 'slug' => 'mn',
460
- 'name' => 'Mongolian',
461
- ),
462
- 'mr' => array(
463
- 'slug' => 'mr',
464
- 'name' => 'Marathi',
465
- ),
466
- 'mri' => array(
467
- 'slug' => 'mri',
468
- 'name' => 'Maori',
469
- ),
470
- 'ms_MY' => array(
471
- 'slug' => 'ms',
472
- 'name' => 'Malay',
473
- ),
474
- 'my_MM' => array(
475
- 'slug' => 'mya',
476
- 'name' => 'Myanmar (Burmese)',
477
- ),
478
- 'ne_NP' => array(
479
- 'slug' => 'ne',
480
- 'name' => 'Nepali',
481
- ),
482
- 'nb_NO' => array(
483
- 'slug' => 'nb',
484
- 'name' => 'Norwegian (Bokmål)',
485
- ),
486
- 'nl_NL' => array(
487
- 'slug' => 'nl',
488
- 'name' => 'Dutch',
489
- ),
490
- 'nl_BE' => array(
491
- 'slug' => 'nl-be',
492
- 'name' => 'Dutch (Belgium)',
493
- ),
494
- 'nn_NO' => array(
495
- 'slug' => 'nn',
496
- 'name' => 'Norwegian (Nynorsk)',
497
- ),
498
- 'oci' => array(
499
- 'slug' => 'oci',
500
- 'name' => 'Occitan',
501
- ),
502
- 'ory' => array(
503
- 'slug' => 'ory',
504
- 'name' => 'Oriya',
505
- ),
506
- 'os' => array(
507
- 'slug' => 'os',
508
- 'name' => 'Ossetic',
509
- ),
510
- 'pa_IN' => array(
511
- 'slug' => 'pa',
512
- 'name' => 'Punjabi',
513
- ),
514
- 'pl_PL' => array(
515
- 'slug' => 'pl',
516
- 'name' => 'Polish',
517
- ),
518
- 'pt_BR' => array(
519
- 'slug' => 'pt-br',
520
- 'name' => 'Portuguese (Brazil)',
521
- ),
522
- 'pt_PT' => array(
523
- 'slug' => 'pt',
524
- 'name' => 'Portuguese (Portugal)',
525
- ),
526
- 'ps' => array(
527
- 'slug' => 'ps',
528
- 'name' => 'Pashto',
529
- ),
530
- 'rhg' => array(
531
- 'slug' => 'rhg',
532
- 'name' => 'Rohingya',
533
- ),
534
- 'ro_RO' => array(
535
- 'slug' => 'ro',
536
- 'name' => 'Romanian',
537
- ),
538
- 'roh' => array(
539
- 'slug' => 'roh',
540
- 'name' => 'Romansh',
541
- ),
542
- 'ru_RU' => array(
543
- 'slug' => 'ru',
544
- 'name' => 'Russian',
545
- ),
546
- 'rue' => array(
547
- 'slug' => 'rue',
548
- 'name' => 'Rusyn',
549
- ),
550
- 'rup_MK' => array(
551
- 'slug' => 'rup',
552
- 'name' => 'Aromanian',
553
- ),
554
- 'sah' => array(
555
- 'slug' => 'sah',
556
- 'name' => 'Sakha',
557
- ),
558
- 'sa_IN' => array(
559
- 'slug' => 'sa-in',
560
- 'name' => 'Sanskrit',
561
- ),
562
- 'scn' => array(
563
- 'slug' => 'scn',
564
- 'name' => 'Sicilian',
565
- ),
566
- 'si_LK' => array(
567
- 'slug' => 'si',
568
- 'name' => 'Sinhala',
569
- ),
570
- 'sk_SK' => array(
571
- 'slug' => 'sk',
572
- 'name' => 'Slovak',
573
- ),
574
- 'sl_SI' => array(
575
- 'slug' => 'sl',
576
- 'name' => 'Slovenian',
577
- ),
578
- 'sna' => array(
579
- 'slug' => 'sna',
580
- 'name' => 'Shona',
581
- ),
582
- 'snd' => array(
583
- 'slug' => 'snd',
584
- 'name' => 'Sindhi',
585
- ),
586
- 'so_SO' => array(
587
- 'slug' => 'so',
588
- 'name' => 'Somali',
589
- ),
590
- 'sq' => array(
591
- 'slug' => 'sq',
592
- 'name' => 'Albanian',
593
- ),
594
- 'sq_XK' => array(
595
- 'slug' => 'sq-xk',
596
- 'name' => 'Shqip (Kosovo)',
597
- ),
598
- 'sr_RS' => array(
599
- 'slug' => 'sr',
600
- 'name' => 'Serbian',
601
- ),
602
- 'srd' => array(
603
- 'slug' => 'srd',
604
- 'name' => 'Sardinian',
605
- ),
606
- 'su_ID' => array(
607
- 'slug' => 'su',
608
- 'name' => 'Sundanese',
609
- ),
610
- 'sv_SE' => array(
611
- 'slug' => 'sv',
612
- 'name' => 'Swedish',
613
- ),
614
- 'sw' => array(
615
- 'slug' => 'sw',
616
- 'name' => 'Swahili',
617
- ),
618
- 'syr' => array(
619
- 'slug' => 'syr',
620
- 'name' => 'Syriac',
621
- ),
622
- 'szl' => array(
623
- 'slug' => 'szl',
624
- 'name' => 'Silesian',
625
- ),
626
- 'ta_IN' => array(
627
- 'slug' => 'ta',
628
- 'name' => 'Tamil',
629
- ),
630
- 'ta_LK' => array(
631
- 'slug' => 'ta-lk',
632
- 'name' => 'Tamil (Sri Lanka)',
633
- ),
634
- 'tah' => array(
635
- 'slug' => 'tah',
636
- 'name' => 'Tahitian',
637
- ),
638
- 'te' => array(
639
- 'slug' => 'te',
640
- 'name' => 'Telugu',
641
- ),
642
- 'tg' => array(
643
- 'slug' => 'tg',
644
- 'name' => 'Tajik',
645
- ),
646
- 'th' => array(
647
- 'slug' => 'th',
648
- 'name' => 'Thai',
649
- ),
650
- 'tir' => array(
651
- 'slug' => 'tir',
652
- 'name' => 'Tigrinya',
653
- ),
654
- 'tl' => array(
655
- 'slug' => 'tl',
656
- 'name' => 'Tagalog',
657
- ),
658
- 'tr_TR' => array(
659
- 'slug' => 'tr',
660
- 'name' => 'Turkish',
661
- ),
662
- 'tt_RU' => array(
663
- 'slug' => 'tt',
664
- 'name' => 'Tatar',
665
- ),
666
- 'tuk' => array(
667
- 'slug' => 'tuk',
668
- 'name' => 'Turkmen',
669
- ),
670
- 'twd' => array(
671
- 'slug' => 'twd',
672
- 'name' => 'Tweants',
673
- ),
674
- 'tzm' => array(
675
- 'slug' => 'tzm',
676
- 'name' => 'Tamazight (Central Atlas)',
677
- ),
678
- 'ug_CN' => array(
679
- 'slug' => 'ug',
680
- 'name' => 'Uighur',
681
- ),
682
- 'uk' => array(
683
- 'slug' => 'uk',
684
- 'name' => 'Ukrainian',
685
- ),
686
- 'ur' => array(
687
- 'slug' => 'ur',
688
- 'name' => 'Urdu',
689
- ),
690
- 'uz_UZ' => array(
691
- 'slug' => 'uz',
692
- 'name' => 'Uzbek',
693
- ),
694
- 'vi' => array(
695
- 'slug' => 'vi',
696
- 'name' => 'Vietnamese',
697
- ),
698
- 'wa' => array(
699
- 'slug' => 'wa',
700
- 'name' => 'Walloon',
701
- ),
702
- 'xho' => array(
703
- 'slug' => 'xho',
704
- 'name' => 'Xhosa',
705
- ),
706
- 'xmf' => array(
707
- 'slug' => 'xmf',
708
- 'name' => 'Mingrelian',
709
- ),
710
- 'yor' => array(
711
- 'slug' => 'yor',
712
- 'name' => 'Yoruba',
713
- ),
714
- 'zh_CN' => array(
715
- 'slug' => 'zh-cn',
716
- 'name' => 'Chinese (China)',
717
- ),
718
- 'zh_HK' => array(
719
- 'slug' => 'zh-hk',
720
- 'name' => 'Chinese (Hong Kong)',
721
- ),
722
- 'zh_TW' => array(
723
- 'slug' => 'zh-tw',
724
- 'name' => 'Chinese (Taiwan)',
725
- ),
726
- 'de_DE_formal' => array(
727
- 'slug' => 'de/formal',
728
- 'name' => 'German (Formal)',
729
- ),
730
- 'nl_NL_formal' => array(
731
- 'slug' => 'nl/formal',
732
- 'name' => 'Dutch (Formal)',
733
- ),
734
- 'de_CH_informal' => array(
735
- 'slug' => 'de-ch/informal',
736
- 'name' => 'Chinese (Taiwan)',
737
- ),
738
- 'pt_PT_ao90' => array(
739
- 'slug' => 'pt/ao90',
740
- 'name' => 'Portuguese (Portugal, AO90)',
741
- ),
742
- );
743
-
744
- /**
745
- * ThemeIsle_SDK_Feedback_Translate constructor.
746
- *
747
- * @param ThemeIsle_SDK_Product $product_object The product object.
748
- */
749
- public function __construct( $product_object ) {
750
- parent::__construct( $product_object );
751
- }
752
-
753
- /**
754
- * Return the locale path.
755
- *
756
- * @param string $locale Locale code.
757
- *
758
- * @return string Locale path.
759
- */
760
- private function get_locale_paths( $locale ) {
761
- if ( empty( $locale ) ) {
762
- return '';
763
- }
764
-
765
- $slug = isset( $this->locales[ $locale ] ) ? $this->locales[ $locale ]['slug'] : '';
766
- if ( empty( $slug ) ) {
767
- return '';
768
- }
769
- if ( strpos( $slug, '/' ) === false ) {
770
- $slug .= '/default';
771
- }
772
- $url = 'https://translate.wordpress.org/projects/wp-' . $this->product->get_type() . 's/' . $this->product->get_slug() . '/' . ( $this->product->get_type() === 'plugin' ? 'dev/' : '' ) . $slug . '?filters%5Bstatus%5D=untranslated&sort%5Bby%5D=random';
773
-
774
- return $url;
775
- }
776
-
777
- /**
778
- * Registers the hooks
779
- */
780
- public function setup_hooks_child() {
781
- add_action( 'wp_ajax_' . $this->product->get_key() . __CLASS__, array( $this, 'dismiss' ) );
782
- }
783
-
784
- /**
785
- * Either we should show the notification or not.
786
- *
787
- * @return bool Valid notification.
788
- */
789
- function can_notify() {
790
- if ( ! $this->product->is_wordpress_available() ) {
791
- $this->disable();
792
- return false;
793
- }
794
- $show = get_option( $this->product->get_key() . '_translate_flag', 'yes' );
795
- if ( 'no' === $show ) {
796
- return false;
797
- }
798
- $lang = $this->get_user_locale();
799
- if ( 'en_US' === $lang ) {
800
- return false;
801
- }
802
- $languages = $this->get_translations();
803
- if ( ! is_array( $languages ) ) {
804
- return false;
805
- }
806
- if ( ! isset( $languages['translations'] ) ) {
807
- return false;
808
- }
809
-
810
- $languages = $languages['translations'];
811
- $available = wp_list_pluck( $languages, 'language' );
812
- if ( in_array( $lang, $available ) ) {
813
- return false;
814
- }
815
- if ( ! isset( $this->locales[ $lang ] ) ) {
816
- return false;
817
- }
818
-
819
- return true;
820
- }
821
-
822
- /**
823
- * Get the user's locale.
824
- */
825
- private function get_user_locale() {
826
- global $wp_version;
827
- if ( version_compare( $wp_version, '4.7.0', '>=' ) ) {
828
- return get_user_locale();
829
- }
830
- $user = wp_get_current_user();
831
- if ( $user ) {
832
- $locale = $user->locale;
833
- }
834
- return $locale ? $locale : get_locale();
835
- }
836
-
837
- /**
838
- * Shows the notification
839
- */
840
- function show_notification() {
841
- add_action( 'admin_notices', array( $this, 'admin_notices' ) );
842
- }
843
-
844
- /**
845
- * Shows the admin notice
846
- */
847
- function admin_notices() {
848
- $id = $this->product->get_key() . '_translate';
849
-
850
- $this->add_css( $this->product->get_key() );
851
- $this->add_js( $this->product->get_key() );
852
- $html = $this->get_html( $this->product->get_key() );
853
-
854
- if ( $html ) {
855
- echo '<div class="notice notice-success is-dismissible" id="' . $id . '" ><div class="themeisle-translate-box">' . $html . '</div></div>';
856
- }
857
- }
858
-
859
- /**
860
- * Loads the css
861
- *
862
- * @param string $key The product key.
863
- */
864
- function add_css( $key ) {
865
- ?>
866
- <style type="text/css" id="<?php echo $key; ?>ti-translate-css">
867
- </style>
868
- <?php
869
- }
870
-
871
- /**
872
- * Loads the js
873
- *
874
- * @param string $key The product key.
875
- */
876
- function add_js( $key ) {
877
- ?>
878
- <script type="text/javascript" id="<?php echo $key; ?>ti-translate-js">
879
- (function ($) {
880
- $(document).ready(function () {
881
- $('#<?php echo $key; ?>_translate').on('click', '.translate-dismiss', function (e) {
882
-
883
- $.ajax({
884
- url: ajaxurl,
885
- method: "post",
886
- data: {
887
- 'nonce': '<?php echo wp_create_nonce( (string) __CLASS__ ); ?>',
888
- 'action': '<?php echo $this->product->get_key() . __CLASS__; ?>'
889
- },
890
- success: function () {
891
- $('#<?php echo $key; ?>_translate').html('<p><b>Thanks for your answer.</b></p>');
892
- }
893
- });
894
- });
895
- });
896
- })(jQuery);
897
- </script>
898
- <?php
899
- }
900
-
901
- /**
902
- * Fetch translations from api.
903
- *
904
- * @return mixed Translation array.
905
- */
906
- private function get_translations() {
907
- $cache_key = $this->product->get_key() . '_all_languages';
908
- $translations = get_transient( $cache_key );
909
-
910
- if ( $translations === false ) {
911
- require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
912
- $translations = translations_api(
913
- $this->product->get_type() . 's',
914
- array(
915
- 'slug' => $this->product->get_slug(),
916
- 'version' => $this->product->get_version(),
917
- )
918
- );
919
- set_transient( $cache_key, $translations, WEEK_IN_SECONDS );
920
- }
921
-
922
- return $translations;
923
-
924
- }
925
-
926
- /**
927
- * Generates the HTML
928
- *
929
- * @param string $key The product key.
930
- *
931
- * @return void|string Html code of the notification.
932
- */
933
- function get_html( $key ) {
934
- $lang = $this->get_user_locale();
935
- $link = $this->get_locale_paths( $lang );
936
- $heading = apply_filters( $this->product->get_key() . '_feedback_translate_heading', $this->heading );
937
- $product = $this->product->get_friendly_name();
938
- $heading = str_replace(
939
- array( '{product}' ),
940
- $product, $heading
941
- );
942
-
943
- $message = apply_filters( $this->product->get_key() . '_feedback_translation', $this->msg );
944
- $language_meta = $this->locales[ $lang ];
945
- $message = str_replace( '{language}', $language_meta['name'], $message );
946
- $message = str_replace( '{product}', $product, $message );
947
- $button_cancel = apply_filters( $this->product->get_key() . '_feedback_translate_button_cancel', $this->button_cancel );
948
- $button_do = apply_filters( $this->product->get_key() . '_feedback_translate_button_do', $this->button_do );
949
-
950
- return '<div id="' . $this->product->get_key() . '-translate-notification" class="themeisle-sdk-translate-box">'
951
- . '<h2>' . $heading . '</h2>'
952
- . '<p>' . $message . '</p>'
953
- . '<div class="actions">'
954
- . '<a href="' . $link . '" target="_blank" class="button button-primary translate-dismiss"> ' . $button_do . '</a>&nbsp;'
955
- . get_submit_button( $button_cancel, 'translate-dismiss ' . $this->product->get_key() . '-ti-translate', $this->product->get_key() . 'ti-translate-no', false )
956
- . '</div></br></div>';
957
- }
958
-
959
- /**
960
- * Called when the either button is clicked
961
- */
962
- function dismiss() {
963
- check_ajax_referer( (string) __CLASS__, 'nonce' );
964
-
965
- $this->disable();
966
- }
967
-
968
- /**
969
- * Disables the notification
970
- */
971
- protected function disable() {
972
-
973
- update_option( $this->product->get_key() . '_translate_flag', 'no' );
974
- }
975
-
976
- /**
977
- * Enables the notification
978
- */
979
- protected function enable() {
980
- update_option( $this->product->get_key() . '_translate_flag', 'yes' );
981
- }
982
- }
983
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback.php DELETED
@@ -1,90 +0,0 @@
1
- <?php
2
- /**
3
- * The feedback model class for ThemeIsle SDK
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Feedback
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- // Exit if accessed directly.
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
- if ( ! class_exists( 'ThemeIsle_SDK_Feedback' ) ) :
16
- /**
17
- * Feedback model for ThemeIsle SDK.
18
- */
19
- abstract class ThemeIsle_SDK_Feedback {
20
- /**
21
- * @var ThemeIsle_SDK_Product $product Themeisle Product.
22
- */
23
- protected $product;
24
-
25
- /**
26
- * @var string $feedback_url Url where to send the feedback
27
- */
28
- private $feedback_url = 'http://feedback.themeisle.com/wordpress/wp-json/__pirate_feedback_/v1/feedback';
29
-
30
- /**
31
- * ThemeIsle_SDK_Feedback constructor.
32
- *
33
- * @param ThemeIsle_SDK_Product $product_object Product Object.
34
- */
35
- public function __construct( $product_object ) {
36
- if ( $product_object instanceof ThemeIsle_SDK_Product ) {
37
- $this->product = $product_object;
38
- }
39
- $this->setup_hooks();
40
- }
41
-
42
- /**
43
- * Registers the hooks and then delegates to the child
44
- */
45
- public function setup_hooks() {
46
- $this->setup_hooks_child();
47
- }
48
-
49
- /**
50
- * Calls the API
51
- *
52
- * @param string $attributes The attributes of the post body.
53
- */
54
- protected function call_api( $attributes ) {
55
- $slug = $this->product->get_slug();
56
- $version = $this->product->get_version();
57
- $attributes['slug'] = $slug;
58
- $attributes['version'] = $version;
59
-
60
- $response = wp_remote_post(
61
- $this->feedback_url, array(
62
- 'body' => $attributes,
63
- )
64
- );
65
- }
66
-
67
- /**
68
- * Randomizes the options array
69
- *
70
- * @param array $options The options array.
71
- */
72
- function randomize_options( $options ) {
73
- $new = array();
74
- $keys = array_keys( $options );
75
- shuffle( $keys );
76
-
77
- foreach ( $keys as $key ) {
78
- $new[ $key ] = $options[ $key ];
79
- }
80
-
81
- return $new;
82
- }
83
-
84
- /**
85
- * Abstract function for delegating to the child
86
- */
87
- protected abstract function setup_hooks_child();
88
-
89
- }
90
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-licenser.php DELETED
@@ -1,686 +0,0 @@
1
- <?php
2
- /**
3
- * The main loader class for license handling.
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Licenser
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- if ( ! class_exists( 'ThemeIsle_SDK_Licenser' ) ) :
12
- /**
13
- * Class ThemeIsle_SDK_Licenser
14
- *
15
- * Used to update the themeisle products
16
- */
17
- class ThemeIsle_SDK_Licenser {
18
-
19
- /**
20
- * @var string $license_key The license key string
21
- */
22
- public $license_key;
23
-
24
- /**
25
- * @var bool $do_check This ensures that the custom API request only runs on the second time that WP fires the update check
26
- */
27
- private $do_check = false;
28
-
29
- /**
30
- * @var bool $failed_checks Number of failed checks to the api endpoint
31
- */
32
- private $failed_checks = 0;
33
- /**
34
- * @var ThemeIsle_SDK_Product $product The ThemeIsle Product.
35
- */
36
- private $product;
37
- /**
38
- * @var string $product_key The product update response key.
39
- */
40
- private $product_key;
41
- /**
42
- * @var int $max_failed Maximum failed checks allowed before show the notice
43
- */
44
- private static $max_failed = 5;
45
-
46
- /**
47
- * ThemeIsle_SDK_Licenser constructor.
48
- *
49
- * @param ThemeIsle_SDK_Product $product The product object.
50
- */
51
- public function __construct( $product ) {
52
- $this->product = $product;
53
-
54
- $this->product_key = $this->product->get_key() . '-update-response';
55
- if ( ! $this->product->requires_license() ) {
56
- $this->license_key = 'free';
57
- } else {
58
- $license_data = get_option( $this->product->get_key() . '_license_data', '' );
59
- $this->failed_checks = intval( get_option( $this->product->get_key() . '_failed_checks', 0 ) );
60
- if ( $license_data !== '' ) {
61
- $this->license_key = isset( $license_data->key ) ? $license_data->key : get_option( $this->product->get_key() . '_license', '' );
62
- } else {
63
- $this->license_key = get_option( $this->product->get_key() . '_license', '' );
64
- }
65
- $this->register_license_hooks();
66
- }
67
- }
68
-
69
- /**
70
- * Register license hooks for the themeisle products
71
- */
72
- public function register_license_hooks() {
73
- add_action( 'admin_init', array( $this, 'register_settings' ) );
74
- add_action( 'admin_init', array( $this, 'activate_license' ) );
75
- add_action( 'admin_init', array( $this, 'product_valid' ), 99999999 );
76
- add_action( 'admin_notices', array( $this, 'show_notice' ) );
77
- add_filter( $this->product->get_key() . '_license_status', array( $this, 'get_license_status' ) );
78
- }
79
-
80
- /**
81
- * @param string $r Update payload.
82
- * @param string $url The api url.
83
- *
84
- * @return mixed List of themes to check for update.
85
- */
86
- function disable_wporg_update( $r, $url ) {
87
-
88
- if ( 0 !== strpos( $url, 'https://api.wordpress.org/themes/update-check/' ) ) {
89
- return $r;
90
- }
91
-
92
- // Decode the JSON response
93
- $themes = json_decode( $r['body']['themes'] );
94
-
95
- unset( $themes->themes->{$this->product->get_slug()} );
96
-
97
- // Encode the updated JSON response
98
- $r['body']['themes'] = json_encode( $themes );
99
-
100
- return $r;
101
- }
102
-
103
- /**
104
- * Register the setting for the license of the product
105
- *
106
- * @return bool
107
- */
108
- public function register_settings() {
109
- if ( ! is_admin() ) {
110
- return false;
111
- }
112
- add_settings_field(
113
- $this->product->get_key() . '_license',
114
- $this->product->get_name() . ' license',
115
- array( $this, 'license_view' ),
116
- 'general'
117
- );
118
- }
119
-
120
- /**
121
- * The license view field
122
- */
123
- public function license_view() {
124
- $status = $this->get_license_status();
125
- $value = $this->license_key;
126
-
127
- $activate_string = apply_filters( $this->product->get_key() . '_lc_activate_string', 'Activate' );
128
- $deactivate_string = apply_filters( $this->product->get_key() . '_lc_deactivate_string', 'Deactivate' );
129
- $valid_string = apply_filters( $this->product->get_key() . '_lc_valid_string', 'Valid' );
130
- $invalid_string = apply_filters( $this->product->get_key() . '_lc_invalid_string', 'Invalid' );
131
- $license_message = apply_filters( $this->product->get_key() . '_lc_license_message', 'Enter your license from %s purchase history in order to get %s updates' );
132
-
133
- echo '<p ><input ' . ( ( $status === 'valid' ) ? ( 'style="border:1px solid #7ad03a; "' ) : '' ) . ' type="text" id="' . $this->product->get_key() . '_license" name="' . $this->product->get_key() . '_license" value="' . $value . '" /><a ' . ( ( $status === 'valid' ) ? ( 'style="color:#fff;background: #7ad03a; display: inline-block;text-decoration: none;font-size: 13px;line-height: 26px;height: 26px; margin-left:5px; padding: 0 10px 1px; -webkit-border-radius: 3px;border-radius: 3px; ">' . $valid_string ) : ( 'style="color:#fff;background: #dd3d36; display: inline-block;text-decoration: none;font-size: 13px;line-height: 26px;height: 26px; margin-left:5px; padding: 0 10px 1px; -webkit-border-radius: 3px;border-radius: 3px; ">' . $invalid_string ) ) . ' </a>&nbsp;&nbsp;&nbsp;<button name="' . $this->product->get_key() . '_btn_trigger" ' . ( ( $status === 'valid' ) ? ( ' class="button button-primary">' . $deactivate_string ) : ( ' class="button button-primary" value="yes" type="submit" >' . $activate_string ) ) . ' </button></p><p class="description">' . sprintf( $license_message, '<a href="' . $this->product->get_store_url() . '">' . $this->product->get_store_name() . '</a> ', $this->product->get_type() ) . '</p>';
134
-
135
- }
136
-
137
- /**
138
- * Return the license status.
139
- *
140
- * @return string The License status.
141
- */
142
- public function get_license_status() {
143
- $license_data = get_option( $this->product->get_key() . '_license_data', '' );
144
- if ( $license_data !== '' ) {
145
- return isset( $license_data->license ) ? $license_data->license : get_option( $this->product->get_key() . '_license_status', 'not_active' );
146
- } else {
147
- return get_option( $this->product->get_key() . '_license_status', 'not_active' );
148
- }
149
-
150
- }
151
-
152
- /**
153
- * Check if the license is active or not
154
- *
155
- * @return bool
156
- */
157
- public function check_activation() {
158
- $license_data = get_option( $this->product->get_key() . '_license_data', '' );
159
- if ( $license_data !== '' ) {
160
- return isset( $license_data->error ) ? ( $license_data->error == 'no_activations_left' ) : false;
161
- }
162
-
163
- return false;
164
- }
165
-
166
- /**
167
- * Check if the license is about to expire in the next month
168
- *
169
- * @return bool
170
- */
171
- function check_expiration() {
172
- $license_data = get_option( $this->product->get_key() . '_license_data', '' );
173
- if ( $license_data !== '' ) {
174
- if ( isset( $license_data->expires ) ) {
175
- if ( strtotime( $license_data->expires ) - time() < 30 * 24 * 3600 ) {
176
- return true;
177
- }
178
- }
179
- }
180
-
181
- return false;
182
- }
183
-
184
- /**
185
- * Return the renew url from the store used
186
- *
187
- * @return string The renew url.
188
- */
189
- function renew_url() {
190
- $license_data = get_option( $this->product->get_key() . '_license_data', '' );
191
- if ( $license_data !== '' ) {
192
- if ( isset( $license_data->download_id ) && isset( $license_data->key ) ) {
193
- return $this->product->get_store_url() . '/checkout/?edd_license_key=' . $license_data->key . '&download_id=' . $license_data->download_id;
194
- }
195
- }
196
-
197
- return $this->product->get_store_url();
198
- }
199
-
200
- /**
201
- * Check if we hide the notificatin nag or not
202
- *
203
- * @param string $hide The notification to hide.
204
- *
205
- * @return bool Either hide them or not.
206
- */
207
- function check_hide( $hide ) {
208
- return true;
209
- }
210
-
211
- /**
212
- * Show the admin notice regarding the license status
213
- *
214
- * @return bool
215
- */
216
- function show_notice() {
217
- if ( ! is_admin() ) {
218
- return false;
219
- }
220
- $status = $this->get_license_status();
221
- $no_activations_string = apply_filters(
222
- $this->product->get_key() . '_lc_no_activations_string', 'No activations left for %s !!!. You need to
223
- upgrade your plan in order to use %s on more
224
- websites. Please ask the %s
225
- Staff for more details.'
226
- );
227
- $no_valid_string = apply_filters(
228
- $this->product->get_key() . '_lc_no_valid_string', 'In order to benefit from updates and support for %s, please add
229
- your license code from your <a href="%s" target="_blank">purchase history</a> and validate it <a
230
- href="%s">here</a>. '
231
- );
232
- $expiration_string = apply_filters(
233
- $this->product->get_key() . '_lc_expiration_string', 'Your license is about to expire
234
- for %s. You can go to %s and renew it '
235
- );
236
- if ( $status != 'valid' ) {
237
- if ( $this->check_activation() ) {
238
- if ( $this->check_hide( 'activation' ) ) {
239
- ?>
240
- <div class="error">
241
- <p><strong>
242
- <?php
243
- echo sprintf(
244
- $no_activations_string, $this->product->get_name(), $this->product->get_name(), '<a href="' . $this->product->get_store_url() . '"
245
- target="_blank">' . $this->product->get_store_name() . '</a>'
246
- );
247
- ?>
248
- </strong>
249
- </p>
250
- </div>
251
- <?php
252
- return false;
253
- }
254
- }
255
- ?>
256
- <?php if ( $this->check_hide( 'valid' ) ) : ?>
257
- <div class="error">
258
- <p>
259
- <strong><?php echo sprintf( $no_valid_string, $this->product->get_name() . ' ' . $this->product->get_type(), $this->product->get_store_url(), admin_url( 'options-general.php' ) . '#' . $this->product->get_key() ); ?> </strong>
260
- </p>
261
- </div>
262
- <?php endif; ?>
263
- <?php
264
- } else {
265
- if ( $this->check_expiration() ) {
266
- if ( $this->check_hide( 'expiration' ) ) {
267
- ?>
268
- <div class="update-nag">
269
- <p>
270
- <strong>
271
- <?php
272
- echo sprintf(
273
- $expiration_string, $this->product->get_name() . ' ' . $this->product->get_type(), '<a
274
- href="' . $this->renew_url() . '"
275
- target="_blank">' . $this->product->get_store_name() . '</a>'
276
- );
277
- ?>
278
- </strong>
279
- </p>
280
- </div>
281
- <?php
282
- }
283
- }
284
- }
285
- }
286
-
287
- /**
288
- * Run the license check call
289
- */
290
- public function product_valid() {
291
- if ( false === ( $license = get_transient( $this->product->get_key() . '_license_data' ) ) ) {
292
- $license = $this->check_license();
293
- set_transient( $this->product->get_key() . '_license_data', $license, 12 * HOUR_IN_SECONDS );
294
- update_option( $this->product->get_key() . '_license_data', $license );
295
- }
296
-
297
- }
298
-
299
- /**
300
- * Increment the failed checks
301
- */
302
- private function increment_failed_checks() {
303
- $this->failed_checks ++;
304
- update_option( $this->product->get_key() . '_failed_checks', $this->failed_checks );
305
- }
306
-
307
- /**
308
- * Reset the failed checks
309
- */
310
- private function reset_failed_checks() {
311
- $this->failed_checks = 1;
312
- update_option( $this->product->get_key() . '_failed_checks', $this->failed_checks );
313
- }
314
-
315
- /**
316
- * Check the license status
317
- *
318
- * @return object The license data.
319
- */
320
- public function check_license() {
321
- $status = $this->get_license_status();
322
- if ( $status == 'not_active' ) {
323
- $license_data = new stdClass();
324
- $license_data->license = 'not_active';
325
-
326
- return $license_data;
327
- }
328
- $license = trim( $this->license_key );
329
- $api_params = array(
330
- 'edd_action' => 'check_license',
331
- 'license' => $license,
332
- 'item_name' => rawurlencode( $this->product->get_name() ),
333
- 'url' => rawurlencode( home_url() ),
334
- );
335
- // Call the custom API.
336
- $response = wp_remote_get(
337
- add_query_arg( $api_params, $this->product->get_store_url() ), array(
338
- 'timeout' => 15,
339
- 'sslverify' => false,
340
- )
341
- );
342
- if ( is_wp_error( $response ) ) {
343
- $license_data = new stdClass();
344
- $license_data->license = 'valid';
345
-
346
- } else {
347
- $license_data = json_decode( wp_remote_retrieve_body( $response ) );
348
- if ( ! is_object( $license_data ) ) {
349
- $license_data = new stdClass();
350
- $license_data->license = 'valid';
351
- }
352
- }
353
- $license_old = get_option( $this->product->get_key() . '_license_data', '' );
354
- if ( $license_old->license == 'valid' && ( $license_data->license != $license_old->license ) ) {
355
- $this->increment_failed_checks();
356
- } else {
357
- $this->reset_failed_checks();
358
- }
359
-
360
- if ( $this->failed_checks <= self::$max_failed ) {
361
- return $license_old;
362
- }
363
-
364
- if ( isset( $license_old->hide_valid ) ) {
365
- $license_data->hide_valid = true;
366
- }
367
-
368
- if ( ! isset( $license_data->key ) ) {
369
- $license_data->key = isset( $license_old->key ) ? $license_old->key : '';
370
- }
371
-
372
- if ( isset( $license_old->hide_expiration ) ) {
373
- $license_data->hide_expiration = true;
374
- }
375
-
376
- if ( isset( $license_old->hide_activation ) ) {
377
- $license_data->hide_activation = true;
378
- }
379
-
380
- return $license_data;
381
-
382
- }
383
-
384
- /**
385
- * Activate the license remotely
386
- */
387
- function activate_license() {
388
- // listen for our activate button to be clicked
389
- if ( isset( $_POST[ $this->product->get_key() . '_btn_trigger' ] ) ) {
390
- $status = $this->get_license_status();
391
- // retrieve the license from the database
392
- $license = $_POST[ $this->product->get_key() . '_license' ];
393
- $api_params = array(
394
- 'license' => $license,
395
- 'item_name' => rawurlencode( $this->product->get_name() ),
396
- 'url' => rawurlencode( home_url() ),
397
- );
398
- if ( $status != 'valid' ) {
399
- // data to send in our API request
400
- $api_params['edd_action'] = 'activate_license';
401
- } else {
402
- $api_params['edd_action'] = 'deactivate_license';
403
- }
404
- // Call the custom API.
405
- $response = wp_remote_get( add_query_arg( $api_params, $this->product->get_store_url() ) );
406
- // make sure the response came back okay
407
- if ( is_wp_error( $response ) ) {
408
- $license_data = new stdClass();
409
- $license_data->license = ( $status != 'valid' ) ? 'valid' : 'invalid';
410
-
411
- } else {
412
- $license_data = json_decode( wp_remote_retrieve_body( $response ) );
413
- if ( ! is_object( $license_data ) ) {
414
- $license_data = new stdClass();
415
- $license_data->license = ( $status != 'valid' ) ? 'valid' : 'invalid';
416
- }
417
- }
418
- if ( ! isset( $license_data->key ) ) {
419
- $license_data->key = $license;
420
- }
421
- if ( $license_data->license == 'valid' ) {
422
- $this->reset_failed_checks();
423
- }
424
-
425
- if ( isset( $license_data->plan ) ) {
426
- update_option( $this->product->get_key() . '_license_plan', $license_data->plan );
427
- }
428
-
429
- update_option( $this->product->get_key() . '_license_data', $license_data );
430
- delete_transient( $this->product->get_key() . '_license_data' );
431
- set_transient( $this->product->get_key() . '_license_data', $license_data, 12 * HOUR_IN_SECONDS );
432
-
433
- }
434
- }
435
-
436
- /**
437
- * Enable the license system
438
- */
439
- public function enable() {
440
- if ( $this->product->get_type() == 'plugin' ) {
441
- add_filter(
442
- 'pre_set_site_transient_update_plugins', array(
443
- $this,
444
- 'pre_set_site_transient_update_plugins_filter',
445
- )
446
- );
447
- add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
448
- add_filter( 'http_request_args', array( $this, 'http_request_args' ), 10, 2 );
449
- }
450
- if ( $this->product->get_type() == 'theme' ) {
451
- add_filter( 'site_transient_update_themes', array( &$this, 'theme_update_transient' ) );
452
- add_filter( 'delete_site_transient_update_themes', array( &$this, 'delete_theme_update_transient' ) );
453
- add_action( 'load-update-core.php', array( &$this, 'delete_theme_update_transient' ) );
454
- add_action( 'load-themes.php', array( &$this, 'delete_theme_update_transient' ) );
455
- add_action( 'load-themes.php', array( &$this, 'load_themes_screen' ) );
456
- add_filter( 'http_request_args', array( $this, 'disable_wporg_update' ), 5, 2 );
457
-
458
- }
459
-
460
- }
461
-
462
- /**
463
- * Load the Themes screen
464
- */
465
- function load_themes_screen() {
466
- add_thickbox();
467
- add_action( 'admin_notices', array( &$this, 'update_nag' ) );
468
- }
469
-
470
- /**
471
- * Alter the nag for themes update
472
- */
473
- function update_nag() {
474
- $theme = wp_get_theme( $this->product->get_slug() );
475
- $api_response = get_transient( $this->product_key );
476
- if ( false === $api_response ) {
477
- return;
478
- }
479
- $update_url = wp_nonce_url( 'update.php?action=upgrade-theme&amp;theme=' . urlencode( $this->product->get_slug() ), 'upgrade-theme_' . $this->product->get_slug() );
480
- $update_message = apply_filters( 'themeisle_sdk_license_update_message', 'Updating this theme will lose any customizations you have made. Cancel to stop, OK to update.' );
481
- $update_onclick = ' onclick="if ( confirm(\'' . esc_js( $update_message ) . '\') ) {return true;}return false;"';
482
- if ( version_compare( $this->product->get_version(), $api_response->new_version, '<' ) ) {
483
- echo '<div id="update-nag">';
484
- printf(
485
- '<strong>%1$s %2$s</strong> is available. <a href="%3$s" class="thickbox" title="%4s">Check out what\'s new</a> or <a href="%5$s"%6$s>update now</a>.',
486
- $theme->get( 'Name' ),
487
- $api_response->new_version,
488
- '#TB_inline?width=640&amp;inlineId=' . $this->product->get_version() . '_changelog',
489
- $theme->get( 'Name' ),
490
- $update_url,
491
- $update_onclick
492
- );
493
- echo '</div>';
494
- echo '<div id="' . $this->product->get_slug() . '_' . 'changelog" style="display:none;">';
495
- echo wpautop( $api_response->sections['changelog'] );
496
- echo '</div>';
497
- }
498
- }
499
-
500
- /**
501
- * @param mixed $value The transient data.
502
- *
503
- * @return mixed
504
- */
505
- function theme_update_transient( $value ) {
506
- $update_data = $this->check_for_update();
507
- if ( $update_data ) {
508
- $value->response[ $this->product->get_slug() ] = $update_data;
509
- }
510
-
511
- return $value;
512
- }
513
-
514
- /**
515
- * Delete the update transient
516
- */
517
- function delete_theme_update_transient() {
518
- delete_transient( $this->product_key );
519
- }
520
-
521
- /**
522
- * Check remote api for latest version.
523
- *
524
- * @return bool|mixed Update api response.
525
- */
526
- private function get_version_data() {
527
- $api_params = array(
528
- 'edd_action' => 'get_version',
529
- 'version' => $this->product->get_version(),
530
- 'license' => $this->license_key,
531
- 'name' => $this->product->get_name(),
532
- 'slug' => $this->product->get_slug(),
533
- 'author' => $this->product->get_store_name(),
534
- 'url' => rawurlencode( home_url() ),
535
- );
536
- $response = wp_remote_post(
537
- $this->product->get_store_url(), array(
538
- 'timeout' => 15,
539
- 'sslverify' => false,
540
- 'body' => $api_params,
541
- )
542
- );
543
- if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
544
- return false;
545
- }
546
- $update_data = json_decode( wp_remote_retrieve_body( $response ) );
547
- if ( ! is_object( $update_data ) ) {
548
- return false;
549
- }
550
-
551
- return $update_data;
552
- }
553
-
554
- /**
555
- * Check for updates
556
- *
557
- * @return array|bool Either the update data or false in case of failure
558
- */
559
- function check_for_update() {
560
- $theme = wp_get_theme( $this->product->get_slug() );
561
- $update_data = get_transient( $this->product_key );
562
-
563
- if ( false === $update_data ) {
564
- $failed = false;
565
-
566
- $update_data = $this->get_version_data();
567
- if ( empty( $update_data ) ) {
568
- $failed = true;
569
- }
570
- // If the response failed, try again in 30 minutes.
571
- if ( $failed ) {
572
- $data = new stdClass;
573
- $data->new_version = $this->product->get_version();
574
- set_transient( $this->product_key, $data, strtotime( '+30 minutes' ) );
575
-
576
- return false;
577
- } else {
578
- $update_data->sections = maybe_unserialize( $update_data->sections );
579
- set_transient( $this->product_key, $update_data, strtotime( '+12 hours' ) );
580
- }
581
- }
582
- if ( ! isset( $update_data->new_version ) ) {
583
- return false;
584
- }
585
- if ( version_compare( $this->product->get_version(), $update_data->new_version, '>=' ) ) {
586
- return false;
587
- }
588
-
589
- return (array) $update_data;
590
- }
591
-
592
- /**
593
- * Check for Updates at the defined API endpoint and modify the update array.
594
- *
595
- * This function dives into the update API just when WordPress creates its update array,
596
- * then adds a custom API call and injects the custom plugin data retrieved from the API.
597
- * It is reassembled from parts of the native WordPress plugin update code.
598
- * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
599
- *
600
- * @uses api_request()
601
- *
602
- * @param array $_transient_data Update array build by WordPress.
603
- *
604
- * @return array Modified update array with custom plugin data.
605
- */
606
- public function pre_set_site_transient_update_plugins_filter( $_transient_data ) {
607
- if ( empty( $_transient_data ) || ! $this->do_check ) {
608
- $this->do_check = true;
609
-
610
- return $_transient_data;
611
- }
612
- $api_response = $this->api_request();
613
- if ( false !== $api_response && is_object( $api_response ) && isset( $api_response->new_version ) ) {
614
- if ( version_compare( $this->product->get_version(), $api_response->new_version, '<' ) ) {
615
- $_transient_data->response[ $this->product->get_slug() . '/' . $this->product->get_file() ] = $api_response;
616
- }
617
- }
618
-
619
- return $_transient_data;
620
- }
621
-
622
- /**
623
- * Calls the API and, if successfull, returns the object delivered by the API.
624
- *
625
- * @uses get_bloginfo()
626
- * @uses wp_remote_post()
627
- * @uses is_wp_error()
628
- *
629
- * @param string $_action The requested action.
630
- * @param array $_data Parameters for the API action.
631
- *
632
- * @return false||object
633
- */
634
- private function api_request( $_action = '', $_data = '' ) {
635
- $update_data = $this->get_version_data();
636
- if ( empty( $update_data ) ) {
637
- return false;
638
- }
639
- if ( $update_data && isset( $update_data->sections ) ) {
640
- $update_data->sections = maybe_unserialize( $update_data->sections );
641
- }
642
- return $update_data;
643
- }
644
-
645
- /**
646
- * Updates information on the "View version x.x details" page with custom data.
647
- *
648
- * @uses api_request()
649
- *
650
- * @param mixed $_data Plugin data.
651
- * @param string $_action Action to send.
652
- * @param object $_args Arguments to use.
653
- *
654
- * @return object $_data
655
- */
656
- public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
657
- if ( ( $_action != 'plugin_information' ) || ! isset( $_args->slug ) || ( $_args->slug != $this->product->get_slug() ) ) {
658
- return $_data;
659
- }
660
- $api_response = $this->api_request();
661
- if ( false !== $api_response ) {
662
- $_data = $api_response;
663
- }
664
-
665
- return $_data;
666
- }
667
-
668
- /**
669
- * Disable SSL verification in order to prevent download update failures
670
- *
671
- * @param array $args Http args.
672
- * @param string $url Url to check.
673
- *
674
- * @return object $array
675
- */
676
- function http_request_args( $args, $url ) {
677
- // If it is an https request and we are performing a package download, disable ssl verification
678
- if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
679
- $args['sslverify'] = false;
680
- }
681
-
682
- return $args;
683
- }
684
-
685
- }
686
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-loader.php DELETED
@@ -1,96 +0,0 @@
1
- <?php
2
- /**
3
- * The main loader class for ThemeIsle SDK
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Loader
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- // Exit if accessed directly.
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
- if ( ! class_exists( 'ThemeIsle_SDK_Loader' ) ) :
16
- /**
17
- * Singleton loader for ThemeIsle SDK.
18
- */
19
- final class ThemeIsle_SDK_Loader {
20
- /**
21
- * @var ThemeIsle_SDK_Loader instance The singleton instance
22
- */
23
- private static $instance;
24
- /**
25
- * @var string $version The class version.
26
- */
27
- private static $version = '1.0.0';
28
- /**
29
- * @var array The products which use the SDK.
30
- */
31
- private static $products;
32
-
33
- /**
34
- * Register product into SDK.
35
- *
36
- * @param string $basefile The product basefile.
37
- *
38
- * @return ThemeIsle_SDK_Loader The singleton object.
39
- */
40
- public static function init_product( $basefile ) {
41
-
42
- if ( ! isset( self::$instance ) && ! ( self::$instance instanceof ThemeIsle_SDK_Loader ) ) {
43
- self::$instance = new ThemeIsle_SDK_Loader;
44
-
45
- }
46
- $product_object = new ThemeIsle_SDK_Product( $basefile );
47
- self::$products[ $product_object->get_slug() ] = $product_object;
48
-
49
- $notifications = array();
50
- // Based on the WordPress Available file header we enable the logger or not.
51
- if ( ! $product_object->is_wordpress_available() && apply_filters( $product_object->get_key() . '_enable_licenser', true ) === true ) {
52
- $licenser = new ThemeIsle_SDK_Licenser( $product_object );
53
- $licenser->enable();
54
- }
55
-
56
- $logger = new ThemeIsle_SDK_Logger( $product_object );
57
- if ( $product_object->is_logger_active() ) {
58
- $logger->enable();
59
- } else {
60
- $notifications[] = $logger;
61
- }
62
-
63
- $feedback = new ThemeIsle_SDK_Feedback_Factory( $product_object, $product_object->get_feedback_types() );
64
-
65
- $instances = $feedback->get_instances();
66
- if ( array_key_exists( 'review', $instances ) ) {
67
- $notifications[] = $instances['review'];
68
- }
69
- if ( array_key_exists( 'translate', $instances ) ) {
70
- $notifications[] = $instances['translate'];
71
- }
72
- new ThemeIsle_SDK_Notification_Manager( $product_object, $notifications );
73
- if ( ! $product_object->is_external_author() ) {
74
- new ThemeIsle_SDK_Widgets_Factory( $product_object, $product_object->get_widget_types() );
75
- }
76
- if ( ! $product_object->is_external_author() ) {
77
- new ThemeIsle_SDK_Rollback( $product_object );
78
- }
79
-
80
- new ThemeIsle_SDK_Endpoints( $product_object );
81
-
82
- return self::$instance;
83
- }
84
-
85
- /**
86
- * Get all products using the SDK.
87
- *
88
- * @return array Products available.
89
- */
90
- public static function get_products() {
91
- return self::$products;
92
- }
93
-
94
-
95
- }
96
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-logger.php DELETED
@@ -1,227 +0,0 @@
1
- <?php
2
- /**
3
- * The main loader class for ThemeIsle SDK
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Logger
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- if ( ! class_exists( 'ThemeIsle_SDK_Logger' ) ) :
12
- /**
13
- * Class ThemeIsle_SDK_Logger
14
- *
15
- * Send the statistics to the Themeisle Endpoint
16
- */
17
- /**
18
- * Class ThemeIsle_SDK_Logger
19
- */
20
- class ThemeIsle_SDK_Logger {
21
-
22
- /**
23
- * @var string $logging_url Url where to send the logs
24
- */
25
- private $logging_url = 'http://log.themeisle.com/wp-json/v1/logs/';
26
-
27
- /**
28
- * @var ThemeIsle_SDK_Product $product Themeisle Product.
29
- */
30
- private $product;
31
-
32
- /**
33
- * @var string $product_cron Cron name handler
34
- */
35
- private $product_cron;
36
-
37
- /**
38
- * @var string $heading The heading of the modal
39
- */
40
- private $heading = 'Do you enjoy <b>{product}</b>? Become a contributor by opting in to our anonymous data tracking. We guarantee no sensitive data is collected.';
41
-
42
- /**
43
- * @var string $button_submit The text of the submit button
44
- */
45
- private $button_submit = 'Sure, I would love to help.';
46
-
47
- /**
48
- * @var string $button_cancel The text of the cancel button
49
- */
50
- private $button_cancel = 'No, thanks.';
51
-
52
- /**
53
- * ThemeIsle_SDK_Logger constructor.
54
- *
55
- * @param ThemeIsle_SDK_Product $product_object Product Object.
56
- */
57
- public function __construct( $product_object ) {
58
- if ( $product_object instanceof ThemeIsle_SDK_Product ) {
59
- $this->product = $product_object;
60
- $this->product_cron = $product_object->get_key() . '_log_activity';
61
- }
62
- add_action( 'wp_ajax_' . $this->product->get_key() . __CLASS__, array( $this, 'dismiss' ) );
63
- }
64
-
65
-
66
- /**
67
- * Start the cron to send the log. It will randomize the interval in order to not send all the logs at the same time.
68
- */
69
- public function enable() {
70
- if ( ! wp_next_scheduled( $this->product_cron ) ) {
71
- wp_schedule_single_event( time() + ( rand( 15, 24 ) * 3600 ), $this->product_cron );
72
- }
73
- add_action( $this->product_cron, array( $this, 'send_log' ) );
74
- }
75
-
76
- /**
77
- * Send the statistics to the api endpoint
78
- */
79
- public function send_log() {
80
- $environment = array();
81
- $theme = wp_get_theme();
82
- $environment['theme'] = array();
83
- $environment['theme']['name'] = $theme->get( 'Name' );
84
- $environment['theme']['author'] = $theme->get( 'Author' );
85
- $environment['plugins'] = get_option( 'active_plugins' );
86
-
87
- wp_remote_post(
88
- $this->logging_url, array(
89
- 'method' => 'POST',
90
- 'timeout' => 3,
91
- 'redirection' => 5,
92
- 'headers' => array(
93
- 'X-ThemeIsle-Event' => 'log_site',
94
- ),
95
- 'body' => array(
96
- 'site' => get_site_url(),
97
- 'slug' => $this->product->get_slug(),
98
- 'version' => $this->product->get_version(),
99
- 'data' => apply_filters( $this->product->get_key() . '_logger_data', array() ),
100
- 'environment' => $environment,
101
- 'license' => apply_filters( $this->product->get_key() . '_license_status', '' ),
102
- ),
103
- )
104
- );
105
- }
106
-
107
- /**
108
- * Dismiss the notification
109
- */
110
- function dismiss() {
111
- check_ajax_referer( (string) __CLASS__, 'nonce' );
112
-
113
- $flag = intval( $_POST['enable'] ) === 1;
114
- update_option( $this->product->logger_option, ( $flag ? 'yes' : 'no' ) );
115
-
116
- if ( true === $flag ) {
117
- $this->enable();
118
- }
119
- }
120
-
121
- /**
122
- * Either we should show the notification or not.
123
- *
124
- * @return bool Valida notification.
125
- */
126
- function can_notify() {
127
- $show = $this->product->is_logger_active();
128
- $checked = get_option( $this->product->logger_option, '' );
129
- if ( ! $show && $checked == '' ) {
130
- return true;
131
- }
132
-
133
- return false;
134
- }
135
-
136
- /**
137
- * Shows the notification
138
- */
139
- function show_notification() {
140
- add_action( 'admin_notices', array( $this, 'admin_notices' ) );
141
- }
142
-
143
- /**
144
- * Shows the admin notice
145
- */
146
- function admin_notices() {
147
- $id = $this->product->get_key() . '_logger';
148
-
149
- $this->add_media( $this->product->get_key() );
150
-
151
- echo '<div class="notice notice-success is-dismissible " id="' . $this->product->get_key() . '-logger-notification" ><div id="' . $id . '" class="themeisle-logger-box">' . $this->get_html( $this->product->get_key() ) . '</div></div>';
152
- }
153
-
154
- /**
155
- * Generates the HTML
156
- *
157
- * @param string $key The product key.
158
- */
159
- function get_html( $key ) {
160
- $heading = apply_filters( $this->product->get_key() . '_logger_heading', $this->heading );
161
- $heading = str_replace(
162
- array( '{product}' ), array(
163
- trim( str_replace( 'Lite', '', $this->product->get_name() ) ),
164
- ),
165
- $heading
166
- );
167
- $button_submit = apply_filters( $this->product->get_key() . '_logger_button_submit', $this->button_submit );
168
- $button_cancel = apply_filters( $this->product->get_key() . '_logger_button_cancel', $this->button_cancel );
169
-
170
- return '<div >'
171
- . '<p>' . $heading . '</p>'
172
- . '<div class="actions">'
173
- . get_submit_button(
174
- $button_submit, 'primary ' . $this->product->get_key() . '-ti-logger', $this->product->get_key() . 'ti-logger-yes', false, array(
175
- 'data-ti-log-enable' => 1,
176
- )
177
- )
178
- . get_submit_button(
179
- $button_cancel, 'secondary ' . $this->product->get_key() . '-ti-logger', $this->product->get_key() . 'ti-logger-no', false, array(
180
- 'data-ti-log-enable' => 0,
181
- )
182
- )
183
- . '</div></div>';
184
- }
185
-
186
- /**
187
- * Loads the js
188
- *
189
- * @param string $key The product key.
190
- */
191
- function add_media( $key ) {
192
- ?>
193
- <style type="text/css">
194
- #<?php echo $key; ?>-logger-notification {
195
- padding-bottom: 5px;
196
- }
197
-
198
- #<?php echo $key; ?>-logger-notification .button {
199
- margin-left: 5px;
200
- }
201
- </style>
202
- <script type="text/javascript" id="<?php echo $key; ?>ti-logger-js">
203
- (function ($) {
204
- $(document).ready(function () {
205
- $('.<?php echo $key; ?>-ti-logger').on('click', function (e) {
206
-
207
- $.ajax({
208
- url: ajaxurl,
209
- method: "post",
210
- data: {
211
- 'nonce': '<?php echo wp_create_nonce( (string) __CLASS__ ); ?>',
212
- 'action': '<?php echo $this->product->get_key() . __CLASS__; ?>',
213
- 'enable': $(this).attr('data-ti-log-enable')
214
- },
215
- success: function () {
216
- $('#<?php echo $key; ?>-logger-notification').hide();
217
- }
218
- });
219
- });
220
- });
221
- })(jQuery);
222
- </script>
223
- <?php
224
- }
225
-
226
- }
227
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-notification-manager.php DELETED
@@ -1,105 +0,0 @@
1
- <?php
2
- /**
3
- * The notification manager class for ThemeIsle SDK
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Notification
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- // Exit if accessed directly.
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
- if ( ! class_exists( 'ThemeIsle_SDK_Notification_Manager' ) ) :
16
- /**
17
- * Notification manager model for ThemeIsle SDK.
18
- */
19
- class ThemeIsle_SDK_Notification_Manager {
20
- /**
21
- * Time between notifications.
22
- */
23
- const NOTIFICATION_INTERVAL_HOURS = 100;
24
- /**
25
- * @var array Notifications for the current product.
26
- */
27
- static private $notifications = array();
28
- /**
29
- * @var ThemeIsle_SDK_Product Current product.
30
- */
31
- private $product;
32
- /**
33
- * @var array ThemeIsle_SDK_Feedback Feedbacks available.
34
- */
35
- private $callbacks = array();
36
-
37
- /**
38
- * ThemeIsle_SDK_Notification_Manager constructor.
39
- *
40
- * @param ThemeIsle_SDK_Product $product_object Product Object.
41
- * @param array $callbacks the objects that will be called when a notification is due.
42
- */
43
- public function __construct( $product_object, $callbacks ) {
44
- $this->product = $product_object;
45
- $this->callbacks = $callbacks;
46
- $this->setup_hooks();
47
- }
48
-
49
- /**
50
- * Setup the notifications.
51
- */
52
- function setup_notifications() {
53
- if ( ! current_user_can( 'manage_options' ) ) {
54
- return;
55
- }
56
- // Load the notifications only if we have it installed after the required interval.
57
- if ( ( time() - $this->product->get_install_time() ) > self::NOTIFICATION_INTERVAL_HOURS * HOUR_IN_SECONDS ) {
58
- if ( $this->product instanceof ThemeIsle_SDK_Product && $this->callbacks && is_array( $this->callbacks ) ) {
59
- foreach ( $this->callbacks as $instance ) {
60
- self::$notifications[ $this->product->get_key() . get_class( $instance ) ] = $instance;
61
- }
62
- }
63
- }
64
- }
65
-
66
- /**
67
- * Setup the internal hooks
68
- */
69
- private function setup_hooks() {
70
- add_action( 'admin_head', array( $this, 'show_notification' ) );
71
- add_action( 'admin_init', array( $this, 'setup_notifications' ) );
72
- }
73
-
74
- /**
75
- * Shows the notification
76
- */
77
- function show_notification() {
78
- $instances = self::$notifications;
79
- if ( empty( $instances ) ) {
80
- return;
81
- }
82
-
83
- $available = array_keys( $instances );
84
- $active = get_option( 'themeisle_sdk_active_notification', array() );
85
-
86
- foreach ( $available as $key ) {
87
- $instance = $instances[ $key ];
88
- if ( $instance->can_notify() ) {
89
-
90
- // Detect notification switch.
91
- if ( empty( $active['key'] ) || ( $active['key'] != $key ) ) {
92
- $active['key'] = $key;
93
- $active['time'] = time();
94
- update_option( 'themeisle_sdk_active_notification', $active );
95
- }
96
- if ( ( time() - $active['time'] ) > ( self::NOTIFICATION_INTERVAL_HOURS * HOUR_IN_SECONDS ) ) {
97
- $instance->show_notification();
98
- }
99
- break;
100
- }
101
- }
102
-
103
- }
104
- }
105
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-product.php DELETED
@@ -1,635 +0,0 @@
1
- <?php
2
- /**
3
- * The product model class for ThemeIsle SDK
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Product
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- // Exit if accessed directly.
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
- if ( ! class_exists( 'ThemeIsle_SDK_Product' ) ) :
16
- /**
17
- * Product model for ThemeIsle SDK.
18
- */
19
- class ThemeIsle_SDK_Product {
20
- /**
21
- * @var string $slug THe product slug.
22
- */
23
- private $slug;
24
- /**
25
- * @var string $basefile The file with headers.
26
- */
27
- private $basefile;
28
- /**
29
- * @var string $type The product type ( plugin | theme ).
30
- */
31
- private $type;
32
- /**
33
- * @var string $file The file name.
34
- */
35
- private $file;
36
- /**
37
- * @var string $name The product name.
38
- */
39
- private $name;
40
- /**
41
- * @var string $key The product ready key.
42
- */
43
- private $key;
44
- /**
45
- * @var string $author_url The url of the author.
46
- */
47
- private $author_url;
48
- /**
49
- * @var string $store_url The store url.
50
- */
51
- private $store_url;
52
- /**
53
- * @var int $install The date of install.
54
- */
55
- private $install;
56
- /**
57
- * @var string $store_name The store name.
58
- */
59
- private $store_name;
60
- /**
61
- * @var array $allowed_authors The allowed authors.
62
- */
63
- private $allowed_authors = array(
64
- 'proteusthemes.com',
65
- 'anarieldesign.com',
66
- 'prothemedesign.com',
67
- 'cssigniter.com',
68
- );
69
- /**
70
- * @var array $allowed_external_products The allowed external_products.
71
- */
72
- private $allowed_products = array(
73
- 'zermatt',
74
- 'neto',
75
- 'olsen',
76
- 'benson',
77
- 'romero',
78
- 'carmack',
79
- 'puzzle',
80
- 'broadsheet',
81
- 'girlywp',
82
- 'veggie',
83
- 'zeko',
84
- 'maishawp',
85
- 'didi',
86
- 'liber',
87
- 'medicpress-pt',
88
- 'adrenaline-pt',
89
- 'consultpress-pt',
90
- 'legalpress-pt',
91
- 'gympress-pt',
92
- 'readable-pt',
93
- 'bolts-pt',
94
- );
95
- /**
96
- * @var bool $requires_license Either user needs to activate it with license.
97
- */
98
- private $requires_license;
99
- /**
100
- * @var bool $wordpress_available Either is available on WordPress or not.
101
- */
102
- private $wordpress_available;
103
- /**
104
- * @var string $version The product version.
105
- */
106
- private $version;
107
- /**
108
- * @var string $logger_option Logger option key.
109
- */
110
- public $logger_option;
111
- /**
112
- * @var string $pro_slug Pro slug, if available.
113
- */
114
- public $pro_slug;
115
- /**
116
- * @var string $feedback_types All the feedback types the product supports
117
- */
118
- private $feedback_types = array();
119
-
120
- /**
121
- * @var string $widget_types All the widget types the product supports
122
- */
123
- private $widget_types = array( 'dashboard_blog' );
124
-
125
- /**
126
- * ThemeIsle_SDK_Product constructor.
127
- *
128
- * @param string $basefile Product basefile.
129
- */
130
- public function __construct( $basefile ) {
131
- if ( ! empty( $basefile ) ) {
132
- if ( is_readable( $basefile ) ) {
133
- $this->basefile = $basefile;
134
- $this->setup_from_path();
135
- $this->setup_from_fileheaders();
136
- }
137
- }
138
- $install = get_option( $this->get_key() . '_install', 0 );
139
- if ( $install === 0 ) {
140
- $install = time();
141
- update_option( $this->get_key() . '_install', time() );
142
- }
143
- $this->install = $install;
144
-
145
- $this->logger_option = $this->get_key() . '_logger_flag';
146
-
147
- }
148
-
149
- /**
150
- * Setup props from fileheaders.
151
- */
152
- public function setup_from_fileheaders() {
153
- $file_headers = array(
154
- 'Requires License' => 'Requires License',
155
- 'WordPress Available' => 'WordPress Available',
156
- 'Pro Slug' => 'Pro Slug',
157
- 'Version' => 'Version',
158
- );
159
- if ( $this->type == 'plugin' ) {
160
- $file_headers['Name'] = 'Plugin Name';
161
- $file_headers['AuthorName'] = 'Author';
162
- $file_headers['AuthorURI'] = 'Author URI';
163
- }
164
- if ( $this->type == 'theme' ) {
165
- $file_headers['Name'] = 'Theme Name';
166
- $file_headers['AuthorName'] = 'Author';
167
- $file_headers['AuthorURI'] = 'Author URI';
168
- }
169
- $file_headers = get_file_data( $this->basefile, $file_headers );
170
-
171
- $this->name = $file_headers['Name'];
172
- $this->store_name = $file_headers['AuthorName'];
173
- $this->author_url = $file_headers['AuthorURI'];
174
- $this->store_url = $file_headers['AuthorURI'];
175
- if ( $this->is_external_author() ) {
176
- $this->store_url = 'https://themeisle.com';
177
- $this->store_name = 'ThemeIsle';
178
- }
179
- $this->requires_license = ( $file_headers['Requires License'] == 'yes' ) ? true : false;
180
- $this->wordpress_available = ( $file_headers['WordPress Available'] == 'yes' ) ? true : false;
181
- $this->pro_slug = ! empty( $file_headers['Pro Slug'] ) ? $file_headers['Pro Slug'] : '';
182
- $this->version = $file_headers['Version'];
183
- if ( $this->require_uninstall_feedback() ) {
184
- $this->feedback_types[] = 'deactivate';
185
- }
186
- if ( $this->is_wordpress_available() ) {
187
- $this->feedback_types[] = 'review';
188
- $this->feedback_types[] = 'translate';
189
- }
190
- }
191
-
192
- /**
193
- * Check if the product is by external author or not.
194
- *
195
- * @return bool Either is external author or no.
196
- */
197
- public function is_external_author() {
198
- foreach ( $this->allowed_authors as $author ) {
199
- if ( strpos( $this->author_url, $author ) !== false ) {
200
- return true;
201
- }
202
- if ( in_array( $this->get_slug(), $this->allowed_products ) ) {
203
- return true;
204
- }
205
- }
206
-
207
- return false;
208
- }
209
-
210
- /**
211
- * The magic var_dump info method.
212
- *
213
- * @return array Debug info.
214
- */
215
- public function __debugInfo() {
216
- return array(
217
- 'name' => $this->name,
218
- 'slug' => $this->slug,
219
- 'version' => $this->version,
220
- 'basefile' => $this->basefile,
221
- 'key' => $this->key,
222
- 'type' => $this->type,
223
- 'store_name' => $this->store_name,
224
- 'store_url' => $this->store_url,
225
- 'wordpress_available' => $this->wordpress_available,
226
- 'requires_license' => $this->requires_license,
227
- );
228
-
229
- }
230
-
231
- /**
232
- * Setup props from path.
233
- */
234
- public function setup_from_path() {
235
- $this->file = basename( $this->basefile );
236
- $dir = dirname( $this->basefile );
237
- $this->slug = basename( $dir );
238
- $exts = explode( '.', $this->basefile );
239
- $ext = $exts[ count( $exts ) - 1 ];
240
- if ( $ext == 'css' ) {
241
- $this->type = 'theme';
242
- }
243
- if ( $ext == 'php' ) {
244
- $this->type = 'plugin';
245
- }
246
- $this->key = self::key_ready_name( $this->slug );
247
- }
248
-
249
- /**
250
- * @param string $string the String to be normalized for cron handler.
251
- *
252
- * @return string $name The normalized string.
253
- */
254
- static function key_ready_name( $string ) {
255
- return str_replace( '-', '_', strtolower( trim( $string ) ) );
256
- }
257
-
258
- /**
259
- * Getter for product name.
260
- *
261
- * @return string The product name.
262
- */
263
- public function get_name() {
264
- return $this->name;
265
- }
266
-
267
- /**
268
- * Getter for product version.
269
- *
270
- * @return string The product version.
271
- */
272
- public function get_version() {
273
- return $this->version;
274
- }
275
-
276
- /**
277
- * If product is available on wordpress.org or not.
278
- *
279
- * @return bool Either is wp available or not.
280
- */
281
- public function is_wordpress_available() {
282
- return $this->wordpress_available;
283
- }
284
-
285
- /**
286
- * @return array Array of available versions.
287
- */
288
- private function get_plugin_versions() {
289
-
290
- $url = sprintf( 'https://api.wordpress.org/plugins/info/1.0/%s', $this->get_slug() );
291
- $response = wp_remote_get( $url );
292
- if ( is_wp_error( $response ) ) {
293
- return array();
294
- }
295
- $response = wp_remote_retrieve_body( $response );
296
- $response = maybe_unserialize( $response );
297
-
298
- if ( ! is_object( $response ) ) {
299
- return array();
300
- }
301
- if ( ! isset( $response->versions ) ) {
302
- return array();
303
- }
304
- $versions = array();
305
- foreach ( $response->versions as $version => $zip ) {
306
- $versions[] = array(
307
- 'version' => $version,
308
- 'url' => $zip,
309
- );
310
- }
311
-
312
- return $versions;
313
- }
314
-
315
- /**
316
- * @return string Return license key, if available.
317
- */
318
- private function get_license() {
319
- $license_data = get_option( $this->get_key() . '_license_data', '' );
320
-
321
- if ( empty( $license_data ) ) {
322
- return '';
323
- }
324
- if ( ! isset( $license_data->key ) ) {
325
- return '';
326
- }
327
-
328
- return $license_data->key;
329
- }
330
-
331
- /**
332
- * @return array Array of available versions.
333
- */
334
- private function get_pro_versions() {
335
- $license = $this->get_license();
336
- $store_url = trailingslashit( $this->store_url );
337
- $url = sprintf( '%s?edd_action=get_versions&name=%s&url=%s&license=%s', $store_url, urlencode( $this->get_name() ), urlencode( get_site_url() ), $license );
338
- $response = wp_remote_get( $url );
339
- if ( is_wp_error( $response ) ) {
340
- return array();
341
- }
342
- $response = wp_remote_retrieve_body( $response );
343
- $response = json_decode( $response );
344
- if ( ! is_object( $response ) ) {
345
- return array();
346
- }
347
- if ( ! isset( $response->versions ) ) {
348
- return array();
349
- }
350
- $versions = array();
351
- foreach ( $response->versions as $key => $version ) {
352
- $versions[] = array(
353
- 'version' => $version->version,
354
- 'url' => $version->file,
355
- );
356
- }
357
-
358
- return $versions;
359
- }
360
-
361
- /**
362
- * Return theme versions.
363
- *
364
- * @return array Theme versions array.
365
- */
366
- public function get_theme_versions() {
367
- $url = sprintf( 'https://api.wordpress.org/themes/info/1.1/?action=theme_information&request[slug]=%s&request[fields][versions]=true', $this->get_slug() );
368
- $response = wp_remote_get( $url );
369
- if ( is_wp_error( $response ) ) {
370
- return array();
371
- }
372
- $response = wp_remote_retrieve_body( $response );
373
- $response = json_decode( $response );
374
-
375
- if ( ! is_object( $response ) ) {
376
- return array();
377
- }
378
- if ( ! isset( $response->versions ) ) {
379
- return array();
380
- }
381
- $versions = array();
382
- foreach ( $response->versions as $version => $zip ) {
383
- $versions[] = array(
384
- 'version' => $version,
385
- 'url' => $zip,
386
- );
387
- }
388
-
389
- return $versions;
390
- }
391
-
392
- /**
393
- * Get versions array from wp.org
394
- *
395
- * @return array Array of versions.
396
- */
397
- private function get_api_versions() {
398
-
399
- $cache_key = $this->get_key() . '_' . preg_replace( '/[^0-9a-zA-Z ]/m', '', $this->version ) . 'versions';
400
- $cache_versions = get_transient( $cache_key );
401
- if ( false === $cache_versions ) {
402
- $versions = array();
403
- if ( ! $this->is_wordpress_available() ) {
404
- $versions = $this->get_pro_versions();
405
- } else {
406
- if ( $this->get_type() === 'plugin' ) {
407
- $versions = $this->get_plugin_versions();
408
- }
409
- if ( $this->get_type() === 'theme' ) {
410
- $versions = $this->get_theme_versions();
411
- }
412
- }
413
- set_transient( $cache_key, $versions, 5 * DAY_IN_SECONDS );
414
- } else {
415
- $versions = is_array( $cache_versions ) ? $cache_versions : array();
416
- }
417
-
418
- return $versions;
419
- }
420
-
421
- /**
422
- * Get the last rollback for this product.
423
- *
424
- * @return array The rollback version.
425
- */
426
- public function get_rollback() {
427
- $rollback = array();
428
- $versions = $this->get_api_versions();
429
- $versions = apply_filters( $this->get_key() . '_rollbacks', $versions );
430
-
431
- if ( $versions ) {
432
- usort( $versions, array( $this, 'sort_rollback_array' ) );
433
- foreach ( $versions as $version ) {
434
- if ( isset( $version['version'] ) && isset( $version['url'] ) && version_compare( $this->version, $version['version'], '>' ) ) {
435
- $rollback = $version;
436
- break;
437
- }
438
- }
439
- }
440
-
441
- return $rollback;
442
- }
443
-
444
- /**
445
- * Sort the rollbacks array in descending order.
446
- */
447
- public function sort_rollback_array( $a, $b ) {
448
- return version_compare( $a['version'], $b['version'], '<' ) > 0;
449
- }
450
-
451
- /**
452
- * If product can be rolled back.
453
- *
454
- * @return bool Can the product be rolled back or not.
455
- */
456
- public function can_rollback() {
457
- if ( $this->get_type() === 'theme' ) {
458
- if ( ! current_user_can( 'switch_themes' ) ) {
459
- return false;
460
- }
461
- }
462
- if ( $this->get_type() === 'plugin' ) {
463
- if ( ! current_user_can( 'install_plugins' ) ) {
464
- return false;
465
- }
466
- }
467
- $rollback = $this->get_rollback();
468
-
469
- return ! empty( $rollback );
470
- }
471
-
472
- /**
473
- * Return the product key.
474
- *
475
- * @return string The product key.
476
- */
477
- public function get_key() {
478
- return $this->key;
479
- }
480
-
481
- /**
482
- * Return friendly name.
483
- *
484
- * @return string Friendly name.
485
- */
486
- public function get_friendly_name() {
487
- $name = apply_filters( $this->get_key() . '_friendly_name', trim( str_replace( 'Lite', '', $this->get_name() ) ) );
488
- $name = rtrim( $name, '- ' );
489
-
490
- return $name;
491
- }
492
-
493
- /**
494
- * Either the product requires license or not.
495
- *
496
- * @return bool Either requires license or not.
497
- */
498
- public function requires_license() {
499
- return $this->requires_license;
500
- }
501
-
502
- /**
503
- * Check if the product is either theme or plugin.
504
- *
505
- * @return string Product type.
506
- */
507
- public function get_type() {
508
- return $this->type;
509
- }
510
-
511
- /**
512
- * Returns the Store name.
513
- *
514
- * @return string Store name.
515
- */
516
- public function get_store_name() {
517
- return $this->store_name;
518
- }
519
-
520
- /**
521
- * Returns the store url.
522
- *
523
- * @return string The store url.
524
- */
525
- public function get_store_url() {
526
- return $this->store_url;
527
- }
528
-
529
- /**
530
- * Returns the product slug.
531
- *
532
- * @return string The product slug.
533
- */
534
- public function get_slug() {
535
- return $this->slug;
536
- }
537
-
538
- /**
539
- * Returns product basefile, which holds the metaheaders.
540
- *
541
- * @return string The product basefile.
542
- */
543
- public function get_basefile() {
544
- return $this->basefile;
545
- }
546
-
547
- /**
548
- * Returns product filename.
549
- *
550
- * @return string The product filename.
551
- */
552
- public function get_file() {
553
- return $this->file;
554
- }
555
-
556
- /**
557
- * Returns feedback types
558
- *
559
- * @return array The feedback types.
560
- */
561
- public function get_feedback_types() {
562
- return apply_filters( $this->get_key() . '_feedback_types', $this->feedback_types );
563
- }
564
-
565
- /**
566
- * Returns widget types
567
- *
568
- * @return array The widget types.
569
- */
570
- public function get_widget_types() {
571
- return apply_filters( $this->get_key() . '_widget_types', $this->widget_types );
572
- }
573
-
574
- /**
575
- * We log the user website and product version.
576
- *
577
- * @return bool Either we log the data or not.
578
- */
579
- public function is_logger_active() {
580
- // If is not available on WordPress log this automatically.
581
- if ( ! $this->is_wordpress_available() ) {
582
- return true;
583
- } else {
584
- $pro_slug = $this->get_pro_slug();
585
- if ( ! empty( $pro_slug ) ) {
586
-
587
- $all_products = ThemeIsle_SDK_Loader::get_products();
588
- if ( isset( $all_products[ $pro_slug ] ) ) {
589
- return true;
590
- }
591
- }
592
-
593
- return ( get_option( $this->get_key() . '_logger_flag', 'no' ) === 'yes' );
594
-
595
- }
596
- }
597
-
598
- /**
599
- * Returns the pro slug, if available.
600
- *
601
- * @return string The pro slug.
602
- */
603
- public function get_pro_slug() {
604
- return $this->pro_slug;
605
- }
606
-
607
- /**
608
- * Return the install timestamp.
609
- *
610
- * @return int The install timestamp.
611
- */
612
- public function get_install_time() {
613
- return $this->install;
614
- }
615
-
616
- /**
617
- * We require feedback on uninstall.
618
- *
619
- * @return bool Either we should require feedback on uninstall or not.
620
- */
621
- public function require_uninstall_feedback() {
622
- if ( $this->get_type() == 'theme' && ! $this->is_external_author() ) {
623
- return ! get_transient( 'ti_sdk_pause_' . $this->get_key(), false );
624
- }
625
-
626
- if ( $this->get_type() == 'plugin' ) {
627
-
628
- return true;
629
- }
630
-
631
- return false;
632
- }
633
-
634
- }
635
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-rollback.php DELETED
@@ -1,223 +0,0 @@
1
- <?php
2
- /**
3
- * The rollback class for ThemeIsle SDK
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Rollback
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- // Exit if accessed directly.
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
- if ( ! class_exists( 'ThemeIsle_SDK_Rollback' ) ) :
16
- /**
17
- * Rollback for ThemeIsle SDK.
18
- */
19
- class ThemeIsle_SDK_Rollback {
20
-
21
- /**
22
- * @var ThemeIsle_SDK_Product $product Themeisle Product.
23
- */
24
- protected $product;
25
-
26
-
27
- /**
28
- * ThemeIsle_SDK_Rollback constructor.
29
- *
30
- * @param ThemeIsle_SDK_Product $product_object Product Object.
31
- */
32
- public function __construct( $product_object ) {
33
- if ( $product_object instanceof ThemeIsle_SDK_Product ) {
34
- $this->product = $product_object;
35
- }
36
- if ( $this->product->can_rollback() ) {
37
- $this->show_link();
38
- $this->add_hooks();
39
-
40
- }
41
- }
42
-
43
- /**
44
- * Add js scripts for themes rollback.
45
- */
46
- public function add_footer() {
47
- $screen = get_current_screen();
48
- if ( ! isset( $screen->parent_file ) ) {
49
- return;
50
- }
51
- if ( $screen->parent_file !== 'themes.php' ) {
52
- return;
53
- }
54
- if ( $this->product->get_type() === 'plugin' ) {
55
- return;
56
- }
57
-
58
- $version = $this->product->get_rollback();
59
- ?>
60
- <script type="text/javascript">
61
- jQuery(document).ready(function ($) {
62
- setInterval(checkTheme, 500);
63
-
64
- function checkTheme() {
65
- var theme = '<?php echo esc_attr( $this->product->get_slug() ); ?>-action';
66
-
67
- if (jQuery('#' + theme).length > 0) {
68
- if (jQuery('.theme-overlay.active').is(':visible')) {
69
- if (jQuery('#' + theme + '-rollback').length === 0) {
70
- jQuery('.theme-actions .active-theme').prepend('<a class="button" style="float:left" id="' + theme + '-rollback" href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=' . $this->product->get_key() . '_rollback' ), $this->product->get_key() . '_rollback' ) ); ?>">Rollback to v<?php echo esc_attr( $version['version'] ); ?></a>')
71
- }
72
- }
73
-
74
- }
75
- }
76
- })
77
-
78
- </script>
79
- <?php
80
-
81
- }
82
-
83
- /**
84
- * Set the rollback hook. Strangely, this does not work if placed in the ThemeIsle_SDK_Rollback class, so it is being called from there instead.
85
- */
86
- public function add_hooks() {
87
- add_action( 'admin_post_' . $this->product->get_key() . '_rollback', array( $this, 'start_rollback' ) );
88
- add_action( 'admin_footer', array( $this, 'add_footer' ) );
89
- }
90
-
91
- /**
92
- * If product can be rolled back, show the link to rollback.
93
- */
94
- private function show_link() {
95
- add_filter(
96
- 'plugin_action_links_' . plugin_basename( $this->product->get_basefile() ), array(
97
- $this,
98
- 'add_rollback_link',
99
- )
100
- );
101
- }
102
-
103
- /**
104
- * Show the rollback links in the plugin page.
105
- *
106
- * @return array The links.
107
- */
108
- public function add_rollback_link( $links ) {
109
- $version = $this->product->get_rollback();
110
- $links[] = '<a href="' . wp_nonce_url( admin_url( 'admin-post.php?action=' . $this->product->get_key() . '_rollback' ), $this->product->get_key() . '_rollback' ) . '">' . sprintf( apply_filters( $this->product->get_key() . '_rollback_label', 'Rollback to v%s' ), $version['version'] ) . '</a>';
111
-
112
- return $links;
113
- }
114
-
115
- /**
116
- * Start the rollback operation.
117
- */
118
- public function start_rollback() {
119
- if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], $this->product->get_key() . '_rollback' ) ) {
120
- wp_nonce_ays( '' );
121
- }
122
-
123
- if ( $this->product->get_type() === 'plugin' ) {
124
- $this->start_rollback_plugin();
125
- } elseif ( $this->product->get_type() === 'theme' ) {
126
- $this->start_rollback_theme();
127
- }
128
- }
129
-
130
- /**
131
- * Alter links and remove duplicate customize message.
132
- *
133
- * @param array $links Array of old links.
134
- *
135
- * @return mixed Array of links.
136
- */
137
- public function alter_links_theme_upgrade( $links ) {
138
- if ( isset( $links['preview'] ) ) {
139
- $links['preview'] = str_replace( '<span aria-hidden="true">Customize</span>', '', $links['preview'] );
140
- }
141
-
142
- return $links;
143
- }
144
-
145
- /**
146
- * Start the rollback operation for the theme.
147
- */
148
- private function start_rollback_theme() {
149
- add_filter( 'update_theme_complete_actions', array( $this, 'alter_links_theme_upgrade' ) );
150
- $rollback = $this->product->get_rollback();
151
- $transient = get_site_transient( 'update_themes' );
152
- $folder = $this->product->get_slug();
153
- $version = $rollback['version'];
154
- $temp_array = array(
155
- 'new_version' => $version,
156
- 'package' => $rollback['url'],
157
- );
158
-
159
- $transient->response[ $folder . '/style.css' ] = $temp_array;
160
- set_site_transient( 'update_themes', $transient );
161
-
162
- $transient = get_transient( $this->product->get_key() . '_warning_rollback' );
163
-
164
- if ( false === $transient ) {
165
- set_transient( $this->product->get_key() . '_warning_rollback', 'in progress', 30 );
166
- require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
167
- $title = sprintf( apply_filters( $this->product->get_key() . '_rollback_message', 'Rolling back %s to v%s' ), $this->product->get_name(), $version );
168
- $theme = $folder . '/style.css';
169
- $nonce = 'upgrade-theme_' . $theme;
170
- $url = 'update.php?action=upgrade-theme&theme=' . urlencode( $theme );
171
-
172
- $upgrader = new Theme_Upgrader( new Theme_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'theme' ) ) );
173
- $upgrader->upgrade( $theme );
174
- delete_transient( $this->product->get_key() . '_warning_rollback' );
175
- wp_die(
176
- '', $title, array(
177
- 'response' => 200,
178
- )
179
- );
180
- }
181
- }
182
-
183
- /**
184
- * Start the rollback operation for the plugin.
185
- */
186
- private function start_rollback_plugin() {
187
- $rollback = $this->product->get_rollback();
188
- $plugin_transient = get_site_transient( 'update_plugins' );
189
- $plugin_folder = $this->product->get_slug();
190
- $plugin_file = $this->product->get_file();
191
- $version = $rollback['version'];
192
- $temp_array = array(
193
- 'slug' => $plugin_folder,
194
- 'new_version' => $version,
195
- 'package' => $rollback['url'],
196
- );
197
-
198
- $temp_object = (object) $temp_array;
199
- $plugin_transient->response[ $plugin_folder . '/' . $plugin_file ] = $temp_object;
200
- set_site_transient( 'update_plugins', $plugin_transient );
201
-
202
- $transient = get_transient( $this->product->get_key() . '_warning_rollback' );
203
-
204
- if ( false === $transient ) {
205
- set_transient( $this->product->get_key() . '_warning_rollback', 'in progress', 30 );
206
- require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
207
- $title = sprintf( apply_filters( $this->product->get_key() . '_rollback_message', 'Rolling back %s to v%s' ), $this->product->get_name(), $version );
208
- $plugin = $plugin_folder . '/' . $plugin_file;
209
- $nonce = 'upgrade-plugin_' . $plugin;
210
- $url = 'update.php?action=upgrade-plugin&plugin=' . urlencode( $plugin );
211
- $upgrader_skin = new Plugin_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'plugin' ) );
212
- $upgrader = new Plugin_Upgrader( $upgrader_skin );
213
- $upgrader->upgrade( $plugin );
214
- delete_transient( $this->product->get_key() . '_warning_rollback' );
215
- wp_die(
216
- '', $title, array(
217
- 'response' => 200,
218
- )
219
- );
220
- }
221
- }
222
- }
223
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-widget-dashboard-blog.php DELETED
@@ -1,412 +0,0 @@
1
- <?php
2
- /**
3
- * The blog dashboard model class for ThemeIsle SDK
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Widgets
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- // Exit if accessed directly.
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
- if ( ! class_exists( 'ThemeIsle_SDK_Widget_Dashboard_Blog' ) ) :
16
- /**
17
- * Blog dashboard widget model for ThemeIsle SDK.
18
- */
19
- class ThemeIsle_SDK_Widget_Dashboard_Blog extends ThemeIsle_SDK_Widget {
20
-
21
- /**
22
- * @var array instance The instances.
23
- */
24
- protected $product;
25
- /**
26
- * @var array Feed items.
27
- */
28
- private $items = array();
29
-
30
- /**
31
- * ThemeIsle_SDK_Widget_Dashboard_Blog constructor.
32
- *
33
- * @param ThemeIsle_SDK_Product $product_object The product object.
34
- */
35
- public function __construct( $product_object ) {
36
- $this->product = $product_object;
37
- parent::__construct( $product_object );
38
- }
39
-
40
- /**
41
- * Registers the hooks
42
- */
43
- public function setup_hooks_child() {
44
- $this->setup_vars();
45
- add_action( 'wp_dashboard_setup', array( &$this, 'add_widget' ) );
46
- add_action( 'wp_network_dashboard_setup', array( &$this, 'add_widget' ) );
47
- add_filter( 'themeisle_sdk_recommend_plugin_or_theme', array( &$this, 'recommend_plugin_or_theme' ) );
48
- }
49
-
50
- /**
51
- * Setup class variables
52
- */
53
- function setup_vars() {
54
- $this->dashboard_name = apply_filters( 'themeisle_sdk_dashboard_widget_name', 'WordPress Guides/Tutorials' );
55
- $this->feeds = apply_filters(
56
- 'themeisle_sdk_dashboard_widget_feeds', array(
57
- 'https://themeisle.com/blog/feed',
58
- )
59
- );
60
- }
61
-
62
- /**
63
- * Add widget to the dashboard
64
- *
65
- * @return string|void
66
- */
67
- function add_widget() {
68
- global $wp_meta_boxes;
69
- if ( isset( $wp_meta_boxes['dashboard']['normal']['core']['themeisle'] ) ) {
70
- return;
71
- }
72
- wp_add_dashboard_widget(
73
- 'themeisle', $this->dashboard_name, array(
74
- &$this,
75
- 'render_dashboard_widget',
76
- )
77
- );
78
- }
79
-
80
- /**
81
- * Setup feed items.
82
- */
83
- private function setup_feeds() {
84
- $items_normalized = array();
85
- if ( false === ( $items_normalized = get_transient( 'themeisle_sdk_feed_items' ) ) ) {
86
- // Load SimplePie Instance
87
- $feed = fetch_feed( $this->feeds );
88
- // TODO report error when is an error loading the feed
89
- if ( is_wp_error( $feed ) ) {
90
- return;
91
- }
92
-
93
- $items = $feed->get_items( 0, 5 );
94
- foreach ( (array) $items as $item ) {
95
- $items_normalized[] = array(
96
- 'title' => $item->get_title(),
97
- 'date' => $item->get_date( 'U' ),
98
- 'link' => $item->get_permalink(),
99
- );
100
- }
101
- set_transient( 'themeisle_sdk_feed_items', $items_normalized, 48 * HOUR_IN_SECONDS );
102
- }
103
- $this->items = $items_normalized;
104
- }
105
-
106
- /**
107
- * Render widget content
108
- */
109
- function render_dashboard_widget() {
110
- $this->setup_feeds();
111
- if ( empty( $this->items ) || ! is_array( $this->items ) ) {
112
- return;
113
- }
114
- ?>
115
- <style type="text/css">
116
- #themeisle ul li.ti-dw-recommend-item {
117
- padding-left: 7px;
118
- border-top: 1px solid #eee;
119
- margin-bottom: 0px;
120
- padding-top: 6px;
121
- }
122
-
123
- #themeisle h2.hndle {
124
- background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3Ny4xMiA3Ny4xMiI+PHRpdGxlPkFzc2V0IDM8L3RpdGxlPjxwYXRoIGQ9Ik03NS43Niw0Ny42cS0xLjUsNi40Ni00LjA3LDkuMjZBMzYuMjIsMzYuMjIsMCwwLDEsNjMuMjYsNjNhNTEsNTEsMCwwLDEtOS43OSw0LjZoLS4xNXY0LjgyQTQuNjYsNC42NiwwLDAsMSw1Miw3NS43Niw0LjA3LDQuMDcsMCwwLDEsNDksNzcuMTJhNCw0LDAsMCwxLTIuMTgtLjYxQTQuOTQsNC45NCwwLDAsMSw0NS4xOSw3NWE0LjQyLDQuNDIsMCwwLDEtNy41NCwwLDQuOTQsNC45NCwwLDAsMS0xLjU4LDEuNSwzLjc1LDMuNzUsMCwwLDEtMiwuNjFBNC4yNyw0LjI3LDAsMCwxLDMwLjI3LDc1YTQuOTQsNC45NCwwLDAsMS0xLjU4LDEuNSw0LDQsMCwwLDEtMi4xOC42MSwzLjkzLDMuOTMsMCwwLDEtMy4xNi0xLjQzLDUuMyw1LjMsMCwwLDEtMS4yMS0zLjU0LDEzLjgxLDEzLjgxLDAsMCwxLTguNTgsMywxMy4yMywxMy4yMywwLDAsMS05LTMuNDdBMTguMjEsMTguMjEsMCwwLDAsOSw3MC43OWExNC4yNiwxNC4yNiwwLDAsMS03LjgzLTUuNDIsMTYuMTIsMTYuMTIsMCwwLDAsNS4xOS4wNywxMi44OSwxMi44OSwwLDAsMCw0LjktMS43M1EzLjE1LDU1LjQzLDEuMDUsNTAuNDZhMTgsMTgsMCwwLDEtMS02LjkzQTQwLDQwLDAsMCwxLDEuMjEsMzQsMjYuNTksMjYuNTksMCwwLDEsNS4yNywyNC4xUTguNDQsMTkuNDMsMTMsMTkuNDNhMy40MSwzLjQxLDAsMCwxLDMuNDcsMi4yNmMuNi0uOCwxLjItMS41NiwxLjgxLTIuMjZsLjQ1LS40NS43NS0uNzUsMS4wNS0xLjgxYTM1LjIsMzUuMiwwLDAsMSwyLjExLTMuMzIsMjguNTcsMjguNTcsMCwwLDEsOS4xMi03LjY4QTIzLjQsMjMuNCwwLDAsMSw0Mi45MywyLjU2YTIyLjIyLDIyLjIyLDAsMCwxLDIuNzEuMTVBOC4xNiw4LjE2LDAsMCwxLDUxLjgxLDAsOC42OSw4LjY5LDAsMCwxLDU4LDIuNDFhMS41MSwxLjUxLDAsMCwxLC4xNS42OGMwLC4yNS0uNTUuOTMtMS42NiwybC0uMy4zYTkuNjksOS42OSwwLDAsMSwxLjU4LjgzYy41NS4zNS44My42NS44My45YTEuNjIsMS42MiwwLDAsMS0uNiwxbC0uMTUuMTVxNi43OCw2LDguNTgsMTYuMjdBMy4zLDMuMywwLDAsMSw2OSwyMy4zNWE2LjQ4LDYuNDgsMCwwLDEsNC4yMiwyLjFxMy45MiwzLjMyLDMuOTIsMTEuOUE0Mi4wNSw0Mi4wNSwwLDAsMSw3NS43Niw0Ny42Wk01My42Miw1NC4wN2EyNCwyNCwwLDAsMS0xNCw0LjUyQTIxLjQxLDIxLjQxLDAsMCwxLDI3LDU0LjY3LDI0LjI4LDI0LjI4LDAsMCwxLDE4LjUzLDQ1YTI5LDI5LDAsMCwxLTMtMTMsMzEuNzgsMzEuNzgsMCwwLDEsLjkxLTcuNTNBMzIuMTcsMzIuMTcsMCwwLDAsMTEuOSw0MS4yN2EzMy41LDMzLjUsMCwwLDAsMi43OSwxMy40LDI5LjEsMjkuMSwwLDAsMCw3LjksMTAuODUsNC42OCw0LjY4LDAsMCwxLDEuNjYtMS44OCw0LjE3LDQuMTcsMCwwLDEsNC40NC0uMDgsNC41LDQuNSwwLDAsMSwxLjU4LDEuNjZBNC4yLDQuMiwwLDAsMSwzNCw2M2EzLjgzLDMuODMsMCwwLDEsMiwuNiw0LjUsNC41LDAsMCwxLDEuNTgsMS42Niw0LjI3LDQuMjcsMCwwLDEsNy41NCwwLDQuNSw0LjUsMCwwLDEsMS41OC0xLjY2LDQuMTcsNC4xNywwLDAsMSw0LjQ0LjA4LDMuODYsMy44NiwwLDAsMSwxLjUxLDEuNzMsMzAuMTcsMzAuMTcsMCwwLDAsNy42OC05Ljk0LDMxLjE4LDMxLjE4LDAsMCwwLDMuMTYtMTIuMzVBMjguMzksMjguMzksMCwwLDEsNTMuNjIsNTQuMDdaTTI4Ljc3LDY1LjM3YTMuMSwzLjEsMCwwLDAtNC4zNywwLDMuMDYsMy4wNiwwLDAsMC0uOSwyLjI2djQuODJhMy4zMiwzLjMyLDAsMCwwLC45LDIuMzMsMi45MywyLjkzLDAsMCwwLDQuMzcsMCwzLjMyLDMuMzIsMCwwLDAsLjktMi4zM1Y2Ny42M0EzLjA2LDMuMDYsMCwwLDAsMjguNzcsNjUuMzdabS45LTQ4YTQuMjQsNC4yNCwwLDAsMCwzLjQ3LDEuNzMsNC40NSw0LjQ1LDAsMCwwLDMuNTQtMS43Myw2LDYsMCwwLDAsMS40My0zLjkyLDUuNyw1LjcsMCwwLDAtMS40My0zLjg0QTQuNTMsNC41MywwLDAsMCwzMy4xNCw4YTQuMzEsNC4zMSwwLDAsMC0zLjQ3LDEuNjYsNS43OSw1Ljc5LDAsMCwwLTEuMzUsMy43N0E2LjMzLDYuMzMsMCwwLDAsMjkuNjcsMTcuNFptNi40OCw0OGEzLjEsMy4xLDAsMCwwLTQuMzcsMCwzLjA2LDMuMDYsMCwwLDAtLjksMi4yNnY0LjgyYTMuMzIsMy4zMiwwLDAsMCwuOSwyLjMzLDIuOTMsMi45MywwLDAsMCw0LjM3LDAsMy4zMiwzLjMyLDAsMCwwLC45LTIuMzNWNjcuNjNBMy4wNiwzLjA2LDAsMCwwLDM2LjE1LDY1LjM3Wm0tNC4wNy01NC4zYTIuMzcsMi4zNywwLDAsMSwyLTEsMi4xNywyLjE3LDAsMCwxLDEuODgsMSw0LjEsNC4xLDAsMCwxLDAsNC41MiwyLjE3LDIuMTcsMCwwLDEtMS44OCwxLDIuMzcsMi4zNywwLDAsMS0yLTEsMy43MiwzLjcyLDAsMCwxLS43NS0yLjM0QTMuNDksMy40OSwwLDAsMSwzMi4wOCwxMS4wN1ptNSw5LjQxYTIwLjYxLDIwLjYxLDAsMCwwLTMuNTQsMTIuMjgsMTcuMTUsMTcuMTUsMCwwLDAsNC4wNywxMSwxMi40MywxMi40MywwLDAsMCw5Ljg3LDQuNDUsMTUuMywxNS4zLDAsMCwwLDktMywxMywxMywwLDAsMCwuNi0zLjMycTAtMy4zMi0zLjE2LTMuMzFhOC41OCw4LjU4LDAsMCwwLTIsLjNxLTcuODMsMS41LTExLjU5LS4zLTQuNTMtMi4xMi00LjUyLTkuMzRBMzcuOTIsMzcuOTIsMCwwLDEsMzcuMDUsMjAuNDhaTTYxLjQ1LDE3QTEyLjg0LDEyLjg0LDAsMCwwLDUxLjIxLDEyLjJhMTUuMTEsMTUuMTEsMCwwLDAtNi40LDEuNDMsMTcuODMsMTcuODMsMCwwLDAtNS41LDRxLTYuMTgsMjAuNjQsNi4xOCwyMC42NEEyNC43NSwyNC43NSwwLDAsMCw0OSwzNy44MWEzOC45MiwzOC45MiwwLDAsMSw0LjgyLS40NmMxLjgxLDAsMy4wNi40NiwzLjc3LDEuMzZxMS4zNSwxLjUuNzUsNS4xMmEyMS43MiwyMS43MiwwLDAsMCw1LTcuMTVBMjEuMzgsMjEuMzgsMCwwLDAsNjUuMDcsMjgsMTcuNDQsMTcuNDQsMCwwLDAsNjEuNDUsMTdaTTQzLjYsNjUuMzdhMi43MiwyLjcyLDAsMCwwLTIuMS0uOSwzLDMsMCwwLDAtMi4xOS45LDMuMDYsMy4wNiwwLDAsMC0uOSwyLjI2djQuODJhMy4zMiwzLjMyLDAsMCwwLC45LDIuMzMsMi44NCwyLjg0LDAsMCwwLDIuMTksMSwyLjYxLDIuNjEsMCwwLDAsMi4xLTEsMy40NSwzLjQ1LDAsMCwwLC44My0yLjMzVjY3LjYzQTMuMTcsMy4xNywwLDAsMCw0My42LDY1LjM3Wm03LjQ2LDBhMywzLDAsMCwwLTIuMTgtLjksMi43MywyLjczLDAsMCwwLTIuMTEuOSwzLjE3LDMuMTcsMCwwLDAtLjgzLDIuMjZ2NC44MmEzLjQ1LDMuNDUsMCwwLDAsLjgzLDIuMzMsMi42MSwyLjYxLDAsMCwwLDIuMTEsMSwyLjgzLDIuODMsMCwwLDAsMi4xOC0xLDMuMzIsMy4zMiwwLDAsMCwuOS0yLjMzVjY3LjYzQTMuMDYsMy4wNiwwLDAsMCw1MS4wNiw2NS4zN1oiLz48L3N2Zz4=');
125
- background-repeat: no-repeat;
126
- background-position: 92% 50%;
127
- background-size: 30px;
128
- }
129
-
130
- #themeisle .inside {
131
- padding: 0;
132
- }
133
-
134
- .ti-feed-list {
135
- padding: 0 12px 5px;
136
- margin-bottom: 10px;
137
- border-bottom: 1px solid #eee;
138
- }
139
-
140
- .ti-dw-feed-item a {
141
- display: flex;
142
- align-items: center;
143
- margin-bottom: 5px;
144
- padding: 5px;
145
- transition: .2s ease;
146
- border-radius: 3px;
147
- }
148
-
149
- .ti-dw-feed-item a:hover {
150
- background-color: #f8f8f8;
151
- }
152
-
153
- .ti-dw-feed-item a:hover .ti-dw-date-container {
154
- opacity: .9;
155
- }
156
-
157
- .ti-dw-feed-item .ti-dw-month-container {
158
- margin-top: -5px;
159
- text-transform: uppercase;
160
- font-size: 10px;
161
- letter-spacing: 1px;
162
- font-weight: 700;
163
- }
164
-
165
- .ti-dw-feed-item .ti-dw-date-container {
166
- border-radius: 3px;
167
- transition: .2s ease;
168
- min-height: 35px;
169
- margin-right: 5px;
170
- min-width: 35px;
171
- text-align: center;
172
- border: 1px solid #2a6f97;
173
- color: #fff;
174
- background: #2ea2cc;
175
- display: flex;
176
- flex-direction: column;
177
- justify-content: center;
178
- }
179
-
180
- .ti-dw-footer {
181
- padding: 0 12px 5px;
182
- text-align: center;
183
- }
184
-
185
- .ti-dw-recommend-item {
186
- display: block;
187
- }
188
-
189
- .ti-dw-recommend-item span {
190
- color: #72777c;
191
- }
192
-
193
- .ti-dw-powered-by {
194
- font-size: 11px;
195
- margin-top: 3px;
196
- display: block;
197
- color: #72777c;
198
- }
199
-
200
- .ti-dw-powered-by span {
201
- font-weight: 600;
202
- }
203
-
204
- </style>
205
- <ul class="ti-feed-list">
206
- <?php
207
- foreach ( $this->items as $item ) {
208
- ?>
209
- <li class="ti-dw-feed-item">
210
- <a href="
211
- <?php
212
- echo add_query_arg(
213
- array(
214
- 'utm_campaign' => 'feed',
215
- 'utm_medium' => 'dashboard_widget',
216
- ), $item['link']
217
- );
218
- ?>
219
- " target="_blank">
220
- <span class="ti-dw-date-container"><span
221
- class="ti-dw-day-container"><?php echo date( 'd', $item['date'] ); ?></span> <span
222
- class="ti-dw-month-container"><?php echo substr( date( 'M', $item['date'] ), 0, 3 ); ?></span></span><?php echo $item['title']; ?>
223
- </a>
224
- </li>
225
- <?php
226
- }
227
- ?>
228
- </ul>
229
- <?php
230
- $recommend = apply_filters( 'themeisle_sdk_recommend_plugin_or_theme', array() );
231
- if ( is_array( $recommend ) && ! empty( $recommend ) ) {
232
-
233
- $type = $recommend['type'];
234
- if ( ( $type == 'theme' && current_user_can( 'install_themes' ) ) || ( $type == 'plugin' && current_user_can( 'install_plugins' ) ) ) {
235
- add_thickbox();
236
- $url = add_query_arg(
237
- array(
238
- 'theme' => $recommend['slug'],
239
- ), network_admin_url( 'theme-install.php' )
240
- );
241
-
242
- if ( 'plugin' === $type ) {
243
-
244
- $url = add_query_arg(
245
- array(
246
- 'tab' => 'plugin-information',
247
- 'plugin' => $recommend['slug'],
248
- ), network_admin_url( 'plugin-install.php' )
249
- );
250
- }
251
- ?>
252
- <div class="ti-dw-footer">
253
- <span class="ti-dw-recommend-item ">
254
- <span class="ti-dw-recommend"><?php echo apply_filters( 'themeisle_sdk_dashboard_popular_label', sprintf( 'Popular %s', ucwords( $type ) ) ); ?>
255
- : </span>
256
- <?php
257
- echo trim(
258
- str_replace(
259
- array(
260
- 'lite',
261
- 'Lite',
262
- ), '', $recommend['name']
263
- )
264
- );
265
- ?>
266
- (<a class="thickbox open-plugin-details-modal"
267
- href="<?php echo $url . '&TB_iframe=true&width=600&height=500'; ?>"><?php echo apply_filters( 'themeisle_sdk_dashboard_install_label', 'Install' ); ?></a>)
268
- </span>
269
- <span class="ti-dw-powered-by">
270
- Powered by <span><?php echo esc_attr( $this->product->get_friendly_name() ); ?></span>
271
- </span>
272
- </div>
273
-
274
- <?php
275
- }
276
- }
277
- ?>
278
-
279
- <?php
280
-
281
- }
282
-
283
- /**
284
- * Either the current product is installed or not.
285
- *
286
- * @param array $val The current recommended product.
287
- *
288
- * @return bool Either we should exclude the plugin or not.
289
- */
290
- public function remove_current_products( $val ) {
291
- if ( $val['type'] === 'theme' ) {
292
- $exist = wp_get_theme( $val['slug'] );
293
-
294
- return ! $exist->exists();
295
- } else {
296
- $all_plugins = array_keys( get_plugins() );
297
- foreach ( $all_plugins as $slug ) {
298
- if ( strpos( $slug, $val['slug'] ) !== false ) {
299
- return false;
300
- }
301
- }
302
-
303
- return true;
304
- }
305
- }
306
-
307
- /**
308
- * Fetch themes from wporg api.
309
- *
310
- * @param string $author The author name.
311
- *
312
- * @return array The list of themes.
313
- */
314
- function get_themes_from_wporg( $author ) {
315
- $products = wp_remote_get(
316
- 'https://api.wordpress.org/themes/info/1.1/?action=query_themes&request[author]=' . $author . '&request[per_page]=30&request[fields][active_installs]=true'
317
- );
318
- $products = json_decode( wp_remote_retrieve_body( $products ) );
319
- if ( is_object( $products ) ) {
320
- $products = isset( $products->themes ) ? $products->themes : array();
321
- } else {
322
- $products = array();
323
- }
324
-
325
- return $products;
326
- }
327
-
328
- /**
329
- * Fetch plugin from wporg api.
330
- *
331
- * @param string $author The author slug.
332
- *
333
- * @return array The list of plugins for the selected author.
334
- */
335
- function get_plugins_from_wporg( $author ) {
336
- $products = wp_remote_get(
337
- 'https://api.wordpress.org/plugins/info/1.1/?action=query_plugins&request[author]=' . $author . '&request[author]=codeinwp&request[per_page]=20&request[fields][active_installs]=true'
338
- );
339
- $products = json_decode( wp_remote_retrieve_body( $products ) );
340
- if ( is_object( $products ) ) {
341
- $products = isset( $products->plugins ) ? $products->plugins : array();
342
- } else {
343
- $products = array();
344
- }
345
-
346
- return $products;
347
- }
348
-
349
- /**
350
- * Fetch products from the recomended section.
351
- *
352
- * @return array|mixed The list of products to use in recomended section.
353
- */
354
- function get_product_from_api() {
355
- if ( false === ( $products = get_transient( 'themeisle_sdk_products' ) ) ) {
356
- $products = array();
357
- $themeisle_themes = $this->get_themes_from_wporg( 'themeisle' );
358
- $codeinwp_themes = $this->get_themes_from_wporg( 'codeinwp' );
359
-
360
- $themeisle_plugins = $this->get_plugins_from_wporg( 'themeisle' );
361
- $codeinwp_plugins = $this->get_plugins_from_wporg( 'codeinwp' );
362
-
363
- $all_themes = array_merge( $themeisle_themes, $codeinwp_themes );
364
- foreach ( $all_themes as $theme ) {
365
- if ( $theme->active_installs < 4999 ) {
366
- continue;
367
- }
368
- $products[] = array(
369
- 'name' => $theme->name,
370
- 'type' => 'theme',
371
- 'slug' => $theme->slug,
372
- 'installs' => $theme->active_installs,
373
- );
374
- }
375
- $all_plugins = array_merge( $themeisle_plugins, $codeinwp_plugins );
376
- foreach ( $all_plugins as $plugin ) {
377
- if ( $plugin->active_installs < 5999 ) {
378
- continue;
379
- }
380
- $products[] = array(
381
- 'name' => $plugin->name,
382
- 'type' => 'plugin',
383
- 'slug' => $plugin->slug,
384
- 'installs' => $plugin->active_installs,
385
- );
386
- }
387
- set_transient( 'themeisle_sdk_products', $products, 6 * HOUR_IN_SECONDS );
388
- }
389
-
390
- return $products;
391
- }
392
-
393
- /**
394
- * Contact the API and fetch the recommended plugins/themes
395
- */
396
- function recommend_plugin_or_theme() {
397
- $products = $this->get_product_from_api();
398
- if ( ! is_array( $products ) ) {
399
- $products = array();
400
- }
401
- $products = array_filter( $products, array( $this, 'remove_current_products' ) );
402
- $products = array_merge( $products );
403
- if ( count( $products ) > 1 ) {
404
- shuffle( $products );
405
- $products = array_slice( $products, 0, 1 );
406
- }
407
- $to_recommend = isset( $products[0] ) ? $products[0] : $products;
408
-
409
- return $to_recommend;
410
- }
411
- }
412
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-widget.php DELETED
@@ -1,50 +0,0 @@
1
- <?php
2
- /**
3
- * The widget model class for ThemeIsle SDK
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Widgets
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- // Exit if accessed directly.
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
- if ( ! class_exists( 'ThemeIsle_SDK_Widget' ) ) :
16
- /**
17
- * Widget model for ThemeIsle SDK.
18
- */
19
- abstract class ThemeIsle_SDK_Widget {
20
- /**
21
- * @var ThemeIsle_SDK_Product $product Themeisle Product.
22
- */
23
- protected $product;
24
-
25
- /**
26
- * ThemeIsle_SDK_Widget constructor.
27
- *
28
- * @param ThemeIsle_SDK_Product $product_object Product Object.
29
- */
30
- public function __construct( $product_object ) {
31
- if ( $product_object instanceof ThemeIsle_SDK_Product ) {
32
- $this->product = $product_object;
33
- }
34
- $this->setup_hooks();
35
- }
36
-
37
- /**
38
- * Registers the hooks and then delegates to the child
39
- */
40
- public function setup_hooks() {
41
- $this->setup_hooks_child();
42
- }
43
-
44
- /**
45
- * Abstract function for delegating to the child
46
- */
47
- protected abstract function setup_hooks_child();
48
-
49
- }
50
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-widgets-factory.php DELETED
@@ -1,37 +0,0 @@
1
- <?php
2
- /**
3
- * The widgets factory class for ThemeIsle SDK
4
- *
5
- * @package ThemeIsleSDK
6
- * @subpackage Widgets
7
- * @copyright Copyright (c) 2017, Marius Cristea
8
- * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
- * @since 1.0.0
10
- */
11
- // Exit if accessed directly.
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
14
- }
15
- if ( ! class_exists( 'ThemeIsle_SDK_Widgets_Factory' ) ) :
16
- /**
17
- * Widgets factory model for ThemeIsle SDK.
18
- */
19
- class ThemeIsle_SDK_Widgets_Factory {
20
-
21
- /**
22
- * ThemeIsle_SDK_Widgets_Factory constructor.
23
- *
24
- * @param ThemeIsle_SDK_Product $product_object Product Object.
25
- * @param array $widgets the widgets.
26
- */
27
- public function __construct( $product_object, $widgets ) {
28
- if ( $product_object instanceof ThemeIsle_SDK_Product && $widgets && is_array( $widgets ) ) {
29
- foreach ( $widgets as $widget ) {
30
- $class = 'ThemeIsle_SDK_Widget_' . str_replace( ' ', '_', ucwords( str_replace( '_', ' ', $widget ) ) );
31
- $instance = new $class( $product_object );
32
- $instance->setup_hooks();
33
- }
34
- }
35
- }
36
- }
37
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/composer.json DELETED
@@ -1,24 +0,0 @@
1
- {
2
- "name": "codeinwp/themeisle-sdk",
3
- "description": "ThemeIsle SDK ",
4
- "keywords": [
5
- "wordpress"
6
- ],
7
- "homepage": "https://github.com/Codeinwp/themeisle-sdk",
8
- "license": "GPL-2.0+",
9
- "authors": [
10
- {
11
- "name": "ThemeIsle team",
12
- "email": "friends@themeisle.com",
13
- "homepage": "https://themeisle.com"
14
- }
15
- ],
16
- "autoload": {
17
- "files": [
18
- "load.php"
19
- ]
20
- },
21
- "support": {
22
- "issues": "https://github.com/Codeinwp/themeisle-sdk/issues"
23
- }
24
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vendor/codeinwp/themeisle-sdk/index.php CHANGED
@@ -1,5 +1,3 @@
1
  <?php
2
- /**
3
- * @package ThemeIsleSDK
4
- * Ignore this.
5
- */
1
  <?php
2
+ // phpcs:ignoreFile
3
+ // Nothing here.
 
 
vendor/codeinwp/themeisle-sdk/load.php CHANGED
@@ -10,24 +10,38 @@
10
  * @since 1.1.0
11
  */
12
 
 
 
 
13
  // Current SDK version and path.
14
- $themeisle_sdk_version = '2.2.8';
15
  $themeisle_sdk_path = dirname( __FILE__ );
16
 
17
  global $themeisle_sdk_max_version;
18
  global $themeisle_sdk_max_path;
19
 
20
- if ( version_compare( $themeisle_sdk_version, $themeisle_sdk_max_version ) >= 0 ) {
 
 
 
 
 
21
  $themeisle_sdk_max_version = $themeisle_sdk_version;
22
  $themeisle_sdk_max_path = $themeisle_sdk_path;
23
  }
24
 
25
- // load the latest sdk version from the active Themeisle products
26
  if ( ! function_exists( 'themeisle_sdk_load_latest' ) ) :
27
  /**
28
  * Always load the latest sdk version.
29
  */
30
  function themeisle_sdk_load_latest() {
 
 
 
 
 
 
31
  global $themeisle_sdk_max_path;
32
  require_once $themeisle_sdk_max_path . '/start.php';
33
  }
10
  * @since 1.1.0
11
  */
12
 
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ return;
15
+ }
16
  // Current SDK version and path.
17
+ $themeisle_sdk_version = '3.0.5';
18
  $themeisle_sdk_path = dirname( __FILE__ );
19
 
20
  global $themeisle_sdk_max_version;
21
  global $themeisle_sdk_max_path;
22
 
23
+ if ( version_compare( $themeisle_sdk_version, $themeisle_sdk_max_path ) == 0 &&
24
+ apply_filters( 'themeisle_sdk_should_overwrite_path', false, $themeisle_sdk_path, $themeisle_sdk_max_path ) ) {
25
+ $themeisle_sdk_max_path = $themeisle_sdk_path;
26
+ }
27
+
28
+ if ( version_compare( $themeisle_sdk_version, $themeisle_sdk_max_version ) > 0 ) {
29
  $themeisle_sdk_max_version = $themeisle_sdk_version;
30
  $themeisle_sdk_max_path = $themeisle_sdk_path;
31
  }
32
 
33
+ // load the latest sdk version from the active Themeisle products.
34
  if ( ! function_exists( 'themeisle_sdk_load_latest' ) ) :
35
  /**
36
  * Always load the latest sdk version.
37
  */
38
  function themeisle_sdk_load_latest() {
39
+ /**
40
+ * Don't load the library if we are on < 5.4.
41
+ */
42
+ if ( version_compare( PHP_VERSION, '5.4.32', '<' ) ) {
43
+ return;
44
+ }
45
  global $themeisle_sdk_max_path;
46
  require_once $themeisle_sdk_max_path . '/start.php';
47
  }
vendor/codeinwp/themeisle-sdk/src/Common/Abstract_module.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The abstract class for module definition.
4
+ *
5
+ * @package ThemeIsleSDK
6
+ * @subpackage Loader
7
+ * @copyright Copyright (c) 2017, Marius Cristea
8
+ * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
+ * @since 3.0.0
10
+ */
11
+
12
+ namespace ThemeisleSDK\Common;
13
+
14
+ use ThemeisleSDK\Product;
15
+
16
+ if ( ! defined( 'ABSPATH' ) ) {
17
+ exit;
18
+ }
19
+
20
+ /**
21
+ * Class Abstract_Module.
22
+ *
23
+ * @package ThemeisleSDK\Common
24
+ */
25
+ abstract class Abstract_Module {
26
+ /**
27
+ * Product which use the module.
28
+ *
29
+ * @var Product $product Product object.
30
+ */
31
+ protected $product = null;
32
+
33
+ /**
34
+ * Can load the module for the selected product.
35
+ *
36
+ * @param Product $product Product data.
37
+ *
38
+ * @return bool Should load module?
39
+ */
40
+ public abstract function can_load( $product );
41
+
42
+ /**
43
+ * Bootstrap the module.
44
+ *
45
+ * @param Product $product Product object.
46
+ */
47
+ public abstract function load( $product );
48
+
49
+ /**
50
+ * Check if the product is from partner.
51
+ *
52
+ * @param Product $product Product data.
53
+ *
54
+ * @return bool Is product from partner.
55
+ */
56
+ public function is_from_partner( $product ) {
57
+
58
+ foreach ( Module_Factory::$domains as $partner_domain ) {
59
+ if ( strpos( $product->get_store_url(), $partner_domain ) !== false ) {
60
+ return true;
61
+ }
62
+ }
63
+
64
+ return array_key_exists( $product->get_slug(), Module_Factory::$slugs );
65
+ }
66
+ }
vendor/codeinwp/themeisle-sdk/src/Common/Module_factory.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The module factory class.
4
+ *
5
+ * @package ThemeIsleSDK
6
+ * @subpackage Loader
7
+ * @copyright Copyright (c) 2017, Marius Cristea
8
+ * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
+ * @since 3.0.0
10
+ */
11
+
12
+ namespace ThemeisleSDK\Common;
13
+
14
+ use ThemeisleSDK\Product;
15
+
16
+ if ( ! defined( 'ABSPATH' ) ) {
17
+ exit;
18
+ }
19
+
20
+ /**
21
+ * Class Job_Factory
22
+ *
23
+ * @package ThemeisleSDK\Common
24
+ */
25
+ class Module_Factory {
26
+ /**
27
+ * Partners slugs.
28
+ *
29
+ * @var array $SLUGS Partners product slugs.
30
+ */
31
+ public static $slugs = [
32
+ 'zermatt' => true,
33
+ 'neto' => true,
34
+ 'olsen' => true,
35
+ 'benson' => true,
36
+ 'romero' => true,
37
+ 'carmack' => true,
38
+ 'puzzle' => true,
39
+ 'broadsheet' => true,
40
+ 'girlywp' => true,
41
+ 'veggie' => true,
42
+ 'zeko' => true,
43
+ 'maishawp' => true,
44
+ 'didi' => true,
45
+ 'liber' => true,
46
+ 'medicpress-pt' => true,
47
+ 'adrenaline-pt' => true,
48
+ 'consultpress-pt' => true,
49
+ 'legalpress-pt' => true,
50
+ 'gympress-pt' => true,
51
+ 'readable-pt' => true,
52
+ 'bolts-pt' => true,
53
+ ];
54
+ /**
55
+ * Partners domains.
56
+ *
57
+ * @var array $DOMAINS Partners domains.
58
+ */
59
+ public static $domains = [
60
+ 'proteusthemes.com',
61
+ 'anarieldesign.com',
62
+ 'prothemedesign.com',
63
+ 'cssigniter.com',
64
+ ];
65
+ /**
66
+ * Map which contains all the modules loaded for each product.
67
+ *
68
+ * @var array Mapping array.
69
+ */
70
+ private static $modules_attached = [];
71
+
72
+ /**
73
+ * Load availabe modules for the selected product.
74
+ *
75
+ * @param Product $product Loaded product.
76
+ * @param array $modules List of modules.
77
+ */
78
+ public static function attach( $product, $modules ) {
79
+
80
+ if ( ! isset( self::$modules_attached[ $product->get_slug() ] ) ) {
81
+ self::$modules_attached[ $product->get_slug() ] = [];
82
+ }
83
+
84
+ foreach ( $modules as $module ) {
85
+ $class = 'ThemeisleSDK\\Modules\\' . ucwords( $module, '_' );
86
+ /**
87
+ * Module object.
88
+ *
89
+ * @var Abstract_Module $module_object Module instance.
90
+ */
91
+ $module_object = new $class( $product );
92
+
93
+ if ( ! $module_object->can_load( $product ) ) {
94
+ continue;
95
+ }
96
+ self::$modules_attached[ $product->get_slug() ][ $module ] = $module_object->load( $product );
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Products/Modules loaded map.
102
+ *
103
+ * @return array Modules map.
104
+ */
105
+ public static function get_modules_map() {
106
+ return self::$modules_attached;
107
+ }
108
+ }
vendor/codeinwp/themeisle-sdk/src/Loader.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The main loader class for ThemeIsle SDK
4
+ *
5
+ * @package ThemeIsleSDK
6
+ * @subpackage Loader
7
+ * @copyright Copyright (c) 2017, Marius Cristea
8
+ * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
+ * @since 1.0.0
10
+ */
11
+
12
+ namespace ThemeisleSDK;
13
+
14
+ use ThemeisleSDK\Common\Module_Factory;
15
+
16
+ if ( ! defined( 'ABSPATH' ) ) {
17
+ exit;
18
+ }
19
+
20
+
21
+ /**
22
+ * Singleton loader for ThemeIsle SDK.
23
+ */
24
+ final class Loader {
25
+ /**
26
+ * Singleton instance.
27
+ *
28
+ * @var Loader instance The singleton instance
29
+ */
30
+ private static $instance;
31
+ /**
32
+ * Current loader version.
33
+ *
34
+ * @var string $version The class version.
35
+ */
36
+ private static $version = '2.0.0';
37
+ /**
38
+ * Holds registered products.
39
+ *
40
+ * @var array The products which use the SDK.
41
+ */
42
+ private static $products = [];
43
+ /**
44
+ * Holds available modules to load.
45
+ *
46
+ * @var array The modules which SDK will be using.
47
+ */
48
+ private static $available_modules = [
49
+ 'dashboard_widget',
50
+ 'rollback',
51
+ 'uninstall_feedback',
52
+ 'licenser',
53
+ 'endpoint',
54
+ 'notification',
55
+ 'logger',
56
+ 'translate',
57
+ 'review',
58
+ 'recommendation',
59
+
60
+ ];
61
+
62
+ /**
63
+ * Initialize the sdk logic.
64
+ */
65
+ public static function init() {
66
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Loader ) ) {
67
+ self::$instance = new Loader();
68
+ $modules = array_merge( self::$available_modules, apply_filters( 'themeisle_sdk_modules', [] ) );
69
+ foreach ( $modules as $key => $module ) {
70
+ if ( ! class_exists( 'ThemeisleSDK\\Modules\\' . ucwords( $module, '_' ) ) ) {
71
+ unset( $modules[ $key ] );
72
+ }
73
+ }
74
+ self::$available_modules = $modules;
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Register product into SDK.
80
+ *
81
+ * @param string $base_file The product base file.
82
+ *
83
+ * @return Loader The singleton object.
84
+ */
85
+ public static function add_product( $base_file ) {
86
+
87
+ if ( ! is_readable( $base_file ) ) {
88
+ return self::$instance;
89
+ }
90
+ $product = new Product( $base_file );
91
+
92
+ Module_Factory::attach( $product, self::get_modules() );
93
+
94
+ self::$products[ $product->get_slug() ] = $product;
95
+
96
+ return self::$instance;
97
+ }
98
+
99
+ /**
100
+ * Get all registered modules by the SDK.
101
+ *
102
+ * @return array Modules available.
103
+ */
104
+ public static function get_modules() {
105
+ return self::$available_modules;
106
+ }
107
+
108
+ /**
109
+ * Get all products using the SDK.
110
+ *
111
+ * @return array Products available.
112
+ */
113
+ public static function get_products() {
114
+ return self::$products;
115
+ }
116
+
117
+ /**
118
+ * Get the version of the SDK.
119
+ *
120
+ * @return string The version.
121
+ */
122
+ public static function get_version() {
123
+ return self::$version;
124
+ }
125
+
126
+ }
vendor/codeinwp/themeisle-sdk/src/Modules/Dashboard_widget.php ADDED
@@ -0,0 +1,464 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The blog dashboard model class for ThemeIsle SDK
4
+ *
5
+ * @package ThemeIsleSDK
6
+ * @subpackage Modules
7
+ * @copyright Copyright (c) 2017, Marius Cristea
8
+ * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
+ * @since 1.0.0
10
+ */
11
+
12
+ namespace ThemeisleSDK\Modules;
13
+
14
+ use ThemeisleSDK\Common\Abstract_Module;
15
+ use ThemeisleSDK\Product;
16
+
17
+ // Exit if accessed directly.
18
+ if ( ! defined( 'ABSPATH' ) ) {
19
+ exit;
20
+ }
21
+
22
+ /**
23
+ * Blog dashboard widget module for ThemeIsle SDK.
24
+ */
25
+ class Dashboard_Widget extends Abstract_Module {
26
+
27
+ /**
28
+ * Fetched feeds items.
29
+ *
30
+ * @var array Feed items.
31
+ */
32
+ private $items = array();
33
+
34
+ /**
35
+ * Dashboard widget title.
36
+ *
37
+ * @var string $dashboard_name Dashboard name.
38
+ */
39
+ private $dashboard_name = '';
40
+
41
+ /**
42
+ * Dashboard widget feed sources.
43
+ *
44
+ * @var array $feeds Feed url.
45
+ */
46
+ private $feeds = [];
47
+
48
+ /**
49
+ * Should we load this module.
50
+ *
51
+ * @param Product $product Product object.
52
+ *
53
+ * @return bool
54
+ */
55
+ public function can_load( $product ) {
56
+ if ( $this->is_from_partner( $product ) ) {
57
+ return false;
58
+ }
59
+
60
+ if ( ! apply_filters( $product->get_slug() . '_load_dashboard_widget', true ) ) {
61
+ return false;
62
+ }
63
+
64
+ return true;
65
+ }
66
+
67
+ /**
68
+ * Registers the hooks.
69
+ *
70
+ * @param Product $product Product to load.
71
+ *
72
+ * @return Dashboard_Widget Module instance.
73
+ */
74
+ public function load( $product ) {
75
+
76
+ $this->product = $product;
77
+ $this->dashboard_name = apply_filters( 'themeisle_sdk_dashboard_widget_name', 'WordPress Guides/Tutorials' );
78
+ $this->feeds = apply_filters(
79
+ 'themeisle_sdk_dashboard_widget_feeds',
80
+ [
81
+ 'https://themeisle.com/blog/feed',
82
+ ]
83
+ );
84
+ add_action( 'wp_dashboard_setup', array( &$this, 'add_widget' ) );
85
+ add_action( 'wp_network_dashboard_setup', array( &$this, 'add_widget' ) );
86
+ add_filter( 'themeisle_sdk_recommend_plugin_or_theme', array( &$this, 'recommend_plugin_or_theme' ) );
87
+
88
+ return $this;
89
+ }
90
+
91
+
92
+ /**
93
+ * Add widget to the dashboard
94
+ *
95
+ * @return string|void
96
+ */
97
+ function add_widget() {
98
+ global $wp_meta_boxes;
99
+ if ( isset( $wp_meta_boxes['dashboard']['normal']['core']['themeisle'] ) ) {
100
+ return;
101
+ }
102
+ wp_add_dashboard_widget(
103
+ 'themeisle',
104
+ $this->dashboard_name,
105
+ [
106
+ $this,
107
+ 'render_dashboard_widget',
108
+ ]
109
+ );
110
+ }
111
+
112
+ /**
113
+ * Render widget content
114
+ */
115
+ function render_dashboard_widget() {
116
+ $this->setup_feeds();
117
+ if ( empty( $this->items ) || ! is_array( $this->items ) ) {
118
+ return;
119
+ }
120
+ ?>
121
+ <style type="text/css">
122
+ #themeisle ul li.ti-dw-recommend-item {
123
+ padding-left: 7px;
124
+ border-top: 1px solid #eee;
125
+ margin-bottom: 0px;
126
+ padding-top: 6px;
127
+ }
128
+
129
+ #themeisle h2.hndle {
130
+ background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3Ny4xMiA3Ny4xMiI+PHRpdGxlPkFzc2V0IDM8L3RpdGxlPjxwYXRoIGQ9Ik03NS43Niw0Ny42cS0xLjUsNi40Ni00LjA3LDkuMjZBMzYuMjIsMzYuMjIsMCwwLDEsNjMuMjYsNjNhNTEsNTEsMCwwLDEtOS43OSw0LjZoLS4xNXY0LjgyQTQuNjYsNC42NiwwLDAsMSw1Miw3NS43Niw0LjA3LDQuMDcsMCwwLDEsNDksNzcuMTJhNCw0LDAsMCwxLTIuMTgtLjYxQTQuOTQsNC45NCwwLDAsMSw0NS4xOSw3NWE0LjQyLDQuNDIsMCwwLDEtNy41NCwwLDQuOTQsNC45NCwwLDAsMS0xLjU4LDEuNSwzLjc1LDMuNzUsMCwwLDEtMiwuNjFBNC4yNyw0LjI3LDAsMCwxLDMwLjI3LDc1YTQuOTQsNC45NCwwLDAsMS0xLjU4LDEuNSw0LDQsMCwwLDEtMi4xOC42MSwzLjkzLDMuOTMsMCwwLDEtMy4xNi0xLjQzLDUuMyw1LjMsMCwwLDEtMS4yMS0zLjU0LDEzLjgxLDEzLjgxLDAsMCwxLTguNTgsMywxMy4yMywxMy4yMywwLDAsMS05LTMuNDdBMTguMjEsMTguMjEsMCwwLDAsOSw3MC43OWExNC4yNiwxNC4yNiwwLDAsMS03LjgzLTUuNDIsMTYuMTIsMTYuMTIsMCwwLDAsNS4xOS4wNywxMi44OSwxMi44OSwwLDAsMCw0LjktMS43M1EzLjE1LDU1LjQzLDEuMDUsNTAuNDZhMTgsMTgsMCwwLDEtMS02LjkzQTQwLDQwLDAsMCwxLDEuMjEsMzQsMjYuNTksMjYuNTksMCwwLDEsNS4yNywyNC4xUTguNDQsMTkuNDMsMTMsMTkuNDNhMy40MSwzLjQxLDAsMCwxLDMuNDcsMi4yNmMuNi0uOCwxLjItMS41NiwxLjgxLTIuMjZsLjQ1LS40NS43NS0uNzUsMS4wNS0xLjgxYTM1LjIsMzUuMiwwLDAsMSwyLjExLTMuMzIsMjguNTcsMjguNTcsMCwwLDEsOS4xMi03LjY4QTIzLjQsMjMuNCwwLDAsMSw0Mi45MywyLjU2YTIyLjIyLDIyLjIyLDAsMCwxLDIuNzEuMTVBOC4xNiw4LjE2LDAsMCwxLDUxLjgxLDAsOC42OSw4LjY5LDAsMCwxLDU4LDIuNDFhMS41MSwxLjUxLDAsMCwxLC4xNS42OGMwLC4yNS0uNTUuOTMtMS42NiwybC0uMy4zYTkuNjksOS42OSwwLDAsMSwxLjU4LjgzYy41NS4zNS44My42NS44My45YTEuNjIsMS42MiwwLDAsMS0uNiwxbC0uMTUuMTVxNi43OCw2LDguNTgsMTYuMjdBMy4zLDMuMywwLDAsMSw2OSwyMy4zNWE2LjQ4LDYuNDgsMCwwLDEsNC4yMiwyLjFxMy45MiwzLjMyLDMuOTIsMTEuOUE0Mi4wNSw0Mi4wNSwwLDAsMSw3NS43Niw0Ny42Wk01My42Miw1NC4wN2EyNCwyNCwwLDAsMS0xNCw0LjUyQTIxLjQxLDIxLjQxLDAsMCwxLDI3LDU0LjY3LDI0LjI4LDI0LjI4LDAsMCwxLDE4LjUzLDQ1YTI5LDI5LDAsMCwxLTMtMTMsMzEuNzgsMzEuNzgsMCwwLDEsLjkxLTcuNTNBMzIuMTcsMzIuMTcsMCwwLDAsMTEuOSw0MS4yN2EzMy41LDMzLjUsMCwwLDAsMi43OSwxMy40LDI5LjEsMjkuMSwwLDAsMCw3LjksMTAuODUsNC42OCw0LjY4LDAsMCwxLDEuNjYtMS44OCw0LjE3LDQuMTcsMCwwLDEsNC40NC0uMDgsNC41LDQuNSwwLDAsMSwxLjU4LDEuNjZBNC4yLDQuMiwwLDAsMSwzNCw2M2EzLjgzLDMuODMsMCwwLDEsMiwuNiw0LjUsNC41LDAsMCwxLDEuNTgsMS42Niw0LjI3LDQuMjcsMCwwLDEsNy41NCwwLDQuNSw0LjUsMCwwLDEsMS41OC0xLjY2LDQuMTcsNC4xNywwLDAsMSw0LjQ0LjA4LDMuODYsMy44NiwwLDAsMSwxLjUxLDEuNzMsMzAuMTcsMzAuMTcsMCwwLDAsNy42OC05Ljk0LDMxLjE4LDMxLjE4LDAsMCwwLDMuMTYtMTIuMzVBMjguMzksMjguMzksMCwwLDEsNTMuNjIsNTQuMDdaTTI4Ljc3LDY1LjM3YTMuMSwzLjEsMCwwLDAtNC4zNywwLDMuMDYsMy4wNiwwLDAsMC0uOSwyLjI2djQuODJhMy4zMiwzLjMyLDAsMCwwLC45LDIuMzMsMi45MywyLjkzLDAsMCwwLDQuMzcsMCwzLjMyLDMuMzIsMCwwLDAsLjktMi4zM1Y2Ny42M0EzLjA2LDMuMDYsMCwwLDAsMjguNzcsNjUuMzdabS45LTQ4YTQuMjQsNC4yNCwwLDAsMCwzLjQ3LDEuNzMsNC40NSw0LjQ1LDAsMCwwLDMuNTQtMS43Myw2LDYsMCwwLDAsMS40My0zLjkyLDUuNyw1LjcsMCwwLDAtMS40My0zLjg0QTQuNTMsNC41MywwLDAsMCwzMy4xNCw4YTQuMzEsNC4zMSwwLDAsMC0zLjQ3LDEuNjYsNS43OSw1Ljc5LDAsMCwwLTEuMzUsMy43N0E2LjMzLDYuMzMsMCwwLDAsMjkuNjcsMTcuNFptNi40OCw0OGEzLjEsMy4xLDAsMCwwLTQuMzcsMCwzLjA2LDMuMDYsMCwwLDAtLjksMi4yNnY0LjgyYTMuMzIsMy4zMiwwLDAsMCwuOSwyLjMzLDIuOTMsMi45MywwLDAsMCw0LjM3LDAsMy4zMiwzLjMyLDAsMCwwLC45LTIuMzNWNjcuNjNBMy4wNiwzLjA2LDAsMCwwLDM2LjE1LDY1LjM3Wm0tNC4wNy01NC4zYTIuMzcsMi4zNywwLDAsMSwyLTEsMi4xNywyLjE3LDAsMCwxLDEuODgsMSw0LjEsNC4xLDAsMCwxLDAsNC41MiwyLjE3LDIuMTcsMCwwLDEtMS44OCwxLDIuMzcsMi4zNywwLDAsMS0yLTEsMy43MiwzLjcyLDAsMCwxLS43NS0yLjM0QTMuNDksMy40OSwwLDAsMSwzMi4wOCwxMS4wN1ptNSw5LjQxYTIwLjYxLDIwLjYxLDAsMCwwLTMuNTQsMTIuMjgsMTcuMTUsMTcuMTUsMCwwLDAsNC4wNywxMSwxMi40MywxMi40MywwLDAsMCw5Ljg3LDQuNDUsMTUuMywxNS4zLDAsMCwwLDktMywxMywxMywwLDAsMCwuNi0zLjMycTAtMy4zMi0zLjE2LTMuMzFhOC41OCw4LjU4LDAsMCwwLTIsLjNxLTcuODMsMS41LTExLjU5LS4zLTQuNTMtMi4xMi00LjUyLTkuMzRBMzcuOTIsMzcuOTIsMCwwLDEsMzcuMDUsMjAuNDhaTTYxLjQ1LDE3QTEyLjg0LDEyLjg0LDAsMCwwLDUxLjIxLDEyLjJhMTUuMTEsMTUuMTEsMCwwLDAtNi40LDEuNDMsMTcuODMsMTcuODMsMCwwLDAtNS41LDRxLTYuMTgsMjAuNjQsNi4xOCwyMC42NEEyNC43NSwyNC43NSwwLDAsMCw0OSwzNy44MWEzOC45MiwzOC45MiwwLDAsMSw0LjgyLS40NmMxLjgxLDAsMy4wNi40NiwzLjc3LDEuMzZxMS4zNSwxLjUuNzUsNS4xMmEyMS43MiwyMS43MiwwLDAsMCw1LTcuMTVBMjEuMzgsMjEuMzgsMCwwLDAsNjUuMDcsMjgsMTcuNDQsMTcuNDQsMCwwLDAsNjEuNDUsMTdaTTQzLjYsNjUuMzdhMi43MiwyLjcyLDAsMCwwLTIuMS0uOSwzLDMsMCwwLDAtMi4xOS45LDMuMDYsMy4wNiwwLDAsMC0uOSwyLjI2djQuODJhMy4zMiwzLjMyLDAsMCwwLC45LDIuMzMsMi44NCwyLjg0LDAsMCwwLDIuMTksMSwyLjYxLDIuNjEsMCwwLDAsMi4xLTEsMy40NSwzLjQ1LDAsMCwwLC44My0yLjMzVjY3LjYzQTMuMTcsMy4xNywwLDAsMCw0My42LDY1LjM3Wm03LjQ2LDBhMywzLDAsMCwwLTIuMTgtLjksMi43MywyLjczLDAsMCwwLTIuMTEuOSwzLjE3LDMuMTcsMCwwLDAtLjgzLDIuMjZ2NC44MmEzLjQ1LDMuNDUsMCwwLDAsLjgzLDIuMzMsMi42MSwyLjYxLDAsMCwwLDIuMTEsMSwyLjgzLDIuODMsMCwwLDAsMi4xOC0xLDMuMzIsMy4zMiwwLDAsMCwuOS0yLjMzVjY3LjYzQTMuMDYsMy4wNiwwLDAsMCw1MS4wNiw2NS4zN1oiLz48L3N2Zz4=');
131
+ background-repeat: no-repeat;
132
+ background-position: 92% 50%;
133
+ background-size: 30px;
134
+ }
135
+
136
+ #themeisle .inside {
137
+ padding: 0;
138
+ }
139
+
140
+ .ti-feed-list {
141
+ padding: 0 12px 5px;
142
+ margin-bottom: 10px;
143
+ border-bottom: 1px solid #eee;
144
+ }
145
+
146
+ .ti-dw-feed-item a {
147
+ display: flex;
148
+ align-items: center;
149
+ margin-bottom: 5px;
150
+ padding: 5px;
151
+ transition: .2s ease;
152
+ border-radius: 3px;
153
+ }
154
+
155
+ .ti-dw-feed-item a:hover {
156
+ background-color: #f8f8f8;
157
+ }
158
+
159
+ .ti-dw-feed-item a:hover .ti-dw-date-container {
160
+ opacity: .9;
161
+ }
162
+
163
+ .ti-dw-feed-item .ti-dw-month-container {
164
+ margin-top: -5px;
165
+ text-transform: uppercase;
166
+ font-size: 10px;
167
+ letter-spacing: 1px;
168
+ font-weight: 700;
169
+ }
170
+
171
+ .ti-dw-feed-item .ti-dw-date-container {
172
+ border-radius: 3px;
173
+ transition: .2s ease;
174
+ min-height: 35px;
175
+ margin-right: 5px;
176
+ min-width: 35px;
177
+ text-align: center;
178
+ border: 1px solid #2a6f97;
179
+ color: #fff;
180
+ background: #2ea2cc;
181
+ display: flex;
182
+ flex-direction: column;
183
+ justify-content: center;
184
+ }
185
+
186
+ .ti-dw-footer {
187
+ padding: 0 12px 5px;
188
+ text-align: center;
189
+ }
190
+
191
+ .ti-dw-recommend-item {
192
+ display: block;
193
+ }
194
+
195
+ .ti-dw-recommend-item span {
196
+ color: #72777c;
197
+ }
198
+
199
+ .ti-dw-powered-by {
200
+ font-size: 11px;
201
+ margin-top: 3px;
202
+ display: block;
203
+ color: #72777c;
204
+ }
205
+
206
+ .ti-dw-powered-by span {
207
+ font-weight: 600;
208
+ }
209
+
210
+ </style>
211
+ <?php do_action( 'themeisle_sdk_dashboard_widget_before', $this->product ); ?>
212
+
213
+ <ul class="ti-feed-list">
214
+ <?php
215
+
216
+ foreach ( $this->items as $item ) {
217
+ ?>
218
+ <li class="ti-dw-feed-item">
219
+ <a href="
220
+ <?php
221
+ echo add_query_arg(
222
+ array(
223
+ 'utm_source' => 'wpadmin',
224
+ 'utm_campaign' => 'feed',
225
+ 'utm_medium' => 'dashboard_widget',
226
+ ),
227
+ $item['link']
228
+ );
229
+ ?>
230
+ " target="_blank">
231
+ <span class="ti-dw-date-container"><span
232
+ class="ti-dw-day-container"><?php echo date( 'd', $item['date'] ); ?></span> <span
233
+ class="ti-dw-month-container"><?php echo substr( date( 'M', $item['date'] ), 0, 3 ); ?></span></span><?php echo $item['title']; ?>
234
+ </a>
235
+ </li>
236
+ <?php
237
+ }
238
+ ?>
239
+ </ul>
240
+ <?php
241
+ $recommend = apply_filters( 'themeisle_sdk_recommend_plugin_or_theme', array() );
242
+ if ( ! is_array( $recommend ) || empty( $recommend ) ) {
243
+ return;
244
+ }
245
+
246
+ $type = $recommend['type'];
247
+
248
+ if ( ( 'theme' === $type && ! current_user_can( 'install_themes' ) ) ) {
249
+ return;
250
+ }
251
+ if ( ( 'plugin' === $type && ! current_user_can( 'install_plugins' ) ) ) {
252
+ return;
253
+ }
254
+
255
+ add_thickbox();
256
+ $url = add_query_arg(
257
+ [
258
+ 'theme' => $recommend['slug'],
259
+ ],
260
+ network_admin_url( 'theme-install.php' )
261
+ );
262
+
263
+ if ( 'plugin' === $type ) {
264
+
265
+ $url = add_query_arg(
266
+ array(
267
+ 'tab' => 'plugin-information',
268
+ 'plugin' => $recommend['slug'],
269
+ ),
270
+ network_admin_url( 'plugin-install.php' )
271
+ );
272
+ }
273
+ ?>
274
+ <div class="ti-dw-footer">
275
+ <span class="ti-dw-recommend-item ">
276
+ <span class="ti-dw-recommend"><?php echo apply_filters( 'themeisle_sdk_dashboard_popular_label', sprintf( 'Popular %s', ucwords( $type ) ) ); ?>
277
+ : </span>
278
+ <?php
279
+ echo trim(
280
+ str_replace(
281
+ array(
282
+ 'lite',
283
+ 'Lite',
284
+ '(Lite)',
285
+ '(lite)',
286
+ ),
287
+ '',
288
+ $recommend['name']
289
+ )
290
+ );
291
+ ?>
292
+ (<a class="thickbox open-plugin-details-modal"
293
+ href="<?php echo $url . '&TB_iframe=true&width=600&height=500'; ?>"><?php echo apply_filters( 'themeisle_sdk_dashboard_install_label', 'Install' ); ?></a>)
294
+ </span>
295
+ <span class="ti-dw-powered-by"><span><?php echo apply_filters( 'themeisle_sdk_dashboard_widget_powered_by', esc_attr( sprintf( 'Powered by %s', $this->product->get_friendly_name() ) ) ); ?></span></span>
296
+ </div>
297
+
298
+ <?php
299
+
300
+ }
301
+
302
+ /**
303
+ * Setup feed items.
304
+ */
305
+ private function setup_feeds() {
306
+ if ( false === ( $items_normalized = get_transient( 'themeisle_sdk_feed_items' ) ) ) {
307
+ // Load SimplePie Instance.
308
+ $feed = fetch_feed( $this->feeds );
309
+ // TODO report error when is an error loading the feed.
310
+ if ( is_wp_error( $feed ) ) {
311
+ return;
312
+ }
313
+
314
+ $items = $feed->get_items( 0, 5 );
315
+ foreach ( (array) $items as $item ) {
316
+ $items_normalized[] = array(
317
+ 'title' => $item->get_title(),
318
+ 'date' => $item->get_date( 'U' ),
319
+ 'link' => $item->get_permalink(),
320
+ );
321
+ }
322
+ set_transient( 'themeisle_sdk_feed_items', $items_normalized, 48 * HOUR_IN_SECONDS );
323
+ }
324
+ $this->items = $items_normalized;
325
+ }
326
+
327
+ /**
328
+ * Either the current product is installed or not.
329
+ *
330
+ * @param array $val The current recommended product.
331
+ *
332
+ * @return bool Either we should exclude the plugin or not.
333
+ */
334
+ public function remove_current_products( $val ) {
335
+ if ( 'theme' === $val['type'] ) {
336
+ $exist = wp_get_theme( $val['slug'] );
337
+
338
+ return ! $exist->exists();
339
+ } else {
340
+ $all_plugins = array_keys( get_plugins() );
341
+ foreach ( $all_plugins as $slug ) {
342
+ if ( strpos( $slug, $val['slug'] ) !== false ) {
343
+ return false;
344
+ }
345
+ }
346
+
347
+ return true;
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Contact the API and fetch the recommended plugins/themes
353
+ */
354
+ function recommend_plugin_or_theme() {
355
+ $products = $this->get_product_from_api();
356
+ if ( ! is_array( $products ) ) {
357
+ $products = array();
358
+ }
359
+ $products = array_filter( $products, array( $this, 'remove_current_products' ) );
360
+ $products = array_merge( $products );
361
+ if ( count( $products ) > 1 ) {
362
+ shuffle( $products );
363
+ $products = array_slice( $products, 0, 1 );
364
+ }
365
+ $to_recommend = isset( $products[0] ) ? $products[0] : $products;
366
+
367
+ return $to_recommend;
368
+ }
369
+
370
+ /**
371
+ * Fetch products from the recomended section.
372
+ *
373
+ * @return array|mixed The list of products to use in recomended section.
374
+ */
375
+ function get_product_from_api() {
376
+ if ( false === ( $products = get_transient( 'themeisle_sdk_products' ) ) ) {
377
+ $products = array();
378
+ $all_themes = $this->get_themes_from_wporg( 'themeisle' );
379
+ $all_plugins = $this->get_plugins_from_wporg( 'themeisle' );
380
+ static $allowed_products = [
381
+ 'hestia' => true,
382
+ 'neve' => true,
383
+ 'visualizer' => true,
384
+ 'feedzy-rss-feeds' => true,
385
+ 'wp-product-review' => true,
386
+ 'otter-blocks' => true,
387
+ 'themeisle-companion' => true,
388
+ ];
389
+ foreach ( $all_themes as $theme ) {
390
+ if ( $theme->active_installs < 4999 ) {
391
+ continue;
392
+ }
393
+ if ( ! isset( $allowed_products[ $theme->slug ] ) ) {
394
+ continue;
395
+ }
396
+ $products[] = array(
397
+ 'name' => $theme->name,
398
+ 'type' => 'theme',
399
+ 'slug' => $theme->slug,
400
+ 'installs' => $theme->active_installs,
401
+ );
402
+ }
403
+ foreach ( $all_plugins as $plugin ) {
404
+ if ( $plugin->active_installs < 4999 ) {
405
+ continue;
406
+ }
407
+ if ( ! isset( $allowed_products[ $plugin->slug ] ) ) {
408
+ continue;
409
+ }
410
+ $products[] = array(
411
+ 'name' => $plugin->name,
412
+ 'type' => 'plugin',
413
+ 'slug' => $plugin->slug,
414
+ 'installs' => $plugin->active_installs,
415
+ );
416
+ }
417
+ set_transient( 'themeisle_sdk_products', $products, 6 * HOUR_IN_SECONDS );
418
+ }
419
+
420
+ return $products;
421
+ }
422
+
423
+ /**
424
+ * Fetch themes from wporg api.
425
+ *
426
+ * @param string $author The author name.
427
+ *
428
+ * @return array The list of themes.
429
+ */
430
+ function get_themes_from_wporg( $author ) {
431
+ $products = wp_remote_get(
432
+ 'https://api.wordpress.org/themes/info/1.1/?action=query_themes&request[author]=' . $author . '&request[per_page]=30&request[fields][active_installs]=true'
433
+ );
434
+ $products = json_decode( wp_remote_retrieve_body( $products ) );
435
+ if ( is_object( $products ) ) {
436
+ $products = isset( $products->themes ) ? $products->themes : array();
437
+ } else {
438
+ $products = array();
439
+ }
440
+
441
+ return (array) $products;
442
+ }
443
+
444
+ /**
445
+ * Fetch plugin from wporg api.
446
+ *
447
+ * @param string $author The author slug.
448
+ *
449
+ * @return array The list of plugins for the selected author.
450
+ */
451
+ function get_plugins_from_wporg( $author ) {
452
+ $products = wp_remote_get(
453
+ 'https://api.wordpress.org/plugins/info/1.1/?action=query_plugins&request[author]=' . $author . '&request[per_page]=40&request[fields][active_installs]=true'
454
+ );
455
+ $products = json_decode( wp_remote_retrieve_body( $products ) );
456
+ if ( is_object( $products ) ) {
457
+ $products = isset( $products->plugins ) ? $products->plugins : array();
458
+ } else {
459
+ $products = array();
460
+ }
461
+
462
+ return (array) $products;
463
+ }
464
+ }
vendor/codeinwp/themeisle-sdk/src/Modules/Endpoint.php ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The class that exposes endpoints.
4
+ *
5
+ * @package ThemeIsleSDK
6
+ * @subpackage Rollback
7
+ * @copyright Copyright (c) 2017, Marius Cristea
8
+ * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
+ * @since 1.0.0
10
+ */
11
+
12
+ namespace ThemeisleSDK\Modules;
13
+
14
+ // Exit if accessed directly.
15
+ use ThemeisleSDK\Common\Abstract_Module;
16
+ use ThemeisleSDK\Loader;
17
+ use ThemeisleSDK\Product;
18
+
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit;
21
+ }
22
+
23
+ /**
24
+ * Expose endpoints for ThemeIsle SDK.
25
+ */
26
+ class Endpoint extends Abstract_Module {
27
+ /**
28
+ * Endpoint slug.
29
+ */
30
+ const SDK_ENDPOINT = 'themeisle-sdk';
31
+ /**
32
+ * Endpoint version.
33
+ */
34
+ const SDK_ENDPOINT_VERSION = 1;
35
+ /**
36
+ * Hash file which contains the checksum.
37
+ */
38
+ const HASH_FILE = 'themeisle-hash.json';
39
+
40
+ /*
41
+ * If true, the endpoint will expect a product slug and will return the value only for that.
42
+ */
43
+ const PRODUCT_SPECIFIC = false;
44
+
45
+ /**
46
+ * Registers the endpoints.
47
+ */
48
+ function rest_register() {
49
+ register_rest_route(
50
+ self::SDK_ENDPOINT . '/v' . self::SDK_ENDPOINT_VERSION,
51
+ '/checksum/' . ( self::PRODUCT_SPECIFIC ? '(?P<slug>.*)/' : '' ),
52
+ array(
53
+ 'methods' => 'GET',
54
+ 'callback' => array( $this, 'checksum' ),
55
+ )
56
+ );
57
+ }
58
+
59
+ /**
60
+ * The checksum endpoint.
61
+ *
62
+ * @param \WP_REST_Request $data the request.
63
+ *
64
+ * @return \WP_REST_Response Response or the error
65
+ */
66
+ function checksum( \WP_REST_Request $data ) {
67
+ $products = Loader::get_products();
68
+ if ( self::PRODUCT_SPECIFIC ) {
69
+ $params = $this->validate_params( $data, array( 'slug' ) );
70
+ foreach ( $products as $product ) {
71
+ if ( $params['slug'] === $product->get_slug() ) {
72
+ $products = array( $product );
73
+ break;
74
+ }
75
+ }
76
+ }
77
+ $response = array();
78
+ $custom_css = $this->has_custom_css();
79
+ if ( is_bool( $custom_css ) ) {
80
+ $response['custom_css'] = $custom_css;
81
+ }
82
+
83
+ $response['child_theme'] = $this->get_theme_properties();
84
+
85
+ foreach ( $products as $product ) {
86
+ $files = array();
87
+ switch ( $product->get_type() ) {
88
+ case 'plugin':
89
+ $files = array();
90
+ break;
91
+ case 'theme':
92
+ $files = array( 'style.css', 'functions.php' );
93
+ break;
94
+ }
95
+
96
+ $error = '';
97
+
98
+ // if any element in the $files array contains a '/', this would imply recursion is required.
99
+ $diff = $this->generate_diff(
100
+ $product,
101
+ $files,
102
+ array_reduce(
103
+ $files,
104
+ array(
105
+ $this,
106
+ 'is_recursion_required',
107
+ ),
108
+ false
109
+ )
110
+ );
111
+ if ( is_wp_error( $diff ) ) {
112
+ /**
113
+ * Error returner by the diff checker method.
114
+ *
115
+ * @var \WP_Error $diff Error returned.
116
+ */
117
+ $error = $diff->get_error_message();
118
+ $diff = array();
119
+ }
120
+
121
+ $response['products'][] = array(
122
+ 'slug' => $product->get_slug(),
123
+ 'version' => $product->get_version(),
124
+ 'diffs' => $diff,
125
+ 'error' => $error,
126
+ );
127
+ }
128
+
129
+ return new \WP_REST_Response( array( 'checksum' => $response ) );
130
+ }
131
+
132
+ /**
133
+ * Validates the parameters to the API
134
+ *
135
+ * @param \WP_REST_Request $data the request.
136
+ * @param array $params the parameters to validate.
137
+ *
138
+ * @return array of parameter name=>value
139
+ */
140
+ private function validate_params( \WP_REST_Request $data, $params ) {
141
+ $collect = array();
142
+ foreach ( $params as $param ) {
143
+ $value = sanitize_text_field( $data[ $param ] );
144
+ if ( empty( $value ) ) {
145
+ return rest_ensure_response(
146
+ new \WP_Error(
147
+ 'themeisle_' . $param . '_invalid',
148
+ sprintf( 'Invalid %', $param ),
149
+ array(
150
+ 'status' => 403,
151
+ )
152
+ )
153
+ );
154
+ } else {
155
+ $collect[ $param ] = $value;
156
+ }
157
+ }
158
+
159
+ return $collect;
160
+ }
161
+
162
+ /**
163
+ * Check if custom css has been added to the theme.
164
+ *
165
+ * @return bool Whether custom css has been added to the theme.
166
+ */
167
+ private function has_custom_css() {
168
+ $query = new \WP_Query(
169
+ array(
170
+ 'post_type' => 'custom_css',
171
+ 'post_status' => 'publish',
172
+ 'numberposts' => 1,
173
+ 'update_post_meta_cache' => false,
174
+ 'update_post_term_cache' => false,
175
+ )
176
+ );
177
+
178
+ if ( $query->have_posts() ) {
179
+ $query->the_post();
180
+ $content = get_the_content();
181
+
182
+ // if the content contains a colon, a CSS rule has been added.
183
+ return strpos( $content, ':' ) === false ? false : true;
184
+ }
185
+
186
+ return false;
187
+ }
188
+
189
+ /**
190
+ * Get the current theme properties.
191
+ *
192
+ * @return mixed Properties of the current theme.
193
+ */
194
+ function get_theme_properties() {
195
+ if ( ! is_child_theme() ) {
196
+ return false;
197
+ }
198
+
199
+ $properties = array();
200
+ $theme = wp_get_theme();
201
+ // @codingStandardsIgnoreStart
202
+ $properties['name'] = $theme->Name;
203
+ // @codingStandardsIgnoreEnd
204
+
205
+ // get the files in the child theme.
206
+ require_once( ABSPATH . 'wp-admin/includes/file.php' );
207
+ WP_Filesystem();
208
+ global $wp_filesystem;
209
+ $path = str_replace( ABSPATH, $wp_filesystem->abspath(), get_stylesheet_directory() );
210
+ $list = $wp_filesystem->dirlist( $path, false, false );
211
+ if ( $list ) {
212
+ $list = array_keys( self::flatten_dirlist( $list ) );
213
+ $properties['files'] = $list;
214
+ }
215
+
216
+ return $properties;
217
+ }
218
+
219
+ /**
220
+ * Flatten the results of WP_Filesystem::dirlist() for iterating over.
221
+ *
222
+ * @access private
223
+ *
224
+ * @param array $nested_files Array of files as returned by WP_Filesystem::dirlist().
225
+ * @param string $path Relative path to prepend to child nodes. Optional.
226
+ *
227
+ * @return array $files A flattened array of the $nested_files specified.
228
+ */
229
+ private static function flatten_dirlist( $nested_files, $path = '' ) {
230
+ $files = array();
231
+ foreach ( $nested_files as $name => $details ) {
232
+ $files[ $path . $name ] = $details;
233
+ // Append children recursively.
234
+ if ( ! empty( $details['files'] ) ) {
235
+ $children = self::flatten_dirlist( $details['files'], $path . $name . '/' );
236
+ // Merge keeping possible numeric keys, which array_merge() will reindex from 0..n.
237
+ $files = $files + $children;
238
+ }
239
+ }
240
+
241
+ return $files;
242
+ }
243
+
244
+ /**
245
+ * Generate the diff of the files.
246
+ *
247
+ * @param Product $product Themeisle Product.
248
+ * @param array $files Array of files.
249
+ * @param bool $recurse Whether to recurse or not.
250
+ *
251
+ * @return mixed Diff data.
252
+ */
253
+ private function generate_diff( $product, $files, $recurse = false ) {
254
+ require_once( ABSPATH . 'wp-admin/includes/file.php' );
255
+ WP_Filesystem();
256
+ global $wp_filesystem;
257
+
258
+ $diff = array();
259
+ $path = str_replace( ABSPATH, $wp_filesystem->abspath(), plugin_dir_path( $product->get_basefile() ) );
260
+ $list = $wp_filesystem->dirlist( $path, false, $recurse );
261
+ // nothing found.
262
+ if ( ! $list ) {
263
+ return $diff;
264
+ }
265
+ $list = array_keys( self::flatten_dirlist( $list ) );
266
+
267
+ // now let's get the valid files that actually exist.
268
+ if ( empty( $files ) ) {
269
+ $files = $list;
270
+ } else {
271
+ $files = array_intersect( $files, $list );
272
+ }
273
+
274
+ // fetch the calculated hashes.
275
+ if ( ! $wp_filesystem->is_readable( $path . '/' . self::HASH_FILE ) ) {
276
+ return new WP_Error( 'themeisle_sdk_hash_not_found', sprintf( '%s not found', self::HASH_FILE ) );
277
+ }
278
+
279
+ $hashes = json_decode( $wp_filesystem->get_contents( $path . '/' . self::HASH_FILE ), true );
280
+ ksort( $hashes );
281
+
282
+ $diff = array();
283
+ foreach ( $files as $file ) {
284
+ // file does not exist in the hashes.
285
+ if ( ! array_key_exists( $file, $hashes ) ) {
286
+ continue;
287
+ }
288
+ $new = md5( $wp_filesystem->get_contents( $path . $file ) );
289
+ $old = $hashes[ $file ];
290
+
291
+ // same hash, bail.
292
+ if ( $new === $old ) {
293
+ continue;
294
+ }
295
+ $diff[] = $file;
296
+ }
297
+
298
+ return $diff;
299
+ }
300
+
301
+ /**
302
+ * Check if recursion needs to be enabled on the WP_Filesystem by reducing the array of files to a boolean.
303
+ *
304
+ * @param string $carry Value of the previous iteration.
305
+ * @param string $item Value of the current iteration.
306
+ *
307
+ * @return bool Whether to recurse or not.
308
+ */
309
+ function is_recursion_required( $carry, $item ) {
310
+ if ( ! $carry ) {
311
+ return ( strpos( $item, '/' ) !== false );
312
+ }
313
+
314
+ return $carry;
315
+ }
316
+
317
+ /**
318
+ * Load module for this product.
319
+ *
320
+ * @param Product $product Product to check.
321
+ *
322
+ * @return bool Should we load this?
323
+ */
324
+ public function can_load( $product ) {
325
+ return true;
326
+ }
327
+
328
+ /**
329
+ * Load module logic.
330
+ *
331
+ * @param Product $product Product to load.
332
+ */
333
+ public function load( $product ) {
334
+ $this->setup_endpoints();
335
+
336
+ return $this;
337
+ }
338
+
339
+ /**
340
+ * Setup endpoints.
341
+ */
342
+ private function setup_endpoints() {
343
+ global $wp_version;
344
+ if ( version_compare( $wp_version, '4.4', '<' ) ) {
345
+ // no REST support.
346
+ return;
347
+ }
348
+
349
+ $this->setup_rest();
350
+ }
351
+
352
+ /**
353
+ * Setup REST endpoints.
354
+ */
355
+ private function setup_rest() {
356
+ add_action( 'rest_api_init', array( $this, 'rest_register' ) );
357
+ }
358
+ }
vendor/codeinwp/themeisle-sdk/src/Modules/Licenser.php ADDED
@@ -0,0 +1,719 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The main loader class for license handling.
4
+ *
5
+ * @package ThemeIsleSDK
6
+ * @subpackage Modules
7
+ * @copyright Copyright (c) 2017, Marius Cristea
8
+ * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
+ * @since 1.0.0
10
+ */
11
+
12
+ namespace ThemeisleSDK\Modules;
13
+
14
+ // Exit if accessed directly.
15
+ use ThemeisleSDK\Common\Abstract_Module;
16
+ use ThemeisleSDK\Product;
17
+
18
+ if ( ! defined( 'ABSPATH' ) ) {
19
+ exit;
20
+ }
21
+
22
+ /**
23
+ * Licenser module for ThemeIsle SDK.
24
+ */
25
+ class Licenser extends Abstract_Module {
26
+
27
+ /**
28
+ * Number of max failed checks before showing the license message.
29
+ *
30
+ * @var int $max_failed Maximum failed checks allowed before show the notice
31
+ */
32
+ private static $max_failed = 5;
33
+ /**
34
+ * License key string.
35
+ *
36
+ * @var string $license_key The license key string
37
+ */
38
+ public $license_key;
39
+ /**
40
+ * This ensures that the custom API request only runs on the second time that WP fires the update check.
41
+ *
42
+ * @var bool $do_check Flag for request.
43
+ */
44
+ private $do_check = false;
45
+ /**
46
+ * Number of failed checks to the api endpoint.
47
+ *
48
+ * @var bool $failed_checks
49
+ */
50
+ private $failed_checks = 0;
51
+ /**
52
+ * The product update response key.
53
+ *
54
+ * @var string $product_key Product key.
55
+ */
56
+ private $product_key;
57
+
58
+ /**
59
+ * Disable wporg updates for premium products.
60
+ *
61
+ * @param string $r Update payload.
62
+ * @param string $url The api url.
63
+ *
64
+ * @return mixed List of themes to check for update.
65
+ */
66
+ function disable_wporg_update( $r, $url ) {
67
+
68
+ if ( 0 !== strpos( $url, 'https://api.wordpress.org/themes/update-check/' ) ) {
69
+ return $r;
70
+ }
71
+
72
+ // Decode the JSON response.
73
+ $themes = json_decode( $r['body']['themes'] );
74
+
75
+ unset( $themes->themes->{$this->product->get_slug()} );
76
+
77
+ // Encode the updated JSON response.
78
+ $r['body']['themes'] = json_encode( $themes );
79
+
80
+ return $r;
81
+ }
82
+
83
+ /**
84
+ * Register the setting for the license of the product.
85
+ *
86
+ * @return bool
87
+ */
88
+ public function register_settings() {
89
+ if ( ! is_admin() ) {
90
+ return false;
91
+ }
92
+ add_settings_field(
93
+ $this->product->get_key() . '_license',
94
+ $this->product->get_name() . ' license',
95
+ array( $this, 'license_view' ),
96
+ 'general'
97
+ );
98
+ }
99
+
100
+ /**
101
+ * The license view field.
102
+ */
103
+ public function license_view() {
104
+ $status = $this->get_license_status();
105
+ $value = $this->license_key;
106
+
107
+ $activate_string = apply_filters( $this->product->get_key() . '_lc_activate_string', 'Activate' );
108
+ $deactivate_string = apply_filters( $this->product->get_key() . '_lc_deactivate_string', 'Deactivate' );
109
+ $valid_string = apply_filters( $this->product->get_key() . '_lc_valid_string', 'Valid' );
110
+ $invalid_string = apply_filters( $this->product->get_key() . '_lc_invalid_string', 'Invalid' );
111
+ $license_message = apply_filters( $this->product->get_key() . '_lc_license_message', 'Enter your license from %s purchase history in order to get %s updates' );
112
+
113
+ echo '<p ><input ' . ( ( 'valid' === $status ) ? ( 'style="border:1px solid #7ad03a; "' ) : '' ) . ' type="text" id="' . $this->product->get_key() . '_license" name="' . $this->product->get_key() . '_license" value="' . $value . '" /><a ' . ( ( 'valid' === $status ) ? ( 'style="color:#fff;background: #7ad03a; display: inline-block;text-decoration: none;font-size: 13px;line-height: 26px;height: 26px; margin-left:5px; padding: 0 10px 1px; -webkit-border-radius: 3px;border-radius: 3px; ">' . $valid_string ) : ( 'style="color:#fff;background: #dd3d36; display: inline-block;text-decoration: none;font-size: 13px;line-height: 26px;height: 26px; margin-left:5px; padding: 0 10px 1px; -webkit-border-radius: 3px;border-radius: 3px; ">' . $invalid_string ) ) . ' </a>&nbsp;&nbsp;&nbsp;<button name="' . $this->product->get_key() . '_btn_trigger" ' . ( ( 'valid' === $status ) ? ( ' class="button button-primary">' . $deactivate_string ) : ( ' class="button button-primary" value="yes" type="submit" >' . $activate_string ) ) . ' </button></p><p class="description">' . sprintf( $license_message, '<a href="' . $this->get_api_url() . '">' . $this->get_distributor_name() . '</a> ', $this->product->get_type() ) . '</p>';
114
+
115
+ }
116
+
117
+ /**
118
+ * Return the license status.
119
+ *
120
+ * @return string The License status.
121
+ */
122
+ public function get_license_status() {
123
+
124
+ $license_data = get_option( $this->product->get_key() . '_license_data', '' );
125
+
126
+ if ( '' === $license_data ) {
127
+ return get_option( $this->product->get_key() . '_license_status', 'not_active' );
128
+ }
129
+
130
+ return isset( $license_data->license ) ? $license_data->license : get_option( $this->product->get_key() . '_license_status', 'not_active' );
131
+
132
+ }
133
+
134
+ /**
135
+ * Get remote api url.
136
+ *
137
+ * @return string Remote api url.
138
+ */
139
+ public function get_api_url() {
140
+ if ( $this->is_from_partner( $this->product ) ) {
141
+ return 'https://themeisle.com';
142
+ }
143
+
144
+ return $this->product->get_store_url();
145
+ }
146
+
147
+ /**
148
+ * Get remote api url.
149
+ *
150
+ * @return string Remote api url.
151
+ */
152
+ public function get_distributor_name() {
153
+ if ( $this->is_from_partner( $this->product ) ) {
154
+ return 'ThemeIsle';
155
+ }
156
+
157
+ return $this->product->get_store_name();
158
+ }
159
+
160
+ /**
161
+ * Show the admin notice regarding the license status.
162
+ *
163
+ * @return bool Should we show the notice ?
164
+ */
165
+ function show_notice() {
166
+ if ( ! is_admin() ) {
167
+ return false;
168
+ }
169
+ $status = $this->get_license_status();
170
+ $no_activations_string = apply_filters( $this->product->get_key() . '_lc_no_activations_string', 'No activations left for %s !!!. You need to upgrade your plan in order to use %s on more websites. Please ask the %s Staff for more details.' );
171
+ $no_valid_string = apply_filters( $this->product->get_key() . '_lc_no_valid_string', 'In order to benefit from updates and support for %s, please add your license code from your <a href="%s" target="_blank">purchase history</a> and validate it <a href="%s">here</a>. ' );
172
+ $expiration_string = apply_filters( $this->product->get_key() . '_lc_expiration_string', 'Your license is about to expire for %s. You can go to %s and renew it ' );
173
+
174
+ // No activations left for this license.
175
+ if ( 'valid' != $status && $this->check_activation() ) {
176
+ ?>
177
+ <div class="error">
178
+ <p><strong>
179
+ <?php
180
+ echo sprintf(
181
+ $no_activations_string,
182
+ $this->product->get_name(),
183
+ $this->product->get_name(),
184
+ '<a href="' . $this->get_api_url() . '" target="_blank">' . $this->get_distributor_name() . '</a>'
185
+ );
186
+ ?>
187
+ </strong>
188
+ </p>
189
+ </div>
190
+ <?php
191
+ return false;
192
+ }
193
+ // Invalid license key.
194
+ if ( 'valid' != $status ) {
195
+ ?>
196
+ <div class="error">
197
+ <p>
198
+ <strong><?php echo sprintf( $no_valid_string, $this->product->get_name() . ' ' . $this->product->get_type(), $this->get_api_url(), admin_url( 'options-general.php' ) . '#' . $this->product->get_key() ); ?> </strong>
199
+ </p>
200
+ </div>
201
+ <?php
202
+
203
+ return false;
204
+ }
205
+
206
+ // Expired and soon to expire license.
207
+ if ( 'valid' == $status && $this->check_expiration() ) {
208
+ ?>
209
+ <div class="update-nag">
210
+ <p>
211
+ <strong>
212
+ <?php
213
+ echo sprintf(
214
+ $expiration_string,
215
+ $this->product->get_name() . ' ' . $this->product->get_type(),
216
+ '<a href="' . $this->renew_url() . '" target="_blank">' . $this->get_distributor_name() . '</a>'
217
+ );
218
+ ?>
219
+ </strong>
220
+ </p>
221
+ </div>
222
+ <?php
223
+ return false;
224
+ }
225
+
226
+ return true;
227
+ }
228
+
229
+ /**
230
+ * Check if the license is active or not.
231
+ *
232
+ * @return bool
233
+ */
234
+ public function check_activation() {
235
+ $license_data = get_option( $this->product->get_key() . '_license_data', '' );
236
+ if ( '' === $license_data ) {
237
+ return false;
238
+ }
239
+
240
+ return isset( $license_data->error ) ? ( 'no_activations_left' == $license_data->error ) : false;
241
+
242
+ }
243
+
244
+ /**
245
+ * Check if the license is about to expire in the next month.
246
+ *
247
+ * @return bool
248
+ */
249
+ function check_expiration() {
250
+ $license_data = get_option( $this->product->get_key() . '_license_data', '' );
251
+ if ( '' === $license_data ) {
252
+ return false;
253
+ }
254
+ if ( ! isset( $license_data->expires ) ) {
255
+ return false;
256
+ }
257
+ if ( strtotime( $license_data->expires ) - time() > 30 * 24 * 3600 ) {
258
+ return false;
259
+ }
260
+
261
+ return true;
262
+ }
263
+
264
+ /**
265
+ * Return the renew url from the store used.
266
+ *
267
+ * @return string The renew url.
268
+ */
269
+ function renew_url() {
270
+ $license_data = get_option( $this->product->get_key() . '_license_data', '' );
271
+ if ( '' === $license_data ) {
272
+ return $this->get_api_url();
273
+ }
274
+ if ( ! isset( $license_data->download_id ) || ! isset( $license_data->key ) ) {
275
+ return $this->get_api_url();
276
+ }
277
+
278
+ return $this->get_api_url() . '/checkout/?edd_license_key=' . $license_data->key . '&download_id=' . $license_data->download_id;
279
+ }
280
+
281
+ /**
282
+ * Run the license check call.
283
+ */
284
+ public function product_valid() {
285
+ if ( false !== ( $license = get_transient( $this->product->get_key() . '_license_data' ) ) ) {
286
+ return;
287
+ }
288
+ $license = $this->check_license();
289
+ set_transient( $this->product->get_key() . '_license_data', $license, 12 * HOUR_IN_SECONDS );
290
+ update_option( $this->product->get_key() . '_license_data', $license );
291
+ }
292
+
293
+ /**
294
+ * Check the license status.
295
+ *
296
+ * @return object The license data.
297
+ */
298
+ public function check_license() {
299
+ $status = $this->get_license_status();
300
+ if ( 'not_active' == $status ) {
301
+ $license_data = new \stdClass();
302
+ $license_data->license = 'not_active';
303
+
304
+ return $license_data;
305
+ }
306
+ $license = trim( $this->license_key );
307
+ $api_params = array(
308
+ 'edd_action' => 'check_license',
309
+ 'license' => $license,
310
+ 'item_name' => rawurlencode( $this->product->get_name() ),
311
+ 'url' => rawurlencode( home_url() ),
312
+ );
313
+ // Call the custom API.
314
+ $response = wp_remote_get(
315
+ add_query_arg( $api_params, $this->get_api_url() ),
316
+ array(
317
+ 'timeout' => 15,
318
+ 'sslverify' => false,
319
+ )
320
+ );
321
+ if ( is_wp_error( $response ) ) {
322
+ $license_data = new \stdClass();
323
+ $license_data->license = 'valid';
324
+
325
+ } else {
326
+ $license_data = json_decode( wp_remote_retrieve_body( $response ) );
327
+ if ( ! is_object( $license_data ) ) {
328
+ $license_data = new \stdClass();
329
+ $license_data->license = 'valid';
330
+ }
331
+ }
332
+ $license_old = get_option( $this->product->get_key() . '_license_data', '' );
333
+ if ( 'valid' == $license_old->license && ( $license_data->license != $license_old->license ) ) {
334
+ $this->increment_failed_checks();
335
+ } else {
336
+ $this->reset_failed_checks();
337
+ }
338
+
339
+ if ( $this->failed_checks <= self::$max_failed ) {
340
+ return $license_old;
341
+ }
342
+
343
+ if ( isset( $license_old->hide_valid ) ) {
344
+ $license_data->hide_valid = true;
345
+ }
346
+
347
+ if ( ! isset( $license_data->key ) ) {
348
+ $license_data->key = isset( $license_old->key ) ? $license_old->key : '';
349
+ }
350
+
351
+ if ( isset( $license_old->hide_expiration ) ) {
352
+ $license_data->hide_expiration = true;
353
+ }
354
+
355
+ if ( isset( $license_old->hide_activation ) ) {
356
+ $license_data->hide_activation = true;
357
+ }
358
+
359
+ return $license_data;
360
+
361
+ }
362
+
363
+ /**
364
+ * Increment the failed checks.
365
+ */
366
+ private function increment_failed_checks() {
367
+ $this->failed_checks ++;
368
+ update_option( $this->product->get_key() . '_failed_checks', $this->failed_checks );
369
+ }
370
+
371
+ /**
372
+ * Reset the failed checks
373
+ */
374
+ private function reset_failed_checks() {
375
+ $this->failed_checks = 1;
376
+ update_option( $this->product->get_key() . '_failed_checks', $this->failed_checks );
377
+ }
378
+
379
+ /**
380
+ * Activate the license remotely.
381
+ */
382
+ function activate_license() {
383
+ // listen for our activate button to be clicked.
384
+ if ( ! isset( $_POST[ $this->product->get_key() . '_btn_trigger' ] ) ) {
385
+ return;
386
+ }
387
+ $status = $this->get_license_status();
388
+ // retrieve the license from the database.
389
+ $license = $_POST[ $this->product->get_key() . '_license' ];
390
+ $api_params = array(
391
+ 'license' => $license,
392
+ 'item_name' => rawurlencode( $this->product->get_name() ),
393
+ 'url' => rawurlencode( home_url() ),
394
+ );
395
+ if ( 'valid' != $status ) {
396
+ // data to send in our API request.
397
+ $api_params['edd_action'] = 'activate_license';
398
+ } else {
399
+ $api_params['edd_action'] = 'deactivate_license';
400
+ }
401
+ // Call the custom API.
402
+ $response = wp_remote_get( add_query_arg( $api_params, $this->get_api_url() ) );
403
+ // make sure the response came back okay.
404
+ if ( is_wp_error( $response ) ) {
405
+ $license_data = new \stdClass();
406
+ $license_data->license = ( 'valid' != $status ) ? 'valid' : 'invalid';
407
+
408
+ } else {
409
+ $license_data = json_decode( wp_remote_retrieve_body( $response ) );
410
+ if ( ! is_object( $license_data ) ) {
411
+ $license_data = new \stdClass();
412
+ $license_data->license = ( 'valid' != $status ) ? 'valid' : 'invalid';
413
+ }
414
+ if ( ! isset( $license_data->license ) ) {
415
+ $license_data->license = 'invalid';
416
+ }
417
+ }
418
+ if ( ! isset( $license_data->key ) ) {
419
+ $license_data->key = $license;
420
+ }
421
+ if ( 'valid' == $license_data->license ) {
422
+ $this->reset_failed_checks();
423
+ }
424
+
425
+ if ( isset( $license_data->plan ) ) {
426
+ update_option( $this->product->get_key() . '_license_plan', $license_data->plan );
427
+ }
428
+
429
+ update_option( $this->product->get_key() . '_license_data', $license_data );
430
+ set_transient( $this->product->get_key() . '_license_data', $license_data, 12 * HOUR_IN_SECONDS );
431
+
432
+ }
433
+
434
+ /**
435
+ * Load the Themes screen.
436
+ */
437
+ function load_themes_screen() {
438
+ add_thickbox();
439
+ add_action( 'admin_notices', array( &$this, 'update_nag' ) );
440
+ }
441
+
442
+ /**
443
+ * Alter the nag for themes update.
444
+ */
445
+ function update_nag() {
446
+ $theme = wp_get_theme( $this->product->get_slug() );
447
+ $api_response = get_transient( $this->product_key );
448
+ if ( false === $api_response ) {
449
+ return;
450
+ }
451
+ $update_url = wp_nonce_url( 'update.php?action=upgrade-theme&amp;theme=' . urlencode( $this->product->get_slug() ), 'upgrade-theme_' . $this->product->get_slug() );
452
+ $update_message = apply_filters( 'themeisle_sdk_license_update_message', 'Updating this theme will lose any customizations you have made. Cancel to stop, OK to update.' );
453
+ $update_onclick = ' onclick="if ( confirm(\'' . esc_js( $update_message ) . '\') ) {return true;}return false;"';
454
+ if ( version_compare( $this->product->get_version(), $api_response->new_version, '<' ) ) {
455
+ echo '<div id="update-nag">';
456
+ printf(
457
+ '<strong>%1$s %2$s</strong> is available. <a href="%3$s" class="thickbox" title="%4s">Check out what\'s new</a> or <a href="%5$s"%6$s>update now</a>.',
458
+ $theme->get( 'Name' ),
459
+ $api_response->new_version,
460
+ '#TB_inline?width=640&amp;inlineId=' . $this->product->get_version() . '_changelog',
461
+ $theme->get( 'Name' ),
462
+ $update_url,
463
+ $update_onclick
464
+ );
465
+ echo '</div>';
466
+ echo '<div id="' . $this->product->get_slug() . '_' . 'changelog" style="display:none;">';
467
+ echo wpautop( $api_response->sections['changelog'] );
468
+ echo '</div>';
469
+ }
470
+ }
471
+
472
+ /**
473
+ * Alter update transient.
474
+ *
475
+ * @param mixed $value The transient data.
476
+ *
477
+ * @return mixed
478
+ */
479
+ function theme_update_transient( $value ) {
480
+ $update_data = $this->check_for_update();
481
+ if ( $update_data ) {
482
+ $value->response[ $this->product->get_slug() ] = $update_data;
483
+ }
484
+
485
+ return $value;
486
+ }
487
+
488
+ /**
489
+ * Check for updates
490
+ *
491
+ * @return array|bool Either the update data or false in case of failure.
492
+ */
493
+ function check_for_update() {
494
+ $update_data = get_transient( $this->product_key );
495
+
496
+ if ( false === $update_data ) {
497
+ $failed = false;
498
+ $update_data = $this->get_version_data();
499
+ if ( empty( $update_data ) ) {
500
+ $failed = true;
501
+ }
502
+ // If the response failed, try again in 30 minutes.
503
+ if ( $failed ) {
504
+ $data = new \stdClass();
505
+ $data->new_version = $this->product->get_version();
506
+ set_transient( $this->product_key, $data, 30 * MINUTE_IN_SECONDS );
507
+
508
+ return false;
509
+ }
510
+ $update_data->sections = maybe_unserialize( $update_data->sections );
511
+
512
+ set_transient( $this->product_key, $update_data, 12 * HOUR_IN_SECONDS );
513
+ }
514
+ if ( ! isset( $update_data->new_version ) ) {
515
+ return false;
516
+ }
517
+ if ( version_compare( $this->product->get_version(), $update_data->new_version, '>=' ) ) {
518
+ return false;
519
+ }
520
+
521
+ return (array) $update_data;
522
+ }
523
+
524
+ /**
525
+ * Check remote api for latest version.
526
+ *
527
+ * @return bool|mixed Update api response.
528
+ */
529
+ private function get_version_data() {
530
+ $api_params = array(
531
+ 'edd_action' => 'get_version',
532
+ 'version' => $this->product->get_version(),
533
+ 'license' => $this->license_key,
534
+ 'name' => $this->product->get_name(),
535
+ 'slug' => $this->product->get_slug(),
536
+ 'author' => $this->get_distributor_name(),
537
+ 'url' => rawurlencode( home_url() ),
538
+ );
539
+ $response = wp_remote_get(
540
+ $this->get_api_url(),
541
+ array(
542
+ 'timeout' => 15,
543
+ 'sslverify' => false,
544
+ 'body' => $api_params,
545
+ )
546
+ );
547
+ if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
548
+ return false;
549
+ }
550
+ $update_data = json_decode( wp_remote_retrieve_body( $response ) );
551
+ if ( ! is_object( $update_data ) ) {
552
+ return false;
553
+ }
554
+
555
+ return $update_data;
556
+ }
557
+
558
+ /**
559
+ * Delete the update transient
560
+ */
561
+ function delete_theme_update_transient() {
562
+ delete_transient( $this->product_key );
563
+ }
564
+
565
+ /**
566
+ * Check for Updates at the defined API endpoint and modify the update array.
567
+ *
568
+ * @param array $_transient_data Update array build by WordPress.
569
+ *
570
+ * @return mixed Modified update array with custom plugin data.
571
+ */
572
+ public function pre_set_site_transient_update_plugins_filter( $_transient_data ) {
573
+ if ( empty( $_transient_data ) || ! $this->do_check ) {
574
+ $this->do_check = true;
575
+
576
+ return $_transient_data;
577
+ }
578
+ $api_response = $this->api_request();
579
+ if ( false !== $api_response && is_object( $api_response ) && isset( $api_response->new_version ) ) {
580
+ if ( version_compare( $this->product->get_version(), $api_response->new_version, '<' ) ) {
581
+ $_transient_data->response[ $this->product->get_slug() . '/' . $this->product->get_file() ] = $api_response;
582
+ }
583
+ }
584
+
585
+ return $_transient_data;
586
+ }
587
+
588
+ /**
589
+ * Calls the API and, if successfull, returns the object delivered by the API.
590
+ *
591
+ * @param string $_action The requested action.
592
+ * @param array $_data Parameters for the API action.
593
+ *
594
+ * @return false||object
595
+ */
596
+ private function api_request( $_action = '', $_data = '' ) {
597
+ $update_data = $this->get_version_data();
598
+ if ( empty( $update_data ) ) {
599
+ return false;
600
+ }
601
+ if ( $update_data && isset( $update_data->sections ) ) {
602
+ $update_data->sections = maybe_unserialize( $update_data->sections );
603
+ }
604
+
605
+ return $update_data;
606
+ }
607
+
608
+ /**
609
+ * Updates information on the "View version x.x details" page with custom data.
610
+ *
611
+ * @param mixed $_data Plugin data.
612
+ * @param string $_action Action to send.
613
+ * @param object $_args Arguments to use.
614
+ *
615
+ * @return object $_data
616
+ */
617
+ public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
618
+ if ( ( 'plugin_information' != $_action ) || ! isset( $_args->slug ) || ( $_args->slug != $this->product->get_slug() ) ) {
619
+ return $_data;
620
+ }
621
+ $api_response = $this->api_request();
622
+ if ( false !== $api_response ) {
623
+ $_data = $api_response;
624
+ }
625
+
626
+ return $_data;
627
+ }
628
+
629
+ /**
630
+ * Disable SSL verification in order to prevent download update failures.
631
+ *
632
+ * @param array $args Http args.
633
+ * @param string $url Url to check.
634
+ *
635
+ * @return array $array
636
+ */
637
+ function http_request_args( $args, $url ) {
638
+ // If it is an https request and we are performing a package download, disable ssl verification.
639
+ if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
640
+ $args['sslverify'] = false;
641
+ }
642
+
643
+ return $args;
644
+ }
645
+
646
+ /**
647
+ * Check if we should load the module for this product.
648
+ *
649
+ * @param Product $product Product data.
650
+ *
651
+ * @return bool Should we load the module?
652
+ */
653
+ public function can_load( $product ) {
654
+
655
+ if ( $product->is_wordpress_available() ) {
656
+ return false;
657
+ }
658
+
659
+ return ( apply_filters( $product->get_key() . '_enable_licenser', true ) === true );
660
+
661
+ }
662
+
663
+ /**
664
+ * Load module logic.
665
+ *
666
+ * @param Product $product Product to load the module for.
667
+ *
668
+ * @return Licenser Module object.
669
+ */
670
+ public function load( $product ) {
671
+ $this->product = $product;
672
+
673
+ $this->product_key = $this->product->get_key() . '-update-response';
674
+
675
+ $this->license_key = $this->product->get_license();
676
+ if ( $this->product->requires_license() ) {
677
+ $this->failed_checks = intval( get_option( $this->product->get_key() . '_failed_checks', 0 ) );
678
+ $this->register_license_hooks();
679
+ }
680
+
681
+ if ( $this->product->is_plugin() ) {
682
+ add_filter(
683
+ 'pre_set_site_transient_update_plugins',
684
+ [
685
+ $this,
686
+ 'pre_set_site_transient_update_plugins_filter',
687
+ ]
688
+ );
689
+ add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
690
+ add_filter( 'http_request_args', array( $this, 'http_request_args' ), 10, 2 );
691
+
692
+ return $this;
693
+ }
694
+ if ( $this->product->is_theme() ) {
695
+ add_filter( 'site_transient_update_themes', array( &$this, 'theme_update_transient' ) );
696
+ add_filter( 'delete_site_transient_update_themes', array( &$this, 'delete_theme_update_transient' ) );
697
+ add_action( 'load-update-core.php', array( &$this, 'delete_theme_update_transient' ) );
698
+ add_action( 'load-themes.php', array( &$this, 'delete_theme_update_transient' ) );
699
+ add_action( 'load-themes.php', array( &$this, 'load_themes_screen' ) );
700
+ add_filter( 'http_request_args', array( $this, 'disable_wporg_update' ), 5, 2 );
701
+
702
+ return $this;
703
+
704
+ }
705
+
706
+ return $this;
707
+ }
708
+
709
+ /**
710
+ * Register license fields for the products.
711
+ */
712
+ public function register_license_hooks() {
713
+ add_action( 'admin_init', array( $this, 'register_settings' ) );
714
+ add_action( 'admin_init', array( $this, 'activate_license' ) );
715
+ add_action( 'admin_init', array( $this, 'product_valid' ), 99999999 );
716
+ add_action( 'admin_notices', array( $this, 'show_notice' ) );
717
+ add_filter( $this->product->get_key() . '_license_status', array( $this, 'get_license_status' ) );
718
+ }
719
+ }
vendor/codeinwp/themeisle-sdk/src/Modules/Logger.php ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The logger model class for ThemeIsle SDK
4
+ *
5
+ * @package ThemeIsleSDK
6
+ * @subpackage Modules
7
+ * @copyright Copyright (c) 2017, Marius Cristea
8
+ * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
+ * @since 1.0.0
10
+ */
11
+
12
+ namespace ThemeisleSDK\Modules;
13
+
14
+ use ThemeisleSDK\Common\Abstract_Module;
15
+ use ThemeisleSDK\Loader;
16
+ use ThemeisleSDK\Product;
17
+
18
+ // Exit if accessed directly.
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit;
21
+ }
22
+
23
+ /**
24
+ * Logger module for ThemeIsle SDK.
25
+ */
26
+ class Logger extends Abstract_Module {
27
+ /**
28
+ * Endpoint where to collect logs.
29
+ */
30
+ const TRACKING_ENDPOINT = 'http://log.themeisle.com/wp-json/v1/logs/';
31
+
32
+
33
+ /**
34
+ * Check if we should load the module for this product.
35
+ *
36
+ * @param Product $product Product to load the module for.
37
+ *
38
+ * @return bool Should we load ?
39
+ */
40
+ public function can_load( $product ) {
41
+
42
+ return apply_filters( $product->get_slug() . '_sdk_enable_logger', true );
43
+ }
44
+
45
+ /**
46
+ * Load module logic.
47
+ *
48
+ * @param Product $product Product to load.
49
+ *
50
+ * @return Logger Module object.
51
+ */
52
+ public function load( $product ) {
53
+ $this->product = $product;
54
+ $this->setup_notification();
55
+ $this->setup_actions();
56
+
57
+ return $this;
58
+ }
59
+
60
+ /**
61
+ * Setup notification on admin.
62
+ */
63
+ public function setup_notification() {
64
+ if ( ! $this->product->is_wordpress_available() ) {
65
+ return;
66
+ }
67
+
68
+ add_filter( 'themeisle_sdk_registered_notifications', [ $this, 'add_notification' ] );
69
+
70
+ }
71
+
72
+ /**
73
+ * Setup tracking actions.
74
+ */
75
+ public function setup_actions() {
76
+ if ( ! $this->is_logger_active() ) {
77
+ return;
78
+ }
79
+ $action_key = $this->product->get_key() . '_log_activity';
80
+ if ( ! wp_next_scheduled( $action_key ) ) {
81
+ wp_schedule_single_event( time() + ( rand( 1, 24 ) * 3600 ), $action_key );
82
+ }
83
+ add_action( $action_key, array( $this, 'send_log' ) );
84
+
85
+ }
86
+
87
+ /**
88
+ * Check if the logger is active.
89
+ *
90
+ * @return bool Is logger active?
91
+ */
92
+ private function is_logger_active() {
93
+ if ( ! $this->product->is_wordpress_available() ) {
94
+ return true;
95
+ }
96
+ $pro_slug = $this->product->get_pro_slug();
97
+
98
+ if ( ! empty( $pro_slug ) ) {
99
+ $all_products = Loader::get_products();
100
+ if ( isset( $all_products[ $pro_slug ] ) ) {
101
+ return true;
102
+ }
103
+ }
104
+
105
+ return ( get_option( $this->product->get_key() . '_logger_flag', 'no' ) === 'yes' );
106
+ }
107
+
108
+ /**
109
+ * Add notification to queue.
110
+ *
111
+ * @param array $all_notifications Previous notification.
112
+ *
113
+ * @return array All notifications.
114
+ */
115
+ public function add_notification( $all_notifications ) {
116
+
117
+ $message = apply_filters( $this->product->get_key() . '_logger_heading', 'Do you enjoy <b>{product}</b>? Become a contributor by opting in to our anonymous data tracking. We guarantee no sensitive data is collected.' );
118
+
119
+ $message = str_replace(
120
+ array( '{product}' ),
121
+ $this->product->get_friendly_name(),
122
+ $message
123
+ );
124
+ $button_submit = apply_filters( $this->product->get_key() . '_logger_button_submit', 'Sure, I would love to help.' );
125
+ $button_cancel = apply_filters( $this->product->get_key() . '_logger_button_cancel', 'No, thanks.' );
126
+
127
+ $all_notifications[] = [
128
+ 'id' => $this->product->get_key() . '_logger_flag',
129
+ 'message' => $message,
130
+ 'ctas' => [
131
+ 'confirm' => [
132
+ 'link' => '#',
133
+ 'text' => $button_submit,
134
+ ],
135
+ 'cancel' => [
136
+ 'link' => '#',
137
+ 'text' => $button_cancel,
138
+ ],
139
+ ],
140
+ ];
141
+
142
+ return $all_notifications;
143
+ }
144
+
145
+ /**
146
+ * Send the statistics to the api endpoint.
147
+ */
148
+ public function send_log() {
149
+ $environment = array();
150
+ $theme = wp_get_theme();
151
+ $environment['theme'] = array();
152
+ $environment['theme']['name'] = $theme->get( 'Name' );
153
+ $environment['theme']['author'] = $theme->get( 'Author' );
154
+ $environment['plugins'] = get_option( 'active_plugins' );
155
+ global $wp_version;
156
+ wp_remote_post(
157
+ self::TRACKING_ENDPOINT,
158
+ array(
159
+ 'method' => 'POST',
160
+ 'timeout' => 3,
161
+ 'redirection' => 5,
162
+ 'headers' => array(
163
+ 'X-ThemeIsle-Event' => 'log_site',
164
+ ),
165
+ 'body' => array(
166
+ 'site' => get_site_url(),
167
+ 'slug' => $this->product->get_slug(),
168
+ 'version' => $this->product->get_version(),
169
+ 'wp_version' => $wp_version,
170
+ 'data' => apply_filters( $this->product->get_key() . '_logger_data', array() ),
171
+ 'environment' => $environment,
172
+ 'license' => apply_filters( $this->product->get_key() . '_license_status', '' ),
173
+ ),
174
+ )
175
+ );
176
+ }
177
+ }
vendor/codeinwp/themeisle-sdk/src/Modules/Notification.php ADDED
@@ -0,0 +1,456 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The notification model class for ThemeIsle SDK
4
+ *
5
+ * @package ThemeIsleSDK
6
+ * @subpackage Modules
7
+ * @copyright Copyright (c) 2017, Marius Cristea
8
+ * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
+ * @since 1.0.0
10
+ */
11
+
12
+ namespace ThemeisleSDK\Modules;
13
+
14
+ use ThemeisleSDK\Common\Abstract_Module;
15
+ use ThemeisleSDK\Product;
16
+
17
+ // Exit if accessed directly.
18
+ if ( ! defined( 'ABSPATH' ) ) {
19
+ exit;
20
+ }
21
+
22
+ /**
23
+ * Notification module for ThemeIsle SDK.
24
+ */
25
+ class Notification extends Abstract_Module {
26
+ /**
27
+ * Show notifications only after the user has the product installed after this amount of time, in hours.
28
+ */
29
+ const MIN_INSTALL_TIME = 100;
30
+ /**
31
+ * How much time should we show the notification, in days.
32
+ */
33
+ const MAX_TIME_TO_LIVE = 7;
34
+
35
+ /**
36
+ * Number of days between notifications.
37
+ */
38
+ const TIME_BETWEEN_NOTIFICATIONS = 5;
39
+
40
+ /**
41
+ * Holds a possible notification list.
42
+ *
43
+ * @var array Notifications list.
44
+ */
45
+ private static $notifications = [];
46
+
47
+ /**
48
+ * Show notification data.
49
+ */
50
+ public static function show_notification() {
51
+
52
+ $current_notification = self::get_last_notification();
53
+
54
+ $notification_details = [];
55
+ // Check if the saved notification is still present among the possible ones.
56
+ if ( ! empty( $current_notification ) ) {
57
+ $notification_details = self::get_notification_details( $current_notification );
58
+ if ( empty( $notification_details ) ) {
59
+ $current_notification = [];
60
+ }
61
+ }
62
+ // Check if the notificatin is expired.
63
+ if ( ! empty( $current_notification ) && self::is_notification_expired( $current_notification ) ) {
64
+ update_option( $current_notification['id'], 'no' );
65
+ self::set_last_active_notification_timestamp();
66
+ $current_notification = [];
67
+ }
68
+ // If we don't have any saved notification, get a new one.
69
+ if ( empty( $current_notification ) ) {
70
+ $notification_details = self::get_random_notification();
71
+ if ( empty( $notification_details ) ) {
72
+ return;
73
+ }
74
+ self::set_active_notification(
75
+ [
76
+ 'id' => $notification_details['id'],
77
+ 'display_at' => time(),
78
+ ]
79
+ );
80
+ }
81
+ if ( empty( $notification_details ) ) {
82
+ return;
83
+ }
84
+ $notification_html = self::get_notification_html( $notification_details );
85
+ do_action( $notification_details['id'] . '_before_render' );
86
+
87
+ echo $notification_html;
88
+
89
+ do_action( $notification_details['id'] . '_after_render' );
90
+ self::render_snippets();
91
+ }
92
+
93
+ /**
94
+ * Get last notification details.
95
+ *
96
+ * @return array Last notification details.
97
+ */
98
+ private static function get_last_notification() {
99
+ $notification = self::get_notifications_metadata();
100
+
101
+ return isset( $notification['last_notification'] ) ? $notification['last_notification'] : [];
102
+ }
103
+
104
+ /**
105
+ * Get notification center details.
106
+ *
107
+ * @return array Notification center details.
108
+ */
109
+ private static function get_notifications_metadata() {
110
+
111
+ $data = get_option(
112
+ 'themeisle_sdk_notifications',
113
+ [
114
+ 'last_notification' => [],
115
+ 'last_notification_active' => 0,
116
+ ]
117
+ );
118
+
119
+ return $data;
120
+
121
+ }
122
+
123
+ /**
124
+ * Check if the notification is still possible.
125
+ *
126
+ * @param array $notification Notification to check.
127
+ *
128
+ * @return array Either is still active or not.
129
+ */
130
+ private static function get_notification_details( $notification ) {
131
+ $notifications = array_filter(
132
+ self::$notifications,
133
+ function ( $value ) use ( $notification ) {
134
+ if ( isset( $value['id'] ) && isset( $notification['id'] ) && $value['id'] === $notification['id'] ) {
135
+ return true;
136
+ }
137
+
138
+ return false;
139
+ }
140
+ );
141
+
142
+ return ! empty( $notifications ) ? reset( $notifications ) : [];
143
+ }
144
+
145
+ /**
146
+ * Check if the notification is expired.
147
+ *
148
+ * @param array $notification Notification to check.
149
+ *
150
+ * @return bool Either the notification is due.
151
+ */
152
+ private static function is_notification_expired( $notification ) {
153
+ if ( ! isset( $notification['display_at'] ) ) {
154
+ return true;
155
+ }
156
+
157
+ $notifications = array_filter(
158
+ self::$notifications,
159
+ function ( $value ) use ( $notification ) {
160
+ if ( isset( $value['id'] ) && isset( $notification['id'] ) && $value['id'] === $notification['id'] ) {
161
+ return true;
162
+ }
163
+
164
+ return false;
165
+ }
166
+ );
167
+
168
+ if ( empty( $notifications ) ) {
169
+ return true;
170
+ }
171
+ $notification_definition = reset( $notifications );
172
+
173
+ $when_to_expire = isset( $notification_definition['expires_at'] )
174
+ ? $notification_definition['expires_at'] :
175
+ ( isset( $notification_definition['expires'] )
176
+ ? ( $notification['display_at'] + $notification_definition['expires'] ) :
177
+ ( $notification['display_at'] + self::MAX_TIME_TO_LIVE * DAY_IN_SECONDS )
178
+ );
179
+
180
+ return ( $when_to_expire - time() ) < 0;
181
+ }
182
+
183
+ /**
184
+ * Set last notification details.
185
+ */
186
+ private static function set_last_active_notification_timestamp() {
187
+ $metadata = self::get_notifications_metadata();
188
+ $metadata['last_notification_active'] = time();
189
+ update_option( 'themeisle_sdk_notifications', $metadata );
190
+ }
191
+
192
+ /**
193
+ * Return notification to show.
194
+ *
195
+ * @return array Notification data.
196
+ */
197
+ public static function get_random_notification() {
198
+ if ( ( time() - self::get_last_active_notification_timestamp() ) < self::TIME_BETWEEN_NOTIFICATIONS * DAY_IN_SECONDS ) {
199
+ return [];
200
+ }
201
+
202
+ $notifications = self::$notifications;
203
+ $notifications = array_filter(
204
+ $notifications,
205
+ function ( $value ) {
206
+ if ( isset( $value['sticky'] ) && true === $value['sticky'] ) {
207
+ return true;
208
+ }
209
+
210
+ return false;
211
+ }
212
+ );
213
+ // No priority notifications, use all.
214
+ if ( empty( $notifications ) ) {
215
+ $notifications = self::$notifications;
216
+ }
217
+ if ( empty( $notifications ) ) {
218
+ return [];
219
+ }
220
+ $notifications = array_values( $notifications );
221
+
222
+ return $notifications[ array_rand( $notifications, 1 ) ];
223
+
224
+ }
225
+
226
+ /**
227
+ * Get last notification details.
228
+ *
229
+ * @return array Last notification details.
230
+ */
231
+ private static function get_last_active_notification_timestamp() {
232
+ $notification = self::get_notifications_metadata();
233
+
234
+ return isset( $notification['last_notification_active'] ) ? $notification['last_notification_active'] : 0;
235
+ }
236
+
237
+ /**
238
+ * Get last notification details.
239
+ *
240
+ * @param array $notification Notification data.
241
+ */
242
+ private static function set_active_notification( $notification ) {
243
+ $metadata = self::get_notifications_metadata();
244
+ $metadata['last_notification'] = $notification;
245
+ update_option( 'themeisle_sdk_notifications', $metadata );
246
+ }
247
+
248
+ /**
249
+ * Get notification html.
250
+ *
251
+ * @param array $notification_details Notification details.
252
+ *
253
+ * @return string Html for notice.
254
+ */
255
+ public static function get_notification_html( $notification_details ) {
256
+ $default = [
257
+ 'id' => '',
258
+ 'heading' => '',
259
+ 'message' => '',
260
+ 'ctas' => [
261
+ 'confirm' => [
262
+ 'link' => '#',
263
+ 'text' => '',
264
+ ],
265
+ 'cancel' => [
266
+ 'link' => '#',
267
+ 'text' => '',
268
+ ],
269
+ ],
270
+ ];
271
+ $notification_details = wp_parse_args( $notification_details, $default );
272
+
273
+ $notification_html = '<div class="notice notice-success is-dismissible themeisle-sdk-notice" data-notification-id="' . esc_attr( $notification_details['id'] ) . '" id="' . esc_attr( $notification_details['id'] ) . '-notification"> <div class="themeisle-sdk-notification-box">';
274
+
275
+ if ( ! empty( $notification_details['heading'] ) ) {
276
+ $notification_html .= sprintf( '<h4>%s</h4>', wp_kses_post( $notification_details['heading'] ) );
277
+ }
278
+ if ( ! empty( $notification_details['message'] ) ) {
279
+ $notification_html .= wp_kses_post( $notification_details['message'] );
280
+ }
281
+ $notification_html .= '<div class="actions">';
282
+
283
+ if ( ! empty( $notification_details['ctas']['confirm']['text'] ) ) {
284
+ $notification_html .= sprintf(
285
+ '<a href="%s" target="_blank" class=" button button-primary %s" data-confirm="yes" >%s</a>',
286
+ esc_url( $notification_details['ctas']['confirm']['link'] ),
287
+ esc_attr( $notification_details['id'] . '_confirm' ),
288
+ wp_kses_post( $notification_details['ctas']['confirm']['text'] )
289
+ );
290
+ }
291
+
292
+ if ( ! empty( $notification_details['ctas']['cancel']['text'] ) ) {
293
+ $notification_html .= sprintf(
294
+ '<a href="%s" class=" button %s" data-confirm="no">%s</a>',
295
+ esc_url( $notification_details['ctas']['cancel']['link'] ),
296
+ esc_attr( $notification_details['id'] ) . '_cancel',
297
+ wp_kses_post( $notification_details['ctas']['cancel']['text'] )
298
+ );
299
+ }
300
+
301
+ $notification_html .= '</div>';
302
+ $notification_html .= ' </div>';
303
+ $notification_html .= ' </div>';
304
+
305
+ return $notification_html;
306
+ }
307
+
308
+ /**
309
+ * Adds js snippet for hiding the notice.
310
+ */
311
+ public static function render_snippets() {
312
+
313
+ ?>
314
+ <style type="text/css">
315
+ .themeisle-sdk-notification-box {
316
+ padding: 3px;
317
+ }
318
+
319
+ .themeisle-sdk-notification-box .actions {
320
+ margin-top: 6px;
321
+ margin-bottom: 4px;
322
+ }
323
+
324
+ .themeisle-sdk-notification-box .button {
325
+ margin-right: 5px;
326
+ }
327
+ </style>
328
+ <script type="text/javascript">
329
+ (function ($) {
330
+ $(document).ready(function () {
331
+ $('#wpbody-content').on('click', ".themeisle-sdk-notice a.button, .themeisle-sdk-notice .notice-dismiss", function (e) {
332
+
333
+ var container = $('.themeisle-sdk-notice');
334
+ var link = $(this);
335
+ var notification_id = container.attr('data-notification-id');
336
+ var confirm = link.attr('data-confirm');
337
+ if (typeof confirm === "undefined") {
338
+ confirm = 'no';
339
+ }
340
+ $.post(
341
+ ajaxurl,
342
+ {
343
+ 'nonce': '<?php echo wp_create_nonce( (string) __CLASS__ ); ?>',
344
+ 'action': 'themeisle_sdk_dismiss_notice',
345
+ 'id': notification_id,
346
+ 'confirm': confirm
347
+ }
348
+ );
349
+ if (confirm === 'yes') {
350
+ $(this).trigger('themeisle-sdk:confirmed');
351
+ } else {
352
+ $(this).trigger('themeisle-sdk:canceled');
353
+ }
354
+ container.hide();
355
+ if (link.attr('href') === '#') {
356
+ return false;
357
+ }
358
+ });
359
+ });
360
+ })(jQuery);
361
+ </script>
362
+ <?php
363
+ }
364
+
365
+ /**
366
+ * Dismiss the notification.
367
+ */
368
+ static function dismiss() {
369
+ check_ajax_referer( (string) __CLASS__, 'nonce' );
370
+
371
+ $id = isset( $_POST['id'] ) ? sanitize_text_field( $_POST['id'] ) : '';
372
+ $confirm = isset( $_POST['confirm'] ) ? sanitize_text_field( $_POST['confirm'] ) : 'no';
373
+
374
+ if ( empty( $id ) ) {
375
+ wp_send_json( [] );
376
+ }
377
+ self::set_last_active_notification_timestamp();
378
+ update_option( $id, $confirm );
379
+ do_action( $id . '_process_confirm', $confirm );
380
+ wp_send_json( [] );
381
+ }
382
+
383
+ /**
384
+ * Check if we should load the notification module.
385
+ *
386
+ * @param Product $product Product to check.
387
+ *
388
+ * @return bool Should we load this?
389
+ */
390
+ public function can_load( $product ) {
391
+
392
+ if ( $this->is_from_partner( $product ) ) {
393
+ return false;
394
+ }
395
+ if ( ! current_user_can( 'manage_options' ) ) {
396
+ return false;
397
+ }
398
+ if ( ( time() - $product->get_install_time() ) < ( self::MIN_INSTALL_TIME * HOUR_IN_SECONDS ) ) {
399
+ return false;
400
+ }
401
+
402
+ return true;
403
+ }
404
+
405
+ /**
406
+ * Setup notifications queue.
407
+ */
408
+ public static function setup_notifications() {
409
+ $notifications = apply_filters( 'themeisle_sdk_registered_notifications', [] );
410
+ $notifications = array_filter(
411
+ $notifications,
412
+ function ( $value ) {
413
+ if ( ! isset( $value['id'] ) ) {
414
+ return false;
415
+ }
416
+ if ( get_option( $value['id'], '' ) !== '' ) {
417
+ return false;
418
+ }
419
+
420
+ return apply_filters( $value['id'] . '_should_show', true );
421
+ }
422
+ );
423
+ self::$notifications = $notifications;
424
+ }
425
+ /**
426
+ * Load the module logic.
427
+ *
428
+ * @param Product $product Product to load the module for.
429
+ *
430
+ * @return Notification Module instance.
431
+ */
432
+ public function load( $product ) {
433
+ $this->product = $product;
434
+
435
+ $notifications = apply_filters( 'themeisle_sdk_registered_notifications', [] );
436
+ $notifications = array_filter(
437
+ $notifications,
438
+ function ( $value ) {
439
+ if ( ! isset( $value['id'] ) ) {
440
+ return false;
441
+ }
442
+ if ( get_option( $value['id'], '' ) !== '' ) {
443
+ return false;
444
+ }
445
+
446
+ return apply_filters( $value['id'] . '_should_show', true );
447
+ }
448
+ );
449
+ self::$notifications = $notifications;
450
+ add_action( 'admin_notices', array( __CLASS__, 'show_notification' ) );
451
+ add_action( 'wp_ajax_themeisle_sdk_dismiss_notice', array( __CLASS__, 'dismiss' ) );
452
+ add_action( 'admin_head', array( __CLASS__, 'setup_notifications' ) );
453
+
454
+ return $this;
455
+ }
456
+ }
vendor/codeinwp/themeisle-sdk/src/Modules/Recommendation.php ADDED
@@ -0,0 +1,374 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The class that exposes hooks for recommend.
4
+ *
5
+ * @package ThemeIsleSDK
6
+ * @subpackage Rollback
7
+ * @copyright Copyright (c) 2017, Marius Cristea
8
+ * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
+ * @since 1.0.0
10
+ */
11
+
12
+ namespace ThemeisleSDK\Modules;
13
+
14
+ // Exit if accessed directly.
15
+ use ThemeisleSDK\Common\Abstract_Module;
16
+ use ThemeisleSDK\Product;
17
+
18
+ if ( ! defined( 'ABSPATH' ) ) {
19
+ exit;
20
+ }
21
+
22
+ /**
23
+ * Expose endpoints for ThemeIsle SDK.
24
+ */
25
+ class Recommendation extends Abstract_Module {
26
+
27
+
28
+ /**
29
+ * Load module logic.
30
+ *
31
+ * @param Product $product Product to load.
32
+ */
33
+ public function load( $product ) {
34
+ $this->product = $product;
35
+ $this->setup_hooks();
36
+
37
+ return $this;
38
+ }
39
+
40
+ /**
41
+ * Setup endpoints.
42
+ */
43
+ private function setup_hooks() {
44
+ add_action( $this->product->get_key() . '_recommend_products', array( $this, 'render_products_box' ), 10, 4 );
45
+ add_action( 'admin_head', array( $this, 'enqueue' ) );
46
+ }
47
+
48
+ /**
49
+ * Check if we should load the module for this product.
50
+ *
51
+ * @param Product $product Product data.
52
+ *
53
+ * @return bool Should we load the module?
54
+ */
55
+ public function can_load( $product ) {
56
+ return true;
57
+ }
58
+
59
+ /**
60
+ * Render products box content.
61
+ *
62
+ * @param array $plugins_list - list of useful plugins (in slug => nicename format).
63
+ * @param array $themes_list - list of useful themes (in slug => nicename format).
64
+ * @param array $strings - list of translated strings.
65
+ * @param array $preferences - list of preferences.
66
+ */
67
+ function render_products_box( $plugins_list, $themes_list, $strings, $preferences = array() ) {
68
+
69
+ if ( empty( $plugins_list ) && empty( $themes_list ) ) {
70
+ return;
71
+ }
72
+
73
+ if ( ! empty( $plugins_list ) && ! current_user_can( 'install_plugins' ) ) {
74
+ return;
75
+ }
76
+
77
+ if ( ! empty( $themes_list ) && ! current_user_can( 'install_themes' ) ) {
78
+ return;
79
+ }
80
+
81
+ add_thickbox();
82
+
83
+ if ( ! empty( $themes_list ) ) {
84
+ $list = $this->get_themes( $themes_list, $preferences );
85
+
86
+ if ( has_action( $this->product->get_key() . '_recommend_products_theme_template' ) ) {
87
+ do_action( $this->product->get_key() . '_recommend_products_theme_template', $list, $strings, $preferences );
88
+ } else {
89
+ echo '<div class="recommend-product">';
90
+
91
+ foreach ( $list as $theme ) {
92
+ echo '<div class="plugin_box">';
93
+ echo ' <img class="theme-banner" src="' . $theme->screenshot_url . '">';
94
+ echo ' <div class="title-action-wrapper">';
95
+ echo ' <span class="plugin-name">' . esc_html( $theme->custom_name ) . '</span>';
96
+ if ( ! isset( $preferences['description'] ) || ( isset( $preferences['description'] ) && $preferences['description'] ) ) {
97
+ echo '<span class="plugin-desc">' . esc_html( substr( $theme->description, 0, strpos( $theme->description, '.' ) ) ) . '.</span>';
98
+ }
99
+ echo ' </div>';
100
+ echo '<div class="plugin-box-footer">';
101
+ echo ' <div class="button-wrap">';
102
+ echo ' <a class="button button-primary " href="' . esc_url( $theme->custom_url ) . '"><span class="dashicons dashicons-external"></span>' . esc_html( $strings['install'] ) . '</a>';
103
+ echo ' </div>';
104
+ echo ' </div>';
105
+ echo '</div>';
106
+ }
107
+
108
+ echo '</div>';
109
+ }
110
+ }
111
+ if ( ! empty( $plugins_list ) ) {
112
+ $list = $this->get_plugins( $plugins_list, $preferences );
113
+
114
+ if ( has_action( $this->product->get_key() . '_recommend_products_plugin_template' ) ) {
115
+ do_action( $this->product->get_key() . '_recommend_products_plugin_template', $list, $strings, $preferences );
116
+ } else {
117
+ echo '<div class="recommend-product">';
118
+
119
+ foreach ( $list as $current_plugin ) {
120
+ echo '<div class="plugin_box">';
121
+ echo ' <img class="plugin-banner" src="' . $current_plugin->custom_image . '">';
122
+ echo ' <div class="title-action-wrapper">';
123
+ echo ' <span class="plugin-name">' . esc_html( $current_plugin->custom_name ) . '</span>';
124
+ if ( ! isset( $preferences['description'] ) || ( isset( $preferences['description'] ) && $preferences['description'] ) ) {
125
+ echo '<span class="plugin-desc">' . esc_html( substr( $current_plugin->short_description, 0, strpos( $current_plugin->short_description, '.' ) ) ) . '. </span>';
126
+ }
127
+ echo ' </div>';
128
+ echo ' <div class="plugin-box-footer">';
129
+ echo ' <a class="button button-primary thickbox open-plugin-details-modal" href="' . esc_url( $current_plugin->custom_url ) . '"><span class="dashicons dashicons-external"></span>' . esc_html( $strings['install'] ) . '</a>';
130
+ echo ' </div>';
131
+ echo '</div>';
132
+ }
133
+
134
+ echo '</div>';
135
+ }
136
+ }
137
+
138
+ }
139
+
140
+ /**
141
+ * Collect all the information for the themes list.
142
+ *
143
+ * @param array $themes_list - list of useful themes (in slug => nicename format).
144
+ * @param array $preferences - list of preferences.
145
+ *
146
+ * @return array
147
+ */
148
+ private function get_themes( $themes_list, $preferences ) {
149
+ $list = array();
150
+ foreach ( $themes_list as $slug => $nicename ) {
151
+ $theme = $this->call_theme_api( $slug );
152
+ if ( ! $theme ) {
153
+ continue;
154
+ }
155
+
156
+ $url = add_query_arg(
157
+ array(
158
+ 'theme' => $theme->slug,
159
+ ),
160
+ network_admin_url( 'theme-install.php' )
161
+ );
162
+
163
+ $name = empty( $nicename ) ? $theme->name : $nicename;
164
+
165
+ $theme->custom_url = $url;
166
+ $theme->custom_name = $name;
167
+
168
+ $list[] = $theme;
169
+ }
170
+
171
+ return $list;
172
+ }
173
+
174
+ /**
175
+ * Call theme api
176
+ *
177
+ * @param string $slug theme slug.
178
+ *
179
+ * @return array|mixed|object
180
+ */
181
+ private function call_theme_api( $slug ) {
182
+ $theme = get_transient( 'ti_theme_info_' . $slug );
183
+
184
+ if ( false !== $theme ) {
185
+ return $theme;
186
+ }
187
+
188
+ $products = wp_remote_get(
189
+ 'https://api.wordpress.org/themes/info/1.1/?action=query_themes&request[theme]=' . $slug . '&request[per_page]=1'
190
+ );
191
+ $products = json_decode( wp_remote_retrieve_body( $products ) );
192
+ if ( is_object( $products ) ) {
193
+ $theme = $products->themes[0];
194
+ set_transient( 'ti_theme_info_' . $slug, $theme, 6 * HOUR_IN_SECONDS );
195
+ }
196
+
197
+ return $theme;
198
+ }
199
+
200
+ /**
201
+ * Collect all the information for the plugins list.
202
+ *
203
+ * @param array $plugins_list - list of useful plugins (in slug => nicename format).
204
+ * @param array $preferences - list of preferences.
205
+ *
206
+ * @return array
207
+ */
208
+ private function get_plugins( $plugins_list, $preferences ) {
209
+ $list = array();
210
+ foreach ( $plugins_list as $plugin => $nicename ) {
211
+ $current_plugin = $this->call_plugin_api( $plugin );
212
+
213
+ $name = empty( $nicename ) ? $current_plugin->name : $nicename;
214
+
215
+ $image = $current_plugin->banners['low'];
216
+ if ( isset( $preferences['image'] ) && 'icon' === $preferences['image'] ) {
217
+ $image = $current_plugin->icons['1x'];
218
+ }
219
+
220
+ $url = add_query_arg(
221
+ array(
222
+ 'tab' => 'plugin-information',
223
+ 'plugin' => $current_plugin->slug,
224
+ 'TB_iframe' => true,
225
+ 'width' => 800,
226
+ 'height' => 800,
227
+ ),
228
+ network_admin_url( 'plugin-install.php' )
229
+ );
230
+
231
+ $current_plugin->custom_url = $url;
232
+ $current_plugin->custom_name = $name;
233
+ $current_plugin->custom_image = $image;
234
+
235
+ $list[] = $current_plugin;
236
+ }
237
+
238
+ return $list;
239
+ }
240
+
241
+ /**
242
+ * Call plugin api
243
+ *
244
+ * @param string $slug plugin slug.
245
+ *
246
+ * @return array|mixed|object
247
+ */
248
+ private function call_plugin_api( $slug ) {
249
+ include_once( ABSPATH . 'wp-admin/includes/plugin-install.php' );
250
+
251
+ $call_api = get_transient( 'ti_plugin_info_' . $slug );
252
+
253
+ if ( false === $call_api ) {
254
+ $call_api = plugins_api(
255
+ 'plugin_information',
256
+ array(
257
+ 'slug' => $slug,
258
+ 'fields' => array(
259
+ 'downloaded' => false,
260
+ 'rating' => false,
261
+ 'description' => false,
262
+ 'short_description' => true,
263
+ 'donate_link' => false,
264
+ 'tags' => false,
265
+ 'sections' => true,
266
+ 'homepage' => true,
267
+ 'added' => false,
268
+ 'last_updated' => false,
269
+ 'compatibility' => false,
270
+ 'tested' => false,
271
+ 'requires' => false,
272
+ 'downloadlink' => false,
273
+ 'icons' => true,
274
+ 'banners' => true,
275
+ ),
276
+ )
277
+ );
278
+ set_transient( 'ti_plugin_info_' . $slug, $call_api, 30 * MINUTE_IN_SECONDS );
279
+ }
280
+
281
+ return $call_api;
282
+ }
283
+
284
+ /**
285
+ * Load css and scripts for the plugin recommend page.
286
+ */
287
+ public function enqueue() {
288
+ $screen = get_current_screen();
289
+
290
+ if ( ! isset( $screen->id ) ) {
291
+ return;
292
+ }
293
+ if ( false === apply_filters( $this->product->get_key() . '_enqueue_recommend', false, $screen->id ) ) {
294
+ return;
295
+ }
296
+
297
+ ?>
298
+ <style type="text/css">
299
+ .recommend-product {
300
+ display: flex;
301
+ justify-content: space-between;
302
+ flex-wrap: wrap;
303
+ }
304
+
305
+ .recommend-product .theme-banner {
306
+ width:200px;
307
+ margin: auto;
308
+ }
309
+ .recommend-product .plugin-banner {
310
+ width: 100px;
311
+ margin: auto;
312
+ }
313
+
314
+ .recommend-product .plugin_box .button span{
315
+
316
+ margin-top: 2px;
317
+ margin-right: 7px;
318
+ }
319
+ .recommend-product .plugin_box .button{
320
+ margin-bottom:10px;
321
+ }
322
+ .recommend-product .plugin_box {
323
+ margin-bottom: 20px;
324
+ padding-top: 5px;
325
+ display: flex;
326
+ box-shadow: 0px 0px 10px -5px rgba(0,0,0,0.55);
327
+ background: #fff;
328
+ border-radius: 5px;
329
+ flex-direction: column;
330
+ justify-content: flex-start;
331
+ width: 95%;
332
+ }
333
+
334
+ .recommend-product .title-action-wrapper {
335
+ padding: 15px 20px 5px 20px;
336
+ }
337
+
338
+ .recommend-product .plugin-name {
339
+ font-size: 18px;
340
+ display: block;
341
+ white-space: nowrap;
342
+ text-overflow: ellipsis;
343
+ margin-bottom: 10px;
344
+ overflow: hidden;
345
+ line-height: normal;
346
+ }
347
+
348
+
349
+ .recommend-product .plugin-desc {
350
+ display: block;
351
+ margin-bottom: 10px;
352
+ font-size: 13px;
353
+ color: #777;
354
+ line-height: 1.6;
355
+ }
356
+
357
+ .recommend-product .button-wrap > div {
358
+ padding: 0;
359
+ margin: 0;
360
+ }
361
+
362
+ .plugin-box-footer {
363
+ display: flex;
364
+ justify-content: space-around;
365
+ vertical-align: middle;
366
+ align-items: center;
367
+ padding: 0px 10px 5px;
368
+ flex: 1;
369
+ margin-top: auto;
370
+ }
371
+ </style>
372
+ <?php
373
+ }
374
+ }
vendor/codeinwp/themeisle-sdk/src/Modules/Review.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The Review model class for ThemeIsle SDK
4
+ *
5
+ * @package ThemeIsleSDK
6
+ * @subpackage Modules
7
+ * @copyright Copyright (c) 2017, Marius Cristea
8
+ * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
+ * @since 1.0.0
10
+ */
11
+
12
+ namespace ThemeisleSDK\Modules;
13
+
14
+ use ThemeisleSDK\Common\Abstract_Module;
15
+ use ThemeisleSDK\Product;
16
+
17
+ // Exit if accessed directly.
18
+ if ( ! defined( 'ABSPATH' ) ) {
19
+ exit;
20
+ }
21
+
22
+ /**
23
+ * Review module for ThemeIsle SDK.
24
+ */
25
+ class Review extends Abstract_Module {
26
+
27
+ /**
28
+ * Check if we should load module for this.
29
+ *
30
+ * @param Product $product Product to check.
31
+ *
32
+ * @return bool Should load ?
33
+ */
34
+ public function can_load( $product ) {
35
+ if ( $this->is_from_partner( $product ) ) {
36
+ return false;
37
+ }
38
+ if ( ! $product->is_wordpress_available() ) {
39
+ return false;
40
+ }
41
+
42
+ return apply_filters( $product->get_slug() . '_sdk_should_review', true );
43
+ }
44
+
45
+
46
+ /**
47
+ * Add notification to queue.
48
+ *
49
+ * @param array $all_notifications Previous notification.
50
+ *
51
+ * @return array All notifications.
52
+ */
53
+ public function add_notification( $all_notifications ) {
54
+
55
+ $developers = [
56
+ 'Bogdan',
57
+ 'Marius',
58
+ 'Hardeep',
59
+ 'Rodica',
60
+ 'Stefan',
61
+ 'Uriahs',
62
+ 'Madalin',
63
+ 'Radu',
64
+ 'Silviu',
65
+ 'Andrei',
66
+ ];
67
+
68
+ $link = 'https://wordpress.org/support/' . $this->product->get_type() . '/' . $this->product->get_slug() . '/reviews/#wporg-footer';
69
+
70
+ $message = apply_filters( $this->product->get_key() . '_feedback_review_message', '<p>Hey, it’s great to see you have <b>{product}</b> active for a few days now. How is everything going? If you can spare a few moments to rate it on WordPress.org it would help us a lot (and boost my motivation). Cheers! <br/> <br/>~ {developer}, developer of {product}</p>' );
71
+
72
+ $button_submit = apply_filters( $this->product->get_key() . '_feedback_review_button_do', 'Ok, I will gladly help.' );
73
+ $button_cancel = apply_filters( $this->product->get_key() . '_feedback_review_button_cancel', 'No, thanks.' );
74
+ $message = str_replace(
75
+ [ '{product}', '{developer}' ],
76
+ [
77
+ $this->product->get_friendly_name(),
78
+ $developers[ strlen( get_site_url() ) % 10 ],
79
+ ],
80
+ $message
81
+ );
82
+
83
+ $all_notifications[] = [
84
+ 'id' => $this->product->get_key() . '_review_flag',
85
+ 'message' => $message,
86
+ 'ctas' => [
87
+ 'confirm' => [
88
+ 'link' => $link,
89
+ 'text' => $button_submit,
90
+ ],
91
+ 'cancel' => [
92
+ 'link' => '#',
93
+ 'text' => $button_cancel,
94
+ ],
95
+ ],
96
+ ];
97
+
98
+ return $all_notifications;
99
+ }
100
+
101
+
102
+ /**
103
+ * Load module logic.
104
+ *
105
+ * @param Product $product Product to load.
106
+ *
107
+ * @return Review Module instance.
108
+ */
109
+ public function load( $product ) {
110
+
111
+ $this->product = $product;
112
+
113
+ add_filter( 'themeisle_sdk_registered_notifications', [ $this, 'add_notification' ] );
114
+
115
+ return $this;
116
+ }
117
+ }
vendor/codeinwp/themeisle-sdk/src/Modules/Rollback.php ADDED
@@ -0,0 +1,376 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The rollback class for ThemeIsle SDK.
4
+ *
5
+ * @package ThemeIsleSDK
6
+ * @subpackage Rollback
7
+ * @copyright Copyright (c) 2017, Marius Cristea
8
+ * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
+ * @since 1.0.0
10
+ */
11
+
12
+ namespace ThemeisleSDK\Modules;
13
+
14
+ // Exit if accessed directly.
15
+ use ThemeisleSDK\Common\Abstract_Module;
16
+ use ThemeisleSDK\Product;
17
+
18
+ if ( ! defined( 'ABSPATH' ) ) {
19
+ exit;
20
+ }
21
+
22
+ /**
23
+ * Rollback for ThemeIsle SDK.
24
+ */
25
+ class Rollback extends Abstract_Module {
26
+
27
+ /**
28
+ * Add js scripts for themes rollback.
29
+ */
30
+ public function add_footer() {
31
+ $screen = get_current_screen();
32
+ if ( ! isset( $screen->parent_file ) ) {
33
+ return;
34
+ }
35
+ if ( 'themes.php' !== $screen->parent_file ) {
36
+ return;
37
+ }
38
+ if ( ! $this->product->is_theme() ) {
39
+ return;
40
+ }
41
+ $version = $this->get_rollback();
42
+ if ( empty( $version ) ) {
43
+ return;
44
+ }
45
+ ?>
46
+ <script type="text/javascript">
47
+ jQuery(document).ready(function ($) {
48
+ setInterval(checkTheme, 500);
49
+
50
+ function checkTheme() {
51
+ var theme = '<?php echo esc_attr( $this->product->get_slug() ); ?>-action';
52
+
53
+ if (jQuery('#' + theme).length > 0) {
54
+ if (jQuery('.theme-overlay.active').is(':visible')) {
55
+ if (jQuery('#' + theme + '-rollback').length === 0) {
56
+ jQuery('.theme-actions .active-theme').prepend('<a class="button" style="float:left" id="' + theme + '-rollback" href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=' . $this->product->get_key() . '_rollback' ), $this->product->get_key() . '_rollback' ) ); ?>">Rollback to v<?php echo esc_attr( $version['version'] ); ?></a>')
57
+ }
58
+ }
59
+
60
+ }
61
+ }
62
+ })
63
+
64
+ </script>
65
+ <?php
66
+
67
+ }
68
+
69
+ /**
70
+ * Get the last rollback for this product.
71
+ *
72
+ * @return array The rollback version.
73
+ */
74
+ public function get_rollback() {
75
+ $rollback = array();
76
+ $versions = $this->get_api_versions();
77
+ $versions = apply_filters( $this->product->get_key() . '_rollbacks', $versions );
78
+ if ( empty( $versions ) ) {
79
+ return $rollback;
80
+ }
81
+ if ( $versions ) {
82
+ usort( $versions, array( $this, 'sort_rollback_array' ) );
83
+ foreach ( $versions as $version ) {
84
+ if ( isset( $version['version'] ) && isset( $version['url'] ) && version_compare( $this->product->get_version(), $version['version'], '>' ) ) {
85
+ $rollback = $version;
86
+ break;
87
+ }
88
+ }
89
+ }
90
+
91
+ return $rollback;
92
+ }
93
+
94
+ /**
95
+ * Get versions array from wp.org
96
+ *
97
+ * @return array Array of versions.
98
+ */
99
+ private function get_api_versions() {
100
+
101
+ $cache_key = $this->product->get_key() . '_' . preg_replace( '/[^0-9a-zA-Z ]/m', '', $this->product->get_version() ) . 'versions';
102
+ $cache_versions = get_transient( $cache_key );
103
+ if ( false === $cache_versions ) {
104
+ $versions = $this->get_remote_versions();
105
+ set_transient( $cache_key, $versions, 5 * DAY_IN_SECONDS );
106
+ } else {
107
+ $versions = is_array( $cache_versions ) ? $cache_versions : array();
108
+ }
109
+
110
+ return $versions;
111
+ }
112
+
113
+ /**
114
+ * Get remote versions zips.
115
+ *
116
+ * @return array Array of available versions.
117
+ */
118
+ private function get_remote_versions() {
119
+ $url = $this->get_versions_api_url();
120
+ if ( empty( $url ) ) {
121
+ return [];
122
+ }
123
+ $response = wp_remote_get( $url );
124
+ if ( is_wp_error( $response ) ) {
125
+ return array();
126
+ }
127
+ $response = wp_remote_retrieve_body( $response );
128
+
129
+ if ( is_serialized( $response ) ) {
130
+ $response = maybe_unserialize( $response );
131
+ } else {
132
+ $response = json_decode( $response );
133
+ }
134
+
135
+ if ( ! is_object( $response ) ) {
136
+ return array();
137
+ }
138
+ if ( ! isset( $response->versions ) ) {
139
+ return array();
140
+ }
141
+
142
+ $versions = array();
143
+ foreach ( $response->versions as $key => $value ) {
144
+ $versions[] = array(
145
+ 'version' => is_object( $value ) ? $value->version : $key,
146
+ 'url' => is_object( $value ) ? $value->file : $value,
147
+ );
148
+ }
149
+
150
+ return $versions;
151
+ }
152
+
153
+ /**
154
+ * Return url where to check for versions.
155
+ *
156
+ * @return string Url where to check for versions.
157
+ */
158
+ private function get_versions_api_url() {
159
+ if ( $this->product->is_wordpress_available() && $this->product->is_plugin() ) {
160
+ return sprintf( 'https://api.wordpress.org/plugins/info/1.0/%s', $this->product->get_slug() );
161
+ }
162
+ if ( $this->product->is_wordpress_available() && $this->product->is_theme() ) {
163
+ return sprintf( 'https://api.wordpress.org/themes/info/1.1/?action=theme_information&request[slug]=%s&request[fields][versions]=true', $this->product->get_slug() );
164
+ }
165
+ $license = $this->product->get_license();
166
+ if ( $this->product->requires_license() && strlen( $license ) < 10 ) {
167
+ return '';
168
+ }
169
+
170
+ return sprintf( '%s?edd_action=get_versions&name=%s&url=%s&license=%s', $this->product->get_store_url(), urlencode( $this->product->get_name() ), urlencode( get_site_url() ), $license );
171
+ }
172
+
173
+ /**
174
+ * Show the rollback links in the plugin page.
175
+ *
176
+ * @param array $links Plugin links.
177
+ *
178
+ * @return array $links Altered links.
179
+ */
180
+ public function add_rollback_link( $links ) {
181
+ $version = $this->get_rollback();
182
+ if ( empty( $version ) ) {
183
+ return $links;
184
+ }
185
+ $links[] = '<a href="' . wp_nonce_url( admin_url( 'admin-post.php?action=' . $this->product->get_key() . '_rollback' ), $this->product->get_key() . '_rollback' ) . '">' . sprintf( apply_filters( $this->product->get_key() . '_rollback_label', 'Rollback to v%s' ), $version['version'] ) . '</a>';
186
+
187
+ return $links;
188
+ }
189
+
190
+ /**
191
+ * Start the rollback operation.
192
+ */
193
+ public function start_rollback() {
194
+ if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], $this->product->get_key() . '_rollback' ) ) {
195
+ wp_nonce_ays( '' );
196
+ }
197
+
198
+ if ( $this->product->is_plugin() ) {
199
+ $this->start_rollback_plugin();
200
+
201
+ return;
202
+ }
203
+ if ( $this->product->is_theme() ) {
204
+ $this->start_rollback_theme();
205
+
206
+ return;
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Start the rollback operation for the plugin.
212
+ */
213
+ private function start_rollback_plugin() {
214
+ $rollback = $this->get_rollback();
215
+ $plugin_transient = get_site_transient( 'update_plugins' );
216
+ $plugin_folder = $this->product->get_slug();
217
+ $plugin_file = $this->product->get_file();
218
+ $version = $rollback['version'];
219
+ $temp_array = array(
220
+ 'slug' => $plugin_folder,
221
+ 'new_version' => $version,
222
+ 'package' => $rollback['url'],
223
+ );
224
+
225
+ $temp_object = (object) $temp_array;
226
+ $plugin_transient->response[ $plugin_folder . '/' . $plugin_file ] = $temp_object;
227
+ set_site_transient( 'update_plugins', $plugin_transient );
228
+
229
+ $transient = get_transient( $this->product->get_key() . '_warning_rollback' );
230
+
231
+ if ( false === $transient ) {
232
+ set_transient( $this->product->get_key() . '_warning_rollback', 'in progress', 30 );
233
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
234
+ $title = sprintf( apply_filters( $this->product->get_key() . '_rollback_message', 'Rolling back %s to v%s' ), $this->product->get_name(), $version );
235
+ $plugin = $plugin_folder . '/' . $plugin_file;
236
+ $nonce = 'upgrade-plugin_' . $plugin;
237
+ $url = 'update.php?action=upgrade-plugin&plugin=' . urlencode( $plugin );
238
+ $upgrader_skin = new \Plugin_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'plugin' ) );
239
+ $upgrader = new \Plugin_Upgrader( $upgrader_skin );
240
+ $upgrader->upgrade( $plugin );
241
+ delete_transient( $this->product->get_key() . '_warning_rollback' );
242
+ wp_die(
243
+ '',
244
+ $title,
245
+ array(
246
+ 'response' => 200,
247
+ )
248
+ );
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Start the rollback operation for the theme.
254
+ */
255
+ private function start_rollback_theme() {
256
+ add_filter( 'update_theme_complete_actions', array( $this, 'alter_links_theme_upgrade' ) );
257
+ $rollback = $this->get_rollback();
258
+ $transient = get_site_transient( 'update_themes' );
259
+ $folder = $this->product->get_slug();
260
+ $version = $rollback['version'];
261
+ $temp_array = array(
262
+ 'new_version' => $version,
263
+ 'package' => $rollback['url'],
264
+ );
265
+
266
+ $transient->response[ $folder . '/style.css' ] = $temp_array;
267
+ set_site_transient( 'update_themes', $transient );
268
+
269
+ $transient = get_transient( $this->product->get_key() . '_warning_rollback' );
270
+
271
+ if ( false === $transient ) {
272
+ set_transient( $this->product->get_key() . '_warning_rollback', 'in progress', 30 );
273
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
274
+ $title = sprintf( apply_filters( $this->product->get_key() . '_rollback_message', 'Rolling back %s to v%s' ), $this->product->get_name(), $version );
275
+ $theme = $folder . '/style.css';
276
+ $nonce = 'upgrade-theme_' . $theme;
277
+ $url = 'update.php?action=upgrade-theme&theme=' . urlencode( $theme );
278
+
279
+ $upgrader = new \Theme_Upgrader( new \Theme_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'theme' ) ) );
280
+ $upgrader->upgrade( $theme );
281
+ delete_transient( $this->product->get_key() . '_warning_rollback' );
282
+ wp_die(
283
+ '',
284
+ $title,
285
+ array(
286
+ 'response' => 200,
287
+ )
288
+ );
289
+ }
290
+ }
291
+
292
+ /**
293
+ * Alter links and remove duplicate customize message.
294
+ *
295
+ * @param array $links Array of old links.
296
+ *
297
+ * @return mixed Array of links.
298
+ */
299
+ public function alter_links_theme_upgrade( $links ) {
300
+ if ( isset( $links['preview'] ) ) {
301
+ $links['preview'] = str_replace( '<span aria-hidden="true">Customize</span>', '', $links['preview'] );
302
+ }
303
+
304
+ return $links;
305
+ }
306
+
307
+ /**
308
+ * Loads product object.
309
+ *
310
+ * @param Product $product Product object.
311
+ *
312
+ * @return bool Should we load the module?
313
+ */
314
+ public function can_load( $product ) {
315
+ if ( $this->is_from_partner( $product ) ) {
316
+ return false;
317
+ }
318
+ if ( $product->is_theme() && ! current_user_can( 'switch_themes' ) ) {
319
+ return false;
320
+ }
321
+
322
+ if ( $product->is_plugin() && ! current_user_can( 'install_plugins' ) ) {
323
+ return false;
324
+ }
325
+
326
+ return true;
327
+ }
328
+
329
+ /**
330
+ * Sort the rollbacks array in descending order.
331
+ *
332
+ * @param mixed $a First version to compare.
333
+ * @param mixed $b Second version to compare.
334
+ *
335
+ * @return bool Which version is greater?
336
+ */
337
+ public function sort_rollback_array( $a, $b ) {
338
+ return version_compare( $a['version'], $b['version'], '<' ) > 0;
339
+ }
340
+
341
+ /**
342
+ * Load module logic.
343
+ *
344
+ * @param Product $product Product object.
345
+ *
346
+ * @return $this Module object.
347
+ */
348
+ public function load( $product ) {
349
+ $this->product = $product;
350
+ $this->show_link();
351
+ $this->add_hooks();
352
+
353
+ return $this;
354
+ }
355
+
356
+ /**
357
+ * If product can be rolled back, show the link to rollback.
358
+ */
359
+ private function show_link() {
360
+ add_filter(
361
+ 'plugin_action_links_' . plugin_basename( $this->product->get_basefile() ),
362
+ array(
363
+ $this,
364
+ 'add_rollback_link',
365
+ )
366
+ );
367
+ }
368
+
369
+ /**
370
+ * Set the rollback hook. Strangely, this does not work if placed in the ThemeIsle_SDK_Rollback class, so it is being called from there instead.
371
+ */
372
+ public function add_hooks() {
373
+ add_action( 'admin_post_' . $this->product->get_key() . '_rollback', array( $this, 'start_rollback' ) );
374
+ add_action( 'admin_footer', array( $this, 'add_footer' ) );
375
+ }
376
+ }
vendor/codeinwp/themeisle-sdk/src/Modules/Translate.php ADDED
@@ -0,0 +1,918 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The translate model class for ThemeIsle SDK
4
+ *
5
+ * @package ThemeIsleSDK
6
+ * @subpackage Modules
7
+ * @copyright Copyright (c) 2017, Marius Cristea
8
+ * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
+ * @since 1.0.0
10
+ */
11
+
12
+ namespace ThemeisleSDK\Modules;
13
+
14
+ use ThemeisleSDK\Common\Abstract_Module;
15
+ use ThemeisleSDK\Product;
16
+
17
+ // Exit if accessed directly.
18
+ if ( ! defined( 'ABSPATH' ) ) {
19
+ exit;
20
+ }
21
+
22
+ /**
23
+ * Translate module for ThemeIsle SDK.
24
+ */
25
+ class Translate extends Abstract_Module {
26
+ /**
27
+ * List of available locales.
28
+ *
29
+ * @var array Array of available locals.
30
+ */
31
+ private static $locales = array(
32
+ 'af' => array(
33
+ 'slug' => 'af',
34
+ 'name' => 'Afrikaans',
35
+ ),
36
+ 'ak' => array(
37
+ 'slug' => 'ak',
38
+ 'name' => 'Akan',
39
+ ),
40
+ 'am' => array(
41
+ 'slug' => 'am',
42
+ 'name' => 'Amharic',
43
+ ),
44
+ 'ar' => array(
45
+ 'slug' => 'ar',
46
+ 'name' => 'Arabic',
47
+ ),
48
+ 'arq' => array(
49
+ 'slug' => 'arq',
50
+ 'name' => 'Algerian Arabic',
51
+ ),
52
+ 'ary' => array(
53
+ 'slug' => 'ary',
54
+ 'name' => 'Moroccan Arabic',
55
+ ),
56
+ 'as' => array(
57
+ 'slug' => 'as',
58
+ 'name' => 'Assamese',
59
+ ),
60
+ 'ast' => array(
61
+ 'slug' => 'ast',
62
+ 'name' => 'Asturian',
63
+ ),
64
+ 'az' => array(
65
+ 'slug' => 'az',
66
+ 'name' => 'Azerbaijani',
67
+ ),
68
+ 'azb' => array(
69
+ 'slug' => 'azb',
70
+ 'name' => 'South Azerbaijani',
71
+ ),
72
+ 'az_TR' => array(
73
+ 'slug' => 'az-tr',
74
+ 'name' => 'Azerbaijani (Turkey)',
75
+ ),
76
+ 'ba' => array(
77
+ 'slug' => 'ba',
78
+ 'name' => 'Bashkir',
79
+ ),
80
+ 'bal' => array(
81
+ 'slug' => 'bal',
82
+ 'name' => 'Catalan (Balear)',
83
+ ),
84
+ 'bcc' => array(
85
+ 'slug' => 'bcc',
86
+ 'name' => 'Balochi Southern',
87
+ ),
88
+ 'bel' => array(
89
+ 'slug' => 'bel',
90
+ 'name' => 'Belarusian',
91
+ ),
92
+ 'bg_BG' => array(
93
+ 'slug' => 'bg',
94
+ 'name' => 'Bulgarian',
95
+ ),
96
+ 'bn_BD' => array(
97
+ 'slug' => 'bn',
98
+ 'name' => 'Bengali',
99
+ ),
100
+ 'bo' => array(
101
+ 'slug' => 'bo',
102
+ 'name' => 'Tibetan',
103
+ ),
104
+ 'bre' => array(
105
+ 'slug' => 'br',
106
+ 'name' => 'Breton',
107
+ ),
108
+ 'bs_BA' => array(
109
+ 'slug' => 'bs',
110
+ 'name' => 'Bosnian',
111
+ ),
112
+ 'ca' => array(
113
+ 'slug' => 'ca',
114
+ 'name' => 'Catalan',
115
+ ),
116
+ 'ceb' => array(
117
+ 'slug' => 'ceb',
118
+ 'name' => 'Cebuano',
119
+ ),
120
+ 'ckb' => array(
121
+ 'slug' => 'ckb',
122
+ 'name' => 'Kurdish (Sorani)',
123
+ ),
124
+ 'co' => array(
125
+ 'slug' => 'co',
126
+ 'name' => 'Corsican',
127
+ ),
128
+ 'cs_CZ' => array(
129
+ 'slug' => 'cs',
130
+ 'name' => 'Czech',
131
+ ),
132
+ 'cy' => array(
133
+ 'slug' => 'cy',
134
+ 'name' => 'Welsh',
135
+ ),
136
+ 'da_DK' => array(
137
+ 'slug' => 'da',
138
+ 'name' => 'Danish',
139
+ ),
140
+ 'de_DE' => array(
141
+ 'slug' => 'de',
142
+ 'name' => 'German',
143
+ ),
144
+ 'de_CH' => array(
145
+ 'slug' => 'de-ch',
146
+ 'name' => 'German (Switzerland)',
147
+ ),
148
+ 'dv' => array(
149
+ 'slug' => 'dv',
150
+ 'name' => 'Dhivehi',
151
+ ),
152
+ 'dzo' => array(
153
+ 'slug' => 'dzo',
154
+ 'name' => 'Dzongkha',
155
+ ),
156
+ 'el' => array(
157
+ 'slug' => 'el',
158
+ 'name' => 'Greek',
159
+ ),
160
+ 'art_xemoji' => array(
161
+ 'slug' => 'art-xemoji',
162
+ 'name' => 'Emoji',
163
+ ),
164
+ 'en_US' => array(
165
+ 'slug' => 'en',
166
+ 'name' => 'English',
167
+ ),
168
+ 'en_AU' => array(
169
+ 'slug' => 'en-au',
170
+ 'name' => 'English (Australia)',
171
+ ),
172
+ 'en_CA' => array(
173
+ 'slug' => 'en-ca',
174
+ 'name' => 'English (Canada)',
175
+ ),
176
+ 'en_GB' => array(
177
+ 'slug' => 'en-gb',
178
+ 'name' => 'English (UK)',
179
+ ),
180
+ 'en_NZ' => array(
181
+ 'slug' => 'en-nz',
182
+ 'name' => 'English (New Zealand)',
183
+ ),
184
+ 'en_ZA' => array(
185
+ 'slug' => 'en-za',
186
+ 'name' => 'English (South Africa)',
187
+ ),
188
+ 'eo' => array(
189
+ 'slug' => 'eo',
190
+ 'name' => 'Esperanto',
191
+ ),
192
+ 'es_ES' => array(
193
+ 'slug' => 'es',
194
+ 'name' => 'Spanish (Spain)',
195
+ ),
196
+ 'es_AR' => array(
197
+ 'slug' => 'es-ar',
198
+ 'name' => 'Spanish (Argentina)',
199
+ ),
200
+ 'es_CL' => array(
201
+ 'slug' => 'es-cl',
202
+ 'name' => 'Spanish (Chile)',
203
+ ),
204
+ 'es_CO' => array(
205
+ 'slug' => 'es-co',
206
+ 'name' => 'Spanish (Colombia)',
207
+ ),
208
+ 'es_CR' => array(
209
+ 'slug' => 'es-cr',
210
+ 'name' => 'Spanish (Costa Rica)',
211
+ ),
212
+ 'es_GT' => array(
213
+ 'slug' => 'es-gt',
214
+ 'name' => 'Spanish (Guatemala)',
215
+ ),
216
+ 'es_MX' => array(
217
+ 'slug' => 'es-mx',
218
+ 'name' => 'Spanish (Mexico)',
219
+ ),
220
+ 'es_PE' => array(
221
+ 'slug' => 'es-pe',
222
+ 'name' => 'Spanish (Peru)',
223
+ ),
224
+ 'es_PR' => array(
225
+ 'slug' => 'es-pr',
226
+ 'name' => 'Spanish (Puerto Rico)',
227
+ ),
228
+ 'es_VE' => array(
229
+ 'slug' => 'es-ve',
230
+ 'name' => 'Spanish (Venezuela)',
231
+ ),
232
+ 'et' => array(
233
+ 'slug' => 'et',
234
+ 'name' => 'Estonian',
235
+ ),
236
+ 'eu' => array(
237
+ 'slug' => 'eu',
238
+ 'name' => 'Basque',
239
+ ),
240
+ 'fa_IR' => array(
241
+ 'slug' => 'fa',
242
+ 'name' => 'Persian',
243
+ ),
244
+ 'fa_AF' => array(
245
+ 'slug' => 'fa-af',
246
+ 'name' => 'Persian (Afghanistan)',
247
+ ),
248
+ 'fuc' => array(
249
+ 'slug' => 'fuc',
250
+ 'name' => 'Fulah',
251
+ ),
252
+ 'fi' => array(
253
+ 'slug' => 'fi',
254
+ 'name' => 'Finnish',
255
+ ),
256
+ 'fo' => array(
257
+ 'slug' => 'fo',
258
+ 'name' => 'Faroese',
259
+ ),
260
+ 'fr_FR' => array(
261
+ 'slug' => 'fr',
262
+ 'name' => 'French (France)',
263
+ ),
264
+ 'fr_BE' => array(
265
+ 'slug' => 'fr-be',
266
+ 'name' => 'French (Belgium)',
267
+ ),
268
+ 'fr_CA' => array(
269
+ 'slug' => 'fr-ca',
270
+ 'name' => 'French (Canada)',
271
+ ),
272
+ 'frp' => array(
273
+ 'slug' => 'frp',
274
+ 'name' => 'Arpitan',
275
+ ),
276
+ 'fur' => array(
277
+ 'slug' => 'fur',
278
+ 'name' => 'Friulian',
279
+ ),
280
+ 'fy' => array(
281
+ 'slug' => 'fy',
282
+ 'name' => 'Frisian',
283
+ ),
284
+ 'ga' => array(
285
+ 'slug' => 'ga',
286
+ 'name' => 'Irish',
287
+ ),
288
+ 'gd' => array(
289
+ 'slug' => 'gd',
290
+ 'name' => 'Scottish Gaelic',
291
+ ),
292
+ 'gl_ES' => array(
293
+ 'slug' => 'gl',
294
+ 'name' => 'Galician',
295
+ ),
296
+ 'gn' => array(
297
+ 'slug' => 'gn',
298
+ 'name' => 'Guaraní',
299
+ ),
300
+ 'gsw' => array(
301
+ 'slug' => 'gsw',
302
+ 'name' => 'Swiss German',
303
+ ),
304
+ 'gu' => array(
305
+ 'slug' => 'gu',
306
+ 'name' => 'Gujarati',
307
+ ),
308
+ 'hat' => array(
309
+ 'slug' => 'hat',
310
+ 'name' => 'Haitian Creole',
311
+ ),
312
+ 'hau' => array(
313
+ 'slug' => 'hau',
314
+ 'name' => 'Hausa',
315
+ ),
316
+ 'haw_US' => array(
317
+ 'slug' => 'haw',
318
+ 'name' => 'Hawaiian',
319
+ ),
320
+ 'haz' => array(
321
+ 'slug' => 'haz',
322
+ 'name' => 'Hazaragi',
323
+ ),
324
+ 'he_IL' => array(
325
+ 'slug' => 'he',
326
+ 'name' => 'Hebrew',
327
+ ),
328
+ 'hi_IN' => array(
329
+ 'slug' => 'hi',
330
+ 'name' => 'Hindi',
331
+ ),
332
+ 'hr' => array(
333
+ 'slug' => 'hr',
334
+ 'name' => 'Croatian',
335
+ ),
336
+ 'hu_HU' => array(
337
+ 'slug' => 'hu',
338
+ 'name' => 'Hungarian',
339
+ ),
340
+ 'hy' => array(
341
+ 'slug' => 'hy',
342
+ 'name' => 'Armenian',
343
+ ),
344
+ 'id_ID' => array(
345
+ 'slug' => 'id',
346
+ 'name' => 'Indonesian',
347
+ ),
348
+ 'ido' => array(
349
+ 'slug' => 'ido',
350
+ 'name' => 'Ido',
351
+ ),
352
+ 'is_IS' => array(
353
+ 'slug' => 'is',
354
+ 'name' => 'Icelandic',
355
+ ),
356
+ 'it_IT' => array(
357
+ 'slug' => 'it',
358
+ 'name' => 'Italian',
359
+ ),
360
+ 'ja' => array(
361
+ 'slug' => 'ja',
362
+ 'name' => 'Japanese',
363
+ ),
364
+ 'jv_ID' => array(
365
+ 'slug' => 'jv',
366
+ 'name' => 'Javanese',
367
+ ),
368
+ 'ka_GE' => array(
369
+ 'slug' => 'ka',
370
+ 'name' => 'Georgian',
371
+ ),
372
+ 'kab' => array(
373
+ 'slug' => 'kab',
374
+ 'name' => 'Kabyle',
375
+ ),
376
+ 'kal' => array(
377
+ 'slug' => 'kal',
378
+ 'name' => 'Greenlandic',
379
+ ),
380
+ 'kin' => array(
381
+ 'slug' => 'kin',
382
+ 'name' => 'Kinyarwanda',
383
+ ),
384
+ 'kk' => array(
385
+ 'slug' => 'kk',
386
+ 'name' => 'Kazakh',
387
+ ),
388
+ 'km' => array(
389
+ 'slug' => 'km',
390
+ 'name' => 'Khmer',
391
+ ),
392
+ 'kn' => array(
393
+ 'slug' => 'kn',
394
+ 'name' => 'Kannada',
395
+ ),
396
+ 'ko_KR' => array(
397
+ 'slug' => 'ko',
398
+ 'name' => 'Korean',
399
+ ),
400
+ 'kir' => array(
401
+ 'slug' => 'kir',
402
+ 'name' => 'Kyrgyz',
403
+ ),
404
+ 'lb_LU' => array(
405
+ 'slug' => 'lb',
406
+ 'name' => 'Luxembourgish',
407
+ ),
408
+ 'li' => array(
409
+ 'slug' => 'li',
410
+ 'name' => 'Limburgish',
411
+ ),
412
+ 'lin' => array(
413
+ 'slug' => 'lin',
414
+ 'name' => 'Lingala',
415
+ ),
416
+ 'lo' => array(
417
+ 'slug' => 'lo',
418
+ 'name' => 'Lao',
419
+ ),
420
+ 'lt_LT' => array(
421
+ 'slug' => 'lt',
422
+ 'name' => 'Lithuanian',
423
+ ),
424
+ 'lv' => array(
425
+ 'slug' => 'lv',
426
+ 'name' => 'Latvian',
427
+ ),
428
+ 'me_ME' => array(
429
+ 'slug' => 'me',
430
+ 'name' => 'Montenegrin',
431
+ ),
432
+ 'mg_MG' => array(
433
+ 'slug' => 'mg',
434
+ 'name' => 'Malagasy',
435
+ ),
436
+ 'mk_MK' => array(
437
+ 'slug' => 'mk',
438
+ 'name' => 'Macedonian',
439
+ ),
440
+ 'ml_IN' => array(
441
+ 'slug' => 'ml',
442
+ 'name' => 'Malayalam',
443
+ ),
444
+ 'mlt' => array(
445
+ 'slug' => 'mlt',
446
+ 'name' => 'Maltese',
447
+ ),
448
+ 'mn' => array(
449
+ 'slug' => 'mn',
450
+ 'name' => 'Mongolian',
451
+ ),
452
+ 'mr' => array(
453
+ 'slug' => 'mr',
454
+ 'name' => 'Marathi',
455
+ ),
456
+ 'mri' => array(
457
+ 'slug' => 'mri',
458
+ 'name' => 'Maori',
459
+ ),
460
+ 'ms_MY' => array(
461
+ 'slug' => 'ms',
462
+ 'name' => 'Malay',
463
+ ),
464
+ 'my_MM' => array(
465
+ 'slug' => 'mya',
466
+ 'name' => 'Myanmar (Burmese)',
467
+ ),
468
+ 'ne_NP' => array(
469
+ 'slug' => 'ne',
470
+ 'name' => 'Nepali',
471
+ ),
472
+ 'nb_NO' => array(
473
+ 'slug' => 'nb',
474
+ 'name' => 'Norwegian (Bokmål)',
475
+ ),
476
+ 'nl_NL' => array(
477
+ 'slug' => 'nl',
478
+ 'name' => 'Dutch',
479
+ ),
480
+ 'nl_BE' => array(
481
+ 'slug' => 'nl-be',
482
+ 'name' => 'Dutch (Belgium)',
483
+ ),
484
+ 'nn_NO' => array(
485
+ 'slug' => 'nn',
486
+ 'name' => 'Norwegian (Nynorsk)',
487
+ ),
488
+ 'oci' => array(
489
+ 'slug' => 'oci',
490
+ 'name' => 'Occitan',
491
+ ),
492
+ 'ory' => array(
493
+ 'slug' => 'ory',
494
+ 'name' => 'Oriya',
495
+ ),
496
+ 'os' => array(
497
+ 'slug' => 'os',
498
+ 'name' => 'Ossetic',
499
+ ),
500
+ 'pa_IN' => array(
501
+ 'slug' => 'pa',
502
+ 'name' => 'Punjabi',
503
+ ),
504
+ 'pl_PL' => array(
505
+ 'slug' => 'pl',
506
+ 'name' => 'Polish',
507
+ ),
508
+ 'pt_BR' => array(
509
+ 'slug' => 'pt-br',
510
+ 'name' => 'Portuguese (Brazil)',
511
+ ),
512
+ 'pt_PT' => array(
513
+ 'slug' => 'pt',
514
+ 'name' => 'Portuguese (Portugal)',
515
+ ),
516
+ 'ps' => array(
517
+ 'slug' => 'ps',
518
+ 'name' => 'Pashto',
519
+ ),
520
+ 'rhg' => array(
521
+ 'slug' => 'rhg',
522
+ 'name' => 'Rohingya',
523
+ ),
524
+ 'ro_RO' => array(
525
+ 'slug' => 'ro',
526
+ 'name' => 'Romanian',
527
+ ),
528
+ 'roh' => array(
529
+ 'slug' => 'roh',
530
+ 'name' => 'Romansh',
531
+ ),
532
+ 'ru_RU' => array(
533
+ 'slug' => 'ru',
534
+ 'name' => 'Russian',
535
+ ),
536
+ 'rue' => array(
537
+ 'slug' => 'rue',
538
+ 'name' => 'Rusyn',
539
+ ),
540
+ 'rup_MK' => array(
541
+ 'slug' => 'rup',
542
+ 'name' => 'Aromanian',
543
+ ),
544
+ 'sah' => array(
545
+ 'slug' => 'sah',
546
+ 'name' => 'Sakha',
547
+ ),
548
+ 'sa_IN' => array(
549
+ 'slug' => 'sa-in',
550
+ 'name' => 'Sanskrit',
551
+ ),
552
+ 'scn' => array(
553
+ 'slug' => 'scn',
554
+ 'name' => 'Sicilian',
555
+ ),
556
+ 'si_LK' => array(
557
+ 'slug' => 'si',
558
+ 'name' => 'Sinhala',
559
+ ),
560
+ 'sk_SK' => array(
561
+ 'slug' => 'sk',
562
+ 'name' => 'Slovak',
563
+ ),
564
+ 'sl_SI' => array(
565
+ 'slug' => 'sl',
566
+ 'name' => 'Slovenian',
567
+ ),
568
+ 'sna' => array(
569
+ 'slug' => 'sna',
570
+ 'name' => 'Shona',
571
+ ),
572
+ 'snd' => array(
573
+ 'slug' => 'snd',
574
+ 'name' => 'Sindhi',
575
+ ),
576
+ 'so_SO' => array(
577
+ 'slug' => 'so',
578
+ 'name' => 'Somali',
579
+ ),
580
+ 'sq' => array(
581
+ 'slug' => 'sq',
582
+ 'name' => 'Albanian',
583
+ ),
584
+ 'sq_XK' => array(
585
+ 'slug' => 'sq-xk',
586
+ 'name' => 'Shqip (Kosovo)',
587
+ ),
588
+ 'sr_RS' => array(
589
+ 'slug' => 'sr',
590
+ 'name' => 'Serbian',
591
+ ),
592
+ 'srd' => array(
593
+ 'slug' => 'srd',
594
+ 'name' => 'Sardinian',
595
+ ),
596
+ 'su_ID' => array(
597
+ 'slug' => 'su',
598
+ 'name' => 'Sundanese',
599
+ ),
600
+ 'sv_SE' => array(
601
+ 'slug' => 'sv',
602
+ 'name' => 'Swedish',
603
+ ),
604
+ 'sw' => array(
605
+ 'slug' => 'sw',
606
+ 'name' => 'Swahili',
607
+ ),
608
+ 'syr' => array(
609
+ 'slug' => 'syr',
610
+ 'name' => 'Syriac',
611
+ ),
612
+ 'szl' => array(
613
+ 'slug' => 'szl',
614
+ 'name' => 'Silesian',
615
+ ),
616
+ 'ta_IN' => array(
617
+ 'slug' => 'ta',
618
+ 'name' => 'Tamil',
619
+ ),
620
+ 'ta_LK' => array(
621
+ 'slug' => 'ta-lk',
622
+ 'name' => 'Tamil (Sri Lanka)',
623
+ ),
624
+ 'tah' => array(
625
+ 'slug' => 'tah',
626
+ 'name' => 'Tahitian',
627
+ ),
628
+ 'te' => array(
629
+ 'slug' => 'te',
630
+ 'name' => 'Telugu',
631
+ ),
632
+ 'tg' => array(
633
+ 'slug' => 'tg',
634
+ 'name' => 'Tajik',
635
+ ),
636
+ 'th' => array(
637
+ 'slug' => 'th',
638
+ 'name' => 'Thai',
639
+ ),
640
+ 'tir' => array(
641
+ 'slug' => 'tir',
642
+ 'name' => 'Tigrinya',
643
+ ),
644
+ 'tl' => array(
645
+ 'slug' => 'tl',
646
+ 'name' => 'Tagalog',
647
+ ),
648
+ 'tr_TR' => array(
649
+ 'slug' => 'tr',
650
+ 'name' => 'Turkish',
651
+ ),
652
+ 'tt_RU' => array(
653
+ 'slug' => 'tt',
654
+ 'name' => 'Tatar',
655
+ ),
656
+ 'tuk' => array(
657
+ 'slug' => 'tuk',
658
+ 'name' => 'Turkmen',
659
+ ),
660
+ 'twd' => array(
661
+ 'slug' => 'twd',
662
+ 'name' => 'Tweants',
663
+ ),
664
+ 'tzm' => array(
665
+ 'slug' => 'tzm',
666
+ 'name' => 'Tamazight (Central Atlas)',
667
+ ),
668
+ 'ug_CN' => array(
669
+ 'slug' => 'ug',
670
+ 'name' => 'Uighur',
671
+ ),
672
+ 'uk' => array(
673
+ 'slug' => 'uk',
674
+ 'name' => 'Ukrainian',
675
+ ),
676
+ 'ur' => array(
677
+ 'slug' => 'ur',
678
+ 'name' => 'Urdu',
679
+ ),
680
+ 'uz_UZ' => array(
681
+ 'slug' => 'uz',
682
+ 'name' => 'Uzbek',
683
+ ),
684
+ 'vi' => array(
685
+ 'slug' => 'vi',
686
+ 'name' => 'Vietnamese',
687
+ ),
688
+ 'wa' => array(
689
+ 'slug' => 'wa',
690
+ 'name' => 'Walloon',
691
+ ),
692
+ 'xho' => array(
693
+ 'slug' => 'xho',
694
+ 'name' => 'Xhosa',
695
+ ),
696
+ 'xmf' => array(
697
+ 'slug' => 'xmf',
698
+ 'name' => 'Mingrelian',
699
+ ),
700
+ 'yor' => array(
701
+ 'slug' => 'yor',
702
+ 'name' => 'Yoruba',
703
+ ),
704
+ 'zh_CN' => array(
705
+ 'slug' => 'zh-cn',
706
+ 'name' => 'Chinese (China)',
707
+ ),
708
+ 'zh_HK' => array(
709
+ 'slug' => 'zh-hk',
710
+ 'name' => 'Chinese (Hong Kong)',
711
+ ),
712
+ 'zh_TW' => array(
713
+ 'slug' => 'zh-tw',
714
+ 'name' => 'Chinese (Taiwan)',
715
+ ),
716
+ 'de_DE_formal' => array(
717
+ 'slug' => 'de/formal',
718
+ 'name' => 'German (Formal)',
719
+ ),
720
+ 'nl_NL_formal' => array(
721
+ 'slug' => 'nl/formal',
722
+ 'name' => 'Dutch (Formal)',
723
+ ),
724
+ 'de_CH_informal' => array(
725
+ 'slug' => 'de-ch/informal',
726
+ 'name' => 'Chinese (Taiwan)',
727
+ ),
728
+ 'pt_PT_ao90' => array(
729
+ 'slug' => 'pt/ao90',
730
+ 'name' => 'Portuguese (Portugal, AO90)',
731
+ ),
732
+ );
733
+
734
+ /**
735
+ * Check if we should load module for this.
736
+ *
737
+ * @param Product $product Product to check.
738
+ *
739
+ * @return bool Should load ?
740
+ */
741
+ public function can_load( $product ) {
742
+ if ( $this->is_from_partner( $product ) ) {
743
+ return false;
744
+ }
745
+ if ( ! $product->is_wordpress_available() ) {
746
+ return false;
747
+ }
748
+
749
+ $lang = $this->get_user_locale();
750
+
751
+ if ( 'en_US' === $lang ) {
752
+ return false;
753
+ }
754
+
755
+ $languages = $this->get_translations( $product );
756
+
757
+ if ( ! is_array( $languages ) ) {
758
+ return false;
759
+ }
760
+
761
+ if ( ! isset( $languages['translations'] ) ) {
762
+ return false;
763
+ }
764
+
765
+ $languages = $languages['translations'];
766
+
767
+ $available = wp_list_pluck( $languages, 'language' );
768
+
769
+ if ( in_array( $lang, $available ) ) {
770
+ return false;
771
+ }
772
+
773
+ if ( ! isset( self::$locales[ $lang ] ) ) {
774
+ return false;
775
+ }
776
+
777
+ return apply_filters( $product->get_slug() . '_sdk_enable_translate', true );
778
+ }
779
+
780
+ /**
781
+ * Get the user's locale.
782
+ */
783
+ private function get_user_locale() {
784
+ global $wp_version;
785
+ if ( version_compare( $wp_version, '4.7.0', '>=' ) ) {
786
+ return get_user_locale();
787
+ }
788
+ $user = wp_get_current_user();
789
+ if ( $user ) {
790
+ $locale = $user->locale;
791
+ }
792
+
793
+ return $locale ? $locale : get_locale();
794
+ }
795
+
796
+ /**
797
+ * Fetch translations from api.
798
+ *
799
+ * @param Product $product Product to check.
800
+ *
801
+ * @return mixed Translation array.
802
+ */
803
+ private function get_translations( $product ) {
804
+ $cache_key = $product->get_key() . '_all_languages';
805
+ $translations = get_transient( $cache_key );
806
+
807
+ if ( false === $translations ) {
808
+ require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
809
+ $translations = translations_api(
810
+ $product->get_type() . 's',
811
+ array(
812
+ 'slug' => $product->get_slug(),
813
+ 'version' => $product->get_version(),
814
+ )
815
+ );
816
+ set_transient( $cache_key, $translations, WEEK_IN_SECONDS );
817
+ }
818
+
819
+ return $translations;
820
+
821
+ }
822
+
823
+ /**
824
+ * Add notification to queue.
825
+ *
826
+ * @param array $all_notifications Previous notification.
827
+ *
828
+ * @return array All notifications.
829
+ */
830
+ public function add_notification( $all_notifications ) {
831
+
832
+ $lang = $this->get_user_locale();
833
+ $link = $this->get_locale_paths( $lang );
834
+ $language_meta = self::$locales[ $lang ];
835
+
836
+ $heading = apply_filters( $this->product->get_key() . '_feedback_translate_heading', 'Improve {product}' );
837
+ $heading = str_replace(
838
+ array( '{product}' ),
839
+ $this->product->get_friendly_name(),
840
+ $heading
841
+ );
842
+ $message = apply_filters(
843
+ $this->product->get_key() . '_feedback_translation',
844
+ 'Translating <b>{product}</b> into as many languages as possible is a huge project. We still need help with a lot of them, so if you are good at translating into <b>{language}</b>, it would be greatly appreciated.
845
+ The process is easy, and you can join by following the link below!'
846
+ );
847
+
848
+ $message = str_replace(
849
+ [ '{product}', '{language}' ],
850
+ [
851
+ $this->product->get_friendly_name(),
852
+ $language_meta['name'],
853
+ ],
854
+ $message
855
+ );
856
+
857
+ $button_submit = apply_filters( $this->product->get_key() . '_feedback_translate_button_do', 'Ok, I will gladly help.' );
858
+ $button_cancel = apply_filters( $this->product->get_key() . '_feedback_translate_button_cancel', 'No, thanks.' );
859
+
860
+ $all_notifications[] = [
861
+ 'id' => $this->product->get_key() . '_translate_flag',
862
+ 'heading' => $heading,
863
+ 'message' => $message,
864
+ 'ctas' => [
865
+ 'confirm' => [
866
+ 'link' => $link,
867
+ 'text' => $button_submit,
868
+ ],
869
+ 'cancel' => [
870
+ 'link' => '#',
871
+ 'text' => $button_cancel,
872
+ ],
873
+ ],
874
+ ];
875
+
876
+ return $all_notifications;
877
+ }
878
+
879
+ /**
880
+ * Return the locale path.
881
+ *
882
+ * @param string $locale Locale code.
883
+ *
884
+ * @return string Locale path.
885
+ */
886
+ private function get_locale_paths( $locale ) {
887
+ if ( empty( $locale ) ) {
888
+ return '';
889
+ }
890
+
891
+ $slug = isset( self::$locales[ $locale ] ) ? self::$locales[ $locale ]['slug'] : '';
892
+ if ( empty( $slug ) ) {
893
+ return '';
894
+ }
895
+ if ( strpos( $slug, '/' ) === false ) {
896
+ $slug .= '/default';
897
+ }
898
+ $url = 'https://translate.wordpress.org/projects/wp-' . $this->product->get_type() . 's/' . $this->product->get_slug() . '/' . ( $this->product->get_type() === 'plugin' ? 'dev/' : '' ) . $slug . '?filters%5Bstatus%5D=untranslated&sort%5Bby%5D=random';
899
+
900
+ return $url;
901
+ }
902
+
903
+ /**
904
+ * Load module logic.
905
+ *
906
+ * @param Product $product Product to load.
907
+ *
908
+ * @return Translate Module instance.
909
+ */
910
+ public function load( $product ) {
911
+
912
+ $this->product = $product;
913
+
914
+ add_filter( 'themeisle_sdk_registered_notifications', [ $this, 'add_notification' ] );
915
+
916
+ return $this;
917
+ }
918
+ }
vendor/codeinwp/themeisle-sdk/src/Modules/Uninstall_feedback.php ADDED
@@ -0,0 +1,728 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The deactivate feedback model class for ThemeIsle SDK
4
+ *
5
+ * @package ThemeIsleSDK
6
+ * @subpackage Feedback
7
+ * @copyright Copyright (c) 2017, Marius Cristea
8
+ * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
+ * @since 1.0.0
10
+ */
11
+
12
+ namespace ThemeisleSDK\Modules;
13
+
14
+ use ThemeisleSDK\Common\Abstract_Module;
15
+ use ThemeisleSDK\Product;
16
+
17
+ // Exit if accessed directly.
18
+ if ( ! defined( 'ABSPATH' ) ) {
19
+ exit;
20
+ }
21
+
22
+ /**
23
+ * Uninstall feedback module for ThemeIsle SDK.
24
+ */
25
+ class Uninstall_Feedback extends Abstract_Module {
26
+ /**
27
+ * How many seconds before the deactivation window is triggered for themes?
28
+ *
29
+ * @var int Number of days.
30
+ */
31
+ const AUTO_TRIGGER_DEACTIVATE_WINDOW_SECONDS = 3;
32
+ /**
33
+ * How many days before the deactivation window pops up again for the theme?
34
+ *
35
+ * @var int Number of days.
36
+ */
37
+ const PAUSE_DEACTIVATE_WINDOW_DAYS = 100;
38
+ /**
39
+ * Where to send the data.
40
+ *
41
+ * @var string Endpoint url.
42
+ */
43
+ const FEEDBACK_ENDPOINT = 'http://feedback.themeisle.com/wordpress/wp-json/__pirate_feedback_/v1/feedback';
44
+
45
+ /**
46
+ * Default options for plugins.
47
+ *
48
+ * @var array $options_plugin The main options list for plugins.
49
+ */
50
+ private $options_plugin = array(
51
+ 'I found a better plugin' => array(
52
+ 'id' => 3,
53
+ 'type' => 'text',
54
+ 'placeholder' => 'What\'s the plugin\'s name?',
55
+ ),
56
+ 'I could not get the plugin to work' => array(
57
+ 'id' => 4,
58
+ ),
59
+ 'I no longer need the plugin' => array(
60
+ 'id' => 5,
61
+ 'type' => 'textarea',
62
+ 'placeholder' => 'If you could improve one thing about our product, what would it be?',
63
+ ),
64
+ 'It\'s a temporary deactivation. I\'m just debugging an issue.' => array(
65
+ 'id' => 6,
66
+ ),
67
+ );
68
+ /**
69
+ * Default options for theme.
70
+ *
71
+ * @var array $options_theme The main options list for themes.
72
+ */
73
+ private $options_theme = array(
74
+ 'I don\'t know how to make it look like demo' => array(
75
+ 'id' => 7,
76
+ ),
77
+ 'It lacks options' => array(
78
+ 'id' => 8,
79
+ ),
80
+ 'Is not working with a plugin that I need' => array(
81
+ 'id' => 9,
82
+ 'type' => 'text',
83
+ 'placeholder' => 'What is the name of the plugin',
84
+ ),
85
+ 'I want to try a new design, I don\'t like {theme} style' => array(
86
+ 'id' => 10,
87
+ ),
88
+ );
89
+ /**
90
+ * Default other option.
91
+ *
92
+ * @var array $other The other option
93
+ */
94
+ private $other = array(
95
+ 'Other' => array(
96
+ 'id' => 999,
97
+ 'type' => 'textarea',
98
+ 'placeholder' => 'cmon cmon tell us',
99
+ ),
100
+ );
101
+ /**
102
+ * Default heading for plugin.
103
+ *
104
+ * @var string $heading_plugin The heading of the modal
105
+ */
106
+ private $heading_plugin = 'Quick Feedback <span>Because we care about our clients, please leave us feedback.</span>';
107
+ /**
108
+ * Default heading for theme.
109
+ *
110
+ * @var string $heading_theme The heading of the modal
111
+ */
112
+ private $heading_theme = 'Looking to change {theme}? <span> What does not work for you?</span>';
113
+ /**
114
+ * Default submit button action text.
115
+ *
116
+ * @var string $button_submit The text of the deactivate button
117
+ */
118
+ private $button_submit = 'Submit &amp; Deactivate';
119
+ /**
120
+ * Default cancel button.
121
+ *
122
+ * @var string $button_cancel The text of the cancel button
123
+ */
124
+ private $button_cancel = 'Skip &amp; Deactivate';
125
+
126
+ /**
127
+ * Loads the additional resources
128
+ */
129
+ function load_resources() {
130
+ add_thickbox();
131
+
132
+ $id = $this->product->get_key() . '_deactivate';
133
+
134
+ $this->add_css( $this->product->get_type(), $this->product->get_key() );
135
+ $this->add_js( $this->product->get_type(), $this->product->get_key(), '#TB_inline?' . apply_filters( $this->product->get_key() . '_feedback_deactivate_attributes', 'width=600&height=550' ) . '&inlineId=' . $id );
136
+
137
+ echo '<div id="' . $id . '" style="display:none;" class="themeisle-deactivate-box">' . $this->get_html( $this->product->get_type(), $this->product->get_key() ) . '</div>';
138
+ }
139
+
140
+ /**
141
+ * Loads the css
142
+ *
143
+ * @param string $type The type of product.
144
+ * @param string $key The product key.
145
+ */
146
+ function add_css( $type, $key ) {
147
+ $key = esc_attr( $key );
148
+ $suffix = Product::THEME_TYPE === $type ? 'theme-install-php' : 'plugins-php';
149
+ $icon = esc_attr( apply_filters( $this->product->get_slug() . '_uninstall_feedback_icon', '' ) );
150
+ if ( empty( $icon ) ) {
151
+ $icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQyIDc5LjE2MDkyNCwgMjAxNy8wNy8xMy0wMTowNjozOSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpDNkVDM0M4RkYxMzMxMUU3OEMyMkQ0NTIxRTVEQ0ZBRiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpDNkVDM0M5MEYxMzMxMUU3OEMyMkQ0NTIxRTVEQ0ZBRiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkM2RUMzQzhERjEzMzExRTc4QzIyRDQ1MjFFNURDRkFGIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkM2RUMzQzhFRjEzMzExRTc4QzIyRDQ1MjFFNURDRkFGIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+KBNOswAAFtFJREFUeNrkWwmUXVWV3W/8Y81zkVAhgUwQg00IAYIRGcRuERDSKqALtVEbxRYcGzWIuhatKCYuUXQtERRtFAccQCDtckCZwpRISEIlIXMqlaGGP///ht7n3vd//YRUUkljN718a53U+++//97d95yzz3BvjDAM8fd02May4YndaZhoDErYeu/laCyN8rN16PuDAPA83mcAjjOxd8jcVypydhrlKspCSidlhPIk5T8p9/+PAP8fTrZJaaQ0UFxKiVKk/CvlU5Rk3b0C+gTKFZRvUa75/wJ4EuVcyimU2RGQdkqCkoOBDExjBoJx3Uwm5OlXt4bFrIPgTXSJK+DY59PEO8a5s0mPiEPyfUrwMieh3ED57qsTsJBhoXAOmps+gd6u85AvGtgxQEOmJcfj+vvxDsvS/hzsB5pkgA9QplJuoux59QD2g1ZUvCXhVe+4pnjxJc5gdx8SxTza1jwDY9ntMDdsBlLJQ4O2CTogRs+vBzydFmLCMm98NWl4OvL5O3Hd+09/9p8/iK/9GOjfRHZKpnHZWy7AlbfPRuK918DYTm3H3PHZWrQbVnHKtUBbh201EvSFvHLX0TLlK3ksRLG4HPPmnL7+0vfiaz8EOkwP+aduwPKbZ+DadyzBnVuPBa4nEQf+/hqW0zKvZcqkJoYmi0DTMXo2+cyltiu8oSi+HQrR3UG5+n9Fw6bFmRYJOVehUf/VAsrPacodOPtM3LcmjmPSwMz4cvzXAJEXt6C89gv49rJTcMk3zkdPL8e9e0iTVNHTTziuGTi9D5jF73oaNVg5RnLAjiywagfwp01ybiJufQOOuYMTdf9hg3s5H83oEQIWhYwOMGySf2KNFTjJchW0EMmPKB1KMx2d2LQFGCKtvPD0A1izbitnitcZbrat+T12Fi8i4C5g6y49kDkk7re/RoNtTmo+DiKmFlPupaZPbAPOp3VceSLwYD/fttrFUPlbSNsL+YgtB48QjGKmje+ceBlKlqsATBywIe82sG9TC5OhONqP2wOnucB0wRY13Cn6qQWPYgEtVNZvf8/J3RhnZAprrtjY81qkxHX3jGrtvn8esHgm0wzek6Vf76Y2Q19ncibBmymeM1Mz+H1IS2ji9XfPAuZzAm5+ajLWDn8JKfvymgprQczHyvbpGEh14f2nX89sLyVsehQmbQewKj5GBxtQzMXQ3DvyWcvxz9rPvFf9Fed+ELjnl8Q07To07FyJ3MATCDouxXmL344pO55nmsFs8avMHE8jmH1/puzmkEsarBo7n2dweCbn06YFxJizWJzFErVW5Kwez8m45VTgM08txqqhu5C0HxyDHNIIDSxedCP6Ozk5Bb6rNHzkpCWQTJqlwQcWcgkUh+NXG2b4sf1uSjDGPvQITh98Bh/5F35s6UXTovvR+eaVuPD6O/DRt8bg/uL7CK+nj75mI7DtD0CefhkUopfYkUZtDdyn75Y2kMz+wvtW6s8yMRmCaCLwG2Za6E5ch4xnoMLPZUo2g3uPPQfr25iNFob3U76BpUMTVK2JBLOmP37hU5hE5yzBvbZz2p6lyXYSiH/AvBVLCI/pRvnmG7Fy8nysYtgVEz+jIYPuu7+NSvIe2OfZMIvh4YuQevIRkxYtx6fxd662hkZOzu9257Fk/esZrlaI2arY+PY70d8yhRNZOWKWPobSS4fPFBx37YaeHkwdGrgCqfDWZGveRHAQI6GWje07EXvfRzB/0XzMn0UfzdBnH/oLwrOogTcfS7BbtSaPxL7kfp+aLayliR+nJytDEz8jnsRpDW/F45kVFTfE0rmXo7+VPOqXjygOn0f5qXgk5QnKc9Ty50MVfozbGjqyVFFwIFWM0XkioXPiB8hct9wGfI15Qmo3gnfSb3MZVW4e1SGmHtL8K1u1G1QYciyCflPqPFRK9ouN0/CJM6+LNBtOKA6Lqy6hfJri1H5jWbFUIX9D75597yM/NSWaiwfG4ZeDlpw4ldLvjXO23zOPeYMPw9/HqY5pRj+qg8/1yebYp0ktzwfNDGdgvnvcKnd6P7yKDmcTzLQE7Oc4SMflty1xA21JEyazng8v/4110uDmrrAphBXzdK47kUNYdS7j94ITEI7uhOkEh56sCefsGQ1cEotkIV3+ePKUm856txCXlKCXqLzgMIDfqEowaqQ1YaCv0URrjJyciGHu9k24+k8PsiB1EW8q6rg40S6GzPbZ3bSnOK1xAJZtHrpwmHDM4HODnDbtcAiPetNnb8x1fBFmebnK+oBHKVeOZ9JMBPEfHKDbTrBdKZMZX4gS3TDvmHjvA79BayGDYSONWKo8ce36BNZGgCd3EmyRRDt8BMw8kaNquhXmLC3vrHhOj2GXqp54POUHUVL0hQM1fBXvOjnlGOgm2Arjrcdn5VwHJ2zZggueXYEc4tSOD8vxxupW4zDAJcuaxBDSmUaQzzKS5HXV87cowWFMgWPElBtSHLPGW1I/L64HzGwB75KTjqShrI3JlBprgbnoPz3xONqZrVRoEKYVQrGzmJSkhgJ6PABGBLiPBBW3SJySXHhjJd8rfhiK/CVtF8X1pk3EdP4iL/x36ZOZtUonxClJ3iQ3lqldscQK70tmczj/mRUoE6z8TqolBboKWDqSVeDjabvZ0n7MxCH0A/ytjqyf5msspTCxTpvDEdCmHtZrKYuqgC8VbTe5ot1QZWjyg6ztYNbmzZi+Y5tkViqlNKhdQ4BVw45Dc3Uj0CIHalvuFfsJyuqrMLReAcI6+DGCHsX+AccZRPSR4JCa40bVtF8no4tJ4a7GxXELWLnRDyUBt7DghReQCop8gHFAmhdGPWd7f007ddqu4hLt+gX6vuTJCX4MXnHvlVRzS2lmrfgQxYVROtDg1sb+D6Zql4Y4PsY6ltasAQfanA3Px4xtWyIXqFZd9EXF0KFuw4h2rQioAu3UmbmpQUtiIKHDFKtoQTlb0t+9YkeFFtmNFUNMJw0ydGjUwErH16VNR6/rkT9zJCSJc8tNnjLnkD5rIp3N44TB7UzHx8KI75mcxGiw5XIENgLp2AdoPLq2Tx6aV1qOt01CcUieUTk8w0848SpjXeFUPDvUQmCBAloFK2IyZzC1jlIy8mnqN2bVlDWPlqnVhlwO7SOj/DymjYCARdRgBbA8yHXHfLhewwJW/GSbaJkaDrKwk0m4bXMwujkLv1JSWaJ6vIyoKvJMSWwM6XuVyXWM374kO8FBJknYKYn1T07hKzxyjPbfsE7qWoEyIsxU8SliNvFdZdJ8sctEIVEq1/xXDCVkdVQpOHAk+ZDYVSCQpubIj0w9SDVoQycnTGIwyAcOcBr7mAp6MSS6ephenonsrrX06wzcRJSLmJoMaYD0FpvjINsZbeQhxvAKx5HfiFR7hWltXV9bUtyB45G6YzPMS0scq1XTcFjT8Jiz26r0k4nlVS9ATUJ+jpVKcFgD1/uwvKY4GkeyI6fnbZQgWlt0fSqrDPJ039DgxfSFmkd5/Uk+9DiadSWrfhZjgRxrWohyIY+glFcmboQmgcdYVzTDdJs4KQ0E18RrBGi5KA3vRqb/e2jsLfKxjp5ctxW4mwnRmgHFlZ7y33BMwxHVBDqSlgVwuxF94YU6u/KV8UtzkjE3Yrux0B4qwGHF4kB4U5GmNkoQba21RoGWqI8soMVzHufnN1CaWc/6jh4N73HTSdJoS9TlqIoVdTwkhPH54u+Bg1hbL7zhhfByD8BtciS7AJa3oXD3Ls73ND7Oh7TpqiYtMELolkBkEFmzuqajTDnyYb/6i4NkRAKYZSdBM5pZUWjas0f/KBar8+U6ApNguJevepD3S1oq5WFYjjqT9GOPbiEpZ00KWgLpcVV0p0OE1uE0dHGiCLSBz3osicqyvchk5V1mzb9rJh2pStrdUSDca0buq8ZbZWgvMt4SycejnRgHKYCkiad8VF5C08fOnWPsXGXsGmh+bqTJ/5Gv+4skeOL/uxWJVTMwMuH+f2vnVcCVKMaWYIiKfsf33pLF8EuuKtsrDv1eIkagDTqo8+OSF1Y1vM6MNF5LOJT/Rg5QJPuWGGfNAzoH8rk4EkdxOKGb8uI8+6i1wUHdxKuxdB14N5J7ONCnKEkBRMuo7NXaRtSDluEoYNXzYIxn42KFW2H8mr/9RoD8YAK5bJqG7yGXSMC3rJqGa2YtU1RbnsJacZS9QlyS45vRzETxB3kOcJQAmlnlAC8v6Ya2NaG7saTSTbUSsX2H1mZ3J99i6BaPYYyJpO5Fyvd8zdxn82Ux+nSZBOinOIBG3cEQkgqicCXEZEvSQlm5De6d62CtcMmPDvYNtCh05GXsaGmlm/Pd5aI230hpokBZoeF8+VXA2yX58ALNxYrMOMNhpYJhFv4bWzswbe+gWp4/0JdL+RiGCbplCrVbbeYx91Ya6u2l9jy9hUHFV1NPgISpMuUXPF8VgZ7O8zSBm6MRUdmatITtZa1pE8H+gdHg90xP88yVYw72bGiHR841VdAMsbp7kn5HqJspSsOGNueK1uJW6cvZ0Yr6BWOa9RnfPSU+zbm/vRMX9P91nGIsxMiuBrXkku6kFXhV0FsYn8mufX3UakL7uBFpu8ri0vXYxGvfpbRR+qQ/ymE2+nqhf4TnWzlhLxLwFko+VGwfsHzd3d+OYjamwIp2C2T21cccq0mwluqHKsUs+DV3FJy7BfCDlE+q7ocCW1Ga0H+BZ6YcC+8xs6b9AwHLRO3a1KxCTLo9r8OQaGcX/ZmlJSZz5pv5vR1qbVc3usgT04a+f4R/VxDg414UNH3USjaJ55KvM8Hw6Q4717eiRP5wIt5leoLdqUb0d3VANe/qxik/r/PfX1cbAOTN8F7RqMkSzvA9DVYYkgnBo32TsT3Vwhf44y4/BjTnLRtbMTSQ1pwvaaGQlmRh617UMjwytvovImvDVUJL8LzBlrKGk0CRxSdh9WaGuTSvxwzkMzG8tJYxl2DdCFKoSj0Pz07qow83wygXUQ1Gmp1R5SQx598qwAZ1bwTBZw2/sgu+NmVEJm0z192VTuGxqceypK1gvCpW6ksh602bmrCV4rGiUhqVBN3k+fAwTZOgX1jDV/PdmYzWpLCqG9XTMgFy7lRragkbJKB8EQMbXWxY08yCy1Wldf3CiVS/D594orIaQ1mo7pULCZfHNsfcSxnU+7Sk7RJiA5/+Sf7gzv1MWkyLL//ZSSfirc8/zzwjPKAuHnt5Ujieyf3OXUkMZ1z09mTR0soUUIBX15IlKxOti7nXJyhG3Sq/76kmurx+eNjFjp2NJPE4Gvn8GIz9Jl2UsLmhDQ/PnKUX2eQdQri81w9q95JR8c0xi4wiMjV9l+GX51C7HzUi4hJN28UAj0yZhGe6e3Dqzu3Iwh23G5siMGmrDBdsrNnYgPSuBDoIurWpzCTMZ4IU+a56pRexeFhXaxsoknn3jiSxZyiGQs5BOrTQRgDmAWCrgH8697UYbOZ00BoNy9HRgn4fmrWGrCwobKgDnNAxTmvu0wQ7jdq9WJk1NW3zb9G1cMcpc3Dab7brimmcJpzyKYLu5PAkaR3OGViXt2EPkNASHhqZbCQI3LGDagRRIMuUfNFGJm+xxONAPQspPqNLadXcr8yrHi45ZWeiEXedOo+2WyJ1cGRq+cZSZaTkBtT0V3jh9v04x3SeQpibxxtGRKPSLriaoNtpWgurmnaLJfxqxhRc8WwfXrd9G0Zgjdt3rA6skeWdLEEXGY4ynLgcZ2AoK9SnSa32+9BQnmhT4jxvJcAUn+9EXYvxmkEpavfW+QuxpZ2ESu2GaoVfp6msukbD0FrCRy57Wa8g9p5f0s+eRzi0AIYnhWmZEc94yPTKi0hkvaJpiw5VJE+v7whx0Ysb4Pr2YZeFor6m0riYZRMhNfJvo3wmoJQ6t9DMJKOV0hY6PLcI+uDmW//cBpTxdFcvPn7hBZxAQ2l3LKMz/0jbvoqgfnawBTvLeRvhpVfDSD3Hp3GWStKkdzJGJfaQEeTONYJyl1FxOePD2HT2UnrALrxx5SSUEE60vVYDL3bhEk6cwJIEFuNfV5X7Ri3OH+6pYsoVMvn7Lv5HvNTWBlfiOlSltJl+chOB/htls+ztODjgxbKKx9fGNsFs+gPM9ntZkrK+tEdGjHz3b81ifD7cHZPDObfAbFmJJ2ZmMXVLA07d2oa8mt8j7i++TCa+ZhgyGnhYsuhM/Oqk6YiXmDeY5mBoWt8kwA9QHmYY9BXYcQDbtWEECf3XGoLR8X2QMSgztgT5rvuQ2ngG0ttglRLw3AAfvfZpdIzE8PrVnRhGpa67ZEZtfh0fxwCadZVW9bpRIz8j+nSo60Jdab7rK/Pm4tvzZiNeLA7CjP2ARHUbtfvShNcmEj9JtEWl0J66TZ6S2b4OZmkx06+FLDSVFdRWP8m07QT8nS/NxzmruzEkoGMBUhcW4E4vo9zvIv/LJIKyLLP6SF2Uh9PnofRXF7n7Eyp0WC28fnEOdpeP4tMMQcvjasKc7gqSb8nDag5QfDSO/J8lswoU2K/PnYUbz16wwTGdH5pm7K7QcjZSFGGFJsWOxIrxL8W0Dgp4drSzzVHNSr3Fty3a0jv+ki9BNzHkfHXpPFzy5CTElg0geWlG0yqDcf7HDdjzuVZ0LtuN+Hl5XWyzasrc3ozh25rQ+d1diJ1WrDWbRm5uRebeNLp/NAB7dinaZ2lg9DOt2Ht3E76+YMajSxfM/QFJ7Sem6exToBTYIwcsfxdR7o7ATsw0JFelVg1iuXXzdFy7uEHFT5BtmQUwQlRQejyO+MKC6lQq77HKCAs+ys/FEDtLth/FdP/KLiEYZhnX7yB2ulyXriSvx3i+r1z6ycfmfehtfed/H+1WOc2iIqiCOgrAJC21sYRFLO6LAM+e6Hq0RQ2ULQ99cwy8OdHNCyIs4o0043ce9hQBm6Tt9PB6g4qehpGFPZlAPH52u/X1MAnDzcCeRAMrs7Jy5DoLkYATksoWEyflbyqY7s7n9/WgUIrBdkNNSgKoKkbd+SFIq/6KOP5llPOjnaq7J7QIz/LOzUlY4ODcTmqL3uB06hXYkpR3BGx31V3nfaVQA3Wi+90u1ZVU99ukEIelnt2uvy+45tSpQ6nvXPgAnrrsDlwxaxUrRwsFz8HRHPYBw1+ktv8CA9FC7oSOuBnuYaLcBrvDqHU7jfU6T5LNKwJA9aaCqKMRRDvsOnV3RJp0og11Pa0nSMrRIK9VUtLLE3M6d+Dui36IM57ehqWr3oD+zGRYTFmtowQcQv9HC9Hy6ye42WCfZeDz81NSxFpfVqZbXVU0qsCk5OvV8xdGSyWmdD9oAW5v1I2sjO3ZkL2V1fv90aoidJzypca2cc3Jf8a7pq/CHS8uwJfXnIvthW7FsbI74Uj3Sz9GOScC/fNqDXmQTRXS87mlFARnzYwnll3U1JZFmR7g7dba9Bjh1F4Ot4IKjSUY0vslKzs0CLle3qZ70GLS5c16c4rBqqL8kloN1PsqX9K9aea7+42gHEfaKeLDJz+MNRd/HjedfB+unPYnloQWg4F52Dh8qO8lHk+Jtv+INWSjpp+MarjAYvvnfVNxSXOrlJWP8pY07BaClRLUl//g8Fma7FJqmfVAU3Q9WMfrzFF9ZkdxQ5GTtGoN40lev4cfblVmbST0xBnmI/xHdhcVDo6A8++UlH0+t28qrlxxPVbnZnBOjYOy9OG2Hm6OZPz9/q6EHNG4eTlHuIQaPY7mzN+Yn1N9JMMq0mQ/icquHmpwLa/LXotHVPEalD5EP23l9VUc+fUc9UoOKQU/9x7OLSndelJfHwesckRqtKyVdnLbOjQ4hUPuATP+3v4r3n8LMAAsR90w+kkNLQAAAABJRU5ErkJggg==';
152
+ }
153
+ ?>
154
+ <style type="text/css" id="<?php echo $key; ?>ti-deactivate-css">
155
+ input[name="ti-deactivate-option"] ~ div {
156
+ display: none;
157
+ }
158
+
159
+ input[name="ti-deactivate-option"]:checked ~ div {
160
+ display: block;
161
+ }
162
+
163
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container #TB_window.thickbox-loading:before {
164
+ background: none !important;
165
+ }
166
+
167
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container #TB_title {
168
+ background: url('<?php echo $icon; ?>') 40px 30px no-repeat;
169
+ border: none;
170
+ box-sizing: border-box;
171
+ color: #373e40;
172
+ font-size: 24px;
173
+ font-weight: 700;
174
+ height: 90px;
175
+ padding: 40px 40px 0 120px;
176
+ text-transform: uppercase;
177
+ width: 100%;
178
+ }
179
+
180
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container #<?php echo $key; ?>-info-disclosure-content ul i {
181
+ padding-left: 5px;
182
+ margin: 0 1px;
183
+ }
184
+
185
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container #<?php echo $key; ?>-info-disclosure-content ul strong {
186
+ width: 125px;
187
+ display: block;
188
+ margin: 0;
189
+ float: left;
190
+ }
191
+
192
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container #<?php echo $key; ?>-info-disclosure-content ul {
193
+ margin-left: 39px;
194
+ margin-top: 2px;
195
+ padding-top: 0px;
196
+ }
197
+
198
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container #<?php echo $key; ?>-info-disclosure-content p {
199
+ font-style: italic;
200
+ margin-bottom: 0px;
201
+ }
202
+
203
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container #<?php echo $key; ?>-info-disclosure-content {
204
+ display: none;
205
+ }
206
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container.<?php echo $key; ?>-container-disc-open #<?php echo $key; ?>-info-disclosure-content {
207
+ display: block;
208
+ position:absolute;
209
+ bottom: 100px;
210
+ }
211
+
212
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container.<?php echo $key; ?>-container-disc-open #<?php echo $key; ?>-info-disclosure {
213
+ top: -130px;
214
+ }
215
+
216
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container.<?php echo $key; ?>-container-disc-open {
217
+ height: 590px !important;
218
+ }
219
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container #<?php echo $key; ?>-info-disclosure {
220
+ position: absolute;
221
+ top: -50px;
222
+ font-size: 13px;
223
+ color: #8d9192;
224
+ font-weight: 400;
225
+ right: 40px;
226
+ }
227
+
228
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container div.actions {
229
+ box-sizing: border-box;
230
+ padding: 30px 40px;
231
+ background-color: #eaeaea;
232
+ }
233
+
234
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button {
235
+ background: #ec5d60;
236
+ border: none;
237
+ box-shadow: none;
238
+ color: #ffffff;
239
+ font-size: 15px;
240
+ font-weight: 700;
241
+ height: auto;
242
+ line-height: 20px;
243
+ padding: 10px 15px;
244
+ text-transform: uppercase;
245
+ -webkit-transition: 0.3s ease;
246
+ -moz-transition: 0.3s ease;
247
+ -ms-transition: 0.3s ease;
248
+ -o-transition: 0.3s ease;
249
+ transition: 0.3s ease;
250
+ }
251
+
252
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button.button-primary {
253
+ background: transparent;
254
+ box-shadow: none;
255
+ color: #8d9192;
256
+ font-weight: 400;
257
+ float: right;
258
+ line-height: 40px;
259
+ padding: 0;
260
+ text-decoration: underline;
261
+ text-shadow: none;
262
+ text-transform: none;
263
+ }
264
+
265
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button:hover {
266
+ background: #e83f42;
267
+ }
268
+
269
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button.button-primary:hover {
270
+ background: transparent;
271
+ }
272
+
273
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button:focus {
274
+ box-shadow: none;
275
+ outline: none;
276
+ }
277
+
278
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button:active {
279
+ box-shadow: none;
280
+ transform: translateY(0);
281
+ }
282
+
283
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button:disabled {
284
+ cursor: not-allowed;
285
+ }
286
+
287
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button.button-primary:hover {
288
+ text-decoration: none;
289
+ }
290
+
291
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container div.revive_network-container {
292
+ background-color: #ffffff;
293
+ }
294
+
295
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list {
296
+ margin: 0;
297
+ }
298
+
299
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list li {
300
+ color: #373e40;
301
+ font-size: 13px;
302
+ margin-bottom: 5px;
303
+ }
304
+
305
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list li label {
306
+ margin-left: 10px;
307
+ line-height: 28px;
308
+ font-size: 15px;
309
+ }
310
+
311
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list input[type=radio] {
312
+ margin-top: 1px;
313
+ }
314
+
315
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container #TB_ajaxContent {
316
+ box-sizing: border-box;
317
+ height: auto !important;
318
+ padding: 20px 40px;
319
+ width: 100% !important;
320
+ }
321
+
322
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container li div textarea {
323
+ padding: 10px 15px;
324
+ width: 100%;
325
+ }
326
+
327
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list li div {
328
+ margin: 10px 30px;
329
+ }
330
+
331
+ .<?php echo $key; ?>-container #TB_title #TB_ajaxWindowTitle {
332
+ box-sizing: border-box;
333
+ display: block;
334
+ float: none;
335
+ font-weight: 700;
336
+ line-height: 1;
337
+ padding: 0;
338
+ text-align: left;
339
+ width: 100%;
340
+ }
341
+
342
+ .<?php echo $key; ?>-container #TB_title #TB_ajaxWindowTitle span {
343
+ color: #8d9192;
344
+ display: block;
345
+ font-size: 15px;
346
+ font-weight: 400;
347
+ margin-top: 5px;
348
+ text-transform: none;
349
+ }
350
+
351
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container .actions {
352
+ width: 100%;
353
+ display: block;
354
+ position: absolute;
355
+ left: 0;
356
+ bottom: 0;
357
+ }
358
+
359
+ .theme-install-php .<?php echo $key; ?>-container #TB_closeWindowButton .tb-close-icon:before {
360
+ font-size: 32px;
361
+ }
362
+
363
+ .<?php echo $key; ?>-container #TB_closeWindowButton .tb-close-icon {
364
+ color: #eee;
365
+ }
366
+
367
+ .<?php echo $key; ?>-container #TB_closeWindowButton {
368
+ left: auto;
369
+ right: -5px;
370
+ top: -35px;
371
+ color: #eee;
372
+ }
373
+
374
+ .<?php echo $key; ?>-container #TB_closeWindowButton .tb-close-icon {
375
+ text-align: right;
376
+ line-height: 25px;
377
+ width: 25px;
378
+ height: 25px;
379
+ }
380
+
381
+ .<?php echo $key; ?>-container #TB_closeWindowButton:focus .tb-close-icon {
382
+ box-shadow: none;
383
+ outline: none;
384
+ }
385
+
386
+ .<?php echo $key; ?>-container #TB_closeWindowButton .tb-close-icon:before {
387
+ font: normal 25px dashicons;
388
+ }
389
+
390
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container {
391
+ margin: auto !important;
392
+ height: 500px !important;
393
+ top: 0 !important;
394
+ left: 0 !important;
395
+ bottom: 0 !important;
396
+ right: 0 !important;
397
+ width: 600px !important;
398
+ }
399
+ </style>
400
+ <?php
401
+ do_action( $this->product->get_key() . '_uninstall_feedback_after_css' );
402
+ }
403
+
404
+ /**
405
+ * Loads the js.
406
+ *
407
+ * @param string $type The type of product.
408
+ * @param string $key The product key.
409
+ * @param string $src The url that will hijack the deactivate button url.
410
+ */
411
+ function add_js( $type, $key, $src ) {
412
+ $heading = Product::PLUGIN_TYPE === $type ? $this->heading_plugin : str_replace( '{theme}', $this->product->get_name(), $this->heading_theme );
413
+ $key = esc_attr( $key );
414
+ $heading = apply_filters( $this->product->get_key() . '_feedback_deactivate_heading', $heading );
415
+ ?>
416
+ <script type="text/javascript" id="ti-deactivate-js">
417
+ (function ($) {
418
+ $(document).ready(function () {
419
+ var auto_trigger = false;
420
+ var target_element = 'tr[data-plugin^="<?php echo $this->product->get_slug(); ?>/"] span.deactivate a';
421
+ <?php
422
+ if ( 'theme' === $type ) {
423
+ ?>
424
+ auto_trigger = true;
425
+ if ($('a.ti-auto-anchor').length == 0) {
426
+ $('body').append($('<a class="ti-auto-anchor" href=""></a>'));
427
+ }
428
+ target_element = 'a.ti-auto-anchor';
429
+ <?php
430
+ }
431
+ ?>
432
+
433
+ if (auto_trigger) {
434
+ setTimeout(function () {
435
+ $('a.ti-auto-anchor').trigger('click');
436
+ }, <?php echo self::AUTO_TRIGGER_DEACTIVATE_WINDOW_SECONDS * 1000; ?> );
437
+ }
438
+ $(document).on('thickbox:removed', function () {
439
+ $.post(ajaxurl, {
440
+ 'action': '<?php echo $key . '_uninstall_feedback'; ?>',
441
+ 'nonce': '<?php echo wp_create_nonce( (string) __CLASS__ ); ?>',
442
+ 'type': '<?php echo $type; ?>',
443
+ 'key': '<?php echo $key; ?>'
444
+ });
445
+ });
446
+ var href = $(target_element).attr('href');
447
+ $('#<?php echo $key; ?>ti-deactivate-no').attr('data-ti-action', href).on('click', function (e) {
448
+ e.preventDefault();
449
+ e.stopPropagation();
450
+
451
+ $('body').unbind('thickbox:removed');
452
+ tb_remove();
453
+ var redirect = $(this).attr('data-ti-action');
454
+ if (redirect !== '') {
455
+ location.href = redirect;
456
+ }
457
+ });
458
+
459
+ $('#<?php echo $key; ?> ul.ti-list label, #<?php echo $key; ?> ul.ti-list input[name="ti-deactivate-option"]').on('click', function (e) {
460
+ $('#<?php echo $key; ?>ti-deactivate-yes').val($('#<?php echo $key; ?>ti-deactivate-yes').attr('data-after-text'));
461
+
462
+ var radio = $(this).prop('tagName') === 'LABEL' ? $(this).parent() : $(this);
463
+ if (radio.parent().find('textarea').length > 0 && radio.parent().find('textarea').val().length === 0) {
464
+ $('#<?php echo $key; ?>ti-deactivate-yes').attr('disabled', 'disabled');
465
+ radio.parent().find('textarea').on('keyup', function (ee) {
466
+ if ($(this).val().length === 0) {
467
+ $('#<?php echo $key; ?>ti-deactivate-yes').attr('disabled', 'disabled');
468
+ } else {
469
+ $('#<?php echo $key; ?>ti-deactivate-yes').removeAttr('disabled');
470
+ }
471
+ });
472
+ } else {
473
+ $('#<?php echo $key; ?>ti-deactivate-yes').removeAttr('disabled');
474
+ }
475
+ });
476
+ $("#<?php echo $key; ?>-info-disclosure").on('click', function () {
477
+ $("#TB_window").toggleClass("<?php echo $key; ?>-container-disc-open");
478
+ return false;
479
+ });
480
+ $('#<?php echo $key; ?>ti-deactivate-yes').attr('data-ti-action', href).on('click', function (e) {
481
+ e.preventDefault();
482
+ e.stopPropagation();
483
+ $.post(ajaxurl, {
484
+ 'action': '<?php echo $key . '_uninstall_feedback'; ?>',
485
+ 'nonce': '<?php echo wp_create_nonce( (string) __CLASS__ ); ?>',
486
+ 'id': $('#<?php echo $key; ?> input[name="ti-deactivate-option"]:checked').parent().attr('ti-option-id'),
487
+ 'msg': $('#<?php echo $key; ?> input[name="ti-deactivate-option"]:checked').parent().find('textarea').val(),
488
+ 'type': '<?php echo $type; ?>',
489
+ });
490
+ var redirect = $(this).attr('data-ti-action');
491
+ if (redirect != '') {
492
+ location.href = redirect;
493
+ } else {
494
+ $('body').unbind('thickbox:removed');
495
+ tb_remove();
496
+ }
497
+ });
498
+
499
+ $(target_element).attr('name', '<?php echo wp_kses( $heading, array( 'span' => array() ) ); ?>').attr('href', '<?php echo $src; ?>').addClass('thickbox');
500
+ var thicbox_timer;
501
+ $(target_element).on('click', function () {
502
+ tiBindThickbox();
503
+ });
504
+
505
+ function tiBindThickbox() {
506
+ var thicbox_timer = setTimeout(function () {
507
+ if ($("#<?php echo esc_html( $key ); ?>").is(":visible")) {
508
+ $("body").trigger('thickbox:iframe:loaded');
509
+ $("#TB_window").addClass("<?php echo $key; ?>-container");
510
+ clearTimeout(thicbox_timer);
511
+ $('body').unbind('thickbox:removed');
512
+ } else {
513
+ tiBindThickbox();
514
+ }
515
+ }, 100);
516
+ }
517
+ });
518
+ })(jQuery);
519
+ </script>
520
+ <?php
521
+
522
+ do_action( $this->product->get_key() . '_uninstall_feedback_after_js' );
523
+ }
524
+
525
+ /**
526
+ * Generates the HTML.
527
+ *
528
+ * @param string $type The type of product.
529
+ * @param string $key The product key.
530
+ */
531
+ function get_html( $type, $key ) {
532
+ $options = Product::PLUGIN_TYPE === $type ? $this->options_plugin : $this->options_theme;
533
+ $button_cancel = Product::PLUGIN_TYPE === $type ? $this->button_cancel : 'Skip';
534
+ $button_submit = Product::PLUGIN_TYPE === $type ? $this->button_submit : 'Submit';
535
+ $options = $this->randomize_options( apply_filters( $this->product->get_key() . '_feedback_deactivate_options', $options ) );
536
+ $button_submit = apply_filters( $this->product->get_key() . '_feedback_deactivate_button_submit', $button_submit );
537
+ $button_cancel = apply_filters( $this->product->get_key() . '_feedback_deactivate_button_cancel', $button_cancel );
538
+
539
+ $options += $this->other;
540
+
541
+ $list = '';
542
+ foreach ( $options as $title => $attributes ) {
543
+ $id = $attributes['id'];
544
+ $list .= '<li ti-option-id="' . $id . '"><input type="radio" name="ti-deactivate-option" id="' . $key . $id . '"><label for="' . $key . $id . '">' . str_replace( '{theme}', $this->product->get_name(), $title ) . '</label>';
545
+ if ( array_key_exists( 'type', $attributes ) ) {
546
+ $list .= '<div>';
547
+ $placeholder = array_key_exists( 'placeholder', $attributes ) ? $attributes['placeholder'] : '';
548
+ switch ( $attributes['type'] ) {
549
+ case 'text':
550
+ $list .= '<textarea style="width: 100%" rows="1" name="comments" placeholder="' . $placeholder . '"></textarea>';
551
+ break;
552
+ case 'textarea':
553
+ $list .= '<textarea style="width: 100%" rows="2" name="comments" placeholder="' . $placeholder . '"></textarea>';
554
+ break;
555
+ }
556
+ $list .= '</div>';
557
+ }
558
+ $list .= '</li>';
559
+ }
560
+
561
+ $disclosure_new_labels = apply_filters( $this->product->get_slug() . '_themeisle_sdk_disclosure_content_labels', [], $this->product );
562
+ $disclosure_labels = array_merge(
563
+ [
564
+ 'title' => 'Below is a detailed view of all data that ThemeIsle will receive if you fill in this survey. No domain name, email address or IP addresses are transmited after you submit the survey.',
565
+ 'items' => [
566
+ sprintf( '%s %s version %s %s %s %s', '<strong>', ucwords( $this->product->get_type() ), '</strong>', '<code>', $this->product->get_version(), '</code>' ),
567
+ sprintf( '%s Uninstall reason %s %s Selected reson from the above survey %s ', '<strong>', '</strong>', '<i>', '</i>' ),
568
+ ],
569
+ ],
570
+ $disclosure_new_labels
571
+ );
572
+
573
+ $info_disclosure_link = '<a href="#" id="' . $this->product->get_key() . '-info-disclosure">' . apply_filters( $this->product->get_slug() . '_themeisle_sdk_info_collect_cta', 'What info do we collect?' ) . '</a>';
574
+ $info_disclosure_content = '<div id="' . $this->product->get_key() . '-info-disclosure-content"><p>' . wp_kses_post( $disclosure_labels['title'] ) . '</p><ul>';
575
+ foreach ( $disclosure_labels['items'] as $disclosure_item ) {
576
+ $info_disclosure_content .= sprintf( '<li>%s</li>', wp_kses_post( $disclosure_item ) );
577
+ }
578
+ $info_disclosure_content .= '</ul></div>';
579
+
580
+ return
581
+ '<div id="' . $this->product->get_key() . '"><ul class="ti-list">' . $list . '</ul>'
582
+ . $info_disclosure_content
583
+ . '<div class="actions">'
584
+ . get_submit_button(
585
+ $button_submit,
586
+ 'secondary',
587
+ $this->product->get_key() . 'ti-deactivate-yes',
588
+ false,
589
+ array(
590
+ 'data-after-text' => $button_submit,
591
+ 'disabled' => true,
592
+ )
593
+ )
594
+ . wp_kses_post( $info_disclosure_link )
595
+ . get_submit_button( $button_cancel, 'primary', $this->product->get_key() . 'ti-deactivate-no', false )
596
+ . '</div></div>';
597
+ }
598
+
599
+ /**
600
+ * Randomizes the options array.
601
+ *
602
+ * @param array $options The options array.
603
+ */
604
+ function randomize_options( $options ) {
605
+ $new = array();
606
+ $keys = array_keys( $options );
607
+ shuffle( $keys );
608
+
609
+ foreach ( $keys as $key ) {
610
+ $new[ $key ] = $options[ $key ];
611
+ }
612
+
613
+ return $new;
614
+ }
615
+
616
+ /**
617
+ * Called when the deactivate button is clicked.
618
+ */
619
+ function post_deactivate() {
620
+ check_ajax_referer( (string) __CLASS__, 'nonce' );
621
+
622
+ $this->post_deactivate_or_cancel();
623
+
624
+ if ( empty( $_POST['id'] ) ) {
625
+
626
+ wp_send_json( [] );
627
+
628
+ return;
629
+ }
630
+ $this->call_api(
631
+ array(
632
+ 'type' => 'deactivate',
633
+ 'id' => $_POST['id'],
634
+ 'comment' => isset( $_POST['msg'] ) ? $_POST['msg'] : '',
635
+ )
636
+ );
637
+ wp_send_json( [] );
638
+
639
+ }
640
+
641
+ /**
642
+ * Called when the deactivate/cancel button is clicked.
643
+ */
644
+ private function post_deactivate_or_cancel() {
645
+ if ( ! isset( $_POST['type'] ) || ! isset( $_POST['key'] ) ) {
646
+ return;
647
+ }
648
+ if ( 'theme' !== $_POST['type'] ) {
649
+ return;
650
+ }
651
+
652
+ set_transient( 'ti_sdk_pause_' . $_POST['key'], true, self::PAUSE_DEACTIVATE_WINDOW_DAYS * DAY_IN_SECONDS );
653
+
654
+ }
655
+
656
+ /**
657
+ * Calls the API
658
+ *
659
+ * @param array $attributes The attributes of the post body.
660
+ *
661
+ * @return bool Is the request succesfull?
662
+ */
663
+ protected function call_api( $attributes ) {
664
+ $slug = $this->product->get_slug();
665
+ $version = $this->product->get_version();
666
+ $attributes['slug'] = $slug;
667
+ $attributes['version'] = $version;
668
+
669
+ $response = wp_remote_post(
670
+ self::FEEDBACK_ENDPOINT,
671
+ array(
672
+ 'body' => $attributes,
673
+ )
674
+ );
675
+
676
+ return is_wp_error( $response );
677
+ }
678
+
679
+ /**
680
+ * Should we load this object?.
681
+ *
682
+ * @param Product $product Product object.
683
+ *
684
+ * @return bool Should we load the module?
685
+ */
686
+ public function can_load( $product ) {
687
+ if ( $this->is_from_partner( $product ) ) {
688
+ return false;
689
+ }
690
+ if ( $product->is_theme() && ( false !== get_transient( 'ti_sdk_pause_' . $product->get_key(), false ) ) ) {
691
+ return false;
692
+ }
693
+
694
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
695
+ return true;
696
+ }
697
+ global $pagenow;
698
+
699
+ if ( ! isset( $pagenow ) || empty( $pagenow ) ) {
700
+ return false;
701
+ }
702
+
703
+ if ( $product->is_plugin() && 'plugins.php' !== $pagenow ) {
704
+ return false;
705
+
706
+ }
707
+ if ( $product->is_theme() && 'theme-install.php' !== $pagenow ) {
708
+ return false;
709
+ }
710
+
711
+ return true;
712
+ }
713
+
714
+ /**
715
+ * Loads module hooks.
716
+ *
717
+ * @param Product $product Product details.
718
+ *
719
+ * @return Uninstall_Feedback Current module instance.
720
+ */
721
+ public function load( $product ) {
722
+ $this->product = $product;
723
+ add_action( 'admin_head', array( $this, 'load_resources' ) );
724
+ add_action( 'wp_ajax_' . $this->product->get_key() . '_uninstall_feedback', array( $this, 'post_deactivate' ) );
725
+
726
+ return $this;
727
+ }
728
+ }
vendor/codeinwp/themeisle-sdk/src/Product.php ADDED
@@ -0,0 +1,396 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The product model class for ThemeIsle SDK
4
+ *
5
+ * @package ThemeIsleSDK
6
+ * @subpackage Product
7
+ * @copyright Copyright (c) 2017, Marius Cristea
8
+ * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9
+ * @since 1.0.0
10
+ */
11
+
12
+ namespace ThemeisleSDK;
13
+
14
+ // Exit if accessed directly.
15
+ if ( ! defined( 'ABSPATH' ) ) {
16
+ exit;
17
+ }
18
+
19
+ /**
20
+ * Product model for ThemeIsle SDK.
21
+ */
22
+ class Product {
23
+ /**
24
+ * Define plugin type string.
25
+ */
26
+ const PLUGIN_TYPE = 'plugin';
27
+ /**
28
+ * Define theme type string.
29
+ */
30
+ const THEME_TYPE = 'theme';
31
+ /**
32
+ * If the product has a pro version, contains the pro slug.
33
+ *
34
+ * @var string $pro_slug Pro slug, if available.
35
+ */
36
+ public $pro_slug;
37
+ /**
38
+ * Current product slug.
39
+ *
40
+ * @var string $slug THe product slug.
41
+ */
42
+ private $slug;
43
+ /**
44
+ * Product basefile, with the proper metadata.
45
+ *
46
+ * @var string $basefile The file with headers.
47
+ */
48
+ private $basefile;
49
+ /**
50
+ * Type of the product.
51
+ *
52
+ * @var string $type The product type ( plugin | theme ).
53
+ */
54
+ private $type;
55
+ /**
56
+ * The file name.
57
+ *
58
+ * @var string $file The file name.
59
+ */
60
+ private $file;
61
+ /**
62
+ * Product name, fetched from the file headers.
63
+ *
64
+ * @var string $name The product name.
65
+ */
66
+ private $name;
67
+ /**
68
+ * Product normalized key.
69
+ *
70
+ * @var string $key The product ready key.
71
+ */
72
+ private $key;
73
+ /**
74
+ * Product store url.
75
+ *
76
+ * @var string $store_url The store url.
77
+ */
78
+ private $store_url;
79
+ /**
80
+ * Product install timestamp.
81
+ *
82
+ * @var int $install The date of install.
83
+ */
84
+ private $install;
85
+ /**
86
+ * Product store/author name.
87
+ *
88
+ * @var string $store_name The store name.
89
+ */
90
+ private $store_name;
91
+ /**
92
+ * Does the product requires license.
93
+ *
94
+ * @var bool $requires_license Either user needs to activate it with license.
95
+ */
96
+ private $requires_license;
97
+ /**
98
+ * Is the product available on wordpress.org
99
+ *
100
+ * @var bool $wordpress_available Either is available on WordPress or not.
101
+ */
102
+ private $wordpress_available;
103
+ /**
104
+ * Current version of the product.
105
+ *
106
+ * @var string $version The product version.
107
+ */
108
+ private $version;
109
+
110
+ /**
111
+ * ThemeIsle_SDK_Product constructor.
112
+ *
113
+ * @param string $basefile Product basefile.
114
+ */
115
+ public function __construct( $basefile ) {
116
+ if ( ! empty( $basefile ) ) {
117
+ if ( is_readable( $basefile ) ) {
118
+ $this->basefile = $basefile;
119
+ $this->setup_from_path();
120
+ $this->setup_from_fileheaders();
121
+ }
122
+ }
123
+ $install = get_option( $this->get_key() . '_install', 0 );
124
+ if ( 0 === $install ) {
125
+ $install = time();
126
+ update_option( $this->get_key() . '_install', time() );
127
+ }
128
+ $this->install = $install;
129
+
130
+ }
131
+
132
+ /**
133
+ * Setup props from path.
134
+ */
135
+ public function setup_from_path() {
136
+ $this->file = basename( $this->basefile );
137
+ $dir = dirname( $this->basefile );
138
+ $this->slug = basename( $dir );
139
+ $exts = explode( '.', $this->basefile );
140
+ $ext = $exts[ count( $exts ) - 1 ];
141
+ if ( 'css' === $ext ) {
142
+ $this->type = 'theme';
143
+ }
144
+ if ( 'php' === $ext ) {
145
+ $this->type = 'plugin';
146
+ }
147
+ $this->key = self::key_ready_name( $this->slug );
148
+ }
149
+
150
+ /**
151
+ * Normalize string.
152
+ *
153
+ * @param string $string the String to be normalized for cron handler.
154
+ *
155
+ * @return string $name The normalized string.
156
+ */
157
+ static function key_ready_name( $string ) {
158
+ return str_replace( '-', '_', strtolower( trim( $string ) ) );
159
+ }
160
+
161
+ /**
162
+ * Setup props from fileheaders.
163
+ */
164
+ public function setup_from_fileheaders() {
165
+ $file_headers = array(
166
+ 'Requires License' => 'Requires License',
167
+ 'WordPress Available' => 'WordPress Available',
168
+ 'Pro Slug' => 'Pro Slug',
169
+ 'Version' => 'Version',
170
+ );
171
+ if ( 'plugin' === $this->type ) {
172
+ $file_headers['Name'] = 'Plugin Name';
173
+ $file_headers['AuthorName'] = 'Author';
174
+ $file_headers['AuthorURI'] = 'Author URI';
175
+ }
176
+ if ( 'theme' === $this->type ) {
177
+ $file_headers['Name'] = 'Theme Name';
178
+ $file_headers['AuthorName'] = 'Author';
179
+ $file_headers['AuthorURI'] = 'Author URI';
180
+ }
181
+ $file_headers = get_file_data( $this->basefile, $file_headers );
182
+
183
+ $this->name = $file_headers['Name'];
184
+ $this->store_name = $file_headers['AuthorName'];
185
+ $this->author_url = $file_headers['AuthorURI'];
186
+ $this->store_url = $file_headers['AuthorURI'];
187
+
188
+ $this->requires_license = ( 'yes' === $file_headers['Requires License'] ) ? true : false;
189
+ $this->wordpress_available = ( 'yes' === $file_headers['WordPress Available'] ) ? true : false;
190
+ $this->pro_slug = ! empty( $file_headers['Pro Slug'] ) ? $file_headers['Pro Slug'] : '';
191
+ $this->version = $file_headers['Version'];
192
+
193
+ }
194
+
195
+ /**
196
+ * Return the product key.
197
+ *
198
+ * @return string The product key.
199
+ */
200
+ public function get_key() {
201
+ return $this->key;
202
+ }
203
+ /**
204
+ * Check if the product is either theme or plugin.
205
+ *
206
+ * @return string Product type.
207
+ */
208
+ public function get_type() {
209
+ return $this->type;
210
+ }
211
+
212
+ /**
213
+ * Return if the product is used as a plugin.
214
+ *
215
+ * @return bool Is plugin?
216
+ */
217
+ public function is_plugin() {
218
+ return self::PLUGIN_TYPE === $this->type;
219
+ }
220
+
221
+ /**
222
+ * Return if the product is used as a theme.
223
+ *
224
+ * @return bool Is theme ?
225
+ */
226
+ public function is_theme() {
227
+ return self::THEME_TYPE === $this->type;
228
+ }
229
+
230
+ /**
231
+ * Returns the product slug.
232
+ *
233
+ * @return string The product slug.
234
+ */
235
+ public function get_slug() {
236
+ return $this->slug;
237
+ }
238
+
239
+ /**
240
+ * The magic var_dump info method.
241
+ *
242
+ * @return array Debug info.
243
+ */
244
+ public function __debugInfo() {
245
+ return array(
246
+ 'name' => $this->name,
247
+ 'slug' => $this->slug,
248
+ 'version' => $this->version,
249
+ 'basefile' => $this->basefile,
250
+ 'key' => $this->key,
251
+ 'type' => $this->type,
252
+ 'store_name' => $this->store_name,
253
+ 'store_url' => $this->store_url,
254
+ 'wordpress_available' => $this->wordpress_available,
255
+ 'requires_license' => $this->requires_license,
256
+ );
257
+
258
+ }
259
+
260
+ /**
261
+ * Getter for product version.
262
+ *
263
+ * @return string The product version.
264
+ */
265
+ public function get_version() {
266
+ return $this->version;
267
+ }
268
+
269
+ /**
270
+ * Returns current product license, if available.
271
+ *
272
+ * @return string Return license key, if available.
273
+ */
274
+ public function get_license() {
275
+
276
+ if ( ! $this->requires_license() && ! $this->is_wordpress_available() ) {
277
+ return 'free';
278
+ }
279
+ $license_data = get_option( $this->get_key() . '_license_data', '' );
280
+
281
+ if ( empty( $license_data ) ) {
282
+ return get_option( $this->get_key() . '_license', '' );
283
+ }
284
+ if ( ! isset( $license_data->key ) ) {
285
+ return get_option( $this->get_key() . '_license', '' );
286
+ }
287
+
288
+ return $license_data->key;
289
+ }
290
+
291
+ /**
292
+ * Either the product requires license or not.
293
+ *
294
+ * @return bool Either requires license or not.
295
+ */
296
+ public function requires_license() {
297
+ return $this->requires_license;
298
+ }
299
+
300
+ /**
301
+ * If product is available on wordpress.org or not.
302
+ *
303
+ * @return bool Either is wp available or not.
304
+ */
305
+ public function is_wordpress_available() {
306
+ return $this->wordpress_available;
307
+ }
308
+
309
+ /**
310
+ * Return friendly name.
311
+ *
312
+ * @return string Friendly name.
313
+ */
314
+ public function get_friendly_name() {
315
+ $name = apply_filters( $this->get_key() . '_friendly_name', trim( str_replace( 'Lite', '', $this->get_name() ) ) );
316
+ $name = rtrim( $name, '- ()' );
317
+
318
+ return $name;
319
+ }
320
+
321
+ /**
322
+ * Getter for product name.
323
+ *
324
+ * @return string The product name.
325
+ */
326
+ public function get_name() {
327
+ return $this->name;
328
+ }
329
+
330
+ /**
331
+ * Returns the Store name.
332
+ *
333
+ * @return string Store name.
334
+ */
335
+ public function get_store_name() {
336
+ return $this->store_name;
337
+ }
338
+
339
+ /**
340
+ * Returns the store url.
341
+ *
342
+ * @return string The store url.
343
+ */
344
+ public function get_store_url() {
345
+ return $this->store_url;
346
+ }
347
+
348
+ /**
349
+ * Returns product basefile, which holds the metaheaders.
350
+ *
351
+ * @return string The product basefile.
352
+ */
353
+ public function get_basefile() {
354
+ return $this->basefile;
355
+ }
356
+
357
+ /**
358
+ * Returns product filename.
359
+ *
360
+ * @return string The product filename.
361
+ */
362
+ public function get_file() {
363
+ return $this->file;
364
+ }
365
+ /**
366
+ * Returns the pro slug, if available.
367
+ *
368
+ * @return string The pro slug.
369
+ */
370
+ public function get_pro_slug() {
371
+ return $this->pro_slug;
372
+ }
373
+
374
+ /**
375
+ * Return the install timestamp.
376
+ *
377
+ * @return int The install timestamp.
378
+ */
379
+ public function get_install_time() {
380
+ return $this->install;
381
+ }
382
+
383
+ /**
384
+ * Returns the URL of the product base file.
385
+ *
386
+ * @param string $path The path to the file.
387
+ *
388
+ * @return string The URL of the product base file.
389
+ */
390
+ public function get_base_url( $path = '/' ) {
391
+ if ( $this->type ) {
392
+ return plugins_url( $path, $this->basefile );
393
+ }
394
+ }
395
+
396
+ }
vendor/codeinwp/themeisle-sdk/start.php CHANGED
@@ -7,32 +7,43 @@
7
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
8
  * @since 1.1.0
9
  */
 
 
 
 
 
 
10
  $products = apply_filters( 'themeisle_sdk_products', array() );
11
  $path = dirname( __FILE__ );
12
- $files_to_load = array(
13
- 'class-themeisle-sdk-loader.php',
14
- 'class-themeisle-sdk-product.php',
15
- 'class-themeisle-sdk-logger.php',
16
- 'class-themeisle-sdk-licenser.php',
17
- 'class-themeisle-sdk-rollback.php',
18
- 'class-themeisle-sdk-feedback-factory.php',
19
- 'class-themeisle-sdk-feedback.php',
20
- 'class-themeisle-sdk-feedback-deactivate.php',
21
- 'class-themeisle-sdk-feedback-review.php',
22
- 'class-themeisle-sdk-feedback-translate.php',
23
- 'class-themeisle-sdk-notification-manager.php',
24
- 'class-themeisle-sdk-widget.php',
25
- 'class-themeisle-sdk-widget-dashboard-blog.php',
26
- 'class-themeisle-sdk-widgets-factory.php',
27
- 'class-themeisle-sdk-endpoints.php',
28
- );
 
 
 
29
 
30
  foreach ( $files_to_load as $file ) {
31
- $file_path = $path . '/' . $file;
32
- if ( is_readable( $file_path ) ) {
33
- require_once $file_path;
34
  }
35
  }
 
 
 
36
  foreach ( $products as $product ) {
37
- ThemeIsle_SDK_Loader::init_product( $product );
38
  }
7
  * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
8
  * @since 1.1.0
9
  */
10
+
11
+ namespace ThemeisleSDK;
12
+
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit;
15
+ }
16
  $products = apply_filters( 'themeisle_sdk_products', array() );
17
  $path = dirname( __FILE__ );
18
+ $files_to_load = [
19
+ $path . '/src/' . 'Loader.php',
20
+ $path . '/src/' . 'Product.php',
21
+
22
+ $path . '/src/' . 'Common/Abstract_module.php',
23
+ $path . '/src/' . 'Common/Module_factory.php',
24
+
25
+ $path . '/src/' . 'Modules/Dashboard_widget.php',
26
+ $path . '/src/' . 'Modules/Rollback.php',
27
+ $path . '/src/' . 'Modules/Uninstall_feedback.php',
28
+ $path . '/src/' . 'Modules/Licenser.php',
29
+ $path . '/src/' . 'Modules/Endpoint.php',
30
+ $path . '/src/' . 'Modules/Notification.php',
31
+ $path . '/src/' . 'Modules/Logger.php',
32
+ $path . '/src/' . 'Modules/Translate.php',
33
+ $path . '/src/' . 'Modules/Review.php',
34
+ $path . '/src/' . 'Modules/Recommendation.php',
35
+ ];
36
+
37
+ $files_to_load = array_merge( $files_to_load, apply_filters( 'themeisle_sdk_required_files', [] ) );
38
 
39
  foreach ( $files_to_load as $file ) {
40
+ if ( is_readable( $file ) ) {
41
+ require_once $file;
 
42
  }
43
  }
44
+
45
+ Loader::init();
46
+
47
  foreach ( $products as $product ) {
48
+ Loader::add_product( $product );
49
  }
vendor/composer/autoload_files.php CHANGED
@@ -6,6 +6,5 @@ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
- '957c51f8f334b5ea3be310bfb8b3492c' => $vendorDir . '/codeinwp/themeisle-sdk/load.php',
10
  'b24dbe7c20cf81879cc2c2a72e964a53' => $vendorDir . '/codeinwp/themeisle-sdk/load.php',
11
  );
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
 
9
  'b24dbe7c20cf81879cc2c2a72e964a53' => $vendorDir . '/codeinwp/themeisle-sdk/load.php',
10
  );
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit0df49950d5c45f5a33cc99a042d21267
6
  {
7
  private static $loader;
8
 
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit0df49950d5c45f5a33cc99a042d21267
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit0df49950d5c45f5a33cc99a042d21267', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit0df49950d5c45f5a33cc99a042d21267', 'loadClassLoader'));
25
 
26
  $map = require __DIR__ . '/autoload_namespaces.php';
27
  foreach ($map as $namespace => $path) {
@@ -42,14 +42,14 @@ class ComposerAutoloaderInit0df49950d5c45f5a33cc99a042d21267
42
 
43
  $includeFiles = require __DIR__ . '/autoload_files.php';
44
  foreach ($includeFiles as $fileIdentifier => $file) {
45
- composerRequire0df49950d5c45f5a33cc99a042d21267($fileIdentifier, $file);
46
  }
47
 
48
  return $loader;
49
  }
50
  }
51
 
52
- function composerRequire0df49950d5c45f5a33cc99a042d21267($fileIdentifier, $file)
53
  {
54
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
55
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit50a5a90c970ef91e5ea0336e536a989f
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit50a5a90c970ef91e5ea0336e536a989f', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit50a5a90c970ef91e5ea0336e536a989f', 'loadClassLoader'));
25
 
26
  $map = require __DIR__ . '/autoload_namespaces.php';
27
  foreach ($map as $namespace => $path) {
42
 
43
  $includeFiles = require __DIR__ . '/autoload_files.php';
44
  foreach ($includeFiles as $fileIdentifier => $file) {
45
+ composerRequire50a5a90c970ef91e5ea0336e536a989f($fileIdentifier, $file);
46
  }
47
 
48
  return $loader;
49
  }
50
  }
51
 
52
+ function composerRequire50a5a90c970ef91e5ea0336e536a989f($fileIdentifier, $file)
53
  {
54
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
55
  require $file;
vendor/composer/installed.json CHANGED
@@ -1,27 +1,27 @@
1
  [
2
  {
3
  "name": "codeinwp/themeisle-sdk",
4
- "version": "dev-master",
5
- "version_normalized": "9999999-dev",
6
  "source": {
7
  "type": "git",
8
  "url": "https://github.com/Codeinwp/themeisle-sdk.git",
9
- "reference": "951cde6e799e00d46a52416b62221fd771ddc326"
10
  },
11
  "dist": {
12
  "type": "zip",
13
- "url": "https://api.github.com/repos/Codeinwp/themeisle-sdk/zipball/951cde6e799e00d46a52416b62221fd771ddc326",
14
- "reference": "951cde6e799e00d46a52416b62221fd771ddc326",
15
  "shasum": ""
16
  },
17
- "time": "2018-11-26 14:24:47",
 
 
 
 
 
18
  "type": "library",
19
  "installation-source": "dist",
20
- "autoload": {
21
- "files": [
22
- "load.php"
23
- ]
24
- },
25
  "notification-url": "https://packagist.org/downloads/",
26
  "license": [
27
  "GPL-2.0+"
@@ -33,7 +33,7 @@
33
  "homepage": "https://themeisle.com"
34
  }
35
  ],
36
- "description": "ThemeIsle SDK ",
37
  "homepage": "https://github.com/Codeinwp/themeisle-sdk",
38
  "keywords": [
39
  "wordpress"
1
  [
2
  {
3
  "name": "codeinwp/themeisle-sdk",
4
+ "version": "3.0.5",
5
+ "version_normalized": "3.0.5.0",
6
  "source": {
7
  "type": "git",
8
  "url": "https://github.com/Codeinwp/themeisle-sdk.git",
9
+ "reference": "7ead6c057d783ea6c827d5b5de52a25c0e72de58"
10
  },
11
  "dist": {
12
  "type": "zip",
13
+ "url": "https://api.github.com/repos/Codeinwp/themeisle-sdk/zipball/7ead6c057d783ea6c827d5b5de52a25c0e72de58",
14
+ "reference": "7ead6c057d783ea6c827d5b5de52a25c0e72de58",
15
  "shasum": ""
16
  },
17
+ "require-dev": {
18
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4",
19
+ "squizlabs/php_codesniffer": "^3.1",
20
+ "wp-coding-standards/wpcs": "^1.0.0"
21
+ },
22
+ "time": "2019-03-07 15:42:52",
23
  "type": "library",
24
  "installation-source": "dist",
 
 
 
 
 
25
  "notification-url": "https://packagist.org/downloads/",
26
  "license": [
27
  "GPL-2.0+"
33
  "homepage": "https://themeisle.com"
34
  }
35
  ],
36
+ "description": "ThemeIsle SDK.",
37
  "homepage": "https://github.com/Codeinwp/themeisle-sdk",
38
  "keywords": [
39
  "wordpress"