FEEDZY RSS Feeds Lite - Version 3.3.2

Version Description

  • 2018-12-22
Download this release

Release Info

Developer codeinwp
Plugin Icon 128x128 FEEDZY RSS Feeds Lite
Version 3.3.2
Comparing to
See all releases

Code changes from version 3.3.1 to 3.3.2

Files changed (148) hide show
  1. CHANGELOG.md +8 -0
  2. css/feedzy-rss-feeds.css +1 -1
  3. feedzy-rss-feed.php +2 -1
  4. includes/abstract/feedzy-rss-feeds-admin-abstract.php +48 -43
  5. includes/admin/feedzy-rss-feeds-admin.php +28 -20
  6. includes/admin/feedzy-rss-feeds-ui-lang.php +41 -1
  7. includes/admin/feedzy-rss-feeds-ui.php +18 -8
  8. includes/feedzy-rss-feeds.php +12 -8
  9. includes/gutenberg/feedzy-rss-feeds-gutenberg-block.php +1 -1
  10. includes/layouts/feedzy-support.php +41 -0
  11. includes/layouts/feedzy-tutorial.php +53 -0
  12. includes/layouts/feedzy-upsell.php +0 -2
  13. readme.md +11 -2
  14. readme.txt +18 -2
  15. themeisle-hash.json +1 -1
  16. vendor/autoload.php +1 -1
  17. vendor/autoload_52.php +1 -1
  18. vendor/codeinwp/themeisle-sdk/CHANGELOG.md +6 -0
  19. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-endpoints.php +0 -312
  20. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback-deactivate.php +0 -556
  21. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback-factory.php +0 -50
  22. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback-review.php +0 -209
  23. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback-translate.php +0 -983
  24. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-feedback.php +0 -90
  25. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-licenser.php +0 -686
  26. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-loader.php +0 -96
  27. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-logger.php +0 -227
  28. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-notification-manager.php +0 -105
  29. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-product.php +0 -635
  30. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-rollback.php +0 -223
  31. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-widget-dashboard-blog.php +0 -412
  32. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-widget.php +0 -50
  33. vendor/codeinwp/themeisle-sdk/class-themeisle-sdk-widgets-factory.php +0 -37
  34. vendor/codeinwp/themeisle-sdk/composer.json +0 -24
  35. vendor/codeinwp/themeisle-sdk/index.php +2 -4
  36. vendor/codeinwp/themeisle-sdk/load.php +17 -3
  37. vendor/codeinwp/themeisle-sdk/src/Common/Abstract_module.php +66 -0
  38. vendor/codeinwp/themeisle-sdk/src/Common/Module_factory.php +108 -0
  39. vendor/codeinwp/themeisle-sdk/src/Loader.php +117 -0
  40. vendor/codeinwp/themeisle-sdk/src/Modules/Dashboard_widget.php +453 -0
  41. vendor/codeinwp/themeisle-sdk/src/Modules/Endpoint.php +358 -0
  42. vendor/codeinwp/themeisle-sdk/src/Modules/Licenser.php +716 -0
  43. vendor/codeinwp/themeisle-sdk/src/Modules/Logger.php +176 -0
  44. vendor/codeinwp/themeisle-sdk/src/Modules/Notification.php +435 -0
  45. vendor/codeinwp/themeisle-sdk/src/Modules/Review.php +117 -0
  46. vendor/codeinwp/themeisle-sdk/src/Modules/Rollback.php +371 -0
  47. vendor/codeinwp/themeisle-sdk/src/Modules/Translate.php +918 -0
  48. vendor/codeinwp/themeisle-sdk/src/Modules/Uninstall_feedback.php +729 -0
  49. vendor/codeinwp/themeisle-sdk/src/Product.php +383 -0
  50. vendor/codeinwp/themeisle-sdk/start.php +31 -21
  51. vendor/composer/autoload_files.php +0 -1
  52. vendor/composer/autoload_psr4.php +1 -0
  53. vendor/composer/autoload_real.php +5 -5
  54. vendor/composer/autoload_real_52.php +3 -4
  55. vendor/composer/installed.json +134 -9
  56. vendor/composer/installers/LICENSE +19 -0
  57. vendor/composer/installers/composer.json +105 -0
  58. vendor/composer/installers/src/Composer/Installers/AglInstaller.php +21 -0
  59. vendor/composer/installers/src/Composer/Installers/AimeosInstaller.php +9 -0
  60. vendor/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php +11 -0
  61. vendor/composer/installers/src/Composer/Installers/AsgardInstaller.php +49 -0
  62. vendor/composer/installers/src/Composer/Installers/AttogramInstaller.php +9 -0
  63. vendor/composer/installers/src/Composer/Installers/BaseInstaller.php +136 -0
  64. vendor/composer/installers/src/Composer/Installers/BitrixInstaller.php +126 -0
  65. vendor/composer/installers/src/Composer/Installers/BonefishInstaller.php +9 -0
  66. vendor/composer/installers/src/Composer/Installers/CakePHPInstaller.php +82 -0
  67. vendor/composer/installers/src/Composer/Installers/ChefInstaller.php +11 -0
  68. vendor/composer/installers/src/Composer/Installers/CiviCrmInstaller.php +9 -0
  69. vendor/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php +10 -0
  70. vendor/composer/installers/src/Composer/Installers/CockpitInstaller.php +34 -0
  71. vendor/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php +11 -0
  72. vendor/composer/installers/src/Composer/Installers/Concrete5Installer.php +13 -0
  73. vendor/composer/installers/src/Composer/Installers/CraftInstaller.php +35 -0
  74. vendor/composer/installers/src/Composer/Installers/CroogoInstaller.php +21 -0
  75. vendor/composer/installers/src/Composer/Installers/DecibelInstaller.php +10 -0
  76. vendor/composer/installers/src/Composer/Installers/DokuWikiInstaller.php +50 -0
  77. vendor/composer/installers/src/Composer/Installers/DolibarrInstaller.php +16 -0
  78. vendor/composer/installers/src/Composer/Installers/DrupalInstaller.php +16 -0
  79. vendor/composer/installers/src/Composer/Installers/ElggInstaller.php +9 -0
  80. vendor/composer/installers/src/Composer/Installers/EliasisInstaller.php +12 -0
  81. vendor/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php +29 -0
  82. vendor/composer/installers/src/Composer/Installers/EzPlatformInstaller.php +10 -0
  83. vendor/composer/installers/src/Composer/Installers/FuelInstaller.php +11 -0
  84. vendor/composer/installers/src/Composer/Installers/FuelphpInstaller.php +9 -0
  85. vendor/composer/installers/src/Composer/Installers/GravInstaller.php +30 -0
  86. vendor/composer/installers/src/Composer/Installers/HuradInstaller.php +25 -0
  87. vendor/composer/installers/src/Composer/Installers/ImageCMSInstaller.php +11 -0
  88. vendor/composer/installers/src/Composer/Installers/Installer.php +274 -0
  89. vendor/composer/installers/src/Composer/Installers/ItopInstaller.php +9 -0
  90. vendor/composer/installers/src/Composer/Installers/JoomlaInstaller.php +15 -0
  91. vendor/composer/installers/src/Composer/Installers/KanboardInstaller.php +18 -0
  92. vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php +11 -0
  93. vendor/composer/installers/src/Composer/Installers/KodiCMSInstaller.php +10 -0
  94. vendor/composer/installers/src/Composer/Installers/KohanaInstaller.php +9 -0
  95. vendor/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php +27 -0
  96. vendor/composer/installers/src/Composer/Installers/LaravelInstaller.php +9 -0
  97. vendor/composer/installers/src/Composer/Installers/LavaLiteInstaller.php +10 -0
  98. vendor/composer/installers/src/Composer/Installers/LithiumInstaller.php +10 -0
  99. vendor/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php +9 -0
  100. vendor/composer/installers/src/Composer/Installers/MODXEvoInstaller.php +16 -0
  101. vendor/composer/installers/src/Composer/Installers/MagentoInstaller.php +11 -0
  102. vendor/composer/installers/src/Composer/Installers/MajimaInstaller.php +37 -0
  103. vendor/composer/installers/src/Composer/Installers/MakoInstaller.php +9 -0
  104. vendor/composer/installers/src/Composer/Installers/MauticInstaller.php +25 -0
  105. vendor/composer/installers/src/Composer/Installers/MayaInstaller.php +33 -0
  106. vendor/composer/installers/src/Composer/Installers/MediaWikiInstaller.php +51 -0
  107. vendor/composer/installers/src/Composer/Installers/MicroweberInstaller.php +111 -0
  108. vendor/composer/installers/src/Composer/Installers/ModxInstaller.php +12 -0
  109. vendor/composer/installers/src/Composer/Installers/MoodleInstaller.php +57 -0
  110. vendor/composer/installers/src/Composer/Installers/OctoberInstaller.php +47 -0
  111. vendor/composer/installers/src/Composer/Installers/OntoWikiInstaller.php +24 -0
  112. vendor/composer/installers/src/Composer/Installers/OsclassInstaller.php +14 -0
  113. vendor/composer/installers/src/Composer/Installers/OxidInstaller.php +59 -0
  114. vendor/composer/installers/src/Composer/Installers/PPIInstaller.php +9 -0
  115. vendor/composer/installers/src/Composer/Installers/PhiftyInstaller.php +11 -0
  116. vendor/composer/installers/src/Composer/Installers/PhpBBInstaller.php +11 -0
  117. vendor/composer/installers/src/Composer/Installers/PimcoreInstaller.php +21 -0
  118. vendor/composer/installers/src/Composer/Installers/PiwikInstaller.php +32 -0
  119. vendor/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php +29 -0
  120. vendor/composer/installers/src/Composer/Installers/Plugin.php +17 -0
  121. vendor/composer/installers/src/Composer/Installers/PortoInstaller.php +9 -0
  122. vendor/composer/installers/src/Composer/Installers/PrestashopInstaller.php +10 -0
  123. vendor/composer/installers/src/Composer/Installers/PuppetInstaller.php +11 -0
  124. vendor/composer/installers/src/Composer/Installers/PxcmsInstaller.php +63 -0
  125. vendor/composer/installers/src/Composer/Installers/RadPHPInstaller.php +24 -0
  126. vendor/composer/installers/src/Composer/Installers/ReIndexInstaller.php +10 -0
  127. vendor/composer/installers/src/Composer/Installers/RedaxoInstaller.php +10 -0
  128. vendor/composer/installers/src/Composer/Installers/RoundcubeInstaller.php +22 -0
  129. vendor/composer/installers/src/Composer/Installers/SMFInstaller.php +10 -0
  130. vendor/composer/installers/src/Composer/Installers/ShopwareInstaller.php +60 -0
  131. vendor/composer/installers/src/Composer/Installers/SilverStripeInstaller.php +35 -0
  132. vendor/composer/installers/src/Composer/Installers/SiteDirectInstaller.php +25 -0
  133. vendor/composer/installers/src/Composer/Installers/SyDESInstaller.php +49 -0
  134. vendor/composer/installers/src/Composer/Installers/Symfony1Installer.php +26 -0
  135. vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php +16 -0
  136. vendor/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php +38 -0
  137. vendor/composer/installers/src/Composer/Installers/TheliaInstaller.php +12 -0
  138. vendor/composer/installers/src/Composer/Installers/TuskInstaller.php +14 -0
  139. vendor/composer/installers/src/Composer/Installers/UserFrostingInstaller.php +9 -0
  140. vendor/composer/installers/src/Composer/Installers/VanillaInstaller.php +10 -0
  141. vendor/composer/installers/src/Composer/Installers/VgmcpInstaller.php +49 -0
  142. vendor/composer/installers/src/Composer/Installers/WHMCSInstaller.php +10 -0
  143. vendor/composer/installers/src/Composer/Installers/WolfCMSInstaller.php +9 -0
  144. vendor/composer/installers/src/Composer/Installers/WordPressInstaller.php +12 -0
  145. vendor/composer/installers/src/Composer/Installers/YawikInstaller.php +32 -0
  146. vendor/composer/installers/src/Composer/Installers/ZendInstaller.php +11 -0
  147. vendor/composer/installers/src/Composer/Installers/ZikulaInstaller.php +10 -0
  148. vendor/composer/installers/src/bootstrap.php +13 -0
CHANGELOG.md CHANGED
@@ -1,4 +1,12 @@
1
 
 
 
 
 
 
 
 
 
2
  ### v3.3.1 - 2018-11-05
3
  **Changes:**
4
  * Import Posts enabled for plan 1 users
1
 
2
+ ### v3.3.2 - 2018-12-22
3
+ **Changes:**
4
+ * Option to handle HTTP images in the shortcode
5
+ * Option to specify nofollow for links in the shortcode
6
+ * Fix Gutenberg block
7
+ * Add video tutorials under Help menu
8
+ * Add support for extracting price from custom feed tags
9
+
10
  ### v3.3.1 - 2018-11-05
11
  **Changes:**
12
  * Import Posts enabled for plan 1 users
css/feedzy-rss-feeds.css CHANGED
@@ -2,7 +2,7 @@
2
  * feedzy-rss-feeds.css
3
  * Feedzy RSS Feed
4
  * Copyright: (c) 2016 Themeisle, themeisle.com
5
- * Version: 3.3.1
6
  * Plugin Name: FEEDZY RSS Feeds
7
  * Plugin URI: http://themeisle.com/plugins/feedzy-rss-feeds/
8
  * Author: Themeisle
2
  * feedzy-rss-feeds.css
3
  * Feedzy RSS Feed
4
  * Copyright: (c) 2016 Themeisle, themeisle.com
5
+ * Version: 3.3.2
6
  * Plugin Name: FEEDZY RSS Feeds
7
  * Plugin URI: http://themeisle.com/plugins/feedzy-rss-feeds/
8
  * Author: Themeisle
feedzy-rss-feed.php CHANGED
@@ -15,7 +15,7 @@
15
  * Plugin Name: Feedzy RSS Feeds Lite
16
  * Plugin URI: https://themeisle.com/plugins/feedzy-rss-feeds-lite/
17
  * Description: A small and lightweight RSS aggregator plugin. Fast and very easy to use, it allows you to aggregate multiple RSS feeds into your WordPress site through fully customizable shortcodes & widgets.
18
- * Version: 3.3.1
19
  * Author: Themeisle
20
  * Author URI: http://themeisle.com
21
  * License: GPL-2.0+
@@ -112,6 +112,7 @@ function feedzy_rss_feeds_autoload( $class ) {
112
  function run_feedzy_rss_feeds() {
113
  define( 'FEEDZY_BASEFILE', __FILE__ );
114
  define( 'FEEDZY_ABSURL', plugins_url( '/', __FILE__ ) );
 
115
  define( 'FEEDZY_ABSPATH', dirname( __FILE__ ) );
116
  define( 'FEEDZY_UPSELL_LINK', 'https://themeisle.com/plugins/feedzy-rss-feeds/' );
117
  define( 'FEEDZY_NAME', 'Feedzy RSS Feeds' );
15
  * Plugin Name: Feedzy RSS Feeds Lite
16
  * Plugin URI: https://themeisle.com/plugins/feedzy-rss-feeds-lite/
17
  * Description: A small and lightweight RSS aggregator plugin. Fast and very easy to use, it allows you to aggregate multiple RSS feeds into your WordPress site through fully customizable shortcodes & widgets.
18
+ * Version: 3.3.2
19
  * Author: Themeisle
20
  * Author URI: http://themeisle.com
21
  * License: GPL-2.0+
112
  function run_feedzy_rss_feeds() {
113
  define( 'FEEDZY_BASEFILE', __FILE__ );
114
  define( 'FEEDZY_ABSURL', plugins_url( '/', __FILE__ ) );
115
+ define( 'FEEDZY_BASENAME', plugin_basename( __FILE__ ) );
116
  define( 'FEEDZY_ABSPATH', dirname( __FILE__ ) );
117
  define( 'FEEDZY_UPSELL_LINK', 'https://themeisle.com/plugins/feedzy-rss-feeds/' );
118
  define( 'FEEDZY_NAME', 'Feedzy RSS Feeds' );
includes/abstract/feedzy-rss-feeds-admin-abstract.php CHANGED
@@ -275,6 +275,8 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
275
  // display feed title yes/no
276
  'target' => '_blank',
277
  // _blank, _self
 
 
278
  'title' => '',
279
  // strip title after X char
280
  'meta' => 'yes',
@@ -290,11 +292,13 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
290
  'size' => '',
291
  // thumbs pixel size
292
  'keywords_title' => '',
293
- // cache refresh
294
  'refresh' => '12_hours',
295
- // sorting.
296
  'sort' => '',
297
- // only display item if title contains specific keywords (comma-separated list/case sensitive)
 
 
298
  ),
299
  $atts,
300
  'feedzy_default'
@@ -624,20 +628,18 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
624
  $content .= '</div>';
625
  }
626
  $content .= '<ul>';
 
 
627
  foreach ( $feed_items as $item ) {
628
  $content .= '
629
  <li ' . $item['itemAttr'] . '>
630
  ' . ( ( ! empty( $item['item_img'] ) && $sc['thumb'] != 'no' ) ? '
631
- <div class="' . $item['item_img_class'] . '" style="' . $item['item_img_style'] . '">
632
- <a href="' . $item['item_url'] . '" target="' . $item['item_url_target'] . '" title="' . $item['item_url_title'] . '" style="' . $item['item_img_style'] . '">
633
- ' . $item['item_img'] . '
634
- </a>
635
- </div>' : '' ) . '
636
- <span class="title">
637
- <a href="' . $item['item_url'] . '" target="' . $item['item_url_target'] . '">
638
- ' . $item['item_title'] . '
639
- </a>
640
- </span>
641
  <div class="' . $item['item_content_class'] . '" style="' . $item['item_content_style'] . '">
642
  ' . ( ! empty( $item['item_meta'] ) ? '<small>
643
  ' . $item['item_meta'] . '
@@ -649,7 +651,6 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
649
  }
650
  $content .= '</ul> </div>';
651
  $content = apply_filters( 'feedzy_global_output', $content, $sc, $feed_title, $feed_items );
652
-
653
  return $content;
654
  }
655
 
@@ -728,18 +729,16 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
728
  $count = 0;
729
  $items = apply_filters( 'feedzy_feed_items', $feed->get_items(), $feedURL );
730
  foreach ( (array) $items as $item ) {
731
- if ( trim( $item->get_title() ) != '' ) {
732
  $continue = apply_filters( 'feedzy_item_keyword', true, $sc, $item, $feedURL );
733
- if ( $continue == true ) {
734
- // Count items. This should be > and not >= because max, when not defined and empty, becomes 0.
735
- if ( $count >= $sc['max'] ) {
736
- break;
737
- }
738
- $itemAttr = apply_filters( 'feedzy_item_attributes', $itemAttr = '', $sizes, $item, $feedURL, $sc );
739
- $feed_items[ $count ] = $this->get_feed_item_filter( $sc, $sizes, $item, $feedURL );
740
- $feed_items[ $count ]['itemAttr'] = $itemAttr;
741
- $count ++;
742
  }
 
 
 
 
743
  }
744
  }
745
 
@@ -756,15 +755,16 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
756
  * @param array $sizes The sizes array.
757
  * @param object $item The feed item object.
758
  * @param string $feedURL The feed url.
 
759
  *
760
  * @return array
761
  */
762
- private function get_feed_item_filter( $sc, $sizes, $item, $feedURL ) {
763
  $itemLink = $item->get_permalink();
764
  $newLink = apply_filters( 'feedzy_item_url_filter', $itemLink, $sc, $item );
765
  // Fetch image thumbnail
766
  if ( $sc['thumb'] == 'yes' || $sc['thumb'] == 'auto' ) {
767
- $theThumbnail = $this->feedzy_retrieve_image( $item );
768
  }
769
  if ( $sc['thumb'] == 'yes' || $sc['thumb'] == 'auto' ) {
770
  $contentThumb = '';
@@ -847,9 +847,10 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
847
  'item_img_style' => 'width:' . $sizes['width'] . 'px; height:' . $sizes['height'] . 'px;',
848
  'item_url' => $newLink,
849
  'item_url_target' => $sc['target'],
 
850
  'item_url_title' => $item->get_title(),
851
  'item_img' => $contentThumb,
852
- 'item_img_path' => $this->feedzy_retrieve_image( $item ),
853
  'item_title' => $contentTitle,
854
  'item_content_class' => 'rss_content',
855
  'item_content_style' => '',
@@ -859,7 +860,7 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
859
  'item_description' => $contentSummary,
860
  'item_content' => apply_filters( 'feedzy_content', $item->get_content( false ), $item ),
861
  );
862
- $itemArray = apply_filters( 'feedzy_item_filter', $itemArray, $item );
863
 
864
  return $itemArray;
865
  }
@@ -871,10 +872,11 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
871
  * @access public
872
  *
873
  * @param object $item The item object.
 
874
  *
875
  * @return string
876
  */
877
- public function feedzy_retrieve_image( $item ) {
878
  $theThumbnail = '';
879
  if ( $enclosures = $item->get_enclosures() ) {
880
  foreach ( (array) $enclosures as $enclosure ) {
@@ -925,6 +927,18 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
925
  $theThumbnail = $this->feedzy_return_image( $feedDescription );
926
  }
927
 
 
 
 
 
 
 
 
 
 
 
 
 
928
  $theThumbnail = apply_filters( 'feedzy_retrieve_image', $theThumbnail, $item );
929
 
930
  return $theThumbnail;
@@ -1049,19 +1063,10 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
1049
  $string = $imgUrl[0][0];
1050
  }
1051
  }
1052
- // Encode image name only en keep extra parameters
1053
- $query = '';
1054
- if ( isset( $url_tab['query'] ) ) {
1055
- $query = '?' . urlencode( $url_tab['query'] );
1056
- }
1057
- $path = ltrim( $url_tab['path'], '/' );
1058
-
1059
- if ( substr( $path, 0, 0 ) !== '/' ) {
1060
- $path = '/' . $path;
1061
- }
1062
 
1063
- // Return a well encoded image url
1064
- return $url_tab['scheme'] . '://' . $url_tab['host'] . $path . $query;
 
1065
  }
1066
 
1067
  /**
@@ -1081,8 +1086,8 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
1081
  * @since 3.0.12
1082
  * @access public
1083
  */
1084
- public function render_upsell() {
1085
- $this->load_layout( 'feedzy-upsell' );
1086
  }
1087
 
1088
  /**
275
  // display feed title yes/no
276
  'target' => '_blank',
277
  // _blank, _self
278
+ 'follow' => '',
279
+ // empty or no for nofollow
280
  'title' => '',
281
  // strip title after X char
282
  'meta' => 'yes',
292
  'size' => '',
293
  // thumbs pixel size
294
  'keywords_title' => '',
295
+ // only display item if title contains specific keywords (comma-separated list/case sensitive)
296
  'refresh' => '12_hours',
297
+ // cache refresh
298
  'sort' => '',
299
+ // sorting.
300
+ 'http' => 'auto',
301
+ // http images, https = force https|default = fall back to default image|auto = continue as it is
302
  ),
303
  $atts,
304
  'feedzy_default'
628
  $content .= '</div>';
629
  }
630
  $content .= '<ul>';
631
+ $anchor1 = '<a href="%s" target="%s" rel="%s" title="%s" style="%s">%s</a>';
632
+ $anchor2 = '<a href="%s" target="%s" rel="%s">%s</a>';
633
  foreach ( $feed_items as $item ) {
634
  $content .= '
635
  <li ' . $item['itemAttr'] . '>
636
  ' . ( ( ! empty( $item['item_img'] ) && $sc['thumb'] != 'no' ) ? '
637
+ <div class="' . $item['item_img_class'] . '" style="' . $item['item_img_style'] . '">'
638
+ . sprintf( $anchor1, $item['item_url'], $item['item_url_target'], $item['item_url_follow'], $item['item_url_title'], $item['item_img_style'], $item['item_img'] )
639
+ . '</div>' : '' )
640
+ . '<span class="title">'
641
+ . sprintf( $anchor2, $item['item_url'], $item['item_url_target'], $item['item_url_follow'], $item['item_title'] )
642
+ . '</span>
 
 
 
 
643
  <div class="' . $item['item_content_class'] . '" style="' . $item['item_content_style'] . '">
644
  ' . ( ! empty( $item['item_meta'] ) ? '<small>
645
  ' . $item['item_meta'] . '
651
  }
652
  $content .= '</ul> </div>';
653
  $content = apply_filters( 'feedzy_global_output', $content, $sc, $feed_title, $feed_items );
 
654
  return $content;
655
  }
656
 
729
  $count = 0;
730
  $items = apply_filters( 'feedzy_feed_items', $feed->get_items(), $feedURL );
731
  foreach ( (array) $items as $item ) {
 
732
  $continue = apply_filters( 'feedzy_item_keyword', true, $sc, $item, $feedURL );
733
+ if ( $continue == true ) {
734
+ // Count items. This should be > and not >= because max, when not defined and empty, becomes 0.
735
+ if ( $count >= $sc['max'] ) {
736
+ break;
 
 
 
 
 
737
  }
738
+ $itemAttr = apply_filters( 'feedzy_item_attributes', $itemAttr = '', $sizes, $item, $feedURL, $sc );
739
+ $feed_items[ $count ] = $this->get_feed_item_filter( $sc, $sizes, $item, $feedURL, $count );
740
+ $feed_items[ $count ]['itemAttr'] = $itemAttr;
741
+ $count ++;
742
  }
743
  }
744
 
755
  * @param array $sizes The sizes array.
756
  * @param object $item The feed item object.
757
  * @param string $feedURL The feed url.
758
+ * @param int $index The item number.
759
  *
760
  * @return array
761
  */
762
+ private function get_feed_item_filter( $sc, $sizes, $item, $feedURL, $index ) {
763
  $itemLink = $item->get_permalink();
764
  $newLink = apply_filters( 'feedzy_item_url_filter', $itemLink, $sc, $item );
765
  // Fetch image thumbnail
766
  if ( $sc['thumb'] == 'yes' || $sc['thumb'] == 'auto' ) {
767
+ $theThumbnail = $this->feedzy_retrieve_image( $item, $sc );
768
  }
769
  if ( $sc['thumb'] == 'yes' || $sc['thumb'] == 'auto' ) {
770
  $contentThumb = '';
847
  'item_img_style' => 'width:' . $sizes['width'] . 'px; height:' . $sizes['height'] . 'px;',
848
  'item_url' => $newLink,
849
  'item_url_target' => $sc['target'],
850
+ 'item_url_follow' => 'no' === $sc['follow'] ? 'nofollow' : '',
851
  'item_url_title' => $item->get_title(),
852
  'item_img' => $contentThumb,
853
+ 'item_img_path' => $this->feedzy_retrieve_image( $item, $sc ),
854
  'item_title' => $contentTitle,
855
  'item_content_class' => 'rss_content',
856
  'item_content_style' => '',
860
  'item_description' => $contentSummary,
861
  'item_content' => apply_filters( 'feedzy_content', $item->get_content( false ), $item ),
862
  );
863
+ $itemArray = apply_filters( 'feedzy_item_filter', $itemArray, $item, $sc, $index );
864
 
865
  return $itemArray;
866
  }
872
  * @access public
873
  *
874
  * @param object $item The item object.
875
+ * @param array $sc The shorcode attributes array.
876
  *
877
  * @return string
878
  */
879
+ public function feedzy_retrieve_image( $item, $sc ) {
880
  $theThumbnail = '';
881
  if ( $enclosures = $item->get_enclosures() ) {
882
  foreach ( (array) $enclosures as $enclosure ) {
927
  $theThumbnail = $this->feedzy_return_image( $feedDescription );
928
  }
929
 
930
+ // handle HTTP images.
931
+ if ( 0 === strpos( $theThumbnail, 'http://' ) ) {
932
+ switch ( $sc['http'] ) {
933
+ case 'https':
934
+ $theThumbnail = str_replace( 'http://', 'https://', $theThumbnail );
935
+ break;
936
+ case 'default':
937
+ $theThumbnail = $sc['default'];
938
+ break;
939
+ }
940
+ }
941
+
942
  $theThumbnail = apply_filters( 'feedzy_retrieve_image', $theThumbnail, $item );
943
 
944
  return $theThumbnail;
1063
  $string = $imgUrl[0][0];
1064
  }
1065
  }
 
 
 
 
 
 
 
 
 
 
1066
 
1067
+ $return = apply_filters( 'feedzy_image_encode', esc_url( $string ), $string );
1068
+ do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'Changing image URL from %s to %s', $string, $return ), 'debug', __FILE__, __LINE__ );
1069
+ return $return;
1070
  }
1071
 
1072
  /**
1086
  * @since 3.0.12
1087
  * @access public
1088
  */
1089
+ public function render_support() {
1090
+ $this->load_layout( 'feedzy-support' );
1091
  }
1092
 
1093
  /**
includes/admin/feedzy-rss-feeds-admin.php CHANGED
@@ -359,26 +359,7 @@ class Feedzy_Rss_Feeds_Admin extends Feedzy_Rss_Feeds_Admin_Abstract {
359
  public function feedzy_menu_pages() {
360
  $svg_base64_icon = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4NTAuMzkiIGhlaWdodD0iODUwLjM5Ij48cGF0aCBmaWxsPSIjREIzOTM5IiBkPSJNNDI1LjIgMkMxOTAuMzYgMiAwIDE5MS45MiAwIDQyNi4yYzAgMjM0LjI3IDE5MC4zNyA0MjQuMiA0MjUuMiA0MjQuMiAyMzQuODIgMCA0MjUuMi0xODkuOTMgNDI1LjItNDI0LjJDODUwLjQgMTkxLjkgNjYwIDIgNDI1LjIgMnptLTQ2LjU1IDY2OC42NmgtOTEuNTh2LTU3LjFMMjM3LjUgNTY0LjFoLTU3LjI2di05MS4yNGg5NS4yNWwxMDMuMTUgMTAyLjh2OTV6bTE1Mi41MiAwSDQzOS42di0xMzMuM0wzMTMuODUgNDExLjk0aC0xMzMuNnYtOTEuMzZIMzUxLjdMNTMxLjE4IDQ5OS42djE3MS4wNnptMTUyLjU1IDBoLTkxLjU4VjQ2MS4yTDM5MC4wNiAyNTkuNzRIMTgwLjI0di05MS4zNmgyNDcuOGwyNTUuNjggMjU1LjA3djI0Ny4yMnoiLz48L3N2Zz4=';
361
  add_menu_page( __( 'Feedzy RSS Feeds', 'feedzy-rss-feeds' ), __( 'Feedzy RSS', 'feedzy-rss-feeds' ), 'manage_options', 'feedzy-admin-menu', '', $svg_base64_icon, 98.7666 );
362
- if ( ! class_exists( 'Feedzy_Rss_Feeds_Pro' ) ) {
363
- add_submenu_page(
364
- 'feedzy-admin-menu',
365
- __( 'More Features', 'feedzy-rss-feeds' ),
366
- __( 'More Features', 'feedzy-rss-feeds' ) . '<span class="dashicons
367
- dashicons-star-filled more-features-icon" style="width: 17px; height: 17px; margin-left: 4px; color: #ffca54; font-size: 17px; vertical-align: -3px;"></span>',
368
- 'manage_options',
369
- 'feedzy-admin-menu-pro-upsell',
370
- array(
371
- $this,
372
- 'render_upsell',
373
- )
374
- );
375
- } else {
376
- // feedzy_is_license_of_type should be enough but if someone has new lite and old pro, they would lose the functionality so let's make it backward compatible.
377
- $is_pro = apply_filters( 'feedzy_is_license_of_type', false, 'pro' ) || apply_filters( 'feedzy_is_business_filter', false );
378
- if ( $is_pro ) {
379
- add_submenu_page( 'feedzy-admin-menu', __( 'Import Posts', 'feedzy-rss-feeds' ), __( 'Import Posts', 'feedzy-rss-feeds' ), 'manage_options', 'edit.php?post_type=feedzy_imports' );
380
- }
381
- }
382
  add_submenu_page(
383
  'feedzy-admin-menu',
384
  __( 'Settings', 'feedzy-rss-feeds' ),
@@ -390,6 +371,17 @@ class Feedzy_Rss_Feeds_Admin extends Feedzy_Rss_Feeds_Admin_Abstract {
390
  'feedzy_settings_page',
391
  )
392
  );
 
 
 
 
 
 
 
 
 
 
 
393
  }
394
 
395
  /**
@@ -553,5 +545,21 @@ class Feedzy_Rss_Feeds_Admin extends Feedzy_Rss_Feeds_Admin_Abstract {
553
  remove_filter( 'http_headers_useragent', array( $this, 'add_user_agent' ) );
554
  }
555
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
556
 
557
  }
359
  public function feedzy_menu_pages() {
360
  $svg_base64_icon = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4NTAuMzkiIGhlaWdodD0iODUwLjM5Ij48cGF0aCBmaWxsPSIjREIzOTM5IiBkPSJNNDI1LjIgMkMxOTAuMzYgMiAwIDE5MS45MiAwIDQyNi4yYzAgMjM0LjI3IDE5MC4zNyA0MjQuMiA0MjUuMiA0MjQuMiAyMzQuODIgMCA0MjUuMi0xODkuOTMgNDI1LjItNDI0LjJDODUwLjQgMTkxLjkgNjYwIDIgNDI1LjIgMnptLTQ2LjU1IDY2OC42NmgtOTEuNTh2LTU3LjFMMjM3LjUgNTY0LjFoLTU3LjI2di05MS4yNGg5NS4yNWwxMDMuMTUgMTAyLjh2OTV6bTE1Mi41MiAwSDQzOS42di0xMzMuM0wzMTMuODUgNDExLjk0aC0xMzMuNnYtOTEuMzZIMzUxLjdMNTMxLjE4IDQ5OS42djE3MS4wNnptMTUyLjU1IDBoLTkxLjU4VjQ2MS4yTDM5MC4wNiAyNTkuNzRIMTgwLjI0di05MS4zNmgyNDcuOGwyNTUuNjggMjU1LjA3djI0Ny4yMnoiLz48L3N2Zz4=';
361
  add_menu_page( __( 'Feedzy RSS Feeds', 'feedzy-rss-feeds' ), __( 'Feedzy RSS', 'feedzy-rss-feeds' ), 'manage_options', 'feedzy-admin-menu', '', $svg_base64_icon, 98.7666 );
362
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
  add_submenu_page(
364
  'feedzy-admin-menu',
365
  __( 'Settings', 'feedzy-rss-feeds' ),
371
  'feedzy_settings_page',
372
  )
373
  );
374
+ add_submenu_page(
375
+ 'feedzy-admin-menu',
376
+ __( 'Support', 'feedzy-rss-feeds' ),
377
+ __( 'Support', 'feedzy-rss-feeds' ) . '<span class="dashicons dashicons-editor-help more-features-icon" style="width: 17px; height: 17px; margin-left: 4px; color: #ffca54; font-size: 17px; vertical-align: -3px;"></span>',
378
+ 'manage_options',
379
+ 'feedzy-support',
380
+ array(
381
+ $this,
382
+ 'render_support',
383
+ )
384
+ );
385
  }
386
 
387
  /**
545
  remove_filter( 'http_headers_useragent', array( $this, 'add_user_agent' ) );
546
  }
547
 
548
+ /**
549
+ * On activation of the plugin
550
+ *
551
+ * @access public
552
+ */
553
+ public function on_activation( $plugin ) {
554
+ if ( defined( 'TI_UNIT_TESTING' ) ) {
555
+ return;
556
+ }
557
+
558
+ if ( $plugin == FEEDZY_BASENAME ) {
559
+ wp_redirect( admin_url( 'admin.php?page=feedzy-support&tab=help#shortcode' ) );
560
+ exit();
561
+ }
562
+ }
563
+
564
 
565
  }
includes/admin/feedzy-rss-feeds-ui-lang.php CHANGED
@@ -210,6 +210,21 @@ class Feedzy_Rss_Feeds_Ui_Lang {
210
  ),
211
  ),
212
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  'title' => array(
214
  'label' => __( 'Trim the title of the item after X characters.', 'feedzy-rss-feeds' ),
215
  'placeholder' => __( '(eg: 160)', 'feedzy-rss-feeds' ),
@@ -305,6 +320,25 @@ class Feedzy_Rss_Feeds_Ui_Lang {
305
  'type' => 'text',
306
  'value' => '',
307
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
  ),
309
  ),
310
  'section_pro' => array(
@@ -312,7 +346,7 @@ class Feedzy_Rss_Feeds_Ui_Lang {
312
  'description' => __( 'Get access to more options and customizations with full version of Feedzy RSS Feeds . Use existing templates or extend them and make them your own.', 'feedzy-rss-feeds' ) . '<br/>' . '<a href="' . FEEDZY_UPSELL_LINK . '" target="_blank"><small>' . __( 'See more features of Feedzy RSS Feeds ', 'feedzy-rss-feeds' ) . '</small></a>',
313
  'elements' => array(
314
  'price' => array(
315
- 'label' => __( 'Should we display the price from the feed if it is available?', 'feedzy-rss-feeds' ),
316
  'type' => 'select',
317
  'disabled' => true,
318
  'value' => '',
@@ -341,6 +375,12 @@ class Feedzy_Rss_Feeds_Ui_Lang {
341
  'disabled' => true,
342
  'value' => '1',
343
  ),
 
 
 
 
 
 
344
  'template' => array(
345
  'label' => __( 'Template to use when displaying the feed.', 'feedzy-rss-feeds' ),
346
  'type' => 'radio',
210
  ),
211
  ),
212
  ),
213
+ 'follow' => array(
214
+ 'label' => __( 'Make this link a "nofollow" link?', 'feedzy-rss-feeds' ),
215
+ 'type' => 'select',
216
+ 'value' => '',
217
+ 'opts' => array(
218
+ 'auto' => array(
219
+ 'label' => __( 'No', 'feedzy-rss-feeds' ),
220
+ 'value' => '',
221
+ ),
222
+ '_blank' => array(
223
+ 'label' => __( 'Yes', 'feedzy-rss-feeds' ),
224
+ 'value' => 'no',
225
+ ),
226
+ ),
227
+ ),
228
  'title' => array(
229
  'label' => __( 'Trim the title of the item after X characters.', 'feedzy-rss-feeds' ),
230
  'placeholder' => __( '(eg: 160)', 'feedzy-rss-feeds' ),
320
  'type' => 'text',
321
  'value' => '',
322
  ),
323
+ 'http' => array(
324
+ 'label' => __( 'How should we treat HTTP images?', 'feedzy-rss-feeds' ),
325
+ 'type' => 'select',
326
+ 'value' => '',
327
+ 'opts' => array(
328
+ 'auto' => array(
329
+ 'label' => __( 'Show with HTTP link', 'feedzy-rss-feeds' ),
330
+ 'value' => '',
331
+ ),
332
+ 'yes' => array(
333
+ 'label' => __( 'Force HTTPS (please verify that the images exist on HTTPS)', 'feedzy-rss-feeds' ),
334
+ 'value' => 'force',
335
+ ),
336
+ 'no' => array(
337
+ 'label' => __( 'Ignore and show the default image instead', 'feedzy-rss-feeds' ),
338
+ 'value' => 'default',
339
+ ),
340
+ ),
341
+ ),
342
  ),
343
  ),
344
  'section_pro' => array(
346
  'description' => __( 'Get access to more options and customizations with full version of Feedzy RSS Feeds . Use existing templates or extend them and make them your own.', 'feedzy-rss-feeds' ) . '<br/>' . '<a href="' . FEEDZY_UPSELL_LINK . '" target="_blank"><small>' . __( 'See more features of Feedzy RSS Feeds ', 'feedzy-rss-feeds' ) . '</small></a>',
347
  'elements' => array(
348
  'price' => array(
349
+ 'label' => __( 'Should we display the price from the feed if it is available? <br/> You can read about how to extract price from a custom tag %1$shere%2$s', 'feedzy-rss-feeds' ),
350
  'type' => 'select',
351
  'disabled' => true,
352
  'value' => '',
375
  'disabled' => true,
376
  'value' => '1',
377
  ),
378
+ 'mapping' => array(
379
+ 'label' => sprintf( __( 'Provide mapping for custom feed elements as per %1$sthis document here%2$s. This will only work for single feeds, not comma-separated feeds.', 'feedzy-rss-feeds' ), '<a href="https://docs.themeisle.com/article/977-how-do-i-extract-values-from-custom-tags-in-feedzy" target="_blank">', '</a>' ),
380
+ 'type' => 'text',
381
+ 'disabled' => true,
382
+ 'value' => '',
383
+ ),
384
  'template' => array(
385
  'label' => __( 'Template to use when displaying the feed.', 'feedzy-rss-feeds' ),
386
  'type' => 'radio',
includes/admin/feedzy-rss-feeds-ui.php CHANGED
@@ -62,6 +62,19 @@ class Feedzy_Rss_Feeds_Ui {
62
 
63
  }
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  /**
66
  * Initialize the hooks and filters for the tinymce button
67
  *
@@ -69,16 +82,13 @@ class Feedzy_Rss_Feeds_Ui {
69
  * @access public
70
  */
71
  public function register_init() {
72
- if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) ) {
73
- if ( 'true' == get_user_option( 'rich_editing' ) ) {
74
-
75
- $this->loader->add_filter( 'mce_external_plugins', $this, 'feedzy_tinymce_plugin', 10, 1 );
76
- $this->loader->add_filter( 'mce_buttons', $this, 'feedzy_register_mce_button', 10, 1 );
77
 
78
- $this->loader->add_action( 'admin_enqueue_scripts', $this, 'enqueue_scripts', 10 );
79
 
80
- $this->loader->run();
81
- }
82
  }
83
  }
84
 
62
 
63
  }
64
 
65
+ /**
66
+ * Checks if this is being called inside the Gutenberg block editor.
67
+ *
68
+ * @since 3.3.2
69
+ * @access private
70
+ */
71
+ private function is_block_editor() {
72
+ require_once( ABSPATH . 'wp-admin/includes/screen.php' );
73
+ global $current_screen;
74
+ $current_screen = get_current_screen();
75
+ return method_exists( $current_screen, 'is_block_editor' ) && $current_screen->is_block_editor();
76
+ }
77
+
78
  /**
79
  * Initialize the hooks and filters for the tinymce button
80
  *
82
  * @access public
83
  */
84
  public function register_init() {
85
+ if ( ! $this->is_block_editor() && current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) {
86
+ $this->loader->add_filter( 'mce_external_plugins', $this, 'feedzy_tinymce_plugin', 10, 1 );
87
+ $this->loader->add_filter( 'mce_buttons', $this, 'feedzy_register_mce_button', 10, 1 );
 
 
88
 
89
+ $this->loader->add_action( 'admin_enqueue_scripts', $this, 'enqueue_scripts', 10 );
90
 
91
+ $this->loader->run();
 
92
  }
93
  }
94
 
includes/feedzy-rss-feeds.php CHANGED
@@ -104,7 +104,7 @@ class Feedzy_Rss_Feeds {
104
  */
105
  public function init() {
106
  self::$plugin_name = 'feedzy-rss-feeds';
107
- self::$version = '3.3.1';
108
  self::$instance->load_dependencies();
109
  self::$instance->set_locale();
110
  self::$instance->define_admin_hooks();
@@ -187,11 +187,12 @@ class Feedzy_Rss_Feeds {
187
  */
188
  private function define_admin_hooks() {
189
  $plugin_ui = new Feedzy_Rss_Feeds_Ui( self::$instance->get_plugin_name(), self::$instance->get_version(), self::$instance->loader );
190
- self::$instance->loader->add_action( 'init', $plugin_ui, 'register_init' );
191
  self::$instance->loader->add_action( 'init', self::$instance->admin, 'register_post_type' );
192
  self::$instance->loader->add_action( 'save_post', self::$instance->admin, 'save_feedzy_post_type_meta', 1, 2 );
193
  self::$instance->loader->add_action( 'feedzy_pre_http_setup', self::$instance->admin, 'pre_http_setup', 10, 1 );
194
  self::$instance->loader->add_action( 'feedzy_post_http_teardown', self::$instance->admin, 'post_http_teardown', 10, 1 );
 
195
 
196
  self::$instance->loader->add_action( 'manage_feedzy_categories_posts_custom_column', self::$instance->admin, 'manage_feedzy_category_columns', 10, 2 );
197
  self::$instance->loader->add_filter( 'manage_feedzy_categories_posts_columns', self::$instance->admin, 'feedzy_category_columns' );
@@ -216,12 +217,15 @@ class Feedzy_Rss_Feeds {
216
  self::$instance->loader->add_action( 'admin_enqueue_scripts', self::$instance->admin, 'enqueue_styles' );
217
  $plugin_widget = new feedzy_wp_widget();
218
  self::$instance->loader->add_action( 'widgets_init', $plugin_widget, 'registerWidget', 10 );
219
- add_action(
220
- 'plugins_loaded', function () {
221
- if ( function_exists( 'register_block_type' ) ) {
222
- Feedzy_Rss_Feeds_Gutenberg_Block::get_instance();
223
- }}
224
- );
 
 
 
225
  }
226
 
227
  /**
104
  */
105
  public function init() {
106
  self::$plugin_name = 'feedzy-rss-feeds';
107
+ self::$version = '3.3.2';
108
  self::$instance->load_dependencies();
109
  self::$instance->set_locale();
110
  self::$instance->define_admin_hooks();
187
  */
188
  private function define_admin_hooks() {
189
  $plugin_ui = new Feedzy_Rss_Feeds_Ui( self::$instance->get_plugin_name(), self::$instance->get_version(), self::$instance->loader );
190
+ self::$instance->loader->add_action( 'admin_enqueue_scripts', $plugin_ui, 'register_init' );
191
  self::$instance->loader->add_action( 'init', self::$instance->admin, 'register_post_type' );
192
  self::$instance->loader->add_action( 'save_post', self::$instance->admin, 'save_feedzy_post_type_meta', 1, 2 );
193
  self::$instance->loader->add_action( 'feedzy_pre_http_setup', self::$instance->admin, 'pre_http_setup', 10, 1 );
194
  self::$instance->loader->add_action( 'feedzy_post_http_teardown', self::$instance->admin, 'post_http_teardown', 10, 1 );
195
+ self::$instance->loader->add_action( 'activated_plugin', self::$instance->admin, 'on_activation', 10, 1 );
196
 
197
  self::$instance->loader->add_action( 'manage_feedzy_categories_posts_custom_column', self::$instance->admin, 'manage_feedzy_category_columns', 10, 2 );
198
  self::$instance->loader->add_filter( 'manage_feedzy_categories_posts_columns', self::$instance->admin, 'feedzy_category_columns' );
217
  self::$instance->loader->add_action( 'admin_enqueue_scripts', self::$instance->admin, 'enqueue_styles' );
218
  $plugin_widget = new feedzy_wp_widget();
219
  self::$instance->loader->add_action( 'widgets_init', $plugin_widget, 'registerWidget', 10 );
220
+
221
+ if ( ! defined( 'TI_UNIT_TESTING' ) ) {
222
+ add_action(
223
+ 'plugins_loaded', function () {
224
+ if ( function_exists( 'register_block_type' ) ) {
225
+ Feedzy_Rss_Feeds_Gutenberg_Block::get_instance();
226
+ }}
227
+ );
228
+ }
229
  }
230
 
231
  /**
includes/gutenberg/feedzy-rss-feeds-gutenberg-block.php CHANGED
@@ -57,7 +57,7 @@ class Feedzy_Rss_Feeds_Gutenberg_Block {
57
  }
58
 
59
  // Enqueue the bundled block JS file
60
- wp_enqueue_script( 'feedzy-gutenberg-block-js', FEEDZY_ABSURL . 'includes/gutenberg/build/block.js', array( 'wp-i18n', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-api', 'lodash' ), $version );
61
 
62
  // Pass in REST URL
63
  wp_localize_script(
57
  }
58
 
59
  // Enqueue the bundled block JS file
60
+ wp_enqueue_script( 'feedzy-gutenberg-block-js', FEEDZY_ABSURL . 'includes/gutenberg/build/block.js', array( 'wp-i18n', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-editor', 'wp-api', 'lodash' ), $version );
61
 
62
  // Pass in REST URL
63
  wp_localize_script(
includes/layouts/feedzy-support.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div id="fz-features" class="fz-settings">
2
+
3
+ <?php load_template( FEEDZY_ABSPATH . '/includes/layouts/header.php' ); ?>
4
+
5
+ <?php
6
+ $active_tab = isset( $_REQUEST['tab'] ) ? sanitize_text_field( $_REQUEST['tab'] ) : 'help';
7
+ ?>
8
+
9
+ <h2 class="nav-tab-wrapper">
10
+ <a href="<?php echo esc_url( admin_url( 'admin.php?page=feedzy-support&tab=help' ) ); ?>"
11
+ class="nav-tab <?php echo $active_tab == 'help' ? 'nav-tab-active' : ''; ?>"><?php _e( 'Support', 'feedzy-rss-feeds' ); ?></a>
12
+ <?php
13
+ if ( ! class_exists( 'Feedzy_Rss_Feeds_Pro' ) ) {
14
+ ?>
15
+ <a href="<?php echo esc_url( admin_url( 'admin.php?page=feedzy-support&tab=more' ) ); ?>"
16
+ class="nav-tab <?php echo $active_tab == 'more' ? 'nav-tab-active' : ''; ?>"><?php _e( 'More Features', 'feedzy-rss-feeds' ); ?></a>
17
+ <?php
18
+ }
19
+ ?>
20
+ </h2>
21
+
22
+ <div class="fz-features-content">
23
+ <div class="fz-feature">
24
+ <div id="feedzy_import_feeds" class="fz-feature-features">
25
+ <?php
26
+ switch ( $active_tab ) {
27
+ case 'help':
28
+ load_template( FEEDZY_ABSPATH . '/includes/layouts/feedzy-tutorial.php' );
29
+ break;
30
+ case 'more':
31
+ if ( ! class_exists( 'Feedzy_Rss_Feeds_Pro' ) ) {
32
+ load_template( FEEDZY_ABSPATH . '/includes/layouts/feedzy-upsell.php' );
33
+ }
34
+ break;
35
+ }
36
+ ?>
37
+ </div>
38
+ </div>
39
+ </div>
40
+
41
+ </div>
includes/layouts/feedzy-tutorial.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!--
2
+ Layout For Tutorial Page of Feedzy RSS Feeds
3
+
4
+ @since ?
5
+ @package feedzy-rss-feeds
6
+ -->
7
+ <div id="fz-features">
8
+
9
+ <div class="fz-features-content">
10
+
11
+ <a name="shortcode"></a>
12
+ <div class="fz-feature">
13
+ <div class="fz-feature-features">
14
+ <h2>Shortcode</h2>
15
+ <p>Show feed items using the <code>[feedzy-rss-feeds]</code>shortcode in a few easy steps.</p>
16
+ <p>You can view our documentation <a href="https://docs.themeisle.com/article/658-feedzy-rss-feeds" target="_blank">here</a></p>
17
+ </div>
18
+ <div class="fz-feature-image">
19
+ <iframe width="603" height="508" src="https://www.youtube.com/embed/GEFAY2IxxEc?start=84" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
20
+ </div>
21
+ </div>
22
+
23
+ <?php if ( class_exists( 'Feedzy_Rss_Feeds_Pro' ) ) { ?>
24
+ <a name="import"></a>
25
+ <div class="fz-feature">
26
+ <div class="fz-feature-features">
27
+ <h2>Feed to Post</h2>
28
+ <p>Convert feed items into WordPress Posts, Pages, or any custom post type in a few easy steps.</p>
29
+ <p>You can view our documentation <a href="https://docs.themeisle.com/article/742-how-to-import-posts-from-feeds-in-feedzy" target="_blank">here</a></p>
30
+ </div>
31
+ <div class="fz-feature-image">
32
+ <iframe width="603" height="508" src="https://www.youtube.com/embed/Fzx5W_PfQsQ" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
33
+ </div>
34
+ </div>
35
+ <?php } ?>
36
+
37
+ <div class="fz-feature">
38
+ <div class="fz-feature-features fz-feature-centered">
39
+ <h2>Grow your WordPress business with Feedzy today.</h4>
40
+ <div class="header-btns">
41
+ <?php
42
+ if ( ! defined( 'FEEDZY_PRO_ABSURL' ) ) :
43
+ ?>
44
+ <a target="_blank" href="<?php echo FEEDZY_UPSELL_LINK; ?>" class="buy-now"><span
45
+ class="dashicons dashicons-cart"></span> Get Feedzy Pro</a>
46
+ <?php
47
+ endif;
48
+ ?>
49
+ </div>
50
+
51
+ </div><!-- .fz-features-content -->
52
+
53
+ </div>
includes/layouts/feedzy-upsell.php CHANGED
@@ -6,8 +6,6 @@ Layout For Upsell Page of Feedzy RSS Feeds
6
  -->
7
  <div id="fz-features">
8
 
9
- <?php load_template( FEEDZY_ABSPATH . '/includes/layouts/header.php' ); ?>
10
-
11
  <div class="fz-features-content">
12
 
13
  <div class="fz-feature">
6
  -->
7
  <div id="fz-features">
8
 
 
 
9
  <div class="fz-features-content">
10
 
11
  <div class="fz-feature">
readme.md CHANGED
@@ -1,9 +1,9 @@
1
  # FEEDZY RSS Feeds Lite #
2
- **Contributors:** [themeisle](https://profiles.wordpress.org/themeisle), [codeinwp](https://profiles.wordpress.org/codeinwp), [hardeepasrani](https://profiles.wordpress.org/hardeepasrani)
3
  **Tags:** RSS feed, autoblogging, autoblog, rss aggregator, feed to post
4
  **Requires at least:** 3.7
5
  **Requires PHP:** 5.3
6
- **Tested up to:** 4.9
7
  **Stable tag:** trunk
8
  **License:** GPLv2 or later
9
  **License URI:** http://www.gnu.org/licenses/gpl-2.0.html
@@ -392,6 +392,15 @@ You have to check first if your feed is valid. Please test it here: https://vali
392
 
393
 
394
  ## Changelog ##
 
 
 
 
 
 
 
 
 
395
  ### 3.3.1 - 2018-11-05 ###
396
 
397
  * Import Posts enabled for plan 1 users
1
  # FEEDZY RSS Feeds Lite #
2
+ **Contributors:** [themeisle](https://profiles.wordpress.org/themeisle), [codeinwp](https://profiles.wordpress.org/codeinwp), [hardeepasrani](https://profiles.wordpress.org/hardeepasrani), [contactashish13](https://profiles.wordpress.org/contactashish13)
3
  **Tags:** RSS feed, autoblogging, autoblog, rss aggregator, feed to post
4
  **Requires at least:** 3.7
5
  **Requires PHP:** 5.3
6
+ **Tested up to:** 5.0
7
  **Stable tag:** trunk
8
  **License:** GPLv2 or later
9
  **License URI:** http://www.gnu.org/licenses/gpl-2.0.html
392
 
393
 
394
  ## Changelog ##
395
+ ### 3.3.2 - 2018-12-22 ###
396
+
397
+ * Option to handle HTTP images in the shortcode
398
+ * Option to specify nofollow for links in the shortcode
399
+ * Fix Gutenberg block
400
+ * Add video tutorials under Help menu
401
+ * Add support for extracting price from custom feed tags
402
+
403
+
404
  ### 3.3.1 - 2018-11-05 ###
405
 
406
  * Import Posts enabled for plan 1 users
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === FEEDZY RSS Feeds Lite ===
2
- Contributors: themeisle,codeinwp,hardeepasrani
3
  Tags: RSS feed, autoblogging, autoblog, rss aggregator, feed to post
4
  Requires at least: 3.7
5
  Requires PHP: 5.3
6
- Tested up to: 4.9
7
  Stable tag: trunk
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -159,6 +159,7 @@ Become a translator and send me your translation! [Contact-me](http://themeisle.
159
 
160
 
161
 
 
162
  = Is it responsive friendly? =
163
 
164
  Yes it is.
@@ -383,6 +384,12 @@ You have to check first if your feed is valid. Please test it here: https://vali
383
  = How price is displayed from the feed =
384
  [https://docs.themeisle.com/article/923-how-price-is-displayed-from-the-feed](https://docs.themeisle.com/article/923-how-price-is-displayed-from-the-feed)
385
 
 
 
 
 
 
 
386
  == Screenshots ==
387
 
388
  1. Simple example
@@ -392,6 +399,15 @@ You have to check first if your feed is valid. Please test it here: https://vali
392
 
393
 
394
  == Changelog ==
 
 
 
 
 
 
 
 
 
395
  = 3.3.1 - 2018-11-05 =
396
 
397
  * Import Posts enabled for plan 1 users
1
  === FEEDZY RSS Feeds Lite ===
2
+ Contributors: themeisle,codeinwp,hardeepasrani,contactashish13
3
  Tags: RSS feed, autoblogging, autoblog, rss aggregator, feed to post
4
  Requires at least: 3.7
5
  Requires PHP: 5.3
6
+ Tested up to: 5.0
7
  Stable tag: trunk
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
159
 
160
 
161
 
162
+
163
  = Is it responsive friendly? =
164
 
165
  Yes it is.
384
  = How price is displayed from the feed =
385
  [https://docs.themeisle.com/article/923-how-price-is-displayed-from-the-feed](https://docs.themeisle.com/article/923-how-price-is-displayed-from-the-feed)
386
 
387
+ = How to find Feed URL for Feedzy RSS Feeds =
388
+ [https://docs.themeisle.com/article/799-how-to-find-feed-url-for-feedzy-rss-feeds](https://docs.themeisle.com/article/799-how-to-find-feed-url-for-feedzy-rss-feeds)
389
+
390
+ = In Feedzy how do I... =
391
+ [https://docs.themeisle.com/article/942-in-feedzy-how-do-i](https://docs.themeisle.com/article/942-in-feedzy-how-do-i)
392
+
393
  == Screenshots ==
394
 
395
  1. Simple example
399
 
400
 
401
  == Changelog ==
402
+ = 3.3.2 - 2018-12-22 =
403
+
404
+ * Option to handle HTTP images in the shortcode
405
+ * Option to specify nofollow for links in the shortcode
406
+ * Fix Gutenberg block
407
+ * Add video tutorials under Help menu
408
+ * Add support for extracting price from custom feed tags
409
+
410
+
411
  = 3.3.1 - 2018-11-05 =
412
 
413
  * Import Posts enabled for plan 1 users
themeisle-hash.json CHANGED
@@ -1 +1 @@
1
- {"feedzy-rss-feed.php":"87038d2119d6a476b39eaa411283ea1c","index.php":"71c0755260138a4b7b2182c3c61179f6","uninstall.php":"cdb21f8648e005cbb9c73481d1750186"}
1
+ {"feedzy-rss-feed.php":"6d0bcc0490803b418b518502ef692e3d","index.php":"71c0755260138a4b7b2182c3c61179f6","uninstall.php":"cdb21f8648e005cbb9c73481d1750186"}
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
- return ComposerAutoloaderInitaea9a626a3fa577057e8dd7c4185e11c::getLoader();
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit192ce97fadbb58f36174182e5bd061ad::getLoader();
vendor/autoload_52.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once dirname(__FILE__) . '/composer'.'/autoload_real_52.php';
6
 
7
- return ComposerAutoloaderInitbb90e47cfa10dd66fde5d5b3c2ee86cf::getLoader();
4
 
5
  require_once dirname(__FILE__) . '/composer'.'/autoload_real_52.php';
6
 
7
+ return ComposerAutoloaderInit7300e34db896a77d95fa9ea47a0613a5::getLoader();
vendor/codeinwp/themeisle-sdk/CHANGELOG.md ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ # 1.0.0 (2018-12-21)
2
+
3
+
4
+ ### Features
5
+
6
+ * 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( $this->get_key() . '_' . preg_replace( '/[^0-9a-zA-Z ]/m', '', $this->version ) . 'versions' );
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, MONTH_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.7';
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
+ exit;
15
+ }
16
  // Current SDK version and path.
17
+ $themeisle_sdk_version = '3.0.0';
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,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
59
+ ];
60
+
61
+ /**
62
+ * Initialize the sdk logic.
63
+ */
64
+ public static function init() {
65
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Loader ) ) {
66
+ self::$instance = new Loader();
67
+ $modules = array_merge( self::$available_modules, apply_filters( 'themeisle_sdk_modules', [] ) );
68
+ foreach ( $modules as $key => $module ) {
69
+ if ( ! class_exists( 'ThemeisleSDK\\Modules\\' . ucwords( $module, '_' ) ) ) {
70
+ unset( $modules[ $key ] );
71
+ }
72
+ }
73
+ self::$available_modules = $modules;
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Register product into SDK.
79
+ *
80
+ * @param string $base_file The product base file.
81
+ *
82
+ * @return Loader The singleton object.
83
+ */
84
+ public static function add_product( $base_file ) {
85
+
86
+ if ( ! is_readable( $base_file ) ) {
87
+ return self::$instance;
88
+ }
89
+ $product = new Product( $base_file );
90
+
91
+ Module_Factory::attach( $product, self::get_modules() );
92
+
93
+ self::$products[ $product->get_slug() ] = $product;
94
+
95
+ return self::$instance;
96
+ }
97
+
98
+ /**
99
+ * Get all registered modules by the SDK.
100
+ *
101
+ * @return array Modules available.
102
+ */
103
+ public static function get_modules() {
104
+ return self::$available_modules;
105
+ }
106
+
107
+ /**
108
+ * Get all products using the SDK.
109
+ *
110
+ * @return array Products available.
111
+ */
112
+ public static function get_products() {
113
+ return self::$products;
114
+ }
115
+
116
+
117
+ }
vendor/codeinwp/themeisle-sdk/src/Modules/Dashboard_widget.php ADDED
@@ -0,0 +1,453 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ ),
285
+ '',
286
+ $recommend['name']
287
+ )
288
+ );
289
+ ?>
290
+ (<a class="thickbox open-plugin-details-modal"
291
+ href="<?php echo $url . '&TB_iframe=true&width=600&height=500'; ?>"><?php echo apply_filters( 'themeisle_sdk_dashboard_install_label', 'Install' ); ?></a>)
292
+ </span>
293
+ <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>
294
+ </div>
295
+
296
+ <?php
297
+
298
+ }
299
+
300
+ /**
301
+ * Setup feed items.
302
+ */
303
+ private function setup_feeds() {
304
+ if ( false === ( $items_normalized = get_transient( 'themeisle_sdk_feed_items' ) ) ) {
305
+ // Load SimplePie Instance.
306
+ $feed = fetch_feed( $this->feeds );
307
+ // TODO report error when is an error loading the feed.
308
+ if ( is_wp_error( $feed ) ) {
309
+ return;
310
+ }
311
+
312
+ $items = $feed->get_items( 0, 5 );
313
+ foreach ( (array) $items as $item ) {
314
+ $items_normalized[] = array(
315
+ 'title' => $item->get_title(),
316
+ 'date' => $item->get_date( 'U' ),
317
+ 'link' => $item->get_permalink(),
318
+ );
319
+ }
320
+ set_transient( 'themeisle_sdk_feed_items', $items_normalized, 48 * HOUR_IN_SECONDS );
321
+ }
322
+ $this->items = $items_normalized;
323
+ }
324
+
325
+ /**
326
+ * Either the current product is installed or not.
327
+ *
328
+ * @param array $val The current recommended product.
329
+ *
330
+ * @return bool Either we should exclude the plugin or not.
331
+ */
332
+ public function remove_current_products( $val ) {
333
+ if ( 'theme' === $val['type'] ) {
334
+ $exist = wp_get_theme( $val['slug'] );
335
+
336
+ return ! $exist->exists();
337
+ } else {
338
+ $all_plugins = array_keys( get_plugins() );
339
+ foreach ( $all_plugins as $slug ) {
340
+ if ( strpos( $slug, $val['slug'] ) !== false ) {
341
+ return false;
342
+ }
343
+ }
344
+
345
+ return true;
346
+ }
347
+ }
348
+
349
+ /**
350
+ * Contact the API and fetch the recommended plugins/themes
351
+ */
352
+ function recommend_plugin_or_theme() {
353
+ $products = $this->get_product_from_api();
354
+ if ( ! is_array( $products ) ) {
355
+ $products = array();
356
+ }
357
+ $products = array_filter( $products, array( $this, 'remove_current_products' ) );
358
+ $products = array_merge( $products );
359
+ if ( count( $products ) > 1 ) {
360
+ shuffle( $products );
361
+ $products = array_slice( $products, 0, 1 );
362
+ }
363
+ $to_recommend = isset( $products[0] ) ? $products[0] : $products;
364
+
365
+ return $to_recommend;
366
+ }
367
+
368
+ /**
369
+ * Fetch products from the recomended section.
370
+ *
371
+ * @return array|mixed The list of products to use in recomended section.
372
+ */
373
+ function get_product_from_api() {
374
+ if ( false === ( $products = get_transient( 'themeisle_sdk_products' ) ) ) {
375
+ $products = array();
376
+ $themeisle_themes = $this->get_themes_from_wporg( 'themeisle' );
377
+ $codeinwp_themes = $this->get_themes_from_wporg( 'codeinwp' );
378
+
379
+ $themeisle_plugins = $this->get_plugins_from_wporg( 'themeisle' );
380
+ $codeinwp_plugins = $this->get_plugins_from_wporg( 'codeinwp' );
381
+
382
+ $all_themes = array_merge( $themeisle_themes, $codeinwp_themes );
383
+ foreach ( $all_themes as $theme ) {
384
+ if ( $theme->active_installs < 4999 ) {
385
+ continue;
386
+ }
387
+ $products[] = array(
388
+ 'name' => $theme->name,
389
+ 'type' => 'theme',
390
+ 'slug' => $theme->slug,
391
+ 'installs' => $theme->active_installs,
392
+ );
393
+ }
394
+ $all_plugins = array_merge( $themeisle_plugins, $codeinwp_plugins );
395
+ foreach ( $all_plugins as $plugin ) {
396
+ if ( $plugin->active_installs < 4999 ) {
397
+ continue;
398
+ }
399
+ $products[] = array(
400
+ 'name' => $plugin->name,
401
+ 'type' => 'plugin',
402
+ 'slug' => $plugin->slug,
403
+ 'installs' => $plugin->active_installs,
404
+ );
405
+ }
406
+ set_transient( 'themeisle_sdk_products', $products, 6 * HOUR_IN_SECONDS );
407
+ }
408
+
409
+ return $products;
410
+ }
411
+
412
+ /**
413
+ * Fetch themes from wporg api.
414
+ *
415
+ * @param string $author The author name.
416
+ *
417
+ * @return array The list of themes.
418
+ */
419
+ function get_themes_from_wporg( $author ) {
420
+ $products = wp_remote_get(
421
+ 'https://api.wordpress.org/themes/info/1.1/?action=query_themes&request[author]=' . $author . '&request[per_page]=30&request[fields][active_installs]=true'
422
+ );
423
+ $products = json_decode( wp_remote_retrieve_body( $products ) );
424
+ if ( is_object( $products ) ) {
425
+ $products = isset( $products->themes ) ? $products->themes : array();
426
+ } else {
427
+ $products = array();
428
+ }
429
+
430
+ return (array) $products;
431
+ }
432
+
433
+ /**
434
+ * Fetch plugin from wporg api.
435
+ *
436
+ * @param string $author The author slug.
437
+ *
438
+ * @return array The list of plugins for the selected author.
439
+ */
440
+ function get_plugins_from_wporg( $author ) {
441
+ $products = wp_remote_get(
442
+ 'https://api.wordpress.org/plugins/info/1.1/?action=query_plugins&request[author]=' . $author . '&request[per_page]=20&request[fields][active_installs]=true'
443
+ );
444
+ $products = json_decode( wp_remote_retrieve_body( $products ) );
445
+ if ( is_object( $products ) ) {
446
+ $products = isset( $products->plugins ) ? $products->plugins : array();
447
+ } else {
448
+ $products = array();
449
+ }
450
+
451
+ return (array) $products;
452
+ }
453
+ }
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,716 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ }
415
+ if ( ! isset( $license_data->key ) ) {
416
+ $license_data->key = $license;
417
+ }
418
+ if ( 'valid' == $license_data->license ) {
419
+ $this->reset_failed_checks();
420
+ }
421
+
422
+ if ( isset( $license_data->plan ) ) {
423
+ update_option( $this->product->get_key() . '_license_plan', $license_data->plan );
424
+ }
425
+
426
+ update_option( $this->product->get_key() . '_license_data', $license_data );
427
+ set_transient( $this->product->get_key() . '_license_data', $license_data, 12 * HOUR_IN_SECONDS );
428
+
429
+ }
430
+
431
+ /**
432
+ * Load the Themes screen.
433
+ */
434
+ function load_themes_screen() {
435
+ add_thickbox();
436
+ add_action( 'admin_notices', array( &$this, 'update_nag' ) );
437
+ }
438
+
439
+ /**
440
+ * Alter the nag for themes update.
441
+ */
442
+ function update_nag() {
443
+ $theme = wp_get_theme( $this->product->get_slug() );
444
+ $api_response = get_transient( $this->product_key );
445
+ if ( false === $api_response ) {
446
+ return;
447
+ }
448
+ $update_url = wp_nonce_url( 'update.php?action=upgrade-theme&amp;theme=' . urlencode( $this->product->get_slug() ), 'upgrade-theme_' . $this->product->get_slug() );
449
+ $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.' );
450
+ $update_onclick = ' onclick="if ( confirm(\'' . esc_js( $update_message ) . '\') ) {return true;}return false;"';
451
+ if ( version_compare( $this->product->get_version(), $api_response->new_version, '<' ) ) {
452
+ echo '<div id="update-nag">';
453
+ printf(
454
+ '<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>.',
455
+ $theme->get( 'Name' ),
456
+ $api_response->new_version,
457
+ '#TB_inline?width=640&amp;inlineId=' . $this->product->get_version() . '_changelog',
458
+ $theme->get( 'Name' ),
459
+ $update_url,
460
+ $update_onclick
461
+ );
462
+ echo '</div>';
463
+ echo '<div id="' . $this->product->get_slug() . '_' . 'changelog" style="display:none;">';
464
+ echo wpautop( $api_response->sections['changelog'] );
465
+ echo '</div>';
466
+ }
467
+ }
468
+
469
+ /**
470
+ * Alter update transient.
471
+ *
472
+ * @param mixed $value The transient data.
473
+ *
474
+ * @return mixed
475
+ */
476
+ function theme_update_transient( $value ) {
477
+ $update_data = $this->check_for_update();
478
+ if ( $update_data ) {
479
+ $value->response[ $this->product->get_slug() ] = $update_data;
480
+ }
481
+
482
+ return $value;
483
+ }
484
+
485
+ /**
486
+ * Check for updates
487
+ *
488
+ * @return array|bool Either the update data or false in case of failure.
489
+ */
490
+ function check_for_update() {
491
+ $update_data = get_transient( $this->product_key );
492
+
493
+ if ( false === $update_data ) {
494
+ $failed = false;
495
+ $update_data = $this->get_version_data();
496
+ if ( empty( $update_data ) ) {
497
+ $failed = true;
498
+ }
499
+ // If the response failed, try again in 30 minutes.
500
+ if ( $failed ) {
501
+ $data = new \stdClass();
502
+ $data->new_version = $this->product->get_version();
503
+ set_transient( $this->product_key, $data, 30 * MINUTE_IN_SECONDS );
504
+
505
+ return false;
506
+ }
507
+ $update_data->sections = maybe_unserialize( $update_data->sections );
508
+
509
+ set_transient( $this->product_key, $update_data, 12 * HOUR_IN_SECONDS );
510
+ }
511
+ if ( ! isset( $update_data->new_version ) ) {
512
+ return false;
513
+ }
514
+ if ( version_compare( $this->product->get_version(), $update_data->new_version, '>=' ) ) {
515
+ return false;
516
+ }
517
+
518
+ return (array) $update_data;
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->get_distributor_name(),
534
+ 'url' => rawurlencode( home_url() ),
535
+ );
536
+ $response = wp_remote_get(
537
+ $this->get_api_url(),
538
+ array(
539
+ 'timeout' => 15,
540
+ 'sslverify' => false,
541
+ 'body' => $api_params,
542
+ )
543
+ );
544
+ if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
545
+ return false;
546
+ }
547
+ $update_data = json_decode( wp_remote_retrieve_body( $response ) );
548
+ if ( ! is_object( $update_data ) ) {
549
+ return false;
550
+ }
551
+
552
+ return $update_data;
553
+ }
554
+
555
+ /**
556
+ * Delete the update transient
557
+ */
558
+ function delete_theme_update_transient() {
559
+ delete_transient( $this->product_key );
560
+ }
561
+
562
+ /**
563
+ * Check for Updates at the defined API endpoint and modify the update array.
564
+ *
565
+ * @param array $_transient_data Update array build by WordPress.
566
+ *
567
+ * @return mixed Modified update array with custom plugin data.
568
+ */
569
+ public function pre_set_site_transient_update_plugins_filter( $_transient_data ) {
570
+ if ( empty( $_transient_data ) || ! $this->do_check ) {
571
+ $this->do_check = true;
572
+
573
+ return $_transient_data;
574
+ }
575
+ $api_response = $this->api_request();
576
+ if ( false !== $api_response && is_object( $api_response ) && isset( $api_response->new_version ) ) {
577
+ if ( version_compare( $this->product->get_version(), $api_response->new_version, '<' ) ) {
578
+ $_transient_data->response[ $this->product->get_slug() . '/' . $this->product->get_file() ] = $api_response;
579
+ }
580
+ }
581
+
582
+ return $_transient_data;
583
+ }
584
+
585
+ /**
586
+ * Calls the API and, if successfull, returns the object delivered by the API.
587
+ *
588
+ * @param string $_action The requested action.
589
+ * @param array $_data Parameters for the API action.
590
+ *
591
+ * @return false||object
592
+ */
593
+ private function api_request( $_action = '', $_data = '' ) {
594
+ $update_data = $this->get_version_data();
595
+ if ( empty( $update_data ) ) {
596
+ return false;
597
+ }
598
+ if ( $update_data && isset( $update_data->sections ) ) {
599
+ $update_data->sections = maybe_unserialize( $update_data->sections );
600
+ }
601
+
602
+ return $update_data;
603
+ }
604
+
605
+ /**
606
+ * Updates information on the "View version x.x details" page with custom data.
607
+ *
608
+ * @param mixed $_data Plugin data.
609
+ * @param string $_action Action to send.
610
+ * @param object $_args Arguments to use.
611
+ *
612
+ * @return object $_data
613
+ */
614
+ public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
615
+ if ( ( 'plugin_information' != $_action ) || ! isset( $_args->slug ) || ( $_args->slug != $this->product->get_slug() ) ) {
616
+ return $_data;
617
+ }
618
+ $api_response = $this->api_request();
619
+ if ( false !== $api_response ) {
620
+ $_data = $api_response;
621
+ }
622
+
623
+ return $_data;
624
+ }
625
+
626
+ /**
627
+ * Disable SSL verification in order to prevent download update failures.
628
+ *
629
+ * @param array $args Http args.
630
+ * @param string $url Url to check.
631
+ *
632
+ * @return array $array
633
+ */
634
+ function http_request_args( $args, $url ) {
635
+ // If it is an https request and we are performing a package download, disable ssl verification.
636
+ if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
637
+ $args['sslverify'] = false;
638
+ }
639
+
640
+ return $args;
641
+ }
642
+
643
+ /**
644
+ * Check if we should load the module for this product.
645
+ *
646
+ * @param Product $product Product data.
647
+ *
648
+ * @return bool Should we load the module?
649
+ */
650
+ public function can_load( $product ) {
651
+
652
+ if ( $product->is_wordpress_available() ) {
653
+ return false;
654
+ }
655
+
656
+ return ( apply_filters( $product->get_key() . '_enable_licenser', true ) === true );
657
+
658
+ }
659
+
660
+ /**
661
+ * Load module logic.
662
+ *
663
+ * @param Product $product Product to load the module for.
664
+ *
665
+ * @return Licenser Module object.
666
+ */
667
+ public function load( $product ) {
668
+ $this->product = $product;
669
+
670
+ $this->product_key = $this->product->get_key() . '-update-response';
671
+
672
+ $this->license_key = $this->product->get_license();
673
+ if ( $this->product->requires_license() ) {
674
+ $this->failed_checks = intval( get_option( $this->product->get_key() . '_failed_checks', 0 ) );
675
+ $this->register_license_hooks();
676
+ }
677
+
678
+ if ( $this->product->is_plugin() ) {
679
+ add_filter(
680
+ 'pre_set_site_transient_update_plugins',
681
+ [
682
+ $this,
683
+ 'pre_set_site_transient_update_plugins_filter',
684
+ ]
685
+ );
686
+ add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
687
+ add_filter( 'http_request_args', array( $this, 'http_request_args' ), 10, 2 );
688
+
689
+ return $this;
690
+ }
691
+ if ( $this->product->is_theme() ) {
692
+ add_filter( 'site_transient_update_themes', array( &$this, 'theme_update_transient' ) );
693
+ add_filter( 'delete_site_transient_update_themes', array( &$this, 'delete_theme_update_transient' ) );
694
+ add_action( 'load-update-core.php', array( &$this, 'delete_theme_update_transient' ) );
695
+ add_action( 'load-themes.php', array( &$this, 'delete_theme_update_transient' ) );
696
+ add_action( 'load-themes.php', array( &$this, 'load_themes_screen' ) );
697
+ add_filter( 'http_request_args', array( $this, 'disable_wporg_update' ), 5, 2 );
698
+
699
+ return $this;
700
+
701
+ }
702
+
703
+ return $this;
704
+ }
705
+
706
+ /**
707
+ * Register license fields for the products.
708
+ */
709
+ public function register_license_hooks() {
710
+ add_action( 'admin_init', array( $this, 'register_settings' ) );
711
+ add_action( 'admin_init', array( $this, 'activate_license' ) );
712
+ add_action( 'admin_init', array( $this, 'product_valid' ), 99999999 );
713
+ add_action( 'admin_notices', array( $this, 'show_notice' ) );
714
+ add_filter( $this->product->get_key() . '_license_status', array( $this, 'get_license_status' ) );
715
+ }
716
+ }
vendor/codeinwp/themeisle-sdk/src/Modules/Logger.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
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
+ 'data' => apply_filters( $this->product->get_key() . '_logger_data', array() ),
170
+ 'environment' => $environment,
171
+ 'license' => apply_filters( $this->product->get_key() . '_license_status', '' ),
172
+ ),
173
+ )
174
+ );
175
+ }
176
+ }
vendor/codeinwp/themeisle-sdk/src/Modules/Notification.php ADDED
@@ -0,0 +1,435 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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( $current_notification['id'] . '_before_render' );
86
+
87
+ echo $notification_html;
88
+
89
+ do_action( $current_notification['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
+ * Load the module logic.
407
+ *
408
+ * @param Product $product Product to load the module for.
409
+ *
410
+ * @return Notification Module instance.
411
+ */
412
+ public function load( $product ) {
413
+ $this->product = $product;
414
+
415
+ $notifications = apply_filters( 'themeisle_sdk_registered_notifications', [] );
416
+ $notifications = array_filter(
417
+ $notifications,
418
+ function ( $value ) {
419
+ if ( ! isset( $value['id'] ) ) {
420
+ return false;
421
+ }
422
+ if ( get_option( $value['id'], '' ) !== '' ) {
423
+ return false;
424
+ }
425
+
426
+ return apply_filters( $value['id'] . '_should_show', true );
427
+ }
428
+ );
429
+ self::$notifications = $notifications;
430
+ add_action( 'admin_notices', array( __CLASS__, 'show_notification' ) );
431
+ add_action( 'wp_ajax_themeisle_sdk_dismiss_notice', array( __CLASS__, 'dismiss' ) );
432
+
433
+ return $this;
434
+ }
435
+ }
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,371 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
79
+ if ( $versions ) {
80
+ usort( $versions, array( $this, 'sort_rollback_array' ) );
81
+ foreach ( $versions as $version ) {
82
+ if ( isset( $version['version'] ) && isset( $version['url'] ) && version_compare( $this->product->get_version(), $version['version'], '>' ) ) {
83
+ $rollback = $version;
84
+ break;
85
+ }
86
+ }
87
+ }
88
+
89
+ return $rollback;
90
+ }
91
+
92
+ /**
93
+ * Get versions array from wp.org
94
+ *
95
+ * @return array Array of versions.
96
+ */
97
+ private function get_api_versions() {
98
+
99
+ $cache_key = $this->product->get_key() . '_' . preg_replace( '/[^0-9a-zA-Z ]/m', '', $this->product->get_version() ) . 'versions';
100
+ $cache_versions = get_transient( $cache_key );
101
+ if ( false === $cache_versions ) {
102
+ $versions = $this->get_remote_versions();
103
+ set_transient( $cache_key, $versions, 5 * DAY_IN_SECONDS );
104
+ } else {
105
+ $versions = is_array( $cache_versions ) ? $cache_versions : array();
106
+ }
107
+
108
+ return $versions;
109
+ }
110
+
111
+ /**
112
+ * Get remote versions zips.
113
+ *
114
+ * @return array Array of available versions.
115
+ */
116
+ private function get_remote_versions() {
117
+ $url = $this->get_versions_api_url();
118
+ if ( empty( $url ) ) {
119
+ return [];
120
+ }
121
+ $response = wp_remote_get( $url );
122
+ if ( is_wp_error( $response ) ) {
123
+ return array();
124
+ }
125
+ $response = wp_remote_retrieve_body( $response );
126
+
127
+ if ( is_serialized( $response ) ) {
128
+ $response = maybe_unserialize( $response );
129
+ } else {
130
+ $response = json_decode( $response );
131
+ }
132
+
133
+ if ( ! is_object( $response ) ) {
134
+ return array();
135
+ }
136
+ if ( ! isset( $response->versions ) ) {
137
+ return array();
138
+ }
139
+
140
+ $versions = array();
141
+ foreach ( $response->versions as $key => $value ) {
142
+ $versions[] = array(
143
+ 'version' => is_object( $value ) ? $value->version : $key,
144
+ 'url' => is_object( $value ) ? $value->file : $value,
145
+ );
146
+ }
147
+
148
+ return $versions;
149
+ }
150
+
151
+ /**
152
+ * Return url where to check for versions.
153
+ *
154
+ * @return string Url where to check for versions.
155
+ */
156
+ private function get_versions_api_url() {
157
+ if ( $this->product->is_wordpress_available() && $this->product->is_plugin() ) {
158
+ return sprintf( 'https://api.wordpress.org/plugins/info/1.0/%s', $this->product->get_slug() );
159
+ }
160
+ if ( $this->product->is_wordpress_available() && $this->product->is_theme() ) {
161
+ return sprintf( 'https://api.wordpress.org/themes/info/1.1/?action=theme_information&request[slug]=%s&request[fields][versions]=true', $this->product->get_slug() );
162
+ }
163
+ $license = $this->product->get_license();
164
+ if ( $this->product->requires_license() && strlen( $license ) < 10 ) {
165
+ return '';
166
+ }
167
+
168
+ 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 );
169
+ }
170
+
171
+ /**
172
+ * Show the rollback links in the plugin page.
173
+ *
174
+ * @param array $links Plugin links.
175
+ *
176
+ * @return array $links Altered links.
177
+ */
178
+ public function add_rollback_link( $links ) {
179
+ $version = $this->get_rollback();
180
+ $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>';
181
+
182
+ return $links;
183
+ }
184
+
185
+ /**
186
+ * Start the rollback operation.
187
+ */
188
+ public function start_rollback() {
189
+ if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], $this->product->get_key() . '_rollback' ) ) {
190
+ wp_nonce_ays( '' );
191
+ }
192
+
193
+ if ( $this->product->is_plugin() ) {
194
+ $this->start_rollback_plugin();
195
+
196
+ return;
197
+ }
198
+ if ( $this->product->is_theme() ) {
199
+ $this->start_rollback_theme();
200
+
201
+ return;
202
+ }
203
+ }
204
+
205
+ /**
206
+ * Start the rollback operation for the plugin.
207
+ */
208
+ private function start_rollback_plugin() {
209
+ $rollback = $this->get_rollback();
210
+ $plugin_transient = get_site_transient( 'update_plugins' );
211
+ $plugin_folder = $this->product->get_slug();
212
+ $plugin_file = $this->product->get_file();
213
+ $version = $rollback['version'];
214
+ $temp_array = array(
215
+ 'slug' => $plugin_folder,
216
+ 'new_version' => $version,
217
+ 'package' => $rollback['url'],
218
+ );
219
+
220
+ $temp_object = (object) $temp_array;
221
+ $plugin_transient->response[ $plugin_folder . '/' . $plugin_file ] = $temp_object;
222
+ set_site_transient( 'update_plugins', $plugin_transient );
223
+
224
+ $transient = get_transient( $this->product->get_key() . '_warning_rollback' );
225
+
226
+ if ( false === $transient ) {
227
+ set_transient( $this->product->get_key() . '_warning_rollback', 'in progress', 30 );
228
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
229
+ $title = sprintf( apply_filters( $this->product->get_key() . '_rollback_message', 'Rolling back %s to v%s' ), $this->product->get_name(), $version );
230
+ $plugin = $plugin_folder . '/' . $plugin_file;
231
+ $nonce = 'upgrade-plugin_' . $plugin;
232
+ $url = 'update.php?action=upgrade-plugin&plugin=' . urlencode( $plugin );
233
+ $upgrader_skin = new \Plugin_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'plugin' ) );
234
+ $upgrader = new \Plugin_Upgrader( $upgrader_skin );
235
+ $upgrader->upgrade( $plugin );
236
+ delete_transient( $this->product->get_key() . '_warning_rollback' );
237
+ wp_die(
238
+ '',
239
+ $title,
240
+ array(
241
+ 'response' => 200,
242
+ )
243
+ );
244
+ }
245
+ }
246
+
247
+ /**
248
+ * Start the rollback operation for the theme.
249
+ */
250
+ private function start_rollback_theme() {
251
+ add_filter( 'update_theme_complete_actions', array( $this, 'alter_links_theme_upgrade' ) );
252
+ $rollback = $this->get_rollback();
253
+ $transient = get_site_transient( 'update_themes' );
254
+ $folder = $this->product->get_slug();
255
+ $version = $rollback['version'];
256
+ $temp_array = array(
257
+ 'new_version' => $version,
258
+ 'package' => $rollback['url'],
259
+ );
260
+
261
+ $transient->response[ $folder . '/style.css' ] = $temp_array;
262
+ set_site_transient( 'update_themes', $transient );
263
+
264
+ $transient = get_transient( $this->product->get_key() . '_warning_rollback' );
265
+
266
+ if ( false === $transient ) {
267
+ set_transient( $this->product->get_key() . '_warning_rollback', 'in progress', 30 );
268
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
269
+ $title = sprintf( apply_filters( $this->product->get_key() . '_rollback_message', 'Rolling back %s to v%s' ), $this->product->get_name(), $version );
270
+ $theme = $folder . '/style.css';
271
+ $nonce = 'upgrade-theme_' . $theme;
272
+ $url = 'update.php?action=upgrade-theme&theme=' . urlencode( $theme );
273
+
274
+ $upgrader = new \Theme_Upgrader( new \Theme_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'theme' ) ) );
275
+ $upgrader->upgrade( $theme );
276
+ delete_transient( $this->product->get_key() . '_warning_rollback' );
277
+ wp_die(
278
+ '',
279
+ $title,
280
+ array(
281
+ 'response' => 200,
282
+ )
283
+ );
284
+ }
285
+ }
286
+
287
+ /**
288
+ * Alter links and remove duplicate customize message.
289
+ *
290
+ * @param array $links Array of old links.
291
+ *
292
+ * @return mixed Array of links.
293
+ */
294
+ public function alter_links_theme_upgrade( $links ) {
295
+ if ( isset( $links['preview'] ) ) {
296
+ $links['preview'] = str_replace( '<span aria-hidden="true">Customize</span>', '', $links['preview'] );
297
+ }
298
+
299
+ return $links;
300
+ }
301
+
302
+ /**
303
+ * Loads product object.
304
+ *
305
+ * @param Product $product Product object.
306
+ *
307
+ * @return bool Should we load the module?
308
+ */
309
+ public function can_load( $product ) {
310
+ if ( $this->is_from_partner( $product ) ) {
311
+ return false;
312
+ }
313
+ if ( $product->is_theme() && ! current_user_can( 'switch_themes' ) ) {
314
+ return false;
315
+ }
316
+
317
+ if ( $product->is_plugin() && ! current_user_can( 'install_plugins' ) ) {
318
+ return false;
319
+ }
320
+
321
+ return true;
322
+ }
323
+
324
+ /**
325
+ * Sort the rollbacks array in descending order.
326
+ *
327
+ * @param mixed $a First version to compare.
328
+ * @param mixed $b Second version to compare.
329
+ *
330
+ * @return bool Which version is greater?
331
+ */
332
+ public function sort_rollback_array( $a, $b ) {
333
+ return version_compare( $a['version'], $b['version'], '<' ) > 0;
334
+ }
335
+
336
+ /**
337
+ * Load module logic.
338
+ *
339
+ * @param Product $product Product object.
340
+ *
341
+ * @return $this Module object.
342
+ */
343
+ public function load( $product ) {
344
+ $this->product = $product;
345
+ $this->show_link();
346
+ $this->add_hooks();
347
+
348
+ return $this;
349
+ }
350
+
351
+ /**
352
+ * If product can be rolled back, show the link to rollback.
353
+ */
354
+ private function show_link() {
355
+ add_filter(
356
+ 'plugin_action_links_' . plugin_basename( $this->product->get_basefile() ),
357
+ array(
358
+ $this,
359
+ 'add_rollback_link',
360
+ )
361
+ );
362
+ }
363
+
364
+ /**
365
+ * 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.
366
+ */
367
+ public function add_hooks() {
368
+ add_action( 'admin_post_' . $this->product->get_key() . '_rollback', array( $this, 'start_rollback' ) );
369
+ add_action( 'admin_footer', array( $this, 'add_footer' ) );
370
+ }
371
+ }
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,729 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
207
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container.<?php echo $key; ?>-container-disc-open #<?php echo $key; ?>-info-disclosure-content {
208
+ display: block;
209
+ margin-top: 80px;
210
+ }
211
+
212
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container.<?php echo $key; ?>-container-disc-open #<?php echo $key; ?>-info-disclosure {
213
+ top: -150px;
214
+ }
215
+
216
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container.<?php echo $key; ?>-container-disc-open {
217
+ height: 570px !important;
218
+ }
219
+
220
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container #<?php echo $key; ?>-info-disclosure {
221
+ position: absolute;
222
+ top: -50px;
223
+ font-size: 13px;
224
+ color: #8d9192;
225
+ font-weight: 400;
226
+ right: 40px;
227
+ }
228
+
229
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container div.actions {
230
+ box-sizing: border-box;
231
+ padding: 30px 40px;
232
+ background-color: #eaeaea;
233
+ }
234
+
235
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button {
236
+ background: #ec5d60;
237
+ border: none;
238
+ box-shadow: none;
239
+ color: #ffffff;
240
+ font-size: 15px;
241
+ font-weight: 700;
242
+ height: auto;
243
+ line-height: 20px;
244
+ padding: 10px 15px;
245
+ text-transform: uppercase;
246
+ -webkit-transition: 0.3s ease;
247
+ -moz-transition: 0.3s ease;
248
+ -ms-transition: 0.3s ease;
249
+ -o-transition: 0.3s ease;
250
+ transition: 0.3s ease;
251
+ }
252
+
253
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button.button-primary {
254
+ background: transparent;
255
+ box-shadow: none;
256
+ color: #8d9192;
257
+ font-weight: 400;
258
+ float: right;
259
+ line-height: 40px;
260
+ padding: 0;
261
+ text-decoration: underline;
262
+ text-shadow: none;
263
+ text-transform: none;
264
+ }
265
+
266
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button:hover {
267
+ background: #e83f42;
268
+ }
269
+
270
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button.button-primary:hover {
271
+ background: transparent;
272
+ }
273
+
274
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button:focus {
275
+ box-shadow: none;
276
+ outline: none;
277
+ }
278
+
279
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button:active {
280
+ box-shadow: none;
281
+ transform: translateY(0);
282
+ }
283
+
284
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button:disabled {
285
+ cursor: not-allowed;
286
+ }
287
+
288
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container input.button.button-primary:hover {
289
+ text-decoration: none;
290
+ }
291
+
292
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container div.revive_network-container {
293
+ background-color: #ffffff;
294
+ }
295
+
296
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list {
297
+ margin: 0;
298
+ }
299
+
300
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list li {
301
+ color: #373e40;
302
+ font-size: 13px;
303
+ margin-bottom: 5px;
304
+ }
305
+
306
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list li label {
307
+ margin-left: 10px;
308
+ line-height: 28px;
309
+ font-size: 15px;
310
+ }
311
+
312
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list input[type=radio] {
313
+ margin-top: 1px;
314
+ }
315
+
316
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container #TB_ajaxContent {
317
+ box-sizing: border-box;
318
+ height: auto !important;
319
+ padding: 20px 40px;
320
+ width: 100% !important;
321
+ }
322
+
323
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container li div textarea {
324
+ padding: 10px 15px;
325
+ width: 100%;
326
+ }
327
+
328
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container ul.ti-list li div {
329
+ margin: 10px 30px;
330
+ }
331
+
332
+ .<?php echo $key; ?>-container #TB_title #TB_ajaxWindowTitle {
333
+ box-sizing: border-box;
334
+ display: block;
335
+ float: none;
336
+ font-weight: 700;
337
+ line-height: 1;
338
+ padding: 0;
339
+ text-align: left;
340
+ width: 100%;
341
+ }
342
+
343
+ .<?php echo $key; ?>-container #TB_title #TB_ajaxWindowTitle span {
344
+ color: #8d9192;
345
+ display: block;
346
+ font-size: 15px;
347
+ font-weight: 400;
348
+ margin-top: 5px;
349
+ text-transform: none;
350
+ }
351
+
352
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container .actions {
353
+ width: 100%;
354
+ display: block;
355
+ position: absolute;
356
+ left: 0;
357
+ bottom: 0;
358
+ }
359
+
360
+ .theme-install-php .<?php echo $key; ?>-container #TB_closeWindowButton .tb-close-icon:before {
361
+ font-size: 32px;
362
+ }
363
+
364
+ .<?php echo $key; ?>-container #TB_closeWindowButton .tb-close-icon {
365
+ color: #eee;
366
+ }
367
+
368
+ .<?php echo $key; ?>-container #TB_closeWindowButton {
369
+ left: auto;
370
+ right: -5px;
371
+ top: -35px;
372
+ color: #eee;
373
+ }
374
+
375
+ .<?php echo $key; ?>-container #TB_closeWindowButton .tb-close-icon {
376
+ text-align: right;
377
+ line-height: 25px;
378
+ width: 25px;
379
+ height: 25px;
380
+ }
381
+
382
+ .<?php echo $key; ?>-container #TB_closeWindowButton:focus .tb-close-icon {
383
+ box-shadow: none;
384
+ outline: none;
385
+ }
386
+
387
+ .<?php echo $key; ?>-container #TB_closeWindowButton .tb-close-icon:before {
388
+ font: normal 25px dashicons;
389
+ }
390
+
391
+ body.<?php echo $suffix; ?> .<?php echo $key; ?>-container {
392
+ margin: auto !important;
393
+ height: 500px !important;
394
+ top: 0 !important;
395
+ left: 0 !important;
396
+ bottom: 0 !important;
397
+ right: 0 !important;
398
+ width: 600px !important;
399
+ }
400
+ </style>
401
+ <?php
402
+ do_action( $this->product->get_key() . '_uninstall_feedback_after_css' );
403
+ }
404
+
405
+ /**
406
+ * Loads the js.
407
+ *
408
+ * @param string $type The type of product.
409
+ * @param string $key The product key.
410
+ * @param string $src The url that will hijack the deactivate button url.
411
+ */
412
+ function add_js( $type, $key, $src ) {
413
+ $heading = Product::PLUGIN_TYPE === $type ? $this->heading_plugin : str_replace( '{theme}', $this->product->get_name(), $this->heading_theme );
414
+ $key = esc_attr( $key );
415
+ $heading = apply_filters( $this->product->get_key() . '_feedback_deactivate_heading', $heading );
416
+ ?>
417
+ <script type="text/javascript" id="ti-deactivate-js">
418
+ (function ($) {
419
+ $(document).ready(function () {
420
+ var auto_trigger = false;
421
+ var target_element = 'tr[data-plugin^="<?php echo $this->product->get_slug(); ?>/"] span.deactivate a';
422
+ <?php
423
+ if ( 'theme' === $type ) {
424
+ ?>
425
+ auto_trigger = true;
426
+ if ($('a.ti-auto-anchor').length == 0) {
427
+ $('body').append($('<a class="ti-auto-anchor" href=""></a>'));
428
+ }
429
+ target_element = 'a.ti-auto-anchor';
430
+ <?php
431
+ }
432
+ ?>
433
+
434
+ if (auto_trigger) {
435
+ setTimeout(function () {
436
+ $('a.ti-auto-anchor').trigger('click');
437
+ }, <?php echo self::AUTO_TRIGGER_DEACTIVATE_WINDOW_SECONDS * 1000; ?> );
438
+ }
439
+ $(document).on('thickbox:removed', function () {
440
+ $.post(ajaxurl, {
441
+ 'action': '<?php echo $key . '_uninstall_feedback'; ?>',
442
+ 'nonce': '<?php echo wp_create_nonce( (string) __CLASS__ ); ?>',
443
+ 'type': '<?php echo $type; ?>',
444
+ 'key': '<?php echo $key; ?>'
445
+ });
446
+ });
447
+ var href = $(target_element).attr('href');
448
+ $('#<?php echo $key; ?>ti-deactivate-no').attr('data-ti-action', href).on('click', function (e) {
449
+ e.preventDefault();
450
+ e.stopPropagation();
451
+
452
+ $('body').unbind('thickbox:removed');
453
+ tb_remove();
454
+ var redirect = $(this).attr('data-ti-action');
455
+ if (redirect !== '') {
456
+ location.href = redirect;
457
+ }
458
+ });
459
+
460
+ $('#<?php echo $key; ?> ul.ti-list label, #<?php echo $key; ?> ul.ti-list input[name="ti-deactivate-option"]').on('click', function (e) {
461
+ $('#<?php echo $key; ?>ti-deactivate-yes').val($('#<?php echo $key; ?>ti-deactivate-yes').attr('data-after-text'));
462
+
463
+ var radio = $(this).prop('tagName') === 'LABEL' ? $(this).parent() : $(this);
464
+ if (radio.parent().find('textarea').length > 0 && radio.parent().find('textarea').val().length === 0) {
465
+ $('#<?php echo $key; ?>ti-deactivate-yes').attr('disabled', 'disabled');
466
+ radio.parent().find('textarea').on('keyup', function (ee) {
467
+ if ($(this).val().length === 0) {
468
+ $('#<?php echo $key; ?>ti-deactivate-yes').attr('disabled', 'disabled');
469
+ } else {
470
+ $('#<?php echo $key; ?>ti-deactivate-yes').removeAttr('disabled');
471
+ }
472
+ });
473
+ } else {
474
+ $('#<?php echo $key; ?>ti-deactivate-yes').removeAttr('disabled');
475
+ }
476
+ });
477
+ $("#<?php echo $key; ?>-info-disclosure").on('click', function () {
478
+ $("#TB_window").toggleClass("<?php echo $key; ?>-container-disc-open");
479
+ return false;
480
+ });
481
+ $('#<?php echo $key; ?>ti-deactivate-yes').attr('data-ti-action', href).on('click', function (e) {
482
+ e.preventDefault();
483
+ e.stopPropagation();
484
+ $.post(ajaxurl, {
485
+ 'action': '<?php echo $key . '_uninstall_feedback'; ?>',
486
+ 'nonce': '<?php echo wp_create_nonce( (string) __CLASS__ ); ?>',
487
+ 'id': $('#<?php echo $key; ?> input[name="ti-deactivate-option"]:checked').parent().attr('ti-option-id'),
488
+ 'msg': $('#<?php echo $key; ?> input[name="ti-deactivate-option"]:checked').parent().find('textarea').val(),
489
+ 'type': '<?php echo $type; ?>',
490
+ });
491
+ var redirect = $(this).attr('data-ti-action');
492
+ if (redirect != '') {
493
+ location.href = redirect;
494
+ } else {
495
+ $('body').unbind('thickbox:removed');
496
+ tb_remove();
497
+ }
498
+ });
499
+
500
+ $(target_element).attr('name', '<?php echo wp_kses( $heading, array( 'span' => array() ) ); ?>').attr('href', '<?php echo $src; ?>').addClass('thickbox');
501
+ var thicbox_timer;
502
+ $(target_element).on('click', function () {
503
+ tiBindThickbox();
504
+ });
505
+
506
+ function tiBindThickbox() {
507
+ var thicbox_timer = setTimeout(function () {
508
+ if ($("#<?php echo esc_html( $key ); ?>").is(":visible")) {
509
+ $("body").trigger('thickbox:iframe:loaded');
510
+ $("#TB_window").addClass("<?php echo $key; ?>-container");
511
+ clearTimeout(thicbox_timer);
512
+ $('body').unbind('thickbox:removed');
513
+ } else {
514
+ tiBindThickbox();
515
+ }
516
+ }, 100);
517
+ }
518
+ });
519
+ })(jQuery);
520
+ </script>
521
+ <?php
522
+
523
+ do_action( $this->product->get_key() . '_uninstall_feedback_after_js' );
524
+ }
525
+
526
+ /**
527
+ * Generates the HTML.
528
+ *
529
+ * @param string $type The type of product.
530
+ * @param string $key The product key.
531
+ */
532
+ function get_html( $type, $key ) {
533
+ $options = Product::PLUGIN_TYPE === $type ? $this->options_plugin : $this->options_theme;
534
+ $button_cancel = Product::PLUGIN_TYPE === $type ? $this->button_cancel : 'Skip';
535
+ $button_submit = Product::PLUGIN_TYPE === $type ? $this->button_submit : 'Submit';
536
+ $options = $this->randomize_options( apply_filters( $this->product->get_key() . '_feedback_deactivate_options', $options ) );
537
+ $button_submit = apply_filters( $this->product->get_key() . '_feedback_deactivate_button_submit', $button_submit );
538
+ $button_cancel = apply_filters( $this->product->get_key() . '_feedback_deactivate_button_cancel', $button_cancel );
539
+
540
+ $options += $this->other;
541
+
542
+ $list = '';
543
+ foreach ( $options as $title => $attributes ) {
544
+ $id = $attributes['id'];
545
+ $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>';
546
+ if ( array_key_exists( 'type', $attributes ) ) {
547
+ $list .= '<div>';
548
+ $placeholder = array_key_exists( 'placeholder', $attributes ) ? $attributes['placeholder'] : '';
549
+ switch ( $attributes['type'] ) {
550
+ case 'text':
551
+ $list .= '<textarea style="width: 100%" rows="1" name="comments" placeholder="' . $placeholder . '"></textarea>';
552
+ break;
553
+ case 'textarea':
554
+ $list .= '<textarea style="width: 100%" rows="2" name="comments" placeholder="' . $placeholder . '"></textarea>';
555
+ break;
556
+ }
557
+ $list .= '</div>';
558
+ }
559
+ $list .= '</li>';
560
+ }
561
+
562
+ $disclosure_new_labels = apply_filters( $this->product->get_slug() . '_themeisle_sdk_disclosure_content_labels', [], $this->product );
563
+ $disclosure_labels = array_merge(
564
+ [
565
+ '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.',
566
+ 'items' => [
567
+ sprintf( '%s %s version %s %s %s %s', '<strong>', ucwords( $this->product->get_type() ), '</strong>', '<code>', $this->product->get_version(), '</code>' ),
568
+ sprintf( '%s Uninstall reason %s %s Selected reson from the above survey %s ', '<strong>', '</strong>', '<i>', '</i>' ),
569
+ ],
570
+ ],
571
+ $disclosure_new_labels
572
+ );
573
+
574
+ $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>';
575
+ $info_disclosure_content = '<div id="' . $this->product->get_key() . '-info-disclosure-content"><p>' . wp_kses_post( $disclosure_labels['title'] ) . '</p><ul>';
576
+ foreach ( $disclosure_labels['items'] as $disclosure_item ) {
577
+ $info_disclosure_content .= sprintf( '<li>%s</li>', wp_kses_post( $disclosure_item ) );
578
+ }
579
+ $info_disclosure_content .= '</ul></div>';
580
+
581
+ return
582
+ '<div id="' . $this->product->get_key() . '"><ul class="ti-list">' . $list . '</ul>'
583
+ . $info_disclosure_content
584
+ . '<div class="actions">'
585
+ . get_submit_button(
586
+ $button_submit,
587
+ 'secondary',
588
+ $this->product->get_key() . 'ti-deactivate-yes',
589
+ false,
590
+ array(
591
+ 'data-after-text' => $button_submit,
592
+ 'disabled' => true,
593
+ )
594
+ )
595
+ . wp_kses_post( $info_disclosure_link )
596
+ . get_submit_button( $button_cancel, 'primary', $this->product->get_key() . 'ti-deactivate-no', false )
597
+ . '</div></div>';
598
+ }
599
+
600
+ /**
601
+ * Randomizes the options array.
602
+ *
603
+ * @param array $options The options array.
604
+ */
605
+ function randomize_options( $options ) {
606
+ $new = array();
607
+ $keys = array_keys( $options );
608
+ shuffle( $keys );
609
+
610
+ foreach ( $keys as $key ) {
611
+ $new[ $key ] = $options[ $key ];
612
+ }
613
+
614
+ return $new;
615
+ }
616
+
617
+ /**
618
+ * Called when the deactivate button is clicked.
619
+ */
620
+ function post_deactivate() {
621
+ check_ajax_referer( (string) __CLASS__, 'nonce' );
622
+
623
+ $this->post_deactivate_or_cancel();
624
+
625
+ if ( empty( $_POST['id'] ) ) {
626
+
627
+ wp_send_json( [] );
628
+
629
+ return;
630
+ }
631
+ $this->call_api(
632
+ array(
633
+ 'type' => 'deactivate',
634
+ 'id' => $_POST['id'],
635
+ 'comment' => isset( $_POST['msg'] ) ? $_POST['msg'] : '',
636
+ )
637
+ );
638
+ wp_send_json( [] );
639
+
640
+ }
641
+
642
+ /**
643
+ * Called when the deactivate/cancel button is clicked.
644
+ */
645
+ private function post_deactivate_or_cancel() {
646
+ if ( ! isset( $_POST['type'] ) || ! isset( $_POST['key'] ) ) {
647
+ return;
648
+ }
649
+ if ( 'theme' !== $_POST['type'] ) {
650
+ return;
651
+ }
652
+
653
+ set_transient( 'ti_sdk_pause_' . $_POST['key'], true, self::PAUSE_DEACTIVATE_WINDOW_DAYS * DAY_IN_SECONDS );
654
+
655
+ }
656
+
657
+ /**
658
+ * Calls the API
659
+ *
660
+ * @param array $attributes The attributes of the post body.
661
+ *
662
+ * @return bool Is the request succesfull?
663
+ */
664
+ protected function call_api( $attributes ) {
665
+ $slug = $this->product->get_slug();
666
+ $version = $this->product->get_version();
667
+ $attributes['slug'] = $slug;
668
+ $attributes['version'] = $version;
669
+
670
+ $response = wp_remote_post(
671
+ self::FEEDBACK_ENDPOINT,
672
+ array(
673
+ 'body' => $attributes,
674
+ )
675
+ );
676
+
677
+ return is_wp_error( $response );
678
+ }
679
+
680
+ /**
681
+ * Should we load this object?.
682
+ *
683
+ * @param Product $product Product object.
684
+ *
685
+ * @return bool Should we load the module?
686
+ */
687
+ public function can_load( $product ) {
688
+ if ( $this->is_from_partner( $product ) ) {
689
+ return false;
690
+ }
691
+ if ( $product->is_theme() && ( false !== get_transient( 'ti_sdk_pause_' . $product->get_key(), false ) ) ) {
692
+ return false;
693
+ }
694
+
695
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
696
+ return true;
697
+ }
698
+ global $pagenow;
699
+
700
+ if ( ! isset( $pagenow ) || empty( $pagenow ) ) {
701
+ return false;
702
+ }
703
+
704
+ if ( $product->is_plugin() && 'plugins.php' !== $pagenow ) {
705
+ return false;
706
+
707
+ }
708
+ if ( $product->is_theme() && 'theme-install.php' !== $pagenow ) {
709
+ return false;
710
+ }
711
+
712
+ return true;
713
+ }
714
+
715
+ /**
716
+ * Loads module hooks.
717
+ *
718
+ * @param Product $product Product details.
719
+ *
720
+ * @return Uninstall_Feedback Current module instance.
721
+ */
722
+ public function load( $product ) {
723
+ $this->product = $product;
724
+ add_action( 'admin_head', array( $this, 'load_resources' ) );
725
+ add_action( 'wp_ajax_' . $this->product->get_key() . '_uninstall_feedback', array( $this, 'post_deactivate' ) );
726
+
727
+ return $this;
728
+ }
729
+ }
vendor/codeinwp/themeisle-sdk/src/Product.php ADDED
@@ -0,0 +1,383 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ }
vendor/codeinwp/themeisle-sdk/start.php CHANGED
@@ -7,32 +7,42 @@
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
+ ];
35
+
36
+ $files_to_load = array_merge( $files_to_load, apply_filters( 'themeisle_sdk_required_files', [] ) );
37
 
38
  foreach ( $files_to_load as $file ) {
39
+ if ( is_readable( $file ) ) {
40
+ require_once $file;
 
41
  }
42
  }
43
+
44
+ Loader::init();
45
+
46
  foreach ( $products as $product ) {
47
+ Loader::add_product( $product );
48
  }
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
  '3df8ee254224091c21b9aebb792d2f8b' => $vendorDir . '/codeinwp/themeisle-sdk/load.php',
11
  );
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
 
9
  '3df8ee254224091c21b9aebb792d2f8b' => $vendorDir . '/codeinwp/themeisle-sdk/load.php',
10
  );
vendor/composer/autoload_psr4.php CHANGED
@@ -6,4 +6,5 @@ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
 
9
  );
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
+ 'Composer\\Installers\\' => array($vendorDir . '/composer/installers/src/Composer/Installers'),
10
  );
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInitaea9a626a3fa577057e8dd7c4185e11c
6
  {
7
  private static $loader;
8
 
@@ -19,9 +19,9 @@ class ComposerAutoloaderInitaea9a626a3fa577057e8dd7c4185e11c
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInitaea9a626a3fa577057e8dd7c4185e11c', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInitaea9a626a3fa577057e8dd7c4185e11c', 'loadClassLoader'));
25
 
26
  $map = require __DIR__ . '/autoload_namespaces.php';
27
  foreach ($map as $namespace => $path) {
@@ -42,14 +42,14 @@ class ComposerAutoloaderInitaea9a626a3fa577057e8dd7c4185e11c
42
 
43
  $includeFiles = require __DIR__ . '/autoload_files.php';
44
  foreach ($includeFiles as $fileIdentifier => $file) {
45
- composerRequireaea9a626a3fa577057e8dd7c4185e11c($fileIdentifier, $file);
46
  }
47
 
48
  return $loader;
49
  }
50
  }
51
 
52
- function composerRequireaea9a626a3fa577057e8dd7c4185e11c($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 ComposerAutoloaderInit192ce97fadbb58f36174182e5bd061ad
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit192ce97fadbb58f36174182e5bd061ad', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit192ce97fadbb58f36174182e5bd061ad', '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
+ composerRequire192ce97fadbb58f36174182e5bd061ad($fileIdentifier, $file);
46
  }
47
 
48
  return $loader;
49
  }
50
  }
51
 
52
+ function composerRequire192ce97fadbb58f36174182e5bd061ad($fileIdentifier, $file)
53
  {
54
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
55
  require $file;
vendor/composer/autoload_real_52.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real_52.php generated by xrstf/composer-php52
4
 
5
- class ComposerAutoloaderInitbb90e47cfa10dd66fde5d5b3c2ee86cf {
6
  private static $loader;
7
 
8
  public static function loadClassLoader($class) {
@@ -19,9 +19,9 @@ class ComposerAutoloaderInitbb90e47cfa10dd66fde5d5b3c2ee86cf {
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInitbb90e47cfa10dd66fde5d5b3c2ee86cf', 'loadClassLoader'), true /*, true */);
23
  self::$loader = $loader = new xrstf_Composer52_ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInitbb90e47cfa10dd66fde5d5b3c2ee86cf', 'loadClassLoader'));
25
 
26
  $vendorDir = dirname(dirname(__FILE__));
27
  $baseDir = dirname($vendorDir);
@@ -39,7 +39,6 @@ class ComposerAutoloaderInitbb90e47cfa10dd66fde5d5b3c2ee86cf {
39
 
40
  $loader->register(true);
41
 
42
- require $vendorDir . '/codeinwp/themeisle-sdk/load.php';
43
  require $vendorDir . '/codeinwp/themeisle-sdk/load.php';
44
 
45
  return $loader;
2
 
3
  // autoload_real_52.php generated by xrstf/composer-php52
4
 
5
+ class ComposerAutoloaderInit7300e34db896a77d95fa9ea47a0613a5 {
6
  private static $loader;
7
 
8
  public static function loadClassLoader($class) {
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit7300e34db896a77d95fa9ea47a0613a5', 'loadClassLoader'), true /*, true */);
23
  self::$loader = $loader = new xrstf_Composer52_ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit7300e34db896a77d95fa9ea47a0613a5', 'loadClassLoader'));
25
 
26
  $vendorDir = dirname(dirname(__FILE__));
27
  $baseDir = dirname($vendorDir);
39
 
40
  $loader->register(true);
41
 
 
42
  require $vendorDir . '/codeinwp/themeisle-sdk/load.php';
43
 
44
  return $loader;
vendor/composer/installed.json CHANGED
@@ -1,4 +1,126 @@
1
  [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  {
3
  "name": "codeinwp/themeisle-sdk",
4
  "version": "dev-master",
@@ -6,22 +128,25 @@
6
  "source": {
7
  "type": "git",
8
  "url": "https://github.com/Codeinwp/themeisle-sdk.git",
9
- "reference": "caa9bf2b2c48c12a0ac745b6e2880c94339a777d"
10
  },
11
  "dist": {
12
  "type": "zip",
13
- "url": "https://api.github.com/repos/Codeinwp/themeisle-sdk/zipball/caa9bf2b2c48c12a0ac745b6e2880c94339a777d",
14
- "reference": "caa9bf2b2c48c12a0ac745b6e2880c94339a777d",
15
  "shasum": ""
16
  },
17
- "time": "2018-07-19 07:48:21",
 
 
 
 
 
 
 
 
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+"
1
  [
2
+ {
3
+ "name": "composer/installers",
4
+ "version": "v1.6.0",
5
+ "version_normalized": "1.6.0.0",
6
+ "source": {
7
+ "type": "git",
8
+ "url": "https://github.com/composer/installers.git",
9
+ "reference": "cfcca6b1b60bc4974324efb5783c13dca6932b5b"
10
+ },
11
+ "dist": {
12
+ "type": "zip",
13
+ "url": "https://api.github.com/repos/composer/installers/zipball/cfcca6b1b60bc4974324efb5783c13dca6932b5b",
14
+ "reference": "cfcca6b1b60bc4974324efb5783c13dca6932b5b",
15
+ "shasum": ""
16
+ },
17
+ "require": {
18
+ "composer-plugin-api": "^1.0"
19
+ },
20
+ "replace": {
21
+ "roundcube/plugin-installer": "*",
22
+ "shama/baton": "*"
23
+ },
24
+ "require-dev": {
25
+ "composer/composer": "1.0.*@dev",
26
+ "phpunit/phpunit": "^4.8.36"
27
+ },
28
+ "time": "2018-08-27 06:10:37",
29
+ "type": "composer-plugin",
30
+ "extra": {
31
+ "class": "Composer\\Installers\\Plugin",
32
+ "branch-alias": {
33
+ "dev-master": "1.0-dev"
34
+ }
35
+ },
36
+ "installation-source": "dist",
37
+ "autoload": {
38
+ "psr-4": {
39
+ "Composer\\Installers\\": "src/Composer/Installers"
40
+ }
41
+ },
42
+ "notification-url": "https://packagist.org/downloads/",
43
+ "license": [
44
+ "MIT"
45
+ ],
46
+ "authors": [
47
+ {
48
+ "name": "Kyle Robinson Young",
49
+ "email": "kyle@dontkry.com",
50
+ "homepage": "https://github.com/shama"
51
+ }
52
+ ],
53
+ "description": "A multi-framework Composer library installer",
54
+ "homepage": "https://composer.github.io/installers/",
55
+ "keywords": [
56
+ "Craft",
57
+ "Dolibarr",
58
+ "Eliasis",
59
+ "Hurad",
60
+ "ImageCMS",
61
+ "Kanboard",
62
+ "Lan Management System",
63
+ "MODX Evo",
64
+ "Mautic",
65
+ "Maya",
66
+ "OXID",
67
+ "Plentymarkets",
68
+ "Porto",
69
+ "RadPHP",
70
+ "SMF",
71
+ "Thelia",
72
+ "WolfCMS",
73
+ "agl",
74
+ "aimeos",
75
+ "annotatecms",
76
+ "attogram",
77
+ "bitrix",
78
+ "cakephp",
79
+ "chef",
80
+ "cockpit",
81
+ "codeigniter",
82
+ "concrete5",
83
+ "croogo",
84
+ "dokuwiki",
85
+ "drupal",
86
+ "eZ Platform",
87
+ "elgg",
88
+ "expressionengine",
89
+ "fuelphp",
90
+ "grav",
91
+ "installer",
92
+ "itop",
93
+ "joomla",
94
+ "kohana",
95
+ "laravel",
96
+ "lavalite",
97
+ "lithium",
98
+ "magento",
99
+ "majima",
100
+ "mako",
101
+ "mediawiki",
102
+ "modulework",
103
+ "modx",
104
+ "moodle",
105
+ "osclass",
106
+ "phpbb",
107
+ "piwik",
108
+ "ppi",
109
+ "puppet",
110
+ "pxcms",
111
+ "reindex",
112
+ "roundcube",
113
+ "shopware",
114
+ "silverstripe",
115
+ "sydes",
116
+ "symfony",
117
+ "typo3",
118
+ "wordpress",
119
+ "yawik",
120
+ "zend",
121
+ "zikula"
122
+ ]
123
+ },
124
  {
125
  "name": "codeinwp/themeisle-sdk",
126
  "version": "dev-master",
128
  "source": {
129
  "type": "git",
130
  "url": "https://github.com/Codeinwp/themeisle-sdk.git",
131
+ "reference": "74b79f888e14ace771202a616c1701da231b4b1a"
132
  },
133
  "dist": {
134
  "type": "zip",
135
+ "url": "https://api.github.com/repos/Codeinwp/themeisle-sdk/zipball/74b79f888e14ace771202a616c1701da231b4b1a",
136
+ "reference": "74b79f888e14ace771202a616c1701da231b4b1a",
137
  "shasum": ""
138
  },
139
+ "require": {
140
+ "composer/installers": "~1.0"
141
+ },
142
+ "require-dev": {
143
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4",
144
+ "squizlabs/php_codesniffer": "^3.1",
145
+ "wp-coding-standards/wpcs": "^1.0.0"
146
+ },
147
+ "time": "2018-12-21 18:15:05",
148
  "type": "library",
149
  "installation-source": "dist",
 
 
 
 
 
150
  "notification-url": "https://packagist.org/downloads/",
151
  "license": [
152
  "GPL-2.0+"
vendor/composer/installers/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2012 Kyle Robinson Young
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is furnished
8
+ to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
vendor/composer/installers/composer.json ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "composer/installers",
3
+ "type": "composer-plugin",
4
+ "license": "MIT",
5
+ "description": "A multi-framework Composer library installer",
6
+ "keywords": [
7
+ "installer",
8
+ "Aimeos",
9
+ "AGL",
10
+ "AnnotateCms",
11
+ "Attogram",
12
+ "Bitrix",
13
+ "CakePHP",
14
+ "Chef",
15
+ "Cockpit",
16
+ "CodeIgniter",
17
+ "concrete5",
18
+ "Craft",
19
+ "Croogo",
20
+ "DokuWiki",
21
+ "Dolibarr",
22
+ "Drupal",
23
+ "Elgg",
24
+ "Eliasis",
25
+ "ExpressionEngine",
26
+ "eZ Platform",
27
+ "FuelPHP",
28
+ "Grav",
29
+ "Hurad",
30
+ "ImageCMS",
31
+ "iTop",
32
+ "Joomla",
33
+ "Kanboard",
34
+ "Kohana",
35
+ "Lan Management System",
36
+ "Laravel",
37
+ "Lavalite",
38
+ "Lithium",
39
+ "Magento",
40
+ "majima",
41
+ "Mako",
42
+ "Mautic",
43
+ "Maya",
44
+ "MODX",
45
+ "MODX Evo",
46
+ "MediaWiki",
47
+ "OXID",
48
+ "osclass",
49
+ "MODULEWork",
50
+ "Moodle",
51
+ "Piwik",
52
+ "pxcms",
53
+ "phpBB",
54
+ "Plentymarkets",
55
+ "PPI",
56
+ "Puppet",
57
+ "Porto",
58
+ "RadPHP",
59
+ "ReIndex",
60
+ "Roundcube",
61
+ "shopware",
62
+ "SilverStripe",
63
+ "SMF",
64
+ "SyDES",
65
+ "symfony",
66
+ "Thelia",
67
+ "TYPO3",
68
+ "WolfCMS",
69
+ "WordPress",
70
+ "YAWIK",
71
+ "Zend",
72
+ "Zikula"
73
+ ],
74
+ "homepage": "https://composer.github.io/installers/",
75
+ "authors": [
76
+ {
77
+ "name": "Kyle Robinson Young",
78
+ "email": "kyle@dontkry.com",
79
+ "homepage": "https://github.com/shama"
80
+ }
81
+ ],
82
+ "autoload": {
83
+ "psr-4": { "Composer\\Installers\\": "src/Composer/Installers" }
84
+ },
85
+ "extra": {
86
+ "class": "Composer\\Installers\\Plugin",
87
+ "branch-alias": {
88
+ "dev-master": "1.0-dev"
89
+ }
90
+ },
91
+ "replace": {
92
+ "shama/baton": "*",
93
+ "roundcube/plugin-installer": "*"
94
+ },
95
+ "require": {
96
+ "composer-plugin-api": "^1.0"
97
+ },
98
+ "require-dev": {
99
+ "composer/composer": "1.0.*@dev",
100
+ "phpunit/phpunit": "^4.8.36"
101
+ },
102
+ "scripts": {
103
+ "test": "phpunit"
104
+ }
105
+ }
vendor/composer/installers/src/Composer/Installers/AglInstaller.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class AglInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'More/{$name}/',
8
+ );
9
+
10
+ /**
11
+ * Format package name to CamelCase
12
+ */
13
+ public function inflectPackageVars($vars)
14
+ {
15
+ $vars['name'] = preg_replace_callback('/(?:^|_|-)(.?)/', function ($matches) {
16
+ return strtoupper($matches[1]);
17
+ }, $vars['name']);
18
+
19
+ return $vars;
20
+ }
21
+ }
vendor/composer/installers/src/Composer/Installers/AimeosInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class AimeosInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'extension' => 'ext/{$name}/',
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class AnnotateCmsInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'addons/modules/{$name}/',
8
+ 'component' => 'addons/components/{$name}/',
9
+ 'service' => 'addons/services/{$name}/',
10
+ );
11
+ }
vendor/composer/installers/src/Composer/Installers/AsgardInstaller.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class AsgardInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'Modules/{$name}/',
8
+ 'theme' => 'Themes/{$name}/'
9
+ );
10
+
11
+ /**
12
+ * Format package name.
13
+ *
14
+ * For package type asgard-module, cut off a trailing '-plugin' if present.
15
+ *
16
+ * For package type asgard-theme, cut off a trailing '-theme' if present.
17
+ *
18
+ */
19
+ public function inflectPackageVars($vars)
20
+ {
21
+ if ($vars['type'] === 'asgard-module') {
22
+ return $this->inflectPluginVars($vars);
23
+ }
24
+
25
+ if ($vars['type'] === 'asgard-theme') {
26
+ return $this->inflectThemeVars($vars);
27
+ }
28
+
29
+ return $vars;
30
+ }
31
+
32
+ protected function inflectPluginVars($vars)
33
+ {
34
+ $vars['name'] = preg_replace('/-module$/', '', $vars['name']);
35
+ $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']);
36
+ $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
37
+
38
+ return $vars;
39
+ }
40
+
41
+ protected function inflectThemeVars($vars)
42
+ {
43
+ $vars['name'] = preg_replace('/-theme$/', '', $vars['name']);
44
+ $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']);
45
+ $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
46
+
47
+ return $vars;
48
+ }
49
+ }
vendor/composer/installers/src/Composer/Installers/AttogramInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class AttogramInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'modules/{$name}/',
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/BaseInstaller.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ use Composer\IO\IOInterface;
5
+ use Composer\Composer;
6
+ use Composer\Package\PackageInterface;
7
+
8
+ abstract class BaseInstaller
9
+ {
10
+ protected $locations = array();
11
+ protected $composer;
12
+ protected $package;
13
+ protected $io;
14
+
15
+ /**
16
+ * Initializes base installer.
17
+ *
18
+ * @param PackageInterface $package
19
+ * @param Composer $composer
20
+ * @param IOInterface $io
21
+ */
22
+ public function __construct(PackageInterface $package = null, Composer $composer = null, IOInterface $io = null)
23
+ {
24
+ $this->composer = $composer;
25
+ $this->package = $package;
26
+ $this->io = $io;
27
+ }
28
+
29
+ /**
30
+ * Return the install path based on package type.
31
+ *
32
+ * @param PackageInterface $package
33
+ * @param string $frameworkType
34
+ * @return string
35
+ */
36
+ public function getInstallPath(PackageInterface $package, $frameworkType = '')
37
+ {
38
+ $type = $this->package->getType();
39
+
40
+ $prettyName = $this->package->getPrettyName();
41
+ if (strpos($prettyName, '/') !== false) {
42
+ list($vendor, $name) = explode('/', $prettyName);
43
+ } else {
44
+ $vendor = '';
45
+ $name = $prettyName;
46
+ }
47
+
48
+ $availableVars = $this->inflectPackageVars(compact('name', 'vendor', 'type'));
49
+
50
+ $extra = $package->getExtra();
51
+ if (!empty($extra['installer-name'])) {
52
+ $availableVars['name'] = $extra['installer-name'];
53
+ }
54
+
55
+ if ($this->composer->getPackage()) {
56
+ $extra = $this->composer->getPackage()->getExtra();
57
+ if (!empty($extra['installer-paths'])) {
58
+ $customPath = $this->mapCustomInstallPaths($extra['installer-paths'], $prettyName, $type, $vendor);
59
+ if ($customPath !== false) {
60
+ return $this->templatePath($customPath, $availableVars);
61
+ }
62
+ }
63
+ }
64
+
65
+ $packageType = substr($type, strlen($frameworkType) + 1);
66
+ $locations = $this->getLocations();
67
+ if (!isset($locations[$packageType])) {
68
+ throw new \InvalidArgumentException(sprintf('Package type "%s" is not supported', $type));
69
+ }
70
+
71
+ return $this->templatePath($locations[$packageType], $availableVars);
72
+ }
73
+
74
+ /**
75
+ * For an installer to override to modify the vars per installer.
76
+ *
77
+ * @param array $vars
78
+ * @return array
79
+ */
80
+ public function inflectPackageVars($vars)
81
+ {
82
+ return $vars;
83
+ }
84
+
85
+ /**
86
+ * Gets the installer's locations
87
+ *
88
+ * @return array
89
+ */
90
+ public function getLocations()
91
+ {
92
+ return $this->locations;
93
+ }
94
+
95
+ /**
96
+ * Replace vars in a path
97
+ *
98
+ * @param string $path
99
+ * @param array $vars
100
+ * @return string
101
+ */
102
+ protected function templatePath($path, array $vars = array())
103
+ {
104
+ if (strpos($path, '{') !== false) {
105
+ extract($vars);
106
+ preg_match_all('@\{\$([A-Za-z0-9_]*)\}@i', $path, $matches);
107
+ if (!empty($matches[1])) {
108
+ foreach ($matches[1] as $var) {
109
+ $path = str_replace('{$' . $var . '}', $$var, $path);
110
+ }
111
+ }
112
+ }
113
+
114
+ return $path;
115
+ }
116
+
117
+ /**
118
+ * Search through a passed paths array for a custom install path.
119
+ *
120
+ * @param array $paths
121
+ * @param string $name
122
+ * @param string $type
123
+ * @param string $vendor = NULL
124
+ * @return string
125
+ */
126
+ protected function mapCustomInstallPaths(array $paths, $name, $type, $vendor = NULL)
127
+ {
128
+ foreach ($paths as $path => $names) {
129
+ if (in_array($name, $names) || in_array('type:' . $type, $names) || in_array('vendor:' . $vendor, $names)) {
130
+ return $path;
131
+ }
132
+ }
133
+
134
+ return false;
135
+ }
136
+ }
vendor/composer/installers/src/Composer/Installers/BitrixInstaller.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Composer\Installers;
4
+
5
+ use Composer\Util\Filesystem;
6
+
7
+ /**
8
+ * Installer for Bitrix Framework. Supported types of extensions:
9
+ * - `bitrix-d7-module` — copy the module to directory `bitrix/modules/<vendor>.<name>`.
10
+ * - `bitrix-d7-component` — copy the component to directory `bitrix/components/<vendor>/<name>`.
11
+ * - `bitrix-d7-template` — copy the template to directory `bitrix/templates/<vendor>_<name>`.
12
+ *
13
+ * You can set custom path to directory with Bitrix kernel in `composer.json`:
14
+ *
15
+ * ```json
16
+ * {
17
+ * "extra": {
18
+ * "bitrix-dir": "s1/bitrix"
19
+ * }
20
+ * }
21
+ * ```
22
+ *
23
+ * @author Nik Samokhvalov <nik@samokhvalov.info>
24
+ * @author Denis Kulichkin <onexhovia@gmail.com>
25
+ */
26
+ class BitrixInstaller extends BaseInstaller
27
+ {
28
+ protected $locations = array(
29
+ 'module' => '{$bitrix_dir}/modules/{$name}/', // deprecated, remove on the major release (Backward compatibility will be broken)
30
+ 'component' => '{$bitrix_dir}/components/{$name}/', // deprecated, remove on the major release (Backward compatibility will be broken)
31
+ 'theme' => '{$bitrix_dir}/templates/{$name}/', // deprecated, remove on the major release (Backward compatibility will be broken)
32
+ 'd7-module' => '{$bitrix_dir}/modules/{$vendor}.{$name}/',
33
+ 'd7-component' => '{$bitrix_dir}/components/{$vendor}/{$name}/',
34
+ 'd7-template' => '{$bitrix_dir}/templates/{$vendor}_{$name}/',
35
+ );
36
+
37
+ /**
38
+ * @var array Storage for informations about duplicates at all the time of installation packages.
39
+ */
40
+ private static $checkedDuplicates = array();
41
+
42
+ /**
43
+ * {@inheritdoc}
44
+ */
45
+ public function inflectPackageVars($vars)
46
+ {
47
+ if ($this->composer->getPackage()) {
48
+ $extra = $this->composer->getPackage()->getExtra();
49
+
50
+ if (isset($extra['bitrix-dir'])) {
51
+ $vars['bitrix_dir'] = $extra['bitrix-dir'];
52
+ }
53
+ }
54
+
55
+ if (!isset($vars['bitrix_dir'])) {
56
+ $vars['bitrix_dir'] = 'bitrix';
57
+ }
58
+
59
+ return parent::inflectPackageVars($vars);
60
+ }
61
+
62
+ /**
63
+ * {@inheritdoc}
64
+ */
65
+ protected function templatePath($path, array $vars = array())
66
+ {
67
+ $templatePath = parent::templatePath($path, $vars);
68
+ $this->checkDuplicates($templatePath, $vars);
69
+
70
+ return $templatePath;
71
+ }
72
+
73
+ /**
74
+ * Duplicates search packages.
75
+ *
76
+ * @param string $path
77
+ * @param array $vars
78
+ */
79
+ protected function checkDuplicates($path, array $vars = array())
80
+ {
81
+ $packageType = substr($vars['type'], strlen('bitrix') + 1);
82
+ $localDir = explode('/', $vars['bitrix_dir']);
83
+ array_pop($localDir);
84
+ $localDir[] = 'local';
85
+ $localDir = implode('/', $localDir);
86
+
87
+ $oldPath = str_replace(
88
+ array('{$bitrix_dir}', '{$name}'),
89
+ array($localDir, $vars['name']),
90
+ $this->locations[$packageType]
91
+ );
92
+
93
+ if (in_array($oldPath, static::$checkedDuplicates)) {
94
+ return;
95
+ }
96
+
97
+ if ($oldPath !== $path && file_exists($oldPath) && $this->io && $this->io->isInteractive()) {
98
+
99
+ $this->io->writeError(' <error>Duplication of packages:</error>');
100
+ $this->io->writeError(' <info>Package ' . $oldPath . ' will be called instead package ' . $path . '</info>');
101
+
102
+ while (true) {
103
+ switch ($this->io->ask(' <info>Delete ' . $oldPath . ' [y,n,?]?</info> ', '?')) {
104
+ case 'y':
105
+ $fs = new Filesystem();
106
+ $fs->removeDirectory($oldPath);
107
+ break 2;
108
+
109
+ case 'n':
110
+ break 2;
111
+
112
+ case '?':
113
+ default:
114
+ $this->io->writeError(array(
115
+ ' y - delete package ' . $oldPath . ' and to continue with the installation',
116
+ ' n - don\'t delete and to continue with the installation',
117
+ ));
118
+ $this->io->writeError(' ? - print help');
119
+ break;
120
+ }
121
+ }
122
+ }
123
+
124
+ static::$checkedDuplicates[] = $oldPath;
125
+ }
126
+ }
vendor/composer/installers/src/Composer/Installers/BonefishInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class BonefishInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'package' => 'Packages/{$vendor}/{$name}/'
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/CakePHPInstaller.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ use Composer\DependencyResolver\Pool;
5
+
6
+ class CakePHPInstaller extends BaseInstaller
7
+ {
8
+ protected $locations = array(
9
+ 'plugin' => 'Plugin/{$name}/',
10
+ );
11
+
12
+ /**
13
+ * Format package name to CamelCase
14
+ */
15
+ public function inflectPackageVars($vars)
16
+ {
17
+ if ($this->matchesCakeVersion('>=', '3.0.0')) {
18
+ return $vars;
19
+ }
20
+
21
+ $nameParts = explode('/', $vars['name']);
22
+ foreach ($nameParts as &$value) {
23
+ $value = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $value));
24
+ $value = str_replace(array('-', '_'), ' ', $value);
25
+ $value = str_replace(' ', '', ucwords($value));
26
+ }
27
+ $vars['name'] = implode('/', $nameParts);
28
+
29
+ return $vars;
30
+ }
31
+
32
+ /**
33
+ * Change the default plugin location when cakephp >= 3.0
34
+ */
35
+ public function getLocations()
36
+ {
37
+ if ($this->matchesCakeVersion('>=', '3.0.0')) {
38
+ $this->locations['plugin'] = $this->composer->getConfig()->get('vendor-dir') . '/{$vendor}/{$name}/';
39
+ }
40
+ return $this->locations;
41
+ }
42
+
43
+ /**
44
+ * Check if CakePHP version matches against a version
45
+ *
46
+ * @param string $matcher
47
+ * @param string $version
48
+ * @return bool
49
+ */
50
+ protected function matchesCakeVersion($matcher, $version)
51
+ {
52
+ if (class_exists('Composer\Semver\Constraint\MultiConstraint')) {
53
+ $multiClass = 'Composer\Semver\Constraint\MultiConstraint';
54
+ $constraintClass = 'Composer\Semver\Constraint\Constraint';
55
+ } else {
56
+ $multiClass = 'Composer\Package\LinkConstraint\MultiConstraint';
57
+ $constraintClass = 'Composer\Package\LinkConstraint\VersionConstraint';
58
+ }
59
+
60
+ $repositoryManager = $this->composer->getRepositoryManager();
61
+ if ($repositoryManager) {
62
+ $repos = $repositoryManager->getLocalRepository();
63
+ if (!$repos) {
64
+ return false;
65
+ }
66
+ $cake3 = new $multiClass(array(
67
+ new $constraintClass($matcher, $version),
68
+ new $constraintClass('!=', '9999999-dev'),
69
+ ));
70
+ $pool = new Pool('dev');
71
+ $pool->addRepository($repos);
72
+ $packages = $pool->whatProvides('cakephp/cakephp');
73
+ foreach ($packages as $package) {
74
+ $installed = new $constraintClass('=', $package->getVersion());
75
+ if ($cake3->matches($installed)) {
76
+ return true;
77
+ }
78
+ }
79
+ }
80
+ return false;
81
+ }
82
+ }
vendor/composer/installers/src/Composer/Installers/ChefInstaller.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class ChefInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'cookbook' => 'Chef/{$vendor}/{$name}/',
8
+ 'role' => 'Chef/roles/{$name}/',
9
+ );
10
+ }
11
+
vendor/composer/installers/src/Composer/Installers/CiviCrmInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class CiviCrmInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'ext' => 'ext/{$name}/'
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class ClanCatsFrameworkInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'ship' => 'CCF/orbit/{$name}/',
8
+ 'theme' => 'CCF/app/themes/{$name}/',
9
+ );
10
+ }
vendor/composer/installers/src/Composer/Installers/CockpitInstaller.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class CockpitInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'cockpit/modules/addons/{$name}/',
8
+ );
9
+
10
+ /**
11
+ * Format module name.
12
+ *
13
+ * Strip `module-` prefix from package name.
14
+ *
15
+ * @param array @vars
16
+ *
17
+ * @return array
18
+ */
19
+ public function inflectPackageVars($vars)
20
+ {
21
+ if ($vars['type'] == 'cockpit-module') {
22
+ return $this->inflectModuleVars($vars);
23
+ }
24
+
25
+ return $vars;
26
+ }
27
+
28
+ public function inflectModuleVars($vars)
29
+ {
30
+ $vars['name'] = ucfirst(preg_replace('/cockpit-/i', '', $vars['name']));
31
+
32
+ return $vars;
33
+ }
34
+ }
vendor/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class CodeIgniterInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'library' => 'application/libraries/{$name}/',
8
+ 'third-party' => 'application/third_party/{$name}/',
9
+ 'module' => 'application/modules/{$name}/',
10
+ );
11
+ }
vendor/composer/installers/src/Composer/Installers/Concrete5Installer.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class Concrete5Installer extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'core' => 'concrete/',
8
+ 'block' => 'application/blocks/{$name}/',
9
+ 'package' => 'packages/{$name}/',
10
+ 'theme' => 'application/themes/{$name}/',
11
+ 'update' => 'updates/{$name}/',
12
+ );
13
+ }
vendor/composer/installers/src/Composer/Installers/CraftInstaller.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ /**
5
+ * Installer for Craft Plugins
6
+ */
7
+ class CraftInstaller extends BaseInstaller
8
+ {
9
+ const NAME_PREFIX = 'craft';
10
+ const NAME_SUFFIX = 'plugin';
11
+
12
+ protected $locations = array(
13
+ 'plugin' => 'craft/plugins/{$name}/',
14
+ );
15
+
16
+ /**
17
+ * Strip `craft-` prefix and/or `-plugin` suffix from package names
18
+ *
19
+ * @param array $vars
20
+ *
21
+ * @return array
22
+ */
23
+ final public function inflectPackageVars($vars)
24
+ {
25
+ return $this->inflectPluginVars($vars);
26
+ }
27
+
28
+ private function inflectPluginVars($vars)
29
+ {
30
+ $vars['name'] = preg_replace('/-' . self::NAME_SUFFIX . '$/i', '', $vars['name']);
31
+ $vars['name'] = preg_replace('/^' . self::NAME_PREFIX . '-/i', '', $vars['name']);
32
+
33
+ return $vars;
34
+ }
35
+ }
vendor/composer/installers/src/Composer/Installers/CroogoInstaller.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class CroogoInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'plugin' => 'Plugin/{$name}/',
8
+ 'theme' => 'View/Themed/{$name}/',
9
+ );
10
+
11
+ /**
12
+ * Format package name to CamelCase
13
+ */
14
+ public function inflectPackageVars($vars)
15
+ {
16
+ $vars['name'] = strtolower(str_replace(array('-', '_'), ' ', $vars['name']));
17
+ $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
18
+
19
+ return $vars;
20
+ }
21
+ }
vendor/composer/installers/src/Composer/Installers/DecibelInstaller.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class DecibelInstaller extends BaseInstaller
5
+ {
6
+ /** @var array */
7
+ protected $locations = array(
8
+ 'app' => 'app/{$name}/',
9
+ );
10
+ }
vendor/composer/installers/src/Composer/Installers/DokuWikiInstaller.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class DokuWikiInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'plugin' => 'lib/plugins/{$name}/',
8
+ 'template' => 'lib/tpl/{$name}/',
9
+ );
10
+
11
+ /**
12
+ * Format package name.
13
+ *
14
+ * For package type dokuwiki-plugin, cut off a trailing '-plugin',
15
+ * or leading dokuwiki_ if present.
16
+ *
17
+ * For package type dokuwiki-template, cut off a trailing '-template' if present.
18
+ *
19
+ */
20
+ public function inflectPackageVars($vars)
21
+ {
22
+
23
+ if ($vars['type'] === 'dokuwiki-plugin') {
24
+ return $this->inflectPluginVars($vars);
25
+ }
26
+
27
+ if ($vars['type'] === 'dokuwiki-template') {
28
+ return $this->inflectTemplateVars($vars);
29
+ }
30
+
31
+ return $vars;
32
+ }
33
+
34
+ protected function inflectPluginVars($vars)
35
+ {
36
+ $vars['name'] = preg_replace('/-plugin$/', '', $vars['name']);
37
+ $vars['name'] = preg_replace('/^dokuwiki_?-?/', '', $vars['name']);
38
+
39
+ return $vars;
40
+ }
41
+
42
+ protected function inflectTemplateVars($vars)
43
+ {
44
+ $vars['name'] = preg_replace('/-template$/', '', $vars['name']);
45
+ $vars['name'] = preg_replace('/^dokuwiki_?-?/', '', $vars['name']);
46
+
47
+ return $vars;
48
+ }
49
+
50
+ }
vendor/composer/installers/src/Composer/Installers/DolibarrInstaller.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ /**
5
+ * Class DolibarrInstaller
6
+ *
7
+ * @package Composer\Installers
8
+ * @author Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
9
+ */
10
+ class DolibarrInstaller extends BaseInstaller
11
+ {
12
+ //TODO: Add support for scripts and themes
13
+ protected $locations = array(
14
+ 'module' => 'htdocs/custom/{$name}/',
15
+ );
16
+ }
vendor/composer/installers/src/Composer/Installers/DrupalInstaller.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class DrupalInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'core' => 'core/',
8
+ 'module' => 'modules/{$name}/',
9
+ 'theme' => 'themes/{$name}/',
10
+ 'library' => 'libraries/{$name}/',
11
+ 'profile' => 'profiles/{$name}/',
12
+ 'drush' => 'drush/{$name}/',
13
+ 'custom-theme' => 'themes/custom/{$name}/',
14
+ 'custom-module' => 'modules/custom/{$name}/',
15
+ );
16
+ }
vendor/composer/installers/src/Composer/Installers/ElggInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class ElggInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'plugin' => 'mod/{$name}/',
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/EliasisInstaller.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class EliasisInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'component' => 'components/{$name}/',
8
+ 'module' => 'modules/{$name}/',
9
+ 'plugin' => 'plugins/{$name}/',
10
+ 'template' => 'templates/{$name}/',
11
+ );
12
+ }
vendor/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ use Composer\Package\PackageInterface;
5
+
6
+ class ExpressionEngineInstaller extends BaseInstaller
7
+ {
8
+
9
+ protected $locations = array();
10
+
11
+ private $ee2Locations = array(
12
+ 'addon' => 'system/expressionengine/third_party/{$name}/',
13
+ 'theme' => 'themes/third_party/{$name}/',
14
+ );
15
+
16
+ private $ee3Locations = array(
17
+ 'addon' => 'system/user/addons/{$name}/',
18
+ 'theme' => 'themes/user/{$name}/',
19
+ );
20
+
21
+ public function getInstallPath(PackageInterface $package, $frameworkType = '')
22
+ {
23
+
24
+ $version = "{$frameworkType}Locations";
25
+ $this->locations = $this->$version;
26
+
27
+ return parent::getInstallPath($package, $frameworkType);
28
+ }
29
+ }
vendor/composer/installers/src/Composer/Installers/EzPlatformInstaller.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class EzPlatformInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'meta-assets' => 'web/assets/ezplatform/',
8
+ 'assets' => 'web/assets/ezplatform/{$name}/',
9
+ );
10
+ }
vendor/composer/installers/src/Composer/Installers/FuelInstaller.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class FuelInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'fuel/app/modules/{$name}/',
8
+ 'package' => 'fuel/packages/{$name}/',
9
+ 'theme' => 'fuel/app/themes/{$name}/',
10
+ );
11
+ }
vendor/composer/installers/src/Composer/Installers/FuelphpInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class FuelphpInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'component' => 'components/{$name}/',
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/GravInstaller.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class GravInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'plugin' => 'user/plugins/{$name}/',
8
+ 'theme' => 'user/themes/{$name}/',
9
+ );
10
+
11
+ /**
12
+ * Format package name
13
+ *
14
+ * @param array $vars
15
+ *
16
+ * @return array
17
+ */
18
+ public function inflectPackageVars($vars)
19
+ {
20
+ $restrictedWords = implode('|', array_keys($this->locations));
21
+
22
+ $vars['name'] = strtolower($vars['name']);
23
+ $vars['name'] = preg_replace('/^(?:grav-)?(?:(?:'.$restrictedWords.')-)?(.*?)(?:-(?:'.$restrictedWords.'))?$/ui',
24
+ '$1',
25
+ $vars['name']
26
+ );
27
+
28
+ return $vars;
29
+ }
30
+ }
vendor/composer/installers/src/Composer/Installers/HuradInstaller.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class HuradInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'plugin' => 'plugins/{$name}/',
8
+ 'theme' => 'plugins/{$name}/',
9
+ );
10
+
11
+ /**
12
+ * Format package name to CamelCase
13
+ */
14
+ public function inflectPackageVars($vars)
15
+ {
16
+ $nameParts = explode('/', $vars['name']);
17
+ foreach ($nameParts as &$value) {
18
+ $value = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $value));
19
+ $value = str_replace(array('-', '_'), ' ', $value);
20
+ $value = str_replace(' ', '', ucwords($value));
21
+ }
22
+ $vars['name'] = implode('/', $nameParts);
23
+ return $vars;
24
+ }
25
+ }
vendor/composer/installers/src/Composer/Installers/ImageCMSInstaller.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class ImageCMSInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'template' => 'templates/{$name}/',
8
+ 'module' => 'application/modules/{$name}/',
9
+ 'library' => 'application/libraries/{$name}/',
10
+ );
11
+ }
vendor/composer/installers/src/Composer/Installers/Installer.php ADDED
@@ -0,0 +1,274 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Composer\Installers;
4
+
5
+ use Composer\Composer;
6
+ use Composer\Installer\BinaryInstaller;
7
+ use Composer\Installer\LibraryInstaller;
8
+ use Composer\IO\IOInterface;
9
+ use Composer\Package\PackageInterface;
10
+ use Composer\Repository\InstalledRepositoryInterface;
11
+ use Composer\Util\Filesystem;
12
+
13
+ class Installer extends LibraryInstaller
14
+ {
15
+
16
+ /**
17
+ * Package types to installer class map
18
+ *
19
+ * @var array
20
+ */
21
+ private $supportedTypes = array(
22
+ 'aimeos' => 'AimeosInstaller',
23
+ 'asgard' => 'AsgardInstaller',
24
+ 'attogram' => 'AttogramInstaller',
25
+ 'agl' => 'AglInstaller',
26
+ 'annotatecms' => 'AnnotateCmsInstaller',
27
+ 'bitrix' => 'BitrixInstaller',
28
+ 'bonefish' => 'BonefishInstaller',
29
+ 'cakephp' => 'CakePHPInstaller',
30
+ 'chef' => 'ChefInstaller',
31
+ 'civicrm' => 'CiviCrmInstaller',
32
+ 'ccframework' => 'ClanCatsFrameworkInstaller',
33
+ 'cockpit' => 'CockpitInstaller',
34
+ 'codeigniter' => 'CodeIgniterInstaller',
35
+ 'concrete5' => 'Concrete5Installer',
36
+ 'craft' => 'CraftInstaller',
37
+ 'croogo' => 'CroogoInstaller',
38
+ 'dokuwiki' => 'DokuWikiInstaller',
39
+ 'dolibarr' => 'DolibarrInstaller',
40
+ 'decibel' => 'DecibelInstaller',
41
+ 'drupal' => 'DrupalInstaller',
42
+ 'elgg' => 'ElggInstaller',
43
+ 'eliasis' => 'EliasisInstaller',
44
+ 'ee3' => 'ExpressionEngineInstaller',
45
+ 'ee2' => 'ExpressionEngineInstaller',
46
+ 'ezplatform' => 'EzPlatformInstaller',
47
+ 'fuel' => 'FuelInstaller',
48
+ 'fuelphp' => 'FuelphpInstaller',
49
+ 'grav' => 'GravInstaller',
50
+ 'hurad' => 'HuradInstaller',
51
+ 'imagecms' => 'ImageCMSInstaller',
52
+ 'itop' => 'ItopInstaller',
53
+ 'joomla' => 'JoomlaInstaller',
54
+ 'kanboard' => 'KanboardInstaller',
55
+ 'kirby' => 'KirbyInstaller',
56
+ 'kodicms' => 'KodiCMSInstaller',
57
+ 'kohana' => 'KohanaInstaller',
58
+ 'lms' => 'LanManagementSystemInstaller',
59
+ 'laravel' => 'LaravelInstaller',
60
+ 'lavalite' => 'LavaLiteInstaller',
61
+ 'lithium' => 'LithiumInstaller',
62
+ 'magento' => 'MagentoInstaller',
63
+ 'majima' => 'MajimaInstaller',
64
+ 'mako' => 'MakoInstaller',
65
+ 'maya' => 'MayaInstaller',
66
+ 'mautic' => 'MauticInstaller',
67
+ 'mediawiki' => 'MediaWikiInstaller',
68
+ 'microweber' => 'MicroweberInstaller',
69
+ 'modulework' => 'MODULEWorkInstaller',
70
+ 'modx' => 'ModxInstaller',
71
+ 'modxevo' => 'MODXEvoInstaller',
72
+ 'moodle' => 'MoodleInstaller',
73
+ 'october' => 'OctoberInstaller',
74
+ 'ontowiki' => 'OntoWikiInstaller',
75
+ 'oxid' => 'OxidInstaller',
76
+ 'osclass' => 'OsclassInstaller',
77
+ 'pxcms' => 'PxcmsInstaller',
78
+ 'phpbb' => 'PhpBBInstaller',
79
+ 'pimcore' => 'PimcoreInstaller',
80
+ 'piwik' => 'PiwikInstaller',
81
+ 'plentymarkets'=> 'PlentymarketsInstaller',
82
+ 'ppi' => 'PPIInstaller',
83
+ 'puppet' => 'PuppetInstaller',
84
+ 'radphp' => 'RadPHPInstaller',
85
+ 'phifty' => 'PhiftyInstaller',
86
+ 'porto' => 'PortoInstaller',
87
+ 'redaxo' => 'RedaxoInstaller',
88
+ 'reindex' => 'ReIndexInstaller',
89
+ 'roundcube' => 'RoundcubeInstaller',
90
+ 'shopware' => 'ShopwareInstaller',
91
+ 'sitedirect' => 'SiteDirectInstaller',
92
+ 'silverstripe' => 'SilverStripeInstaller',
93
+ 'smf' => 'SMFInstaller',
94
+ 'sydes' => 'SyDESInstaller',
95
+ 'symfony1' => 'Symfony1Installer',
96
+ 'thelia' => 'TheliaInstaller',
97
+ 'tusk' => 'TuskInstaller',
98
+ 'typo3-cms' => 'TYPO3CmsInstaller',
99
+ 'typo3-flow' => 'TYPO3FlowInstaller',
100
+ 'userfrosting' => 'UserFrostingInstaller',
101
+ 'vanilla' => 'VanillaInstaller',
102
+ 'whmcs' => 'WHMCSInstaller',
103
+ 'wolfcms' => 'WolfCMSInstaller',
104
+ 'wordpress' => 'WordPressInstaller',
105
+ 'yawik' => 'YawikInstaller',
106
+ 'zend' => 'ZendInstaller',
107
+ 'zikula' => 'ZikulaInstaller',
108
+ 'prestashop' => 'PrestashopInstaller'
109
+ );
110
+
111
+ /**
112
+ * Installer constructor.
113
+ *
114
+ * Disables installers specified in main composer extra installer-disable
115
+ * list
116
+ *
117
+ * @param IOInterface $io
118
+ * @param Composer $composer
119
+ * @param string $type
120
+ * @param Filesystem|null $filesystem
121
+ * @param BinaryInstaller|null $binaryInstaller
122
+ */
123
+ public function __construct(
124
+ IOInterface $io,
125
+ Composer $composer,
126
+ $type = 'library',
127
+ Filesystem $filesystem = null,
128
+ BinaryInstaller $binaryInstaller = null
129
+ ) {
130
+ parent::__construct($io, $composer, $type, $filesystem,
131
+ $binaryInstaller);
132
+ $this->removeDisabledInstallers();
133
+ }
134
+
135
+ /**
136
+ * {@inheritDoc}
137
+ */
138
+ public function getInstallPath(PackageInterface $package)
139
+ {
140
+ $type = $package->getType();
141
+ $frameworkType = $this->findFrameworkType($type);
142
+
143
+ if ($frameworkType === false) {
144
+ throw new \InvalidArgumentException(
145
+ 'Sorry the package type of this package is not yet supported.'
146
+ );
147
+ }
148
+
149
+ $class = 'Composer\\Installers\\' . $this->supportedTypes[$frameworkType];
150
+ $installer = new $class($package, $this->composer, $this->getIO());
151
+
152
+ return $installer->getInstallPath($package, $frameworkType);
153
+ }
154
+
155
+ public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
156
+ {
157
+ parent::uninstall($repo, $package);
158
+ $installPath = $this->getPackageBasePath($package);
159
+ $this->io->write(sprintf('Deleting %s - %s', $installPath, !file_exists($installPath) ? '<comment>deleted</comment>' : '<error>not deleted</error>'));
160
+ }
161
+
162
+ /**
163
+ * {@inheritDoc}
164
+ */
165
+ public function supports($packageType)
166
+ {
167
+ $frameworkType = $this->findFrameworkType($packageType);
168
+
169
+ if ($frameworkType === false) {
170
+ return false;
171
+ }
172
+
173
+ $locationPattern = $this->getLocationPattern($frameworkType);
174
+
175
+ return preg_match('#' . $frameworkType . '-' . $locationPattern . '#', $packageType, $matches) === 1;
176
+ }
177
+
178
+ /**
179
+ * Finds a supported framework type if it exists and returns it
180
+ *
181
+ * @param string $type
182
+ * @return string
183
+ */
184
+ protected function findFrameworkType($type)
185
+ {
186
+ $frameworkType = false;
187
+
188
+ krsort($this->supportedTypes);
189
+
190
+ foreach ($this->supportedTypes as $key => $val) {
191
+ if ($key === substr($type, 0, strlen($key))) {
192
+ $frameworkType = substr($type, 0, strlen($key));
193
+ break;
194
+ }
195
+ }
196
+
197
+ return $frameworkType;
198
+ }
199
+
200
+ /**
201
+ * Get the second part of the regular expression to check for support of a
202
+ * package type
203
+ *
204
+ * @param string $frameworkType
205
+ * @return string
206
+ */
207
+ protected function getLocationPattern($frameworkType)
208
+ {
209
+ $pattern = false;
210
+ if (!empty($this->supportedTypes[$frameworkType])) {
211
+ $frameworkClass = 'Composer\\Installers\\' . $this->supportedTypes[$frameworkType];
212
+ /** @var BaseInstaller $framework */
213
+ $framework = new $frameworkClass(null, $this->composer, $this->getIO());
214
+ $locations = array_keys($framework->getLocations());
215
+ $pattern = $locations ? '(' . implode('|', $locations) . ')' : false;
216
+ }
217
+
218
+ return $pattern ? : '(\w+)';
219
+ }
220
+
221
+ /**
222
+ * Get I/O object
223
+ *
224
+ * @return IOInterface
225
+ */
226
+ private function getIO()
227
+ {
228
+ return $this->io;
229
+ }
230
+
231
+ /**
232
+ * Look for installers set to be disabled in composer's extra config and
233
+ * remove them from the list of supported installers.
234
+ *
235
+ * Globals:
236
+ * - true, "all", and "*" - disable all installers.
237
+ * - false - enable all installers (useful with
238
+ * wikimedia/composer-merge-plugin or similar)
239
+ *
240
+ * @return void
241
+ */
242
+ protected function removeDisabledInstallers()
243
+ {
244
+ $extra = $this->composer->getPackage()->getExtra();
245
+
246
+ if (!isset($extra['installer-disable']) || $extra['installer-disable'] === false) {
247
+ // No installers are disabled
248
+ return;
249
+ }
250
+
251
+ // Get installers to disable
252
+ $disable = $extra['installer-disable'];
253
+
254
+ // Ensure $disabled is an array
255
+ if (!is_array($disable)) {
256
+ $disable = array($disable);
257
+ }
258
+
259
+ // Check which installers should be disabled
260
+ $all = array(true, "all", "*");
261
+ $intersect = array_intersect($all, $disable);
262
+ if (!empty($intersect)) {
263
+ // Disable all installers
264
+ $this->supportedTypes = array();
265
+ } else {
266
+ // Disable specified installers
267
+ foreach ($disable as $key => $installer) {
268
+ if (is_string($installer) && key_exists($installer, $this->supportedTypes)) {
269
+ unset($this->supportedTypes[$installer]);
270
+ }
271
+ }
272
+ }
273
+ }
274
+ }
vendor/composer/installers/src/Composer/Installers/ItopInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class ItopInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'extension' => 'extensions/{$name}/',
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/JoomlaInstaller.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class JoomlaInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'component' => 'components/{$name}/',
8
+ 'module' => 'modules/{$name}/',
9
+ 'template' => 'templates/{$name}/',
10
+ 'plugin' => 'plugins/{$name}/',
11
+ 'library' => 'libraries/{$name}/',
12
+ );
13
+
14
+ // TODO: Add inflector for mod_ and com_ names
15
+ }
vendor/composer/installers/src/Composer/Installers/KanboardInstaller.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ /**
5
+ *
6
+ * Installer for kanboard plugins
7
+ *
8
+ * kanboard.net
9
+ *
10
+ * Class KanboardInstaller
11
+ * @package Composer\Installers
12
+ */
13
+ class KanboardInstaller extends BaseInstaller
14
+ {
15
+ protected $locations = array(
16
+ 'plugin' => 'plugins/{$name}/',
17
+ );
18
+ }
vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class KirbyInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'plugin' => 'site/plugins/{$name}/',
8
+ 'field' => 'site/fields/{$name}/',
9
+ 'tag' => 'site/tags/{$name}/'
10
+ );
11
+ }
vendor/composer/installers/src/Composer/Installers/KodiCMSInstaller.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class KodiCMSInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'plugin' => 'cms/plugins/{$name}/',
8
+ 'media' => 'cms/media/vendor/{$name}/'
9
+ );
10
+ }
vendor/composer/installers/src/Composer/Installers/KohanaInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class KohanaInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'modules/{$name}/',
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Composer\Installers;
4
+
5
+ class LanManagementSystemInstaller extends BaseInstaller
6
+ {
7
+
8
+ protected $locations = array(
9
+ 'plugin' => 'plugins/{$name}/',
10
+ 'template' => 'templates/{$name}/',
11
+ 'document-template' => 'documents/templates/{$name}/',
12
+ 'userpanel-module' => 'userpanel/modules/{$name}/',
13
+ );
14
+
15
+ /**
16
+ * Format package name to CamelCase
17
+ */
18
+ public function inflectPackageVars($vars)
19
+ {
20
+ $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name']));
21
+ $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']);
22
+ $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
23
+
24
+ return $vars;
25
+ }
26
+
27
+ }
vendor/composer/installers/src/Composer/Installers/LaravelInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class LaravelInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'library' => 'libraries/{$name}/',
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/LavaLiteInstaller.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class LavaLiteInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'package' => 'packages/{$vendor}/{$name}/',
8
+ 'theme' => 'public/themes/{$name}/',
9
+ );
10
+ }
vendor/composer/installers/src/Composer/Installers/LithiumInstaller.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class LithiumInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'library' => 'libraries/{$name}/',
8
+ 'source' => 'libraries/_source/{$name}/',
9
+ );
10
+ }
vendor/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class MODULEWorkInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'modules/{$name}/',
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/MODXEvoInstaller.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ /**
5
+ * An installer to handle MODX Evolution specifics when installing packages.
6
+ */
7
+ class MODXEvoInstaller extends BaseInstaller
8
+ {
9
+ protected $locations = array(
10
+ 'snippet' => 'assets/snippets/{$name}/',
11
+ 'plugin' => 'assets/plugins/{$name}/',
12
+ 'module' => 'assets/modules/{$name}/',
13
+ 'template' => 'assets/templates/{$name}/',
14
+ 'lib' => 'assets/lib/{$name}/'
15
+ );
16
+ }
vendor/composer/installers/src/Composer/Installers/MagentoInstaller.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class MagentoInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'theme' => 'app/design/frontend/{$name}/',
8
+ 'skin' => 'skin/frontend/default/{$name}/',
9
+ 'library' => 'lib/{$name}/',
10
+ );
11
+ }
vendor/composer/installers/src/Composer/Installers/MajimaInstaller.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ /**
5
+ * Plugin/theme installer for majima
6
+ * @author David Neustadt
7
+ */
8
+ class MajimaInstaller extends BaseInstaller
9
+ {
10
+ protected $locations = array(
11
+ 'plugin' => 'plugins/{$name}/',
12
+ );
13
+
14
+ /**
15
+ * Transforms the names
16
+ * @param array $vars
17
+ * @return array
18
+ */
19
+ public function inflectPackageVars($vars)
20
+ {
21
+ return $this->correctPluginName($vars);
22
+ }
23
+
24
+ /**
25
+ * Change hyphenated names to camelcase
26
+ * @param array $vars
27
+ * @return array
28
+ */
29
+ private function correctPluginName($vars)
30
+ {
31
+ $camelCasedName = preg_replace_callback('/(-[a-z])/', function ($matches) {
32
+ return strtoupper($matches[0][1]);
33
+ }, $vars['name']);
34
+ $vars['name'] = ucfirst($camelCasedName);
35
+ return $vars;
36
+ }
37
+ }
vendor/composer/installers/src/Composer/Installers/MakoInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class MakoInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'package' => 'app/packages/{$name}/',
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/MauticInstaller.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class MauticInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'plugin' => 'plugins/{$name}/',
8
+ 'theme' => 'themes/{$name}/',
9
+ );
10
+
11
+ /**
12
+ * Format package name of mautic-plugins to CamelCase
13
+ */
14
+ public function inflectPackageVars($vars)
15
+ {
16
+ if ($vars['type'] == 'mautic-plugin') {
17
+ $vars['name'] = preg_replace_callback('/(-[a-z])/', function ($matches) {
18
+ return strtoupper($matches[0][1]);
19
+ }, ucfirst($vars['name']));
20
+ }
21
+
22
+ return $vars;
23
+ }
24
+
25
+ }
vendor/composer/installers/src/Composer/Installers/MayaInstaller.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class MayaInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'modules/{$name}/',
8
+ );
9
+
10
+ /**
11
+ * Format package name.
12
+ *
13
+ * For package type maya-module, cut off a trailing '-module' if present.
14
+ *
15
+ */
16
+ public function inflectPackageVars($vars)
17
+ {
18
+ if ($vars['type'] === 'maya-module') {
19
+ return $this->inflectModuleVars($vars);
20
+ }
21
+
22
+ return $vars;
23
+ }
24
+
25
+ protected function inflectModuleVars($vars)
26
+ {
27
+ $vars['name'] = preg_replace('/-module$/', '', $vars['name']);
28
+ $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']);
29
+ $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
30
+
31
+ return $vars;
32
+ }
33
+ }
vendor/composer/installers/src/Composer/Installers/MediaWikiInstaller.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class MediaWikiInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'core' => 'core/',
8
+ 'extension' => 'extensions/{$name}/',
9
+ 'skin' => 'skins/{$name}/',
10
+ );
11
+
12
+ /**
13
+ * Format package name.
14
+ *
15
+ * For package type mediawiki-extension, cut off a trailing '-extension' if present and transform
16
+ * to CamelCase keeping existing uppercase chars.
17
+ *
18
+ * For package type mediawiki-skin, cut off a trailing '-skin' if present.
19
+ *
20
+ */
21
+ public function inflectPackageVars($vars)
22
+ {
23
+
24
+ if ($vars['type'] === 'mediawiki-extension') {
25
+ return $this->inflectExtensionVars($vars);
26
+ }
27
+
28
+ if ($vars['type'] === 'mediawiki-skin') {
29
+ return $this->inflectSkinVars($vars);
30
+ }
31
+
32
+ return $vars;
33
+ }
34
+
35
+ protected function inflectExtensionVars($vars)
36
+ {
37
+ $vars['name'] = preg_replace('/-extension$/', '', $vars['name']);
38
+ $vars['name'] = str_replace('-', ' ', $vars['name']);
39
+ $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
40
+
41
+ return $vars;
42
+ }
43
+
44
+ protected function inflectSkinVars($vars)
45
+ {
46
+ $vars['name'] = preg_replace('/-skin$/', '', $vars['name']);
47
+
48
+ return $vars;
49
+ }
50
+
51
+ }
vendor/composer/installers/src/Composer/Installers/MicroweberInstaller.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class MicroweberInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'userfiles/modules/{$name}/',
8
+ 'module-skin' => 'userfiles/modules/{$name}/templates/',
9
+ 'template' => 'userfiles/templates/{$name}/',
10
+ 'element' => 'userfiles/elements/{$name}/',
11
+ 'vendor' => 'vendor/{$name}/',
12
+ 'components' => 'components/{$name}/'
13
+ );
14
+
15
+ /**
16
+ * Format package name.
17
+ *
18
+ * For package type microweber-module, cut off a trailing '-module' if present
19
+ *
20
+ * For package type microweber-template, cut off a trailing '-template' if present.
21
+ *
22
+ */
23
+ public function inflectPackageVars($vars)
24
+ {
25
+ if ($vars['type'] === 'microweber-template') {
26
+ return $this->inflectTemplateVars($vars);
27
+ }
28
+ if ($vars['type'] === 'microweber-templates') {
29
+ return $this->inflectTemplatesVars($vars);
30
+ }
31
+ if ($vars['type'] === 'microweber-core') {
32
+ return $this->inflectCoreVars($vars);
33
+ }
34
+ if ($vars['type'] === 'microweber-adapter') {
35
+ return $this->inflectCoreVars($vars);
36
+ }
37
+ if ($vars['type'] === 'microweber-module') {
38
+ return $this->inflectModuleVars($vars);
39
+ }
40
+ if ($vars['type'] === 'microweber-modules') {
41
+ return $this->inflectModulesVars($vars);
42
+ }
43
+ if ($vars['type'] === 'microweber-skin') {
44
+ return $this->inflectSkinVars($vars);
45
+ }
46
+ if ($vars['type'] === 'microweber-element' or $vars['type'] === 'microweber-elements') {
47
+ return $this->inflectElementVars($vars);
48
+ }
49
+
50
+ return $vars;
51
+ }
52
+
53
+ protected function inflectTemplateVars($vars)
54
+ {
55
+ $vars['name'] = preg_replace('/-template$/', '', $vars['name']);
56
+ $vars['name'] = preg_replace('/template-$/', '', $vars['name']);
57
+
58
+ return $vars;
59
+ }
60
+
61
+ protected function inflectTemplatesVars($vars)
62
+ {
63
+ $vars['name'] = preg_replace('/-templates$/', '', $vars['name']);
64
+ $vars['name'] = preg_replace('/templates-$/', '', $vars['name']);
65
+
66
+ return $vars;
67
+ }
68
+
69
+ protected function inflectCoreVars($vars)
70
+ {
71
+ $vars['name'] = preg_replace('/-providers$/', '', $vars['name']);
72
+ $vars['name'] = preg_replace('/-provider$/', '', $vars['name']);
73
+ $vars['name'] = preg_replace('/-adapter$/', '', $vars['name']);
74
+
75
+ return $vars;
76
+ }
77
+
78
+ protected function inflectModuleVars($vars)
79
+ {
80
+ $vars['name'] = preg_replace('/-module$/', '', $vars['name']);
81
+ $vars['name'] = preg_replace('/module-$/', '', $vars['name']);
82
+
83
+ return $vars;
84
+ }
85
+
86
+ protected function inflectModulesVars($vars)
87
+ {
88
+ $vars['name'] = preg_replace('/-modules$/', '', $vars['name']);
89
+ $vars['name'] = preg_replace('/modules-$/', '', $vars['name']);
90
+
91
+ return $vars;
92
+ }
93
+
94
+ protected function inflectSkinVars($vars)
95
+ {
96
+ $vars['name'] = preg_replace('/-skin$/', '', $vars['name']);
97
+ $vars['name'] = preg_replace('/skin-$/', '', $vars['name']);
98
+
99
+ return $vars;
100
+ }
101
+
102
+ protected function inflectElementVars($vars)
103
+ {
104
+ $vars['name'] = preg_replace('/-elements$/', '', $vars['name']);
105
+ $vars['name'] = preg_replace('/elements-$/', '', $vars['name']);
106
+ $vars['name'] = preg_replace('/-element$/', '', $vars['name']);
107
+ $vars['name'] = preg_replace('/element-$/', '', $vars['name']);
108
+
109
+ return $vars;
110
+ }
111
+ }
vendor/composer/installers/src/Composer/Installers/ModxInstaller.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ /**
5
+ * An installer to handle MODX specifics when installing packages.
6
+ */
7
+ class ModxInstaller extends BaseInstaller
8
+ {
9
+ protected $locations = array(
10
+ 'extra' => 'core/packages/{$name}/'
11
+ );
12
+ }
vendor/composer/installers/src/Composer/Installers/MoodleInstaller.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class MoodleInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'mod' => 'mod/{$name}/',
8
+ 'admin_report' => 'admin/report/{$name}/',
9
+ 'atto' => 'lib/editor/atto/plugins/{$name}/',
10
+ 'tool' => 'admin/tool/{$name}/',
11
+ 'assignment' => 'mod/assignment/type/{$name}/',
12
+ 'assignsubmission' => 'mod/assign/submission/{$name}/',
13
+ 'assignfeedback' => 'mod/assign/feedback/{$name}/',
14
+ 'auth' => 'auth/{$name}/',
15
+ 'availability' => 'availability/condition/{$name}/',
16
+ 'block' => 'blocks/{$name}/',
17
+ 'booktool' => 'mod/book/tool/{$name}/',
18
+ 'cachestore' => 'cache/stores/{$name}/',
19
+ 'cachelock' => 'cache/locks/{$name}/',
20
+ 'calendartype' => 'calendar/type/{$name}/',
21
+ 'format' => 'course/format/{$name}/',
22
+ 'coursereport' => 'course/report/{$name}/',
23
+ 'datafield' => 'mod/data/field/{$name}/',
24
+ 'datapreset' => 'mod/data/preset/{$name}/',
25
+ 'editor' => 'lib/editor/{$name}/',
26
+ 'enrol' => 'enrol/{$name}/',
27
+ 'filter' => 'filter/{$name}/',
28
+ 'gradeexport' => 'grade/export/{$name}/',
29
+ 'gradeimport' => 'grade/import/{$name}/',
30
+ 'gradereport' => 'grade/report/{$name}/',
31
+ 'gradingform' => 'grade/grading/form/{$name}/',
32
+ 'local' => 'local/{$name}/',
33
+ 'logstore' => 'admin/tool/log/store/{$name}/',
34
+ 'ltisource' => 'mod/lti/source/{$name}/',
35
+ 'ltiservice' => 'mod/lti/service/{$name}/',
36
+ 'message' => 'message/output/{$name}/',
37
+ 'mnetservice' => 'mnet/service/{$name}/',
38
+ 'plagiarism' => 'plagiarism/{$name}/',
39
+ 'portfolio' => 'portfolio/{$name}/',
40
+ 'qbehaviour' => 'question/behaviour/{$name}/',
41
+ 'qformat' => 'question/format/{$name}/',
42
+ 'qtype' => 'question/type/{$name}/',
43
+ 'quizaccess' => 'mod/quiz/accessrule/{$name}/',
44
+ 'quiz' => 'mod/quiz/report/{$name}/',
45
+ 'report' => 'report/{$name}/',
46
+ 'repository' => 'repository/{$name}/',
47
+ 'scormreport' => 'mod/scorm/report/{$name}/',
48
+ 'search' => 'search/engine/{$name}/',
49
+ 'theme' => 'theme/{$name}/',
50
+ 'tinymce' => 'lib/editor/tinymce/plugins/{$name}/',
51
+ 'profilefield' => 'user/profile/field/{$name}/',
52
+ 'webservice' => 'webservice/{$name}/',
53
+ 'workshopallocation' => 'mod/workshop/allocation/{$name}/',
54
+ 'workshopeval' => 'mod/workshop/eval/{$name}/',
55
+ 'workshopform' => 'mod/workshop/form/{$name}/'
56
+ );
57
+ }
vendor/composer/installers/src/Composer/Installers/OctoberInstaller.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class OctoberInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'modules/{$name}/',
8
+ 'plugin' => 'plugins/{$vendor}/{$name}/',
9
+ 'theme' => 'themes/{$name}/'
10
+ );
11
+
12
+ /**
13
+ * Format package name.
14
+ *
15
+ * For package type october-plugin, cut off a trailing '-plugin' if present.
16
+ *
17
+ * For package type october-theme, cut off a trailing '-theme' if present.
18
+ *
19
+ */
20
+ public function inflectPackageVars($vars)
21
+ {
22
+ if ($vars['type'] === 'october-plugin') {
23
+ return $this->inflectPluginVars($vars);
24
+ }
25
+
26
+ if ($vars['type'] === 'october-theme') {
27
+ return $this->inflectThemeVars($vars);
28
+ }
29
+
30
+ return $vars;
31
+ }
32
+
33
+ protected function inflectPluginVars($vars)
34
+ {
35
+ $vars['name'] = preg_replace('/^oc-|-plugin$/', '', $vars['name']);
36
+ $vars['vendor'] = preg_replace('/[^a-z0-9_]/i', '', $vars['vendor']);
37
+
38
+ return $vars;
39
+ }
40
+
41
+ protected function inflectThemeVars($vars)
42
+ {
43
+ $vars['name'] = preg_replace('/^oc-|-theme$/', '', $vars['name']);
44
+
45
+ return $vars;
46
+ }
47
+ }
vendor/composer/installers/src/Composer/Installers/OntoWikiInstaller.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class OntoWikiInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'extension' => 'extensions/{$name}/',
8
+ 'theme' => 'extensions/themes/{$name}/',
9
+ 'translation' => 'extensions/translations/{$name}/',
10
+ );
11
+
12
+ /**
13
+ * Format package name to lower case and remove ".ontowiki" suffix
14
+ */
15
+ public function inflectPackageVars($vars)
16
+ {
17
+ $vars['name'] = strtolower($vars['name']);
18
+ $vars['name'] = preg_replace('/.ontowiki$/', '', $vars['name']);
19
+ $vars['name'] = preg_replace('/-theme$/', '', $vars['name']);
20
+ $vars['name'] = preg_replace('/-translation$/', '', $vars['name']);
21
+
22
+ return $vars;
23
+ }
24
+ }
vendor/composer/installers/src/Composer/Installers/OsclassInstaller.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+
5
+ class OsclassInstaller extends BaseInstaller
6
+ {
7
+
8
+ protected $locations = array(
9
+ 'plugin' => 'oc-content/plugins/{$name}/',
10
+ 'theme' => 'oc-content/themes/{$name}/',
11
+ 'language' => 'oc-content/languages/{$name}/',
12
+ );
13
+
14
+ }
vendor/composer/installers/src/Composer/Installers/OxidInstaller.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ use Composer\Package\PackageInterface;
5
+
6
+ class OxidInstaller extends BaseInstaller
7
+ {
8
+ const VENDOR_PATTERN = '/^modules\/(?P<vendor>.+)\/.+/';
9
+
10
+ protected $locations = array(
11
+ 'module' => 'modules/{$name}/',
12
+ 'theme' => 'application/views/{$name}/',
13
+ 'out' => 'out/{$name}/',
14
+ );
15
+
16
+ /**
17
+ * getInstallPath
18
+ *
19
+ * @param PackageInterface $package
20
+ * @param string $frameworkType
21
+ * @return void
22
+ */
23
+ public function getInstallPath(PackageInterface $package, $frameworkType = '')
24
+ {
25
+ $installPath = parent::getInstallPath($package, $frameworkType);
26
+ $type = $this->package->getType();
27
+ if ($type === 'oxid-module') {
28
+ $this->prepareVendorDirectory($installPath);
29
+ }
30
+ return $installPath;
31
+ }
32
+
33
+ /**
34
+ * prepareVendorDirectory
35
+ *
36
+ * Makes sure there is a vendormetadata.php file inside
37
+ * the vendor folder if there is a vendor folder.
38
+ *
39
+ * @param string $installPath
40
+ * @return void
41
+ */
42
+ protected function prepareVendorDirectory($installPath)
43
+ {
44
+ $matches = '';
45
+ $hasVendorDirectory = preg_match(self::VENDOR_PATTERN, $installPath, $matches);
46
+ if (!$hasVendorDirectory) {
47
+ return;
48
+ }
49
+
50
+ $vendorDirectory = $matches['vendor'];
51
+ $vendorPath = getcwd() . '/modules/' . $vendorDirectory;
52
+ if (!file_exists($vendorPath)) {
53
+ mkdir($vendorPath, 0755, true);
54
+ }
55
+
56
+ $vendorMetaDataPath = $vendorPath . '/vendormetadata.php';
57
+ touch($vendorMetaDataPath);
58
+ }
59
+ }
vendor/composer/installers/src/Composer/Installers/PPIInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class PPIInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'modules/{$name}/',
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/PhiftyInstaller.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class PhiftyInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'bundle' => 'bundles/{$name}/',
8
+ 'library' => 'libraries/{$name}/',
9
+ 'framework' => 'frameworks/{$name}/',
10
+ );
11
+ }
vendor/composer/installers/src/Composer/Installers/PhpBBInstaller.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class PhpBBInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'extension' => 'ext/{$vendor}/{$name}/',
8
+ 'language' => 'language/{$name}/',
9
+ 'style' => 'styles/{$name}/',
10
+ );
11
+ }
vendor/composer/installers/src/Composer/Installers/PimcoreInstaller.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class PimcoreInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'plugin' => 'plugins/{$name}/',
8
+ );
9
+
10
+ /**
11
+ * Format package name to CamelCase
12
+ */
13
+ public function inflectPackageVars($vars)
14
+ {
15
+ $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name']));
16
+ $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']);
17
+ $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
18
+
19
+ return $vars;
20
+ }
21
+ }
vendor/composer/installers/src/Composer/Installers/PiwikInstaller.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ /**
5
+ * Class PiwikInstaller
6
+ *
7
+ * @package Composer\Installers
8
+ */
9
+ class PiwikInstaller extends BaseInstaller
10
+ {
11
+ /**
12
+ * @var array
13
+ */
14
+ protected $locations = array(
15
+ 'plugin' => 'plugins/{$name}/',
16
+ );
17
+
18
+ /**
19
+ * Format package name to CamelCase
20
+ * @param array $vars
21
+ *
22
+ * @return array
23
+ */
24
+ public function inflectPackageVars($vars)
25
+ {
26
+ $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name']));
27
+ $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']);
28
+ $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
29
+
30
+ return $vars;
31
+ }
32
+ }
vendor/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class PlentymarketsInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'plugin' => '{$name}/'
8
+ );
9
+
10
+ /**
11
+ * Remove hyphen, "plugin" and format to camelcase
12
+ * @param array $vars
13
+ *
14
+ * @return array
15
+ */
16
+ public function inflectPackageVars($vars)
17
+ {
18
+ $vars['name'] = explode("-", $vars['name']);
19
+ foreach ($vars['name'] as $key => $name) {
20
+ $vars['name'][$key] = ucfirst($vars['name'][$key]);
21
+ if (strcasecmp($name, "Plugin") == 0) {
22
+ unset($vars['name'][$key]);
23
+ }
24
+ }
25
+ $vars['name'] = implode("",$vars['name']);
26
+
27
+ return $vars;
28
+ }
29
+ }
vendor/composer/installers/src/Composer/Installers/Plugin.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Composer\Installers;
4
+
5
+ use Composer\Composer;
6
+ use Composer\IO\IOInterface;
7
+ use Composer\Plugin\PluginInterface;
8
+
9
+ class Plugin implements PluginInterface
10
+ {
11
+
12
+ public function activate(Composer $composer, IOInterface $io)
13
+ {
14
+ $installer = new Installer($io, $composer);
15
+ $composer->getInstallationManager()->addInstaller($installer);
16
+ }
17
+ }
vendor/composer/installers/src/Composer/Installers/PortoInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class PortoInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'container' => 'app/Containers/{$name}/',
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/PrestashopInstaller.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class PrestashopInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'modules/{$name}/',
8
+ 'theme' => 'themes/{$name}/',
9
+ );
10
+ }
vendor/composer/installers/src/Composer/Installers/PuppetInstaller.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Composer\Installers;
4
+
5
+ class PuppetInstaller extends BaseInstaller
6
+ {
7
+
8
+ protected $locations = array(
9
+ 'module' => 'modules/{$name}/',
10
+ );
11
+ }
vendor/composer/installers/src/Composer/Installers/PxcmsInstaller.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class PxcmsInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'app/Modules/{$name}/',
8
+ 'theme' => 'themes/{$name}/',
9
+ );
10
+
11
+ /**
12
+ * Format package name.
13
+ *
14
+ * @param array $vars
15
+ *
16
+ * @return array
17
+ */
18
+ public function inflectPackageVars($vars)
19
+ {
20
+ if ($vars['type'] === 'pxcms-module') {
21
+ return $this->inflectModuleVars($vars);
22
+ }
23
+
24
+ if ($vars['type'] === 'pxcms-theme') {
25
+ return $this->inflectThemeVars($vars);
26
+ }
27
+
28
+ return $vars;
29
+ }
30
+
31
+ /**
32
+ * For package type pxcms-module, cut off a trailing '-plugin' if present.
33
+ *
34
+ * return string
35
+ */
36
+ protected function inflectModuleVars($vars)
37
+ {
38
+ $vars['name'] = str_replace('pxcms-', '', $vars['name']); // strip out pxcms- just incase (legacy)
39
+ $vars['name'] = str_replace('module-', '', $vars['name']); // strip out module-
40
+ $vars['name'] = preg_replace('/-module$/', '', $vars['name']); // strip out -module
41
+ $vars['name'] = str_replace('-', '_', $vars['name']); // make -'s be _'s
42
+ $vars['name'] = ucwords($vars['name']); // make module name camelcased
43
+
44
+ return $vars;
45
+ }
46
+
47
+
48
+ /**
49
+ * For package type pxcms-module, cut off a trailing '-plugin' if present.
50
+ *
51
+ * return string
52
+ */
53
+ protected function inflectThemeVars($vars)
54
+ {
55
+ $vars['name'] = str_replace('pxcms-', '', $vars['name']); // strip out pxcms- just incase (legacy)
56
+ $vars['name'] = str_replace('theme-', '', $vars['name']); // strip out theme-
57
+ $vars['name'] = preg_replace('/-theme$/', '', $vars['name']); // strip out -theme
58
+ $vars['name'] = str_replace('-', '_', $vars['name']); // make -'s be _'s
59
+ $vars['name'] = ucwords($vars['name']); // make module name camelcased
60
+
61
+ return $vars;
62
+ }
63
+ }
vendor/composer/installers/src/Composer/Installers/RadPHPInstaller.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class RadPHPInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'bundle' => 'src/{$name}/'
8
+ );
9
+
10
+ /**
11
+ * Format package name to CamelCase
12
+ */
13
+ public function inflectPackageVars($vars)
14
+ {
15
+ $nameParts = explode('/', $vars['name']);
16
+ foreach ($nameParts as &$value) {
17
+ $value = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $value));
18
+ $value = str_replace(array('-', '_'), ' ', $value);
19
+ $value = str_replace(' ', '', ucwords($value));
20
+ }
21
+ $vars['name'] = implode('/', $nameParts);
22
+ return $vars;
23
+ }
24
+ }
vendor/composer/installers/src/Composer/Installers/ReIndexInstaller.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class ReIndexInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'theme' => 'themes/{$name}/',
8
+ 'plugin' => 'plugins/{$name}/'
9
+ );
10
+ }
vendor/composer/installers/src/Composer/Installers/RedaxoInstaller.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class RedaxoInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'addon' => 'redaxo/include/addons/{$name}/',
8
+ 'bestyle-plugin' => 'redaxo/include/addons/be_style/plugins/{$name}/'
9
+ );
10
+ }
vendor/composer/installers/src/Composer/Installers/RoundcubeInstaller.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class RoundcubeInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'plugin' => 'plugins/{$name}/',
8
+ );
9
+
10
+ /**
11
+ * Lowercase name and changes the name to a underscores
12
+ *
13
+ * @param array $vars
14
+ * @return array
15
+ */
16
+ public function inflectPackageVars($vars)
17
+ {
18
+ $vars['name'] = strtolower(str_replace('-', '_', $vars['name']));
19
+
20
+ return $vars;
21
+ }
22
+ }
vendor/composer/installers/src/Composer/Installers/SMFInstaller.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class SMFInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'Sources/{$name}/',
8
+ 'theme' => 'Themes/{$name}/',
9
+ );
10
+ }
vendor/composer/installers/src/Composer/Installers/ShopwareInstaller.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ /**
5
+ * Plugin/theme installer for shopware
6
+ * @author Benjamin Boit
7
+ */
8
+ class ShopwareInstaller extends BaseInstaller
9
+ {
10
+ protected $locations = array(
11
+ 'backend-plugin' => 'engine/Shopware/Plugins/Local/Backend/{$name}/',
12
+ 'core-plugin' => 'engine/Shopware/Plugins/Local/Core/{$name}/',
13
+ 'frontend-plugin' => 'engine/Shopware/Plugins/Local/Frontend/{$name}/',
14
+ 'theme' => 'templates/{$name}/',
15
+ 'plugin' => 'custom/plugins/{$name}/',
16
+ 'frontend-theme' => 'themes/Frontend/{$name}/',
17
+ );
18
+
19
+ /**
20
+ * Transforms the names
21
+ * @param array $vars
22
+ * @return array
23
+ */
24
+ public function inflectPackageVars($vars)
25
+ {
26
+ if ($vars['type'] === 'shopware-theme') {
27
+ return $this->correctThemeName($vars);
28
+ }
29
+
30
+ return $this->correctPluginName($vars);
31
+ }
32
+
33
+ /**
34
+ * Changes the name to a camelcased combination of vendor and name
35
+ * @param array $vars
36
+ * @return array
37
+ */
38
+ private function correctPluginName($vars)
39
+ {
40
+ $camelCasedName = preg_replace_callback('/(-[a-z])/', function ($matches) {
41
+ return strtoupper($matches[0][1]);
42
+ }, $vars['name']);
43
+
44
+ $vars['name'] = ucfirst($vars['vendor']) . ucfirst($camelCasedName);
45
+
46
+ return $vars;
47
+ }
48
+
49
+ /**
50
+ * Changes the name to a underscore separated name
51
+ * @param array $vars
52
+ * @return array
53
+ */
54
+ private function correctThemeName($vars)
55
+ {
56
+ $vars['name'] = str_replace('-', '_', $vars['name']);
57
+
58
+ return $vars;
59
+ }
60
+ }
vendor/composer/installers/src/Composer/Installers/SilverStripeInstaller.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ use Composer\Package\PackageInterface;
5
+
6
+ class SilverStripeInstaller extends BaseInstaller
7
+ {
8
+ protected $locations = array(
9
+ 'module' => '{$name}/',
10
+ 'theme' => 'themes/{$name}/',
11
+ );
12
+
13
+ /**
14
+ * Return the install path based on package type.
15
+ *
16
+ * Relies on built-in BaseInstaller behaviour with one exception: silverstripe/framework
17
+ * must be installed to 'sapphire' and not 'framework' if the version is <3.0.0
18
+ *
19
+ * @param PackageInterface $package
20
+ * @param string $frameworkType
21
+ * @return string
22
+ */
23
+ public function getInstallPath(PackageInterface $package, $frameworkType = '')
24
+ {
25
+ if (
26
+ $package->getName() == 'silverstripe/framework'
27
+ && preg_match('/^\d+\.\d+\.\d+/', $package->getVersion())
28
+ && version_compare($package->getVersion(), '2.999.999') < 0
29
+ ) {
30
+ return $this->templatePath($this->locations['module'], array('name' => 'sapphire'));
31
+ }
32
+
33
+ return parent::getInstallPath($package, $frameworkType);
34
+ }
35
+ }
vendor/composer/installers/src/Composer/Installers/SiteDirectInstaller.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Composer\Installers;
4
+
5
+ class SiteDirectInstaller extends BaseInstaller
6
+ {
7
+ protected $locations = array(
8
+ 'module' => 'modules/{$vendor}/{$name}/',
9
+ 'plugin' => 'plugins/{$vendor}/{$name}/'
10
+ );
11
+
12
+ public function inflectPackageVars($vars)
13
+ {
14
+ return $this->parseVars($vars);
15
+ }
16
+
17
+ protected function parseVars($vars)
18
+ {
19
+ $vars['vendor'] = strtolower($vars['vendor']) == 'sitedirect' ? 'SiteDirect' : $vars['vendor'];
20
+ $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']);
21
+ $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
22
+
23
+ return $vars;
24
+ }
25
+ }
vendor/composer/installers/src/Composer/Installers/SyDESInstaller.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class SyDESInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'app/modules/{$name}/',
8
+ 'theme' => 'themes/{$name}/',
9
+ );
10
+
11
+ /**
12
+ * Format module name.
13
+ *
14
+ * Strip `sydes-` prefix and a trailing '-theme' or '-module' from package name if present.
15
+ *
16
+ * @param array @vars
17
+ *
18
+ * @return array
19
+ */
20
+ public function inflectPackageVars($vars)
21
+ {
22
+ if ($vars['type'] == 'sydes-module') {
23
+ return $this->inflectModuleVars($vars);
24
+ }
25
+
26
+ if ($vars['type'] === 'sydes-theme') {
27
+ return $this->inflectThemeVars($vars);
28
+ }
29
+
30
+ return $vars;
31
+ }
32
+
33
+ public function inflectModuleVars($vars)
34
+ {
35
+ $vars['name'] = preg_replace('/(^sydes-|-module$)/i', '', $vars['name']);
36
+ $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']);
37
+ $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
38
+
39
+ return $vars;
40
+ }
41
+
42
+ protected function inflectThemeVars($vars)
43
+ {
44
+ $vars['name'] = preg_replace('/(^sydes-|-theme$)/', '', $vars['name']);
45
+ $vars['name'] = strtolower($vars['name']);
46
+
47
+ return $vars;
48
+ }
49
+ }
vendor/composer/installers/src/Composer/Installers/Symfony1Installer.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ /**
5
+ * Plugin installer for symfony 1.x
6
+ *
7
+ * @author Jérôme Tamarelle <jerome@tamarelle.net>
8
+ */
9
+ class Symfony1Installer extends BaseInstaller
10
+ {
11
+ protected $locations = array(
12
+ 'plugin' => 'plugins/{$name}/',
13
+ );
14
+
15
+ /**
16
+ * Format package name to CamelCase
17
+ */
18
+ public function inflectPackageVars($vars)
19
+ {
20
+ $vars['name'] = preg_replace_callback('/(-[a-z])/', function ($matches) {
21
+ return strtoupper($matches[0][1]);
22
+ }, $vars['name']);
23
+
24
+ return $vars;
25
+ }
26
+ }
vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ /**
5
+ * Extension installer for TYPO3 CMS
6
+ *
7
+ * @deprecated since 1.0.25, use https://packagist.org/packages/typo3/cms-composer-installers instead
8
+ *
9
+ * @author Sascha Egerer <sascha.egerer@dkd.de>
10
+ */
11
+ class TYPO3CmsInstaller extends BaseInstaller
12
+ {
13
+ protected $locations = array(
14
+ 'extension' => 'typo3conf/ext/{$name}/',
15
+ );
16
+ }
vendor/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ /**
5
+ * An installer to handle TYPO3 Flow specifics when installing packages.
6
+ */
7
+ class TYPO3FlowInstaller extends BaseInstaller
8
+ {
9
+ protected $locations = array(
10
+ 'package' => 'Packages/Application/{$name}/',
11
+ 'framework' => 'Packages/Framework/{$name}/',
12
+ 'plugin' => 'Packages/Plugins/{$name}/',
13
+ 'site' => 'Packages/Sites/{$name}/',
14
+ 'boilerplate' => 'Packages/Boilerplates/{$name}/',
15
+ 'build' => 'Build/{$name}/',
16
+ );
17
+
18
+ /**
19
+ * Modify the package name to be a TYPO3 Flow style key.
20
+ *
21
+ * @param array $vars
22
+ * @return array
23
+ */
24
+ public function inflectPackageVars($vars)
25
+ {
26
+ $autoload = $this->package->getAutoload();
27
+ if (isset($autoload['psr-0']) && is_array($autoload['psr-0'])) {
28
+ $namespace = key($autoload['psr-0']);
29
+ $vars['name'] = str_replace('\\', '.', $namespace);
30
+ }
31
+ if (isset($autoload['psr-4']) && is_array($autoload['psr-4'])) {
32
+ $namespace = key($autoload['psr-4']);
33
+ $vars['name'] = rtrim(str_replace('\\', '.', $namespace), '.');
34
+ }
35
+
36
+ return $vars;
37
+ }
38
+ }
vendor/composer/installers/src/Composer/Installers/TheliaInstaller.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class TheliaInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'local/modules/{$name}/',
8
+ 'frontoffice-template' => 'templates/frontOffice/{$name}/',
9
+ 'backoffice-template' => 'templates/backOffice/{$name}/',
10
+ 'email-template' => 'templates/email/{$name}/',
11
+ );
12
+ }
vendor/composer/installers/src/Composer/Installers/TuskInstaller.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+ /**
4
+ * Composer installer for 3rd party Tusk utilities
5
+ * @author Drew Ewing <drew@phenocode.com>
6
+ */
7
+ class TuskInstaller extends BaseInstaller
8
+ {
9
+ protected $locations = array(
10
+ 'task' => '.tusk/tasks/{$name}/',
11
+ 'command' => '.tusk/commands/{$name}/',
12
+ 'asset' => 'assets/tusk/{$name}/',
13
+ );
14
+ }
vendor/composer/installers/src/Composer/Installers/UserFrostingInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class UserFrostingInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'sprinkle' => 'app/sprinkles/{$name}/',
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/VanillaInstaller.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class VanillaInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'plugin' => 'plugins/{$name}/',
8
+ 'theme' => 'themes/{$name}/',
9
+ );
10
+ }
vendor/composer/installers/src/Composer/Installers/VgmcpInstaller.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class VgmcpInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'bundle' => 'src/{$vendor}/{$name}/',
8
+ 'theme' => 'themes/{$name}/'
9
+ );
10
+
11
+ /**
12
+ * Format package name.
13
+ *
14
+ * For package type vgmcp-bundle, cut off a trailing '-bundle' if present.
15
+ *
16
+ * For package type vgmcp-theme, cut off a trailing '-theme' if present.
17
+ *
18
+ */
19
+ public function inflectPackageVars($vars)
20
+ {
21
+ if ($vars['type'] === 'vgmcp-bundle') {
22
+ return $this->inflectPluginVars($vars);
23
+ }
24
+
25
+ if ($vars['type'] === 'vgmcp-theme') {
26
+ return $this->inflectThemeVars($vars);
27
+ }
28
+
29
+ return $vars;
30
+ }
31
+
32
+ protected function inflectPluginVars($vars)
33
+ {
34
+ $vars['name'] = preg_replace('/-bundle$/', '', $vars['name']);
35
+ $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']);
36
+ $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
37
+
38
+ return $vars;
39
+ }
40
+
41
+ protected function inflectThemeVars($vars)
42
+ {
43
+ $vars['name'] = preg_replace('/-theme$/', '', $vars['name']);
44
+ $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']);
45
+ $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
46
+
47
+ return $vars;
48
+ }
49
+ }
vendor/composer/installers/src/Composer/Installers/WHMCSInstaller.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Composer\Installers;
4
+
5
+ class WHMCSInstaller extends BaseInstaller
6
+ {
7
+ protected $locations = array(
8
+ 'gateway' => 'modules/gateways/{$name}/',
9
+ );
10
+ }
vendor/composer/installers/src/Composer/Installers/WolfCMSInstaller.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class WolfCMSInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'plugin' => 'wolf/plugins/{$name}/',
8
+ );
9
+ }
vendor/composer/installers/src/Composer/Installers/WordPressInstaller.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class WordPressInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'plugin' => 'wp-content/plugins/{$name}/',
8
+ 'theme' => 'wp-content/themes/{$name}/',
9
+ 'muplugin' => 'wp-content/mu-plugins/{$name}/',
10
+ 'dropin' => 'wp-content/{$name}/',
11
+ );
12
+ }
vendor/composer/installers/src/Composer/Installers/YawikInstaller.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Created by PhpStorm.
4
+ * User: cbleek
5
+ * Date: 25.03.16
6
+ * Time: 20:55
7
+ */
8
+
9
+ namespace Composer\Installers;
10
+
11
+
12
+ class YawikInstaller extends BaseInstaller
13
+ {
14
+ protected $locations = array(
15
+ 'module' => 'module/{$name}/',
16
+ );
17
+
18
+ /**
19
+ * Format package name to CamelCase
20
+ * @param array $vars
21
+ *
22
+ * @return array
23
+ */
24
+ public function inflectPackageVars($vars)
25
+ {
26
+ $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name']));
27
+ $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']);
28
+ $vars['name'] = str_replace(' ', '', ucwords($vars['name']));
29
+
30
+ return $vars;
31
+ }
32
+ }
vendor/composer/installers/src/Composer/Installers/ZendInstaller.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class ZendInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'library' => 'library/{$name}/',
8
+ 'extra' => 'extras/library/{$name}/',
9
+ 'module' => 'module/{$name}/',
10
+ );
11
+ }
vendor/composer/installers/src/Composer/Installers/ZikulaInstaller.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Composer\Installers;
3
+
4
+ class ZikulaInstaller extends BaseInstaller
5
+ {
6
+ protected $locations = array(
7
+ 'module' => 'modules/{$vendor}-{$name}/',
8
+ 'theme' => 'themes/{$vendor}-{$name}/'
9
+ );
10
+ }
vendor/composer/installers/src/bootstrap.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ function includeIfExists($file)
3
+ {
4
+ if (file_exists($file)) {
5
+ return include $file;
6
+ }
7
+ }
8
+ if ((!$loader = includeIfExists(__DIR__ . '/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__ . '/../../../autoload.php'))) {
9
+ die('You must set up the project dependencies, run the following commands:'.PHP_EOL.
10
+ 'curl -s http://getcomposer.org/installer | php'.PHP_EOL.
11
+ 'php composer.phar install'.PHP_EOL);
12
+ }
13
+ return $loader;