PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.10
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.10
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 / Dashboard_widget.php

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

467 lines 12.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 if ( apply_filters( 'themeisle_sdk_hide_dashboard_widget', false ) ) {
76 return;
77 }
78 $this->product = $product;
79 $this->dashboard_name = apply_filters( 'themeisle_sdk_dashboard_widget_name', 'WordPress Guides/Tutorials' );
80 $this->feeds = apply_filters(
81 'themeisle_sdk_dashboard_widget_feeds',
82 [
83 'https://themeisle.com/blog/feed',
84 ]
85 );
86 add_action( 'wp_dashboard_setup', array( &$this, 'add_widget' ) );
87 add_action( 'wp_network_dashboard_setup', array( &$this, 'add_widget' ) );
88 add_filter( 'themeisle_sdk_recommend_plugin_or_theme', array( &$this, 'recommend_plugin_or_theme' ) );
89
90 return $this;
91 }
92
93
94 /**
95 * Add widget to the dashboard
96 *
97 * @return string|void
98 */
99 function add_widget() {
100 global $wp_meta_boxes;
101 if ( isset( $wp_meta_boxes['dashboard']['normal']['core']['themeisle'] ) ) {
102 return;
103 }
104 wp_add_dashboard_widget(
105 'themeisle',
106 $this->dashboard_name,
107 [
108 $this,
109 'render_dashboard_widget',
110 ]
111 );
112 }
113
114 /**
115 * Render widget content
116 */
117 function render_dashboard_widget() {
118 $this->setup_feeds();
119 if ( empty( $this->items ) || ! is_array( $this->items ) ) {
120 return;
121 }
122 ?>
123 <style type="text/css">
124 #themeisle ul li.ti-dw-recommend-item {
125 padding-left: 7px;
126 border-top: 1px solid #eee;
127 margin-bottom: 0px;
128 padding-top: 6px;
129 }
130
131 #themeisle h2.hndle {
132 background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABbCAMAAADncTNAAAAAtFBMVEVHcEyAgIB/f3+xsbGgoaGBgYGCgoKKioqAgIC1tbW5ubnFx8iAgIDU1taBgYGCgoKAgIC0tLXW19jW2NiAgIC3uLiBgYHLzMy4uLhycnLW19d/f3/T1NW0tLTX19mVlZWvr6+BgYHl5eWKiottbW5JSUnW2Nm5ubnh4eHT1NWVlZVjY2N4eHh9fX6pqqq+v79PT0/39/fu7u7Nzc7Z2ttYWFgBAQHDw8P////JysoZGRk0NTZqJc/sAAAAIXRSTlMA0FL7/oEnEPL6eibivm9gwJya76/enFq2CXI+2lFAyM8GATmPAAADj0lEQVR4Xu2YaW/iOhSGAwRCWDosnXa6znjJvm8svf//f12TuARyhiR2pfnUR6gSEnr0+uT4xK7yRb755pvhHePli5K7Bfpkuhoq8ozRJdMH+WWha6Z3sqYparCSLRJqspjImVbANJU03cNMMpofAwQZCGsmpQYyFvVM0Q00OQ9koMl5IPcCoro+RA1Dt2Ea9n9eZ0+YHJLkgIlkDywQx00wCTyaReiKH8LbNU9ybJOdkchV6QFxyCFLbVvdfaREqgUWg/tx2UbqIcK2Hex2TdGLwFTjIj3XP3YfCZFsb23KRZn/3263oymSFI0/a5S4PqUBjoBIJBDjeEhCN0wxQSRybIxtJ3K5SGzuE/vAwIQc8ZmMMJFAIM4oikZItfEFtorGgoE43FObwqHU68OtPCnOz8KZ2Jbl5LgkSW0Tc7YyIz/EFWmS4jMbiZU5mJOmKRaJpKGGyLZtDJh3iyaNUu/3+xyKnrtFL71EG+FTiMpENhQtxUQ8kSOXCIr2tnCNhg/gTX0SHYFp0t7TCwQZ7U841yoHrW6rtGroUwTWVnLMssxx+H4bgZcSOFf5MYx0Ae8FghomMDyC2EBNImBywPkNTDNqGLQpIg2TjUNU8tBy9DQMo0DAZF16rAi7vJAtFTIYFAHUc6hIRW6OuOhJgaCSwmDEAYK4oa7ro+qIEyJU/US7KTJKPNSFT9tFgVFBu0SF1y7yjX4masRA9Da7EFGj28R/BkQz6xGIOurkx38T/bKs9Uk8aIiMwm/Jw0VP1yLrJwt13xAxvABBgsK4KWLov35DkRF7ZaqgzuZ7MQ8MOntmVYyAqKTwaICKqvSUFnVccMN5sziEP/5+xGDTahbH5Q3ZB76zr8fI+nJtvUUU3t3ml5GKviK/npCg3CGodnuJ4JVkfRFJYGVDBZrqKnn9RLf+CzDTS5PaN5J38+auzX4ykU4Qoj0rdKfcYs5ijfo9OL/uRUgZyQr7NCWtWwiUSLc4arfJa7lpszTA1OJZAQ8w8dXFrR5YHzCWSnS3pZ18tOi4Ps4vl/c7i/6qomjRecN+UubrPyPGn/VEMU3T0UFHkaPzpgjxmJsnjmrtionlMDZiog0TsY/DPtn8SXtlBvbtxKtwopy7lqW3smQO+yoGE1Uu55GJ3pmI8ygoejZNnqj0vnIRCyTKfLstRdtStGQi09myUsvwvlkuzSUXbV+Xz5ryBebV33fln/A/moud69FZiEYAAAAASUVORK5CYII=');
133 background-repeat: no-repeat;
134 background-position: 92% 50%;
135 background-size: 25px;
136 }
137
138 #themeisle .inside {
139 padding: 0;
140 }
141
142 .ti-feed-list {
143 padding: 0 12px 5px;
144 margin-bottom: 10px;
145 border-bottom: 1px solid #eee;
146 }
147
148 .ti-dw-feed-item a {
149 display: flex;
150 align-items: center;
151 margin-bottom: 5px;
152 padding: 5px;
153 transition: .2s ease;
154 border-radius: 3px;
155 }
156
157 .ti-dw-feed-item a:hover {
158 background-color: #f8f8f8;
159 }
160
161 .ti-dw-feed-item a:hover .ti-dw-date-container {
162 opacity: .9;
163 }
164
165 .ti-dw-feed-item .ti-dw-month-container {
166 margin-top: -5px;
167 text-transform: uppercase;
168 font-size: 10px;
169 letter-spacing: 1px;
170 font-weight: 700;
171 }
172
173 .ti-dw-feed-item .ti-dw-date-container {
174 border-radius: 3px;
175 transition: .2s ease;
176 min-height: 35px;
177 margin-right: 5px;
178 min-width: 35px;
179 text-align: center;
180 border: 1px solid #2a6f97;
181 color: #fff;
182 background: #2ea2cc;
183 display: flex;
184 flex-direction: column;
185 justify-content: center;
186 }
187
188 .ti-dw-footer {
189 padding: 0 12px 5px;
190 text-align: center;
191 }
192
193 .ti-dw-recommend-item {
194 display: block;
195 }
196
197 .ti-dw-recommend-item span {
198 color: #72777c;
199 }
200
201 .ti-dw-powered-by {
202 font-size: 11px;
203 margin-top: 3px;
204 display: block;
205 color: #72777c;
206 }
207
208 .ti-dw-powered-by span {
209 font-weight: 600;
210 }
211
212 </style>
213 <?php do_action( 'themeisle_sdk_dashboard_widget_before', $this->product ); ?>
214
215 <ul class="ti-feed-list">
216 <?php
217
218 foreach ( $this->items as $item ) {
219 ?>
220 <li class="ti-dw-feed-item">
221 <a href="
222 <?php
223 echo add_query_arg(
224 array(
225 'utm_source' => 'wpadmin',
226 'utm_campaign' => 'feed',
227 'utm_medium' => 'dashboard_widget',
228 ),
229 $item['link']
230 );
231 ?>
232 " target="_blank">
233 <span class="ti-dw-date-container"><span
234 class="ti-dw-day-container"><?php echo date( 'd', $item['date'] ); ?></span> <span
235 class="ti-dw-month-container"><?php echo substr( date( 'M', $item['date'] ), 0, 3 ); ?></span></span><?php echo $item['title']; ?>
236 </a>
237 </li>
238 <?php
239 }
240 ?>
241 </ul>
242 <?php
243 $recommend = apply_filters( 'themeisle_sdk_recommend_plugin_or_theme', array() );
244 if ( ! is_array( $recommend ) || empty( $recommend ) ) {
245 return;
246 }
247
248 $type = $recommend['type'];
249
250 if ( ( 'theme' === $type && ! current_user_can( 'install_themes' ) ) ) {
251 return;
252 }
253 if ( ( 'plugin' === $type && ! current_user_can( 'install_plugins' ) ) ) {
254 return;
255 }
256
257 add_thickbox();
258 $url = add_query_arg(
259 [
260 'theme' => $recommend['slug'],
261 ],
262 network_admin_url( 'theme-install.php' )
263 );
264
265 if ( 'plugin' === $type ) {
266
267 $url = add_query_arg(
268 array(
269 'tab' => 'plugin-information',
270 'plugin' => $recommend['slug'],
271 ),
272 network_admin_url( 'plugin-install.php' )
273 );
274 }
275 ?>
276 <div class="ti-dw-footer">
277 <span class="ti-dw-recommend-item ">
278 <span class="ti-dw-recommend"><?php echo apply_filters( 'themeisle_sdk_dashboard_popular_label', sprintf( 'Popular %s', ucwords( $type ) ) ); ?>
279 : </span>
280 <?php
281 echo trim(
282 str_replace(
283 array(
284 'lite',
285 'Lite',
286 '(Lite)',
287 '(lite)',
288 ),
289 '',
290 $recommend['name']
291 )
292 );
293 ?>
294 (<a class="thickbox open-plugin-details-modal"
295 href="<?php echo $url . '&TB_iframe=true&width=600&height=500'; ?>"><?php echo apply_filters( 'themeisle_sdk_dashboard_install_label', 'Install' ); ?></a>)
296 </span>
297 <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>
298 </div>
299
300 <?php
301
302 }
303
304 /**
305 * Setup feed items.
306 */
307 private function setup_feeds() {
308 if ( false === ( $items_normalized = get_transient( 'themeisle_sdk_feed_items' ) ) ) {
309 // Load SimplePie Instance.
310 $feed = fetch_feed( $this->feeds );
311 // TODO report error when is an error loading the feed.
312 if ( is_wp_error( $feed ) ) {
313 return;
314 }
315
316 $items = $feed->get_items( 0, 5 );
317 foreach ( (array) $items as $item ) {
318 $items_normalized[] = array(
319 'title' => $item->get_title(),
320 'date' => $item->get_date( 'U' ),
321 'link' => $item->get_permalink(),
322 );
323 }
324 set_transient( 'themeisle_sdk_feed_items', $items_normalized, 48 * HOUR_IN_SECONDS );
325 }
326 $this->items = $items_normalized;
327 }
328
329 /**
330 * Either the current product is installed or not.
331 *
332 * @param array $val The current recommended product.
333 *
334 * @return bool Either we should exclude the plugin or not.
335 */
336 public function remove_current_products( $val ) {
337 if ( 'theme' === $val['type'] ) {
338 $exist = wp_get_theme( $val['slug'] );
339
340 return ! $exist->exists();
341 } else {
342 $all_plugins = array_keys( get_plugins() );
343 foreach ( $all_plugins as $slug ) {
344 if ( strpos( $slug, $val['slug'] ) !== false ) {
345 return false;
346 }
347 }
348
349 return true;
350 }
351 }
352
353 /**
354 * Contact the API and fetch the recommended plugins/themes
355 */
356 function recommend_plugin_or_theme() {
357 $products = $this->get_product_from_api();
358 if ( ! is_array( $products ) ) {
359 $products = array();
360 }
361 $products = array_filter( $products, array( $this, 'remove_current_products' ) );
362 $products = array_merge( $products );
363 if ( count( $products ) > 1 ) {
364 shuffle( $products );
365 $products = array_slice( $products, 0, 1 );
366 }
367 $to_recommend = isset( $products[0] ) ? $products[0] : $products;
368
369 return $to_recommend;
370 }
371
372 /**
373 * Fetch products from the recomended section.
374 *
375 * @return array|mixed The list of products to use in recomended section.
376 */
377 function get_product_from_api() {
378 if ( false === ( $products = get_transient( 'themeisle_sdk_products' ) ) ) {
379 $products = array();
380 $all_themes = $this->get_themes_from_wporg( 'themeisle' );
381 $all_plugins = $this->get_plugins_from_wporg( 'themeisle' );
382 static $allowed_products = [
383 'hestia' => true,
384 'neve' => true,
385 'visualizer' => true,
386 'feedzy-rss-feeds' => true,
387 'wp-product-review' => true,
388 'otter-blocks' => true,
389 'themeisle-companion' => true,
390 ];
391 foreach ( $all_themes as $theme ) {
392 if ( $theme->active_installs < 4999 ) {
393 continue;
394 }
395 if ( ! isset( $allowed_products[ $theme->slug ] ) ) {
396 continue;
397 }
398 $products[] = array(
399 'name' => $theme->name,
400 'type' => 'theme',
401 'slug' => $theme->slug,
402 'installs' => $theme->active_installs,
403 );
404 }
405 foreach ( $all_plugins as $plugin ) {
406 if ( $plugin->active_installs < 4999 ) {
407 continue;
408 }
409 if ( ! isset( $allowed_products[ $plugin->slug ] ) ) {
410 continue;
411 }
412 $products[] = array(
413 'name' => $plugin->name,
414 'type' => 'plugin',
415 'slug' => $plugin->slug,
416 'installs' => $plugin->active_installs,
417 );
418 }
419 set_transient( 'themeisle_sdk_products', $products, 6 * HOUR_IN_SECONDS );
420 }
421
422 return $products;
423 }
424
425 /**
426 * Fetch themes from wporg api.
427 *
428 * @param string $author The author name.
429 *
430 * @return array The list of themes.
431 */
432 function get_themes_from_wporg( $author ) {
433 $products = wp_remote_get(
434 'https://api.wordpress.org/themes/info/1.1/?action=query_themes&request[author]=' . $author . '&request[per_page]=30&request[fields][active_installs]=true'
435 );
436 $products = json_decode( wp_remote_retrieve_body( $products ) );
437 if ( is_object( $products ) ) {
438 $products = isset( $products->themes ) ? $products->themes : array();
439 } else {
440 $products = array();
441 }
442
443 return (array) $products;
444 }
445
446 /**
447 * Fetch plugin from wporg api.
448 *
449 * @param string $author The author slug.
450 *
451 * @return array The list of plugins for the selected author.
452 */
453 function get_plugins_from_wporg( $author ) {
454 $products = wp_remote_get(
455 'https://api.wordpress.org/plugins/info/1.1/?action=query_plugins&request[author]=' . $author . '&request[per_page]=40&request[fields][active_installs]=true'
456 );
457 $products = json_decode( wp_remote_retrieve_body( $products ) );
458 if ( is_object( $products ) ) {
459 $products = isset( $products->plugins ) ? $products->plugins : array();
460 } else {
461 $products = array();
462 }
463
464 return (array) $products;
465 }
466 }
467