PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 4.0.5
Visualizer – Tables & Charts Manager with Built-in AI Generator v4.0.5
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 All 149 releases
visualizer / vendor / codeinwp / themeisle-sdk / src / Modules / Featured_plugins.php

Featured_plugins.php in Visualizer – Tables & Charts Manager with Built-in AI Generator 4.0.5, at vendor/codeinwp/themeisle-sdk/src/Modules/Featured_plugins.php

291 lines 7.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * File responsible for showing plugins inside the featured tab.
4 *
5 * This is used to display information about limited events, such as Black Friday.
6 *
7 * @package ThemeIsleSDK
8 * @subpackage Modules
9 * @copyright Copyright (c) 2017, Marius Cristea
10 * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
11 * @since 3.3.0
12 */
13 namespace ThemeisleSDK\Modules;
14
15 use ThemeisleSDK\Common\Abstract_Module;
16 use ThemeisleSDK\Loader;
17 use ThemeisleSDK\Product;
18
19 // Exit if accessed directly.
20 if ( ! defined( 'ABSPATH' ) ) {
21 exit;
22 }
23
24 /**
25 * Featured_Plugins module for the ThemeIsle SDK.
26 */
27 class Featured_Plugins extends Abstract_Module {
28
29 /**
30 * The transient key prefix.
31 *
32 * @var string $transient_key
33 */
34 private $transient_key = 'themeisle_sdk_featured_plugins_';
35
36 /**
37 * The current product instance.
38 *
39 * @var Product|null
40 */
41 protected $product = null;
42
43 /**
44 * Check if the module can be loaded.
45 *
46 * @param Product $product Product data.
47 *
48 * @return bool
49 */
50 public function can_load( $product ) {
51 if ( $this->is_from_partner( $product ) ) {
52 return false;
53 }
54
55 if ( $product->is_wordpress_available() ) {
56 return false;
57 }
58
59 return ! apply_filters( 'themeisle_sdk_disable_featured_plugins', false );
60 }
61
62 /**
63 * Load the module for the selected product.
64 *
65 * @param Product $product Product data.
66 *
67 * @return void
68 */
69 public function load( $product ) {
70 $this->product = $product;
71
72 if ( ! current_user_can( 'install_plugins' ) ) {
73 return;
74 }
75
76 // bail if we already registered a filter for the plugin API.
77 if ( apply_filters( 'themeisle_sdk_plugin_api_filter_registered', false ) ) {
78 return;
79 }
80 add_filter( 'themeisle_sdk_plugin_api_filter_registered', '__return_true' );
81
82 add_filter( 'plugins_api_result', [ $this, 'filter_plugin_api_results' ], 11, 3 );
83
84 // Enqueue inline JS only on plugin-install.php.
85 add_action( 'admin_enqueue_scripts', [ $this, 'maybe_add_inline_js' ] );
86 }
87
88 /**
89 * Enqueue inline JavaScript only on plugin-install.php.
90 *
91 * @return void
92 */
93 public function maybe_add_inline_js() {
94 $screen = get_current_screen();
95 if ( isset( $screen->base ) && 'plugin-install' === $screen->base ) {
96 add_action(
97 'admin_footer',
98 function() {
99 $text = esc_html( sprintf( Loader::$labels['promotions']['recommended'], $this->product->get_friendly_name() ) );
100
101 echo '<script>(function(){
102 function onPluginCardFound(card) {
103 var recommendedDiv = document.createElement("div");
104 Object.assign(recommendedDiv.style, {
105 display: "block",
106 textAlign: "center",
107 padding: "0 12px 12px",
108 background: "#f6f7f7"
109 });
110 recommendedDiv.innerHTML = "' . esc_html( $text ) . '";
111 card.appendChild(recommendedDiv);
112 }
113
114 function checkAndRun() {
115 var card = document.querySelector(".plugin-card-learning-management-system");
116 if (card && !card.dataset.recommendedAdded) {
117 onPluginCardFound(card);
118 card.dataset.recommendedAdded = "true";
119 }
120 }
121
122 var observer = new MutationObserver(function(mutations) {
123 checkAndRun();
124 });
125
126 observer.observe(document.body, { childList: true, subtree: true });
127
128 // Initial check in case the card is already present.
129 checkAndRun();
130 })();</script>';
131 }
132 );
133 }
134 }
135
136 /**
137 * Filter the plugin API results to include the featured plugins.
138 *
139 * @param object $res The result object.
140 * @param string $action The type of information being requested from the Plugin Install API.
141 * @param object $args Plugin API arguments.
142 *
143 * @return object
144 */
145 public function filter_plugin_api_results( $res, $action, $args ) {
146
147 if ( 'query_plugins' !== $action ) {
148 return $res;
149 }
150
151 if ( isset( $args->page ) && 1 === (int) $args->page && isset( $args->search ) && ! empty( $args->search ) ) {
152 $res->plugins = $this->maybe_prepend_lms_plugin( $res->plugins, $args );
153 return $res;
154 }
155
156 if ( ! isset( $args->browse ) || $args->browse !== 'featured' ) {
157 return $res;
158 }
159
160 $featured = $this->query_plugins_by_author( $args );
161
162 $plugins = array_merge( $featured, (array) $res->plugins );
163 $plugins = array_slice( $plugins, 0, $res->info['results'] );
164 $res->plugins = $plugins;
165
166 return $res;
167 }
168
169 /**
170 * Prepend the LMS plugin if the search query matches LMS-related terms.
171 *
172 * @param array $plugins The plugins array.
173 * @param object $args The plugin API arguments.
174 * @return array
175 */
176 private function maybe_prepend_lms_plugin( $plugins, $args ) {
177 $search = isset( $args->search ) ? strtolower( $args->search ) : '';
178 if ( $this->matches_lms_search_keywords( $search ) ) {
179 $filter_slugs = apply_filters( 'themeisle_sdk_masteriyo_filter_slugs', [ 'learning-management-system' ] );
180 $masteriyo = $this->get_plugins_filtered_from_author( $args, $filter_slugs, 'masteriyo' );
181
182 if ( ! empty( $masteriyo ) ) {
183 // Remove existing LMS plugin if present to avoid duplicates.
184 $plugins = array_filter(
185 $plugins,
186 function( $plugin ) {
187 return ( is_object( $plugin ) && isset( $plugin->slug ) && $plugin->slug !== 'learning-management-system' ) ||
188 ( is_array( $plugin ) && isset( $plugin['slug'] ) && $plugin['slug'] !== 'learning-management-system' );
189 }
190 );
191
192 $plugins = array_merge( $masteriyo, $plugins );
193 }
194 }
195 return $plugins;
196 }
197
198 /**
199 * Check if a plugin search query matches LMS-related terms.
200 *
201 * @param string $search Search query.
202 *
203 * @return bool True if the search query matches LMS-related terms.
204 */
205 private function matches_lms_search_keywords( $search ) {
206 $lms_keywords = array(
207 'lms',
208 'learn',
209 'course',
210 'courses',
211 'learning',
212 'academy',
213 'training',
214 'student',
215 'students',
216 'quiz',
217 );
218
219 foreach ( $lms_keywords as $keyword ) {
220 if ( preg_match( '/(^|[^a-z0-9])' . preg_quote( $keyword, '/' ) . '([^a-z0-9]|$)/', $search ) === 1 ) {
221 return true;
222 }
223 }
224
225 return false;
226 }
227
228 /**
229 * Query plugins by author.
230 *
231 * @param object $args The arguments for the query.
232 *
233 * @return array
234 */
235 private function query_plugins_by_author( $args ) {
236 $featured = [];
237
238 $optimole_filter_slugs = apply_filters( 'themeisle_sdk_optimole_filter_slugs', [ 'optimole-wp' ] );
239 $filtered_from_optimole = $this->get_plugins_filtered_from_author( $args, $optimole_filter_slugs, 'Optimole' );
240 $featured = array_merge( $featured, $filtered_from_optimole );
241
242 $themeisle_filter_slugs = apply_filters( 'themeisle_sdk_themeisle_filter_slugs', [ 'otter-blocks', 'wp-cloudflare-page-cache' ] );
243 $filtered_from_themeisle = $this->get_plugins_filtered_from_author( $args, $themeisle_filter_slugs );
244 $featured = array_merge( $featured, $filtered_from_themeisle );
245
246 return $featured;
247 }
248
249 /**
250 * Get plugins filtered from an author.
251 *
252 * @param object $args The arguments for the query.
253 * @param array $filter_slugs The slugs to filter.
254 * @param string $author The author to filter.
255 *
256 * @return array
257 */
258 protected function get_plugins_filtered_from_author( $args, $filter_slugs = [], $author = 'Themeisle' ) {
259
260 $cached = get_transient( $this->transient_key . $author );
261 if ( $cached ) {
262 return $cached;
263 }
264
265 $new_args = [
266 'page' => 1,
267 'per_page' => 36,
268 'locale' => get_user_locale(),
269 'author' => $author,
270 'wp_version' => isset( $args->wp_version ) ? $args->wp_version : get_bloginfo( 'version' ),
271 ];
272
273 $api = plugins_api( 'query_plugins', $new_args );
274 if ( is_wp_error( $api ) ) {
275 return [];
276 }
277
278 $filtered = array_filter(
279 $api->plugins,
280 function( $plugin ) use ( $filter_slugs ) {
281 $array_plugin = (array) $plugin;
282 return in_array( $array_plugin['slug'], $filter_slugs );
283 }
284 );
285
286 set_transient( $this->transient_key . $author, $filtered, 12 * HOUR_IN_SECONDS );
287
288 return $filtered;
289 }
290 }
291