PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.7.9
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.7.9
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 3.10.4 All 148 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.7.9, at vendor/codeinwp/themeisle-sdk/src/Modules/Dashboard_widget.php

471 lines 13.0 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 public 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 public 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 esc_url(
224 add_query_arg(
225 array(
226 'utm_source' => 'wpadmin',
227 'utm_campaign' => 'feed',
228 'utm_medium' => 'dashboard_widget',
229 ),
230 $item['link']
231 )
232 );
233 ?>
234 " target="_blank">
235 <span class="ti-dw-date-container"><span
236 class="ti-dw-day-container"><?php echo esc_attr( gmdate( 'd', $item['date'] ) ); ?></span> <span
237 class="ti-dw-month-container"><?php echo esc_attr( substr( gmdate( 'M', $item['date'] ), 0, 3 ) ); ?></span></span><?php echo esc_attr( $item['title'] ); ?>
238 </a>
239 </li>
240 <?php
241 }
242 ?>
243 </ul>
244 <?php
245 $recommend = apply_filters( 'themeisle_sdk_recommend_plugin_or_theme', array() );
246 if ( ! is_array( $recommend ) || empty( $recommend ) ) {
247 return;
248 }
249
250 $type = $recommend['type'];
251
252 if ( ( 'theme' === $type && ! current_user_can( 'install_themes' ) ) ) {
253 return;
254 }
255 if ( ( 'plugin' === $type && ! current_user_can( 'install_plugins' ) ) ) {
256 return;
257 }
258
259 add_thickbox();
260 $url = add_query_arg(
261 [
262 'theme' => $recommend['slug'],
263 ],
264 network_admin_url( 'theme-install.php' )
265 );
266
267 if ( 'plugin' === $type ) {
268
269 $url = add_query_arg(
270 array(
271 'tab' => 'plugin-information',
272 'plugin' => $recommend['slug'],
273 ),
274 network_admin_url( 'plugin-install.php' )
275 );
276 }
277 ?>
278 <div class="ti-dw-footer">
279 <span class="ti-dw-recommend-item ">
280 <span class="ti-dw-recommend"><?php echo esc_attr( apply_filters( 'themeisle_sdk_dashboard_popular_label', sprintf( 'Popular %s', ucwords( $type ) ) ) ); ?>
281 : </span>
282 <?php
283 echo esc_attr(
284 trim(
285 str_replace(
286 array(
287 'lite',
288 'Lite',
289 '(Lite)',
290 '(lite)',
291 ),
292 '',
293 $recommend['name']
294 )
295 )
296 );
297 ?>
298 (<a class="thickbox open-plugin-details-modal"
299 href="<?php echo esc_url( $url . '&TB_iframe=true&width=600&height=500' ); ?>"><?php echo esc_attr( apply_filters( 'themeisle_sdk_dashboard_install_label', 'Install' ) ); ?></a>)
300 </span>
301 <span class="ti-dw-powered-by"><span><?php echo esc_attr( apply_filters( 'themeisle_sdk_dashboard_widget_powered_by', sprintf( 'Powered by %s', $this->product->get_friendly_name() ) ) ); ?></span></span>
302 </div>
303
304 <?php
305
306 }
307
308 /**
309 * Setup feed items.
310 */
311 private function setup_feeds() {
312 if ( false === ( $items_normalized = get_transient( 'themeisle_sdk_feed_items' ) ) ) { //phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
313 // Load SimplePie Instance.
314 $feed = fetch_feed( $this->feeds );
315 // TODO report error when is an error loading the feed.
316 if ( is_wp_error( $feed ) ) {
317 return;
318 }
319
320 $items = $feed->get_items( 0, 5 );
321 foreach ( (array) $items as $item ) {
322 $items_normalized[] = array(
323 'title' => $item->get_title(),
324 'date' => $item->get_date( 'U' ),
325 'link' => $item->get_permalink(),
326 );
327 }
328 set_transient( 'themeisle_sdk_feed_items', $items_normalized, 48 * HOUR_IN_SECONDS );
329 }
330 $this->items = $items_normalized;
331 }
332
333 /**
334 * Either the current product is installed or not.
335 *
336 * @param array $val The current recommended product.
337 *
338 * @return bool Either we should exclude the plugin or not.
339 */
340 public function remove_current_products( $val ) {
341 if ( 'theme' === $val['type'] ) {
342 $exist = wp_get_theme( $val['slug'] );
343
344 return ! $exist->exists();
345 } else {
346 $all_plugins = array_keys( get_plugins() );
347 foreach ( $all_plugins as $slug ) {
348 if ( strpos( $slug, $val['slug'] ) !== false ) {
349 return false;
350 }
351 }
352
353 return true;
354 }
355 }
356
357 /**
358 * Contact the API and fetch the recommended plugins/themes
359 */
360 public function recommend_plugin_or_theme() {
361 $products = $this->get_product_from_api();
362 if ( ! is_array( $products ) ) {
363 $products = array();
364 }
365 $products = array_filter( $products, array( $this, 'remove_current_products' ) );
366 $products = array_merge( $products );
367 if ( count( $products ) > 1 ) {
368 shuffle( $products );
369 $products = array_slice( $products, 0, 1 );
370 }
371 $to_recommend = isset( $products[0] ) ? $products[0] : $products;
372
373 return $to_recommend;
374 }
375
376 /**
377 * Fetch products from the recomended section.
378 *
379 * @return array|mixed The list of products to use in recomended section.
380 */
381 public function get_product_from_api() {
382 if ( false === ( $products = get_transient( 'themeisle_sdk_products' ) ) ) { //phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
383 $products = array();
384 $all_themes = $this->get_themes_from_wporg( 'themeisle' );
385 $all_plugins = $this->get_plugins_from_wporg( 'themeisle' );
386 static $allowed_products = [
387 'hestia' => true,
388 'neve' => true,
389 'visualizer' => true,
390 'feedzy-rss-feeds' => true,
391 'wp-product-review' => true,
392 'otter-blocks' => true,
393 'themeisle-companion' => true,
394 ];
395 foreach ( $all_themes as $theme ) {
396 if ( $theme->active_installs < 4999 ) {
397 continue;
398 }
399 if ( ! isset( $allowed_products[ $theme->slug ] ) ) {
400 continue;
401 }
402 $products[] = array(
403 'name' => $theme->name,
404 'type' => 'theme',
405 'slug' => $theme->slug,
406 'installs' => $theme->active_installs,
407 );
408 }
409 foreach ( $all_plugins as $plugin ) {
410 if ( $plugin->active_installs < 4999 ) {
411 continue;
412 }
413 if ( ! isset( $allowed_products[ $plugin->slug ] ) ) {
414 continue;
415 }
416 $products[] = array(
417 'name' => $plugin->name,
418 'type' => 'plugin',
419 'slug' => $plugin->slug,
420 'installs' => $plugin->active_installs,
421 );
422 }
423 set_transient( 'themeisle_sdk_products', $products, 6 * HOUR_IN_SECONDS );
424 }
425
426 return $products;
427 }
428
429 /**
430 * Fetch themes from wporg api.
431 *
432 * @param string $author The author name.
433 *
434 * @return array The list of themes.
435 */
436 public function get_themes_from_wporg( $author ) {
437 $products = $this->safe_get(
438 'https://api.wordpress.org/themes/info/1.1/?action=query_themes&request[author]=' . $author . '&request[per_page]=30&request[fields][active_installs]=true'
439 );
440 $products = json_decode( wp_remote_retrieve_body( $products ) );
441 if ( is_object( $products ) ) {
442 $products = isset( $products->themes ) ? $products->themes : array();
443 } else {
444 $products = array();
445 }
446
447 return (array) $products;
448 }
449
450 /**
451 * Fetch plugin from wporg api.
452 *
453 * @param string $author The author slug.
454 *
455 * @return array The list of plugins for the selected author.
456 */
457 public function get_plugins_from_wporg( $author ) {
458 $products = $this->safe_get(
459 'https://api.wordpress.org/plugins/info/1.1/?action=query_plugins&request[author]=' . $author . '&request[per_page]=40&request[fields][active_installs]=true'
460 );
461 $products = json_decode( wp_remote_retrieve_body( $products ) );
462 if ( is_object( $products ) ) {
463 $products = isset( $products->plugins ) ? $products->plugins : array();
464 } else {
465 $products = array();
466 }
467
468 return (array) $products;
469 }
470 }
471