PluginProbe
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization / 3.11.3
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization v3.11.3
4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 2.5.5 2.5.6 2.5.7 3.0.0 3.0.1 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.11.0 3.11.1 3.11.2 3.11.3 3.12.0 3.12.1 All 134 releases
optimole-wp / vendor / codeinwp / themeisle-sdk / src / Modules / Dashboard_widget.php

Dashboard_widget.php in Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization 3.11.3, at vendor/codeinwp/themeisle-sdk/src/Modules/Dashboard_widget.php

478 lines 13.1 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 'https://www.codeinwp.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 #themeisle ul li.ti-dw-recommend-item {
127 padding-left: 7px;
128 border-top: 1px solid #eee;
129 margin-bottom: 0px;
130 padding-top: 6px;
131 }
132
133 #themeisle h2.hndle {
134 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=');
135 background-repeat: no-repeat;
136 background-position: 2% 50%;
137 background-size: 25px;
138 padding-left: 39px;
139 }
140
141 #themeisle .inside {
142 padding: 0;
143 }
144
145 .ti-feed-list {
146 padding: 0 12px 5px;
147 margin-bottom: 10px;
148 border-bottom: 1px solid #eee;
149 }
150
151 .ti-dw-feed-item a {
152 display: flex;
153 align-items: center;
154 margin-bottom: 5px;
155 padding: 5px;
156 transition: .2s ease;
157 border-radius: 3px;
158 }
159
160 .ti-dw-feed-item a:hover {
161 background-color: #f8f8f8;
162 }
163
164 .ti-dw-feed-item a:hover .ti-dw-date-container {
165 opacity: .9;
166 }
167
168 .ti-dw-feed-item .ti-dw-month-container {
169 margin-top: -5px;
170 text-transform: uppercase;
171 font-size: 10px;
172 letter-spacing: 1px;
173 font-weight: 700;
174 }
175
176 .ti-dw-feed-item .ti-dw-date-container {
177 border-radius: 3px;
178 transition: .2s ease;
179 min-height: 35px;
180 margin-right: 5px;
181 min-width: 35px;
182 text-align: center;
183 border: 1px solid #2a6f97;
184 color: #fff;
185 background: #2ea2cc;
186 display: flex;
187 flex-direction: column;
188 justify-content: center;
189 }
190
191 .ti-dw-footer {
192 padding: 0 12px 5px;
193 text-align: center;
194 }
195
196 .ti-dw-recommend-item {
197 display: block;
198 }
199
200 .ti-dw-recommend-item span {
201 color: #72777c;
202 }
203
204 .ti-dw-powered-by {
205 font-size: 11px;
206 margin-top: 3px;
207 display: block;
208 color: #72777c;
209 }
210
211 .ti-dw-powered-by span {
212 font-weight: 600;
213 }
214
215 </style>
216 <?php do_action( 'themeisle_sdk_dashboard_widget_before', $this->product ); ?>
217
218 <ul class="ti-feed-list">
219 <?php
220
221 foreach ( $this->items as $item ) {
222 ?>
223 <li class="ti-dw-feed-item">
224 <a href="
225 <?php
226 echo esc_url(
227 add_query_arg(
228 array(
229 'utm_source' => 'wpadmin',
230 'utm_campaign' => 'feed',
231 'utm_medium' => 'dashboard_widget',
232 ),
233 $item['link']
234 )
235 );
236 ?>
237 " target="_blank">
238 <span class="ti-dw-date-container"><span
239 class="ti-dw-day-container"><?php echo esc_attr( gmdate( 'd', $item['date'] ) ); ?></span> <span
240 class="ti-dw-month-container"><?php echo esc_attr( substr( gmdate( 'M', $item['date'] ), 0, 3 ) ); ?></span></span><?php echo esc_attr( $item['title'] ); ?>
241 </a>
242 </li>
243 <?php
244 }
245 ?>
246 </ul>
247 <?php
248 $recommend = apply_filters( 'themeisle_sdk_recommend_plugin_or_theme', array() );
249 if ( ! is_array( $recommend ) || empty( $recommend ) ) {
250 return;
251 }
252
253 $type = $recommend['type'];
254
255 if ( ( 'theme' === $type && ! current_user_can( 'install_themes' ) ) ) {
256 return;
257 }
258 if ( ( 'plugin' === $type && ! current_user_can( 'install_plugins' ) ) ) {
259 return;
260 }
261
262 add_thickbox();
263 $url = add_query_arg(
264 [
265 'theme' => $recommend['slug'],
266 ],
267 network_admin_url( 'theme-install.php' )
268 );
269
270 if ( 'plugin' === $type ) {
271
272 $url = add_query_arg(
273 array(
274 'tab' => 'plugin-information',
275 'plugin' => $recommend['slug'],
276 ),
277 network_admin_url( 'plugin-install.php' )
278 );
279 }
280 ?>
281 <div class="ti-dw-footer">
282 <span class="ti-dw-recommend-item ">
283 <span class="ti-dw-recommend"><?php echo esc_attr( apply_filters( 'themeisle_sdk_dashboard_popular_label', sprintf( 'Popular %s', ucwords( $type ) ) ) ); ?>
284 : </span>
285 <?php
286 echo esc_attr(
287 trim(
288 str_replace(
289 array(
290 'lite',
291 'Lite',
292 '(Lite)',
293 '(lite)',
294 ),
295 '',
296 $recommend['name']
297 )
298 )
299 );
300 ?>
301 (<a class="thickbox open-plugin-details-modal"
302 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>)
303 </span>
304 <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>
305 </div>
306
307 <?php
308
309 }
310
311 /**
312 * Setup feed items.
313 */
314 private function setup_feeds() {
315 if ( false === ( $items_normalized = get_transient( 'themeisle_sdk_feed_items' ) ) ) { //phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
316 // Load SimplePie Instance.
317 $feed = fetch_feed( $this->feeds );
318 // TODO report error when is an error loading the feed.
319 if ( is_wp_error( $feed ) ) {
320 return;
321 }
322
323 $items = $feed->get_items( 0, 5 );
324 $items = is_array( $items ) ? $items : [];
325
326 $items_normalized = [];
327
328 foreach ( $items as $item ) {
329 $items_normalized[] = array(
330 'title' => $item->get_title(),
331 'date' => $item->get_date( 'U' ),
332 'link' => $item->get_permalink(),
333 );
334 }
335 set_transient( 'themeisle_sdk_feed_items', $items_normalized, 48 * HOUR_IN_SECONDS );
336 }
337 $this->items = $items_normalized;
338 }
339
340 /**
341 * Either the current product is installed or not.
342 *
343 * @param array $val The current recommended product.
344 *
345 * @return bool Either we should exclude the plugin or not.
346 */
347 public function remove_current_products( $val ) {
348 if ( 'theme' === $val['type'] ) {
349 $exist = wp_get_theme( $val['slug'] );
350
351 return ! $exist->exists();
352 } else {
353 $all_plugins = array_keys( get_plugins() );
354 foreach ( $all_plugins as $slug ) {
355 if ( strpos( $slug, $val['slug'] ) !== false ) {
356 return false;
357 }
358 }
359
360 return true;
361 }
362 }
363
364 /**
365 * Contact the API and fetch the recommended plugins/themes
366 */
367 public function recommend_plugin_or_theme() {
368 $products = $this->get_product_from_api();
369 if ( ! is_array( $products ) ) {
370 $products = array();
371 }
372 $products = array_filter( $products, array( $this, 'remove_current_products' ) );
373 $products = array_merge( $products );
374 if ( count( $products ) > 1 ) {
375 shuffle( $products );
376 $products = array_slice( $products, 0, 1 );
377 }
378 $to_recommend = isset( $products[0] ) ? $products[0] : $products;
379
380 return $to_recommend;
381 }
382
383 /**
384 * Fetch products from the recomended section.
385 *
386 * @return array|mixed The list of products to use in recomended section.
387 */
388 public function get_product_from_api() {
389 if ( false === ( $products = get_transient( 'themeisle_sdk_products' ) ) ) { //phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
390 $products = array();
391 $all_themes = $this->get_themes_from_wporg( 'themeisle' );
392 $all_plugins = $this->get_plugins_from_wporg( 'themeisle' );
393 static $allowed_products = [
394 'hestia' => true,
395 'neve' => true,
396 'visualizer' => true,
397 'feedzy-rss-feeds' => true,
398 'wp-product-review' => true,
399 'otter-blocks' => true,
400 'themeisle-companion' => true,
401 ];
402 foreach ( $all_themes as $theme ) {
403 if ( $theme->active_installs < 4999 ) {
404 continue;
405 }
406 if ( ! isset( $allowed_products[ $theme->slug ] ) ) {
407 continue;
408 }
409 $products[] = array(
410 'name' => $theme->name,
411 'type' => 'theme',
412 'slug' => $theme->slug,
413 'installs' => $theme->active_installs,
414 );
415 }
416 foreach ( $all_plugins as $plugin ) {
417 if ( $plugin->active_installs < 4999 ) {
418 continue;
419 }
420 if ( ! isset( $allowed_products[ $plugin->slug ] ) ) {
421 continue;
422 }
423 $products[] = array(
424 'name' => $plugin->name,
425 'type' => 'plugin',
426 'slug' => $plugin->slug,
427 'installs' => $plugin->active_installs,
428 );
429 }
430 set_transient( 'themeisle_sdk_products', $products, 6 * HOUR_IN_SECONDS );
431 }
432
433 return $products;
434 }
435
436 /**
437 * Fetch themes from wporg api.
438 *
439 * @param string $author The author name.
440 *
441 * @return array The list of themes.
442 */
443 public function get_themes_from_wporg( $author ) {
444 $products = $this->safe_get(
445 'https://api.wordpress.org/themes/info/1.1/?action=query_themes&request[author]=' . $author . '&request[per_page]=30&request[fields][active_installs]=true'
446 );
447 $products = json_decode( wp_remote_retrieve_body( $products ) );
448 if ( is_object( $products ) ) {
449 $products = isset( $products->themes ) ? $products->themes : array();
450 } else {
451 $products = array();
452 }
453
454 return (array) $products;
455 }
456
457 /**
458 * Fetch plugin from wporg api.
459 *
460 * @param string $author The author slug.
461 *
462 * @return array The list of plugins for the selected author.
463 */
464 public function get_plugins_from_wporg( $author ) {
465 $products = $this->safe_get(
466 'https://api.wordpress.org/plugins/info/1.1/?action=query_plugins&request[author]=' . $author . '&request[per_page]=40&request[fields][active_installs]=true'
467 );
468 $products = json_decode( wp_remote_retrieve_body( $products ) );
469 if ( is_object( $products ) ) {
470 $products = isset( $products->plugins ) ? $products->plugins : array();
471 } else {
472 $products = array();
473 }
474
475 return (array) $products;
476 }
477 }
478