PluginProbe ʕ •ᴥ•ʔ
Blocks Animation: CSS Animations for Gutenberg Blocks / 3.2.0
Blocks Animation: CSS Animations for Gutenberg Blocks v3.2.0
3.2.0 3.1.11 3.1.10 2.2.5 2.2.6 2.2.7 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.6.0 2.6.1 2.6.10 2.6.11 2.6.12 2.6.13 2.6.2 2.6.3 2.6.4 2.6.5 2.6.6 2.6.7 2.6.8 2.6.9 3.0.0 3.0.1 3.0.10 3.0.11 3.0.12 3.0.2 3.0.3 3.0.4 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.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 trunk 1.0.0 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4
blocks-animation / vendor / codeinwp / themeisle-sdk / src / Modules / Dashboard_widget.php
blocks-animation / vendor / codeinwp / themeisle-sdk / src / Modules Last commit date
About_us.php 1 week ago Abstract_Migration.php 1 month ago Announcements.php 1 month ago Compatibilities.php 1 year ago Dashboard_widget.php 1 week ago Featured_plugins.php 1 month ago Float_widget.php 1 year ago Licenser.php 1 month ago Logger.php 8 months ago Migrator.php 1 month ago Notification.php 1 year ago Promotions.php 1 week ago Recommendation.php 1 year ago Review.php 8 months ago Rollback.php 1 year ago Script_loader.php 8 months ago Translate.php 1 year ago Translations.php 8 months ago Uninstall_feedback.php 1 week ago Welcome.php 1 year ago
Dashboard_widget.php
510 lines
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\Loader;
16 use ThemeisleSDK\Product;
17
18 // Exit if accessed directly.
19 if ( ! defined( 'ABSPATH' ) ) {
20 exit;
21 }
22
23 /**
24 * Blog dashboard widget module for ThemeIsle SDK.
25 */
26 class Dashboard_Widget extends Abstract_Module {
27
28 /**
29 * Fetched feeds items.
30 *
31 * @var array Feed items.
32 */
33 private $items = array();
34
35 /**
36 * Dashboard widget title.
37 *
38 * @var string $dashboard_name Dashboard name.
39 */
40 private $dashboard_name = '';
41
42 /**
43 * Dashboard widget feed sources.
44 *
45 * @var array $feeds Feed url.
46 */
47 private $feeds = [];
48
49 /**
50 * Should we load this module.
51 *
52 * @param Product $product Product object.
53 *
54 * @return bool
55 */
56 public function can_load( $product ) {
57 if ( $this->is_from_partner( $product ) ) {
58 return false;
59 }
60
61 if ( ! apply_filters( $product->get_slug() . '_load_dashboard_widget', true ) ) {
62 return false;
63 }
64
65 return true;
66 }
67
68 /**
69 * Registers the hooks.
70 *
71 * @param Product $product Product to load.
72 *
73 * @return Dashboard_Widget Module instance.
74 */
75 public function load( $product ) {
76 if ( apply_filters( 'themeisle_sdk_hide_dashboard_widget', false ) ) {
77 return;
78 }
79 $this->product = $product;
80 $this->dashboard_name = apply_filters( 'themeisle_sdk_dashboard_widget_name', Loader::$labels['dashboard_widget']['title'] );
81 $this->feeds = apply_filters(
82 'themeisle_sdk_dashboard_widget_feeds',
83 [
84 'https://themeisle.com/blog/feed',
85 'https://wpshout.com/feed',
86 ]
87 );
88 add_action( 'wp_dashboard_setup', array( &$this, 'add_widget' ) );
89 add_action( 'wp_network_dashboard_setup', array( &$this, 'add_widget' ) );
90 add_filter( 'themeisle_sdk_recommend_plugin_or_theme', array( &$this, 'recommend_plugin_or_theme' ) );
91
92 return $this;
93 }
94
95
96 /**
97 * Add widget to the dashboard
98 *
99 * @return string|void
100 */
101 public function add_widget() {
102 global $wp_meta_boxes;
103 if ( isset( $wp_meta_boxes['dashboard']['normal']['core']['themeisle'] ) ) {
104 return;
105 }
106 wp_add_dashboard_widget(
107 'themeisle',
108 $this->dashboard_name,
109 [
110 $this,
111 'render_dashboard_widget',
112 ]
113 );
114 }
115
116 /**
117 * Render widget content
118 */
119 public function render_dashboard_widget() {
120 $this->setup_feeds();
121 if ( empty( $this->items ) || ! is_array( $this->items ) ) {
122 return;
123 }
124 ?>
125 <style type="text/css">
126 #dashboard-widgets #themeisle .hndle {
127 padding-left: 39px;
128 }
129
130 #themeisle ul li.ti-dw-recommend-item {
131 padding-left: 7px;
132 border-top: 1px solid #eee;
133 margin-bottom: 0px;
134 padding-top: 6px;
135 }
136
137 #themeisle h2.hndle {
138 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=');
139 background-repeat: no-repeat;
140 background-position: 2% 50%;
141 background-size: 25px;
142 }
143
144 #themeisle .inside {
145 padding: 0;
146 }
147
148 .ti-feed-list {
149 padding: 0 12px 5px;
150 margin-bottom: 10px;
151 border-bottom: 1px solid #eee;
152 }
153
154 .ti-dw-feed-item a {
155 display: flex;
156 align-items: center;
157 margin-bottom: 5px;
158 padding: 5px;
159 transition: .2s ease;
160 border-radius: 3px;
161 }
162
163 .ti-dw-feed-item a:hover {
164 background-color: #f8f8f8;
165 }
166
167 .ti-dw-feed-item a:hover .ti-dw-date-container {
168 opacity: .9;
169 }
170
171 .ti-dw-feed-item .ti-dw-month-container {
172 margin-top: -5px;
173 text-transform: uppercase;
174 font-size: 10px;
175 letter-spacing: 1px;
176 font-weight: 700;
177 }
178
179 .ti-dw-feed-item .ti-dw-date-container {
180 border-radius: 3px;
181 transition: .2s ease;
182 min-height: 35px;
183 margin-right: 5px;
184 min-width: 35px;
185 text-align: center;
186 border: 1px solid #2a6f97;
187 color: #fff;
188 background: #2ea2cc;
189 display: flex;
190 flex-direction: column;
191 justify-content: center;
192 }
193
194 .ti-dw-footer {
195 padding: 0 12px 5px;
196 text-align: center;
197 }
198
199 .ti-dw-recommend-item {
200 display: block;
201 }
202
203 .ti-dw-recommend-item span {
204 color: #72777c;
205 }
206
207 .ti-dw-powered-by {
208 font-size: 11px;
209 margin-top: 3px;
210 display: block;
211 color: #72777c;
212 }
213
214 .ti-dw-powered-by span {
215 font-weight: 600;
216 }
217
218 </style>
219 <?php do_action( 'themeisle_sdk_dashboard_widget_before', $this->product ); ?>
220
221 <ul class="ti-feed-list">
222 <?php
223
224 foreach ( $this->items as $item ) {
225 ?>
226 <li class="ti-dw-feed-item">
227 <a href="
228 <?php
229 echo esc_url(
230 add_query_arg(
231 array(
232 'utm_source' => 'wpadmin',
233 'utm_campaign' => 'feed',
234 'utm_medium' => 'dashboard_widget',
235 ),
236 $item['link']
237 )
238 );
239 ?>
240 " target="_blank">
241 <span class="ti-dw-date-container"><span
242 class="ti-dw-day-container"><?php echo esc_attr( gmdate( 'd', $item['date'] ) ); ?></span> <span
243 class="ti-dw-month-container"><?php echo esc_attr( substr( gmdate( 'M', $item['date'] ), 0, 3 ) ); ?></span></span><?php echo esc_attr( $item['title'] ); ?>
244 </a>
245 </li>
246 <?php
247 }
248 ?>
249 </ul>
250 <?php
251 $recommend = apply_filters( 'themeisle_sdk_recommend_plugin_or_theme', array() );
252 if ( ! is_array( $recommend ) || empty( $recommend ) ) {
253 return;
254 }
255
256 $type = $recommend['type'];
257
258 if ( ( 'theme' === $type && ! current_user_can( 'install_themes' ) ) ) {
259 return;
260 }
261 if ( ( 'plugin' === $type && ! current_user_can( 'install_plugins' ) ) ) {
262 return;
263 }
264
265 add_thickbox();
266 $url = add_query_arg(
267 [
268 'theme' => $recommend['slug'],
269 ],
270 network_admin_url( 'theme-install.php' )
271 );
272
273 if ( 'plugin' === $type ) {
274
275 $url = add_query_arg(
276 array(
277 'tab' => 'plugin-information',
278 'plugin' => $recommend['slug'],
279 ),
280 network_admin_url( 'plugin-install.php' )
281 );
282 }
283 ?>
284 <div class="ti-dw-footer">
285 <span class="ti-dw-recommend-item ">
286 <span class="ti-dw-recommend"><?php echo esc_attr( apply_filters( 'themeisle_sdk_dashboard_popular_label', sprintf( Loader::$labels['dashboard_widget']['popular'], ucwords( $type ) ) ) ); ?>
287 : </span>
288 <?php
289 echo esc_attr(
290 trim(
291 str_replace(
292 array(
293 'lite',
294 'Lite',
295 '(Lite)',
296 '(lite)',
297 ),
298 '',
299 $recommend['name']
300 )
301 )
302 );
303 ?>
304 (<a class="thickbox open-plugin-details-modal"
305 href="<?php echo esc_url( $url . '&TB_iframe=true&width=600&height=500' ); ?>"><?php echo esc_attr( apply_filters( 'themeisle_sdk_dashboard_install_label', Loader::$labels['dashboard_widget']['install'] ) ); ?></a>)
306 </span>
307 <span class="ti-dw-powered-by"><span><?php echo esc_attr( apply_filters( 'themeisle_sdk_dashboard_widget_powered_by', sprintf( Loader::$labels['dashboard_widget']['powered'], $this->product->get_friendly_name() ) ) ); ?></span></span>
308 </div>
309
310 <?php
311
312 }
313
314 /**
315 * Setup feed items.
316 */
317 private function setup_feeds() {
318 if ( false === ( $items_normalized = get_transient( 'themeisle_sdk_feed_items' ) ) ) { //phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
319 // Do not force the feed for the items in the sdk feeds list.
320 // this prevents showing notices if another plugin will force all SimplePie feeds to load, instead it will
321 // use the regular SimplePie validation and abort early if the feed is not valid.
322 $sdk_feeds = $this->feeds;
323 add_action(
324 'wp_feed_options',
325 function ( $feed, $url ) use ( $sdk_feeds ) {
326 if ( defined( 'TI_SDK_PHPUNIT' ) && true === TI_SDK_PHPUNIT ) {
327 return;
328 }
329
330 if ( ! is_string( $url ) && in_array( $url, $sdk_feeds, true ) ) {
331 $feed->force_feed( false );
332
333 return;
334 }
335 if ( is_array( $url ) ) {
336 foreach ( $url as $feed_url ) {
337 if ( in_array( $feed_url, $sdk_feeds, true ) ) {
338 $feed->force_feed( false );
339
340 return;
341 }
342 }
343 }
344 },
345 PHP_INT_MAX,
346 2
347 );
348 // Load SimplePie Instance.
349 $feed = fetch_feed( $sdk_feeds );
350 // TODO report error when is an error loading the feed.
351 if ( is_wp_error( $feed ) ) {
352 return;
353 }
354
355 $items = $feed->get_items( 0, 5 );
356 $items = is_array( $items ) ? $items : [];
357
358 $items_normalized = [];
359
360 foreach ( $items as $item ) {
361 $items_normalized[] = array(
362 'title' => $item->get_title(),
363 'date' => $item->get_date( 'U' ),
364 'link' => $item->get_permalink(),
365 );
366 }
367 set_transient( 'themeisle_sdk_feed_items', $items_normalized, 48 * HOUR_IN_SECONDS );
368 }
369 $this->items = $items_normalized;
370 }
371
372 /**
373 * Either the current product is installed or not.
374 *
375 * @param array $val The current recommended product.
376 *
377 * @return bool Either we should exclude the plugin or not.
378 */
379 public function remove_current_products( $val ) {
380 if ( 'theme' === $val['type'] ) {
381 $exist = wp_get_theme( $val['slug'] );
382
383 return ! $exist->exists();
384 } else {
385 $all_plugins = array_keys( get_plugins() );
386 foreach ( $all_plugins as $slug ) {
387 if ( strpos( $slug, $val['slug'] ) !== false ) {
388 return false;
389 }
390 }
391
392 return true;
393 }
394 }
395
396 /**
397 * Contact the API and fetch the recommended plugins/themes
398 */
399 public function recommend_plugin_or_theme() {
400 $products = $this->get_product_from_api();
401 if ( ! is_array( $products ) ) {
402 $products = array();
403 }
404 $products = array_filter( $products, array( $this, 'remove_current_products' ) );
405 $products = array_merge( $products );
406 if ( count( $products ) > 1 ) {
407 shuffle( $products );
408 $products = array_slice( $products, 0, 1 );
409 }
410 $to_recommend = isset( $products[0] ) ? $products[0] : $products;
411
412 return $to_recommend;
413 }
414
415 /**
416 * Fetch products from the recomended section.
417 *
418 * @return array|mixed The list of products to use in recomended section.
419 */
420 public function get_product_from_api() {
421 if ( false === ( $products = get_transient( 'themeisle_sdk_products' ) ) ) { //phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
422 $products = array();
423 $all_themes = $this->get_themes_from_wporg( 'themeisle' );
424 $all_plugins = $this->get_plugins_from_wporg( 'themeisle' );
425 static $allowed_products = [
426 'hestia' => true,
427 'neve' => true,
428 'visualizer' => true,
429 'feedzy-rss-feeds' => true,
430 'wp-product-review' => true,
431 'otter-blocks' => true,
432 'themeisle-companion' => true,
433 ];
434 foreach ( $all_themes as $theme ) {
435 if ( $theme->active_installs < 4999 ) {
436 continue;
437 }
438 if ( ! isset( $allowed_products[ $theme->slug ] ) ) {
439 continue;
440 }
441 $products[] = array(
442 'name' => $theme->name,
443 'type' => 'theme',
444 'slug' => $theme->slug,
445 'installs' => $theme->active_installs,
446 );
447 }
448 foreach ( $all_plugins as $plugin ) {
449 if ( $plugin->active_installs < 4999 ) {
450 continue;
451 }
452 if ( ! isset( $allowed_products[ $plugin->slug ] ) ) {
453 continue;
454 }
455 $products[] = array(
456 'name' => $plugin->name,
457 'type' => 'plugin',
458 'slug' => $plugin->slug,
459 'installs' => $plugin->active_installs,
460 );
461 }
462 set_transient( 'themeisle_sdk_products', $products, 6 * HOUR_IN_SECONDS );
463 }
464
465 return $products;
466 }
467
468 /**
469 * Fetch themes from wporg api.
470 *
471 * @param string $author The author name.
472 *
473 * @return array The list of themes.
474 */
475 public function get_themes_from_wporg( $author ) {
476 $products = $this->safe_get(
477 'https://api.wordpress.org/themes/info/1.1/?action=query_themes&request[author]=' . $author . '&request[per_page]=30&request[fields][active_installs]=true'
478 );
479 $products = json_decode( wp_remote_retrieve_body( $products ) );
480 if ( is_object( $products ) ) {
481 $products = isset( $products->themes ) ? $products->themes : array();
482 } else {
483 $products = array();
484 }
485
486 return (array) $products;
487 }
488
489 /**
490 * Fetch plugin from wporg api.
491 *
492 * @param string $author The author slug.
493 *
494 * @return array The list of plugins for the selected author.
495 */
496 public function get_plugins_from_wporg( $author ) {
497 $products = $this->safe_get(
498 'https://api.wordpress.org/plugins/info/1.1/?action=query_plugins&request[author]=' . $author . '&request[per_page]=40&request[fields][active_installs]=true'
499 );
500 $products = json_decode( wp_remote_retrieve_body( $products ) );
501 if ( is_object( $products ) ) {
502 $products = isset( $products->plugins ) ? $products->plugins : array();
503 } else {
504 $products = array();
505 }
506
507 return (array) $products;
508 }
509 }
510