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

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

1,473 lines 60.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The promotions model class for ThemeIsle SDK
4 *
5 * Here's how to hook it in your plugin: add_filter( 'menu_icons_load_promotions', function() { return array( 'otter' ); } );
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 1.0.0
12 */
13
14 namespace ThemeisleSDK\Modules;
15
16 use ThemeisleSDK\Common\Abstract_Module;
17 use ThemeisleSDK\Loader;
18 use ThemeisleSDK\Product;
19
20 // Exit if accessed directly.
21 if ( ! defined( 'ABSPATH' ) ) {
22 exit;
23 }
24
25 /**
26 * Promotions module for ThemeIsle SDK.
27 */
28 class Promotions extends Abstract_Module {
29
30 /**
31 * Holds the promotions.
32 *
33 * @var array
34 */
35 public $promotions = array();
36
37 /**
38 * Holds the values of the promotions that are not allowed to be shown.
39 * Can be filtered by each product.
40 *
41 * @var array
42 */
43 private $dissallowed_promotions = array();
44
45 /**
46 * Option key for promos.
47 *
48 * @var string
49 */
50 private $option_main = 'themeisle_sdk_promotions';
51
52 /**
53 * Option key for otter promos.
54 *
55 * @var string
56 */
57 private $option_otter = 'themeisle_sdk_promotions_otter_installed';
58
59 /**
60 * Option key for optimole promos.
61 *
62 * @var string
63 */
64 private $option_optimole = 'themeisle_sdk_promotions_optimole_installed';
65
66 /**
67 * Option key for ROP promos.
68 *
69 * @var string
70 */
71 private $option_rop = 'themeisle_sdk_promotions_rop_installed';
72
73 /**
74 * Option key for Neve promo.
75 *
76 * @var string
77 */
78 private $option_neve = 'themeisle_sdk_promotions_neve_installed';
79
80 /**
81 * Option key for Redirection for CF7.
82 *
83 * @var string
84 */
85 private $option_redirection_cf7 = 'themeisle_sdk_promotions_redirection_cf7_installed';
86
87 /**
88 * Option key for Hyve.
89 *
90 * @var string
91 */
92 private $option_hyve = 'themeisle_sdk_promotions_hyve_installed';
93
94 /**
95 * Option key for WP Full Pay.
96 *
97 * @var string
98 */
99 private $option_wp_full_pay = 'themeisle_sdk_promotions_wp_full_pay_installed';
100
101 /**
102 * Option key for Feedzy.
103 *
104 * @var string
105 */
106 private $option_feedzy = 'themeisle_sdk_promotions_feedzy_installed';
107
108 /**
109 * Option key for Masteriyo promos.
110 *
111 * @var string
112 */
113 private $option_masteriyo = 'themeisle_sdk_promotions_masteriyo_installed';
114
115 /**
116 * Loaded promotion.
117 *
118 * @var string
119 */
120 private $loaded_promo;
121
122 /**
123 * Woo promotions.
124 *
125 * @var array
126 */
127 private $woo_promos = array();
128
129 /**
130 * Debug mode.
131 *
132 * @var bool
133 */
134 private $debug = false;
135
136 /**
137 * Should we load this module.
138 *
139 * @param Product $product Product object.
140 *
141 * @return bool
142 */
143 public function can_load( $product ) {
144 if ( apply_filters( 'themeisle_sdk_ran_promos', false ) === true ) {
145 return false;
146 }
147 if ( $this->is_from_partner( $product ) ) {
148 return false;
149 }
150
151 $this->debug = apply_filters( 'themeisle_sdk_promo_debug', $this->debug );
152 $promotions_to_load = apply_filters( $product->get_key() . '_load_promotions', array() );
153
154 $promotions_to_load[] = 'optimole';
155 $promotions_to_load[] = 'rop';
156 $promotions_to_load[] = 'woo_plugins';
157 $promotions_to_load[] = 'neve';
158 $promotions_to_load[] = 'redirection-cf7';
159 $promotions_to_load[] = 'hyve';
160 $promotions_to_load[] = 'wp_full_pay';
161 $promotions_to_load[] = 'feedzy_import';
162 $promotions_to_load[] = 'learning-management-system';
163
164 if ( defined( 'NEVE_VERSION' ) || defined( 'WPMM_PATH' ) || defined( 'OTTER_BLOCKS_VERSION' ) || defined( 'OBFX_URL' ) ) {
165 $promotions_to_load[] = 'feedzy_embed';
166 }
167 $promotions_to_load = array_unique( $promotions_to_load );
168
169 $this->promotions = $this->get_promotions();
170
171 $this->dissallowed_promotions = apply_filters( $product->get_key() . '_dissallowed_promotions', array() );
172
173 foreach ( $this->promotions as $slug => $data ) {
174 if ( ! in_array( $slug, $promotions_to_load, true ) ) {
175 unset( $this->promotions[ $slug ] );
176 }
177 }
178 add_action( 'init', array( $this, 'register_settings' ), 99 );
179 add_action( 'admin_init', array( $this, 'register_reference' ), 99 );
180
181 return ! empty( $this->promotions );
182 }
183
184 /**
185 * Registers the hooks.
186 *
187 * @param Product $product Product to load.
188 */
189 public function load( $product ) {
190 if ( ! $this->is_writeable() || ! current_user_can( 'install_plugins' ) ) {
191 return;
192 }
193
194 $last_dismiss_time = $this->get_last_dismiss_time();
195
196 if ( ! $this->debug && is_int( $last_dismiss_time ) && ( time() - $last_dismiss_time ) < ( 3 * WEEK_IN_SECONDS ) ) {
197 return;
198 }
199
200 $this->product = $product;
201
202 add_filter( 'attachment_fields_to_edit', array( $this, 'add_attachment_field' ), 10, 2 );
203 add_action( 'current_screen', [ $this, 'load_available' ] );
204 add_action( 'elementor/editor/after_enqueue_scripts', array( $this, 'enqueue' ) );
205 add_action( 'wp_ajax_tisdk_update_option', array( $this, 'dismiss_promotion' ) );
206 add_filter( 'themeisle_sdk_ran_promos', '__return_true' );
207
208 if ( get_option( $this->option_neve, false ) !== true ) {
209 add_action( 'wp_ajax_themeisle_sdk_dismiss_notice', 'ThemeisleSDK\Modules\Notification::regular_dismiss' );
210 }
211 }
212
213 /**
214 * Load available promotions.
215 */
216 public function load_available() {
217 $this->promotions = $this->filter_by_screen_and_merge();
218 if ( empty( $this->promotions ) ) {
219 return;
220 }
221
222 $this->load_promotion( $this->promotions[ array_rand( $this->promotions ) ] );
223 }
224
225
226 /**
227 * Register plugin reference.
228 *
229 * @return void
230 */
231 public function register_reference() {
232 if ( ! current_user_can( 'activate_plugins' ) ) {
233 return;
234 }
235
236 if ( ! isset( $_GET['plugin'] ) || ! isset( $_GET['_wpnonce'] ) ) {
237 return;
238 }
239
240 $plugin = rawurldecode( $_GET['plugin'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
241 if ( wp_verify_nonce( $_GET['_wpnonce'], 'activate-plugin_' . $plugin ) === false ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
242 return;
243 }
244
245 if ( isset( $_GET['reference_key'] ) ) {
246 update_option( 'otter_reference_key', sanitize_key( $_GET['reference_key'] ) );
247 }
248
249 if ( isset( $_GET['optimole_reference_key'] ) ) {
250 update_option( 'optimole_reference_key', sanitize_key( $_GET['optimole_reference_key'] ) );
251 }
252
253 if ( isset( $_GET['rop_reference_key'] ) ) {
254 update_option( 'rop_reference_key', sanitize_key( $_GET['rop_reference_key'] ) );
255 }
256
257 if ( isset( $_GET['neve_reference_key'] ) ) {
258 update_option( 'neve_reference_key', sanitize_key( $_GET['neve_reference_key'] ) );
259 }
260
261 if ( isset( $_GET['hyve_reference_key'] ) ) {
262 update_option( 'hyve_reference_key', sanitize_key( $_GET['hyve_reference_key'] ) );
263 }
264
265 if ( isset( $_GET['wp_full_pay_reference_key'] ) ) {
266 update_option( 'wp_full_pay_reference_key', sanitize_key( $_GET['wp_full_pay_reference_key'] ) );
267 }
268
269 if ( isset( $_GET['feedzy_reference_key'] ) || ( isset( $_GET['from'], $_GET['plugin'] ) && $_GET['from'] === 'import' && str_starts_with( sanitize_key( $_GET['plugin'] ), 'feedzy' ) ) ) {
270 update_option( 'feedzy_reference_key', sanitize_key( $_GET['feedzy_reference_key'] ?? 'i-' . $this->product->get_key() ) );
271 update_option( $this->option_feedzy, 1 );
272 }
273 }
274
275 /**
276 * Register Settings
277 */
278 public function register_settings() {
279 $default = get_option( 'themeisle_sdk_promotions_otter', '{}' );
280
281 register_setting(
282 'themeisle_sdk_settings',
283 $this->option_main,
284 array(
285 'type' => 'string',
286 'sanitize_callback' => 'sanitize_text_field',
287 'show_in_rest' => true,
288 'default' => $default,
289 )
290 );
291
292 register_setting(
293 'themeisle_sdk_settings',
294 $this->option_otter,
295 array(
296 'type' => 'boolean',
297 'sanitize_callback' => 'rest_sanitize_boolean',
298 'show_in_rest' => true,
299 'default' => false,
300 )
301 );
302 register_setting(
303 'themeisle_sdk_settings',
304 $this->option_optimole,
305 array(
306 'type' => 'boolean',
307 'sanitize_callback' => 'rest_sanitize_boolean',
308 'show_in_rest' => true,
309 'default' => false,
310 )
311 );
312 register_setting(
313 'themeisle_sdk_settings',
314 $this->option_rop,
315 array(
316 'type' => 'boolean',
317 'sanitize_callback' => 'rest_sanitize_boolean',
318 'show_in_rest' => true,
319 'default' => false,
320 )
321 );
322 register_setting(
323 'themeisle_sdk_settings',
324 $this->option_neve,
325 array(
326 'type' => 'boolean',
327 'sanitize_callback' => 'rest_sanitize_boolean',
328 'show_in_rest' => true,
329 'default' => false,
330 )
331 );
332 register_setting(
333 'themeisle_sdk_settings',
334 $this->option_redirection_cf7,
335 array(
336 'type' => 'boolean',
337 'sanitize_callback' => 'rest_sanitize_boolean',
338 'show_in_rest' => true,
339 'default' => false,
340 )
341 );
342 register_setting(
343 'themeisle_sdk_settings',
344 $this->option_hyve,
345 array(
346 'type' => 'boolean',
347 'sanitize_callback' => 'rest_sanitize_boolean',
348 'show_in_rest' => true,
349 'default' => false,
350 )
351 );
352 register_setting(
353 'themeisle_sdk_settings',
354 $this->option_wp_full_pay,
355 array(
356 'type' => 'boolean',
357 'sanitize_callback' => 'rest_sanitize_boolean',
358 'show_in_rest' => true,
359 'default' => false,
360 )
361 );
362 register_setting(
363 'themeisle_sdk_settings',
364 $this->option_masteriyo,
365 array(
366 'type' => 'boolean',
367 'sanitize_callback' => 'rest_sanitize_boolean',
368 'show_in_rest' => true,
369 'default' => false,
370 )
371 );
372 }
373
374 /**
375 * Check if the path is writable.
376 *
377 * @return boolean
378 * @access public
379 */
380 public function is_writeable() {
381
382 include_once ABSPATH . 'wp-admin/includes/file.php';
383 $filesystem_method = get_filesystem_method();
384
385 if ( 'direct' === $filesystem_method ) {
386 return true;
387 }
388
389 return false;
390 }
391
392 /**
393 * Third-party compatibility.
394 *
395 * @return boolean
396 */
397 private function has_conflicts() {
398 global $pagenow;
399
400 // Editor notices aren't compatible with Enfold theme.
401 if ( defined( 'AV_FRAMEWORK_VERSION' ) && in_array( $pagenow, array( 'post.php', 'post-new.php' ) ) ) {
402 return true;
403 }
404
405 return false;
406 }
407
408 /**
409 * Get promotions.
410 *
411 * @return array
412 */
413 private function get_promotions() {
414 $has_otter = defined( 'OTTER_BLOCKS_VERSION' ) || $this->is_plugin_installed( 'otter-blocks' );
415 $had_otter_from_promo = get_option( $this->option_otter, false );
416 $has_optimole = defined( 'OPTIMOLE_VERSION' ) || $this->is_plugin_installed( 'optimole-wp' );
417 $had_optimole_from_promo = get_option( $this->option_optimole, false );
418 $has_rop = defined( 'ROP_LITE_VERSION' ) || $this->is_plugin_installed( 'tweet-old-post' );
419 $had_rop_from_promo = get_option( $this->option_rop, false );
420 $has_woocommerce = class_exists( 'WooCommerce' );
421 $has_sparks = defined( 'SPARKS_WC_VERSION' ) || $this->is_plugin_installed( 'sparks-for-woocommerce' );
422 $has_ppom = defined( 'PPOM_VERSION' ) || $this->is_plugin_installed( 'woocommerce-product-addon' );
423 $has_redirection_cf7 = defined( 'WPCF7_PRO_REDIRECT_PLUGIN_VERSION' ) || $this->is_plugin_installed( 'wpcf7-redirect' );
424 $had_redirection_cf7_promo = get_option( $this->option_redirection_cf7, false );
425 $has_hyve = defined( 'HYVE_LITE_VERSION' ) || $this->is_plugin_installed( 'hyve' ) || $this->is_plugin_installed( 'hyve-lite' );
426 $had_hyve_from_promo = get_option( $this->option_hyve, false );
427 $has_hyve_conditions = version_compare( get_bloginfo( 'version' ), '6.2', '>=' ) && $this->has_support_page();
428 $has_wfp_full_pay = defined( 'WP_FULL_STRIPE_BASENAME' ) || $this->is_plugin_installed( 'wp-full-stripe-free' );
429 $had_wfp_from_promo = get_option( $this->option_wp_full_pay, false );
430 $has_wfp_conditions = $this->has_donate_page();
431 $is_min_req_v = version_compare( get_bloginfo( 'version' ), '5.8', '>=' );
432 $current_theme = wp_get_theme();
433 $has_neve = $current_theme->template === 'neve' || $current_theme->parent() === 'neve';
434 $has_neve_from_promo = get_option( $this->option_neve, false );
435 $has_enough_attachments = $this->has_min_media_attachments();
436 $has_enough_old_posts = $this->has_old_posts();
437 $is_min_php_7_4 = version_compare( PHP_VERSION, '7.4', '>=' );
438 $has_feedzy = defined( 'FEEDZY_BASEFILE' ) || $this->is_plugin_installed( 'feedzy-rss-feedss' );
439 $had_feedzy_from_promo = get_option( $this->option_feedzy, false );
440 $has_masteriyo = defined( 'MASTERIYO_VERSION' ) || $this->is_plugin_installed( 'learning-management-system' );
441 $had_masteriyo_from_promo = get_option( $this->option_masteriyo, false );
442 $has_masteriyo_conditions = $this->has_lms_tagline();
443 $is_min_php_7_2 = version_compare( PHP_VERSION, '7.2', '>=' );
444
445 $all = [
446 'optimole' => [
447 'om-editor' => [
448 'env' => ! $has_optimole && $is_min_req_v && ! $had_optimole_from_promo,
449 'screen' => 'editor',
450 'delayed' => true,
451 ],
452 'om-image-block' => [
453 'env' => ! $has_optimole && $is_min_req_v && ! $had_optimole_from_promo,
454 'screen' => 'editor',
455 'delayed' => true,
456 ],
457 'om-attachment' => [
458 'env' => ! $has_optimole && ! $had_optimole_from_promo,
459 'screen' => 'media-editor',
460 ],
461 'om-media' => [
462 'env' => ! $has_optimole && ! $had_optimole_from_promo && $has_enough_attachments,
463 'screen' => 'media',
464 ],
465 'om-elementor' => [
466 'env' => ! $has_optimole && ! $had_optimole_from_promo && defined( 'ELEMENTOR_VERSION' ),
467 'screen' => 'elementor',
468 'delayed' => true,
469 ],
470 ],
471 'feedzy_import' => [
472 'feedzy-import' => [
473 'env' => true,
474 'screen' => 'import',
475 'always' => true,
476 ],
477 ],
478 'feedzy_embed' => [
479 'feedzy-editor' => [
480 'env' => ! $has_feedzy && is_main_site() && ! $had_feedzy_from_promo,
481 'screen' => 'editor',
482 ],
483 ],
484 'otter' => [
485 'blocks-css' => [
486 'env' => ! $has_otter && $is_min_req_v && ! $had_otter_from_promo,
487 'screen' => 'editor',
488 'delayed' => true,
489 ],
490 'blocks-animation' => [
491 'env' => ! $has_otter && $is_min_req_v && ! $had_otter_from_promo,
492 'screen' => 'editor',
493 'delayed' => true,
494 ],
495 'blocks-conditions' => [
496 'env' => ! $has_otter && $is_min_req_v && ! $had_otter_from_promo,
497 'screen' => 'editor',
498 'delayed' => true,
499 ],
500 ],
501 'rop' => [
502 'rop-posts' => [
503 'env' => ! $has_rop && ! $had_rop_from_promo && $has_enough_old_posts,
504 'screen' => 'edit-post',
505 'delayed' => true,
506 ],
507 ],
508 'woo_plugins' => [
509 'ppom' => [
510 'env' => ! $has_ppom && $has_woocommerce,
511 'screen' => 'edit-product',
512 ],
513 'sparks-wishlist' => [
514 'env' => ! $has_sparks && $has_woocommerce,
515 'screen' => 'edit-product',
516 ],
517 'sparks-announcement' => [
518 'env' => ! $has_sparks && $has_woocommerce,
519 'screen' => 'edit-product',
520 ],
521 'sparks-product-review' => [
522 'env' => ! $has_sparks && $has_woocommerce,
523 'screen' => 'edit-product',
524 ],
525 ],
526 'neve' => [
527 'neve-themes-popular' => [
528 'env' => ! $has_neve && ! $has_neve_from_promo,
529 'screen' => 'themes-install-popular',
530 ],
531 ],
532 'redirection-cf7' => [
533 'wpcf7' => [
534 'env' => ! $has_redirection_cf7 && ! $had_redirection_cf7_promo,
535 'screen' => 'wpcf7',
536 'delayed' => true,
537 ],
538 ],
539 'hyve' => [
540 'hyve-plugins-install' => [
541 'env' => $is_min_php_7_4 && ! $has_hyve && ! $had_hyve_from_promo && $has_hyve_conditions,
542 'screen' => 'plugin-install',
543 ],
544 ],
545 'wp_full_pay' => [
546 'wp-full-pay-plugins-install' => [
547 'env' => ! $has_wfp_full_pay && ! $had_wfp_from_promo && $has_wfp_conditions,
548 'screen' => 'plugin-install',
549 ],
550 ],
551 'learning-management-system' => [
552 'masteriyo-plugins-install' => [
553 'env' => $is_min_php_7_2 && ! $has_masteriyo && ! $had_masteriyo_from_promo && $has_masteriyo_conditions,
554 'screen' => 'plugin-install',
555 ],
556 ],
557 ];
558
559 foreach ( $all as $slug => $data ) {
560 foreach ( $data as $key => $conditions ) {
561 if ( ! $conditions['env'] || $this->has_conflicts() ) {
562 unset( $all[ $slug ][ $key ] );
563
564 continue;
565 }
566
567 if ( $this->get_upsells_dismiss_time( $key ) ) {
568 unset( $all[ $slug ][ $key ] );
569 }
570 }
571
572 if ( empty( $all[ $slug ] ) ) {
573 unset( $all[ $slug ] );
574 }
575 }
576 return $all;
577 }
578
579 /**
580 * Get the upsell dismiss time.
581 *
582 * @param string $key The upsell key. If empty will return all dismiss times.
583 *
584 * @return false | string | array
585 */
586 private function get_upsells_dismiss_time( $key = '' ) {
587 $old = get_option( 'themeisle_sdk_promotions_otter', '{}' );
588 $data = get_option( $this->option_main, $old );
589
590 $data = json_decode( $data, true );
591
592 if ( empty( $key ) ) {
593 return $data;
594 }
595
596 return isset( $data[ $key ] ) ? $data[ $key ] : false;
597 }
598
599 /**
600 * Get the last dismiss time of a promotion.
601 *
602 * @return int | false The timestamp of last dismiss or false.
603 */
604 private function get_last_dismiss_time() {
605 $dismissed = $this->get_upsells_dismiss_time();
606
607 return empty( $dismissed ) ? false : max( array_values( $dismissed ) );
608 }
609
610 /**
611 * Filter by screen & merge into single array of keys.
612 *
613 * @return array
614 */
615 private function filter_by_screen_and_merge() {
616 $current_screen = get_current_screen();
617
618 $is_elementor = isset( $_GET['action'] ) && $_GET['action'] === 'elementor';
619 $is_media = isset( $current_screen->id ) && $current_screen->id === 'upload';
620 $is_posts = isset( $current_screen->id ) && $current_screen->id === 'edit-post';
621 $is_editor = method_exists( $current_screen, 'is_block_editor' ) && $current_screen->is_block_editor();
622 $is_theme_install = isset( $current_screen->id ) && ( $current_screen->id === 'theme-install' );
623 $is_plugin_install = isset( $current_screen->id ) && ( $current_screen->id === 'plugin-install' );
624 $is_product = isset( $current_screen->id ) && $current_screen->id === 'product';
625 $is_import = isset( $current_screen->id ) && $current_screen->id === 'import';
626 $is_cf7_install = isset( $current_screen->id ) && function_exists( 'str_contains' ) ? str_contains( $current_screen->id, 'page_wpcf7' ) : false;
627
628 $return = [];
629 $product_install_time = (int) $this->product->get_install_time();
630 $is_older = time() > ( $product_install_time + ( 3 * DAY_IN_SECONDS ) );
631 $is_newer = time() < ( $product_install_time + ( 6 * HOUR_IN_SECONDS ) );
632 foreach ( $this->promotions as $slug => $promos ) {
633 foreach ( $promos as $key => $data ) {
634
635 $data = wp_parse_args(
636 $data,
637 [
638 'delayed' => false,
639 'always' => false,
640 ]
641 );
642
643 if (
644 ! $this->debug &&
645 (
646 ( $data['delayed'] === true && ! $is_older ) || // Skip promotions that are delayed for 3 days.
647 $is_newer // Skip promotions for the first 6 hours after install.
648 )
649 && ! $data['always']
650 ) {
651 unset( $this->promotions[ $slug ][ $key ] );
652
653 continue;
654 }
655 switch ( $data['screen'] ) {
656 case 'media-editor':
657 if ( ! $is_media && ! $is_editor ) {
658 unset( $this->promotions[ $slug ][ $key ] );
659 }
660 break;
661 case 'media':
662 if ( ! $is_media ) {
663 unset( $this->promotions[ $slug ][ $key ] );
664 }
665 break;
666 case 'editor':
667 if ( ! $is_editor || $is_elementor ) {
668 unset( $this->promotions[ $slug ][ $key ] );
669 }
670 break;
671 case 'import':
672 if ( ! $is_import ) {
673 unset( $this->promotions[ $slug ][ $key ] );
674 }
675 break;
676 case 'elementor':
677 if ( ! $is_elementor ) {
678 unset( $this->promotions[ $slug ][ $key ] );
679 }
680 break;
681 case 'edit-post':
682 if ( ! $is_posts ) {
683 unset( $this->promotions[ $slug ][ $key ] );
684 }
685 break;
686 case 'edit-product':
687 if ( ! $is_product ) {
688 unset( $this->promotions[ $slug ][ $key ] );
689 }
690 break;
691 case 'themes-install-popular':
692 if ( ! $is_theme_install ) {
693 unset( $this->promotions[ $slug ][ $key ] );
694 }
695 break;
696 case 'wpcf7':
697 if ( ! $is_cf7_install ) {
698 unset( $this->promotions[ $slug ][ $key ] );
699 }
700 break;
701 case 'plugin-install':
702 if ( ! $is_plugin_install ) {
703 unset( $this->promotions[ $slug ][ $key ] );
704 }
705 break;
706 }
707 }
708
709 $return = array_merge( $return, $this->promotions[ $slug ] );
710 }
711
712 $return = array_filter(
713 $return,
714 function ( $value, $key ) {
715 return ! in_array( $key, $this->dissallowed_promotions, true );
716 },
717 ARRAY_FILTER_USE_BOTH
718 );
719
720 return array_keys( $return );
721 }
722
723 /**
724 * Load single promotion.
725 *
726 * @param string $slug slug of the promotion.
727 */
728 private function load_promotion( $slug ) {
729 $this->loaded_promo = $slug;
730
731 if ( $this->debug ) {
732 add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue' ] );
733 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
734 if ( $this->get_upsells_dismiss_time( 'om-media' ) === false ) {
735 add_action( 'admin_notices', [ $this, 'render_optimole_dash_notice' ] );
736 }
737 if ( $this->get_upsells_dismiss_time( 'rop-posts' ) === false ) {
738 add_action( 'admin_notices', [ $this, 'render_rop_dash_notice' ] );
739 }
740 if ( $this->get_upsells_dismiss_time( 'neve-themes-popular' ) === false ) {
741 add_action( 'admin_notices', [ $this, 'render_neve_themes_notice' ] );
742 }
743 if ( $this->get_upsells_dismiss_time( 'redirection-cf7' ) === false ) {
744 add_action( 'admin_notices', [ $this, 'render_redirection_cf7_notice' ] );
745 }
746 if ( $this->get_upsells_dismiss_time( 'hyve-plugins-install' ) === false ) {
747 add_action( 'admin_notices', [ $this, 'render_hyve_notice' ] );
748 }
749
750 if ( $this->get_upsells_dismiss_time( 'wp-full-pay-plugins-install' ) === false ) {
751 add_action( 'admin_notices', [ $this, 'render_wp_full_pay_notice' ] );
752 }
753
754 if ( $this->get_upsells_dismiss_time( 'masteriyo-plugins-install' ) === false ) {
755 add_action( 'admin_notices', [ $this, 'render_masteriyo_notice' ] );
756 }
757
758 add_action( 'load-import.php', [ $this, 'add_import' ] );
759 $this->load_woo_promos();
760
761 return;
762 }
763 switch ( $slug ) {
764 case 'om-editor':
765 case 'om-image-block':
766 case 'blocks-css':
767 case 'blocks-animation':
768 case 'blocks-conditions':
769 add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue' ] );
770 break;
771 case 'om-attachment':
772 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
773 break;
774 case 'om-media':
775 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
776 add_action( 'admin_notices', [ $this, 'render_optimole_dash_notice' ] );
777 break;
778 case 'rop-posts':
779 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
780 add_action( 'admin_notices', [ $this, 'render_rop_dash_notice' ] );
781 break;
782 case 'feedzy-import':
783 add_action( 'load-import.php', [ $this, 'add_import' ] );
784
785 break;
786 case 'feedzy-editor':
787 add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue' ] );
788 break;
789 case 'ppom':
790 case 'sparks-wishlist':
791 case 'sparks-announcement':
792 case 'sparks-product-reviews':
793 $this->load_woo_promos();
794 break;
795 case 'neve-themes-popular':
796 // Remove any other notifications if Neve promotion is showing
797 remove_action( 'admin_notices', array( 'ThemeisleSDK\Modules\Notification', 'show_notification' ) );
798 remove_action(
799 'wp_ajax_themeisle_sdk_dismiss_notice',
800 array(
801 'ThemeisleSDK\Modules\Notification',
802 'dismiss',
803 )
804 );
805 remove_action( 'admin_head', array( 'ThemeisleSDK\Modules\Notification', 'dismiss_get' ) );
806 remove_action( 'admin_head', array( 'ThemeisleSDK\Modules\Notification', 'setup_notifications' ) );
807 // Add required actions to display this notification
808 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
809 add_action( 'admin_notices', [ $this, 'render_neve_themes_notice' ] );
810 break;
811 case 'wpcf7':
812 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
813 add_action( 'admin_notices', [ $this, 'render_redirection_cf7_notice' ] );
814 break;
815 case 'hyve-plugins-install':
816 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
817 add_action( 'admin_notices', [ $this, 'render_hyve_notice' ] );
818 break;
819 case 'wp-full-pay-plugins-install':
820 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
821 add_action( 'admin_notices', [ $this, 'render_wp_full_pay_notice' ] );
822 break;
823 case 'masteriyo-plugins-install':
824 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
825 add_action( 'admin_notices', [ $this, 'render_masteriyo_notice' ] );
826 break;
827 }
828 }
829
830 /**
831 * Add import row.
832 *
833 * @return void
834 */
835 public function add_import() {
836 global $wp_importers;
837 if ( isset( $wp_importers['feedzy-rss-feeds'] ) ) {
838 return;
839 }
840 $wp_importers['feedzy-rss-feeds'] = array( // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
841 'Feedzy',
842 sprintf( Loader::$labels['promotions']['feedzy']['import_desc'], '<span style="float: left; font-style: italic;margin-top:0.4em;">', $this->product->get_friendly_name(), '</span>' ),
843 'install' => 'feedzy-rss-feeds',
844 );
845 if ( defined( 'FEEDZY_BASEFILE' ) ) {
846 unset( $wp_importers['feedzy-rss-feeds']['install'] );
847 }
848 }
849 /**
850 * Render dashboard notice.
851 */
852 public function render_optimole_dash_notice() {
853 $screen = get_current_screen();
854
855 if ( ! isset( $screen->id ) || $screen->id !== 'upload' ) {
856 return;
857 }
858
859 echo '<div id="ti-optml-notice" class="notice notice-info ti-sdk-om-notice"></div>';
860 }
861
862 /**
863 * Enqueue the assets.
864 */
865 public function enqueue() {
866 global $themeisle_sdk_max_path;
867 $handle = 'ti-sdk-promo';
868 $saved = $this->get_upsells_dismiss_time();
869 $themeisle_sdk_src = $this->get_sdk_uri();
870 $user = wp_get_current_user();
871 $asset_file = require $themeisle_sdk_max_path . '/assets/js/build/promos/index.asset.php';
872 $deps = array_merge( $asset_file['dependencies'], [ 'updates' ] );
873
874 $themes = wp_get_themes();
875 $neve_action = isset( $themes['neve'] ) ? 'activate' : 'install';
876 $labels = Loader::$labels['promotions'];
877 $labels['feedzy']['editor_recommends'] = sprintf(
878 $labels['feedzy']['editor_recommends'],
879 $this->product->get_friendly_name(),
880 '<a target="_blank" href="' . add_query_arg(
881 array(
882 'tab' => 'plugin-information',
883 'plugin' => 'feedzy-rss-feeds',
884 '_wpnonce' => wp_create_nonce( 'activate-plugin_feedzy-rss-feeds' ),
885 'feedzy_reference_key' => 'e-' . $this->product->get_key(),
886 ),
887 network_admin_url( 'plugin-install.php' )
888 ) . '">',
889 '</a>'
890 );
891 wp_register_script( $handle, $themeisle_sdk_src . 'assets/js/build/promos/index.js', $deps, $asset_file['version'], true );
892 wp_localize_script(
893 $handle,
894 'themeisleSDKPromotions',
895 [
896 'debug' => $this->debug,
897 'labels' => $labels,
898 'email' => $user->user_email,
899 'showPromotion' => $this->loaded_promo,
900 'optionKey' => $this->option_main,
901 'product' => $this->product->get_name(),
902 'option' => empty( $saved ) ? new \stdClass() : $saved,
903 'nonce' => wp_create_nonce( 'wp_rest' ),
904 'assets' => $themeisle_sdk_src . 'assets/images/',
905 'optimoleApi' => esc_url( rest_url( 'optml/v1/register_service' ) ),
906 'optimoleActivationUrl' => $this->get_plugin_activation_link( 'optimole-wp' ),
907 'otterActivationUrl' => $this->get_plugin_activation_link( 'otter-blocks' ),
908 'ropActivationUrl' => $this->get_plugin_activation_link( 'tweet-old-post' ),
909 'optimoleDash' => esc_url( add_query_arg( [ 'page' => 'optimole' ], admin_url( 'upload.php' ) ) ),
910 'ropDash' => esc_url( add_query_arg( [ 'page' => 'TweetOldPost' ], admin_url( 'admin.php' ) ) ),
911 // translators: %s is the product name.
912 'title' => esc_html( sprintf( Loader::$labels['promotions']['recommended'], $this->product->get_name() ) ),
913 'redirectionCF7MoreUrl' => tsdk_utmify( 'https://docs.themeisle.com/collection/2014-redirection-for-contact-form-7', 'redirection-for-contact-form-7', 'plugin-install' ),
914 'rfCF7ActivationUrl' => $this->get_plugin_activation_link( 'wpcf7-redirect' ),
915 'cf7Dash' => esc_url( add_query_arg( [ 'page' => 'wpcf7-new' ], admin_url( 'admin.php' ) ) ),
916 'hyveActivationUrl' => $this->get_plugin_activation_link( 'hyve-lite' ),
917 'hyveDash' => esc_url( add_query_arg( [ 'page' => 'wpfs-settings-stripe' ], admin_url( 'admin.php' ) ) ),
918 'wpFullPayActivationUrl' => $this->get_plugin_activation_link( 'wp-full-stripe-free' ),
919 'wpFullPayDash' => esc_url( add_query_arg( [ 'page' => 'wpfs-settings-stripe' ], admin_url( 'admin.php' ) ) ),
920 'masteriyoActivationUrl' => $this->get_plugin_activation_link( 'masteriyo' ),
921 'masteriyoDash' => esc_url( add_query_arg( [ 'page' => 'masteriyo-onboard' ], admin_url( 'index.php' ) ) ),
922 'nevePreviewURL' => esc_url( add_query_arg( [ 'theme' => 'neve' ], admin_url( 'theme-install.php' ) ) ),
923 'neveAction' => $neve_action,
924 'activateNeveURL' => esc_url(
925 add_query_arg(
926 [
927 'action' => 'activate',
928 'stylesheet' => 'neve',
929 '_wpnonce' => wp_create_nonce( 'switch-theme_neve' ),
930 ],
931 admin_url( 'themes.php' )
932 )
933 ),
934 ]
935 );
936 wp_enqueue_script( $handle );
937 wp_enqueue_style( $handle, $themeisle_sdk_src . 'assets/js/build/promos/style-index.css', [ 'wp-components' ], $asset_file['version'] );
938 }
939
940 /**
941 * Render rop notice.
942 */
943 public function render_rop_dash_notice() {
944 $screen = get_current_screen();
945
946 if ( ! isset( $screen->id ) || $screen->id !== 'edit-post' ) {
947 return;
948 }
949
950 echo '<div id="ti-rop-notice" class="notice notice-info ti-sdk-rop-notice"></div>';
951 }
952
953 /**
954 * Render Neve Themes notice.
955 */
956 public function render_neve_themes_notice() {
957 echo '<div id="ti-neve-notice" class="notice notice-info ti-sdk-om-notice"></div>';
958 }
959
960 /**
961 * Render Hyve notice.
962 */
963 public function render_hyve_notice() {
964 echo '<div id="ti-hyve-notice" class="notice notice-info ti-sdk-om-notice"></div>';
965 }
966
967 /**
968 * Render WP Full Pay notice.
969 */
970 public function render_wp_full_pay_notice() {
971 echo '<div id="ti-wp-full-pay-notice" class="notice notice-info ti-sdk-om-notice"></div>';
972 }
973
974 /**
975 * Render Redirection for CF7 notice.
976 */
977 public function render_redirection_cf7_notice() {
978 echo '<div id="ti-redirection-cf7-notice" class="notice notice-info ti-sdk-om-notice"></div>';
979 }
980
981 /**
982 * Render Masteriyo notice.
983 */
984 public function render_masteriyo_notice() {
985 echo '<div id="ti-masteriyo-notice" class="notice notice-info ti-sdk-om-notice"></div>';
986 }
987
988 /**
989 * Add promo to attachment modal.
990 *
991 * @param array $fields Fields array.
992 * @param \WP_Post $post Post object.
993 *
994 * @return array
995 */
996 public function add_attachment_field( $fields, $post ) {
997 if ( $post->post_type !== 'attachment' ) {
998 return $fields;
999 }
1000
1001 if ( ! isset( $post->post_mime_type ) || strpos( $post->post_mime_type, 'image' ) === false ) {
1002 return $fields;
1003 }
1004
1005 $meta = wp_get_attachment_metadata( $post->ID );
1006
1007 if ( isset( $meta['filesize'] ) && $meta['filesize'] < 100000 ) {
1008 return $fields;
1009 }
1010
1011 $fields['optimole'] = array(
1012 'input' => 'html',
1013 'html' => '<div id="ti-optml-notice-helper"></div>',
1014 'label' => '',
1015 );
1016
1017 if ( count( $fields ) < 2 ) {
1018 add_filter( 'wp_required_field_message', '__return_empty_string' );
1019 }
1020
1021 return $fields;
1022 }
1023
1024 /**
1025 * Check if has 50 image media items.
1026 *
1027 * @return bool
1028 */
1029 private function has_min_media_attachments() {
1030 if ( $this->debug ) {
1031 return true;
1032 }
1033 $attachment_count = get_transient( 'tsk_attachment_count' );
1034 if ( false === $attachment_count ) {
1035 $args = array(
1036 'post_type' => 'attachment',
1037 'posts_per_page' => 51,
1038 'fields' => 'ids',
1039 'post_status' => 'inherit',
1040 'no_found_rows' => true,
1041 );
1042
1043 $query = new \WP_Query( $args );
1044 $attachment_count = $query->post_count;
1045
1046
1047 set_transient( 'tsk_attachment_count', $attachment_count, DAY_IN_SECONDS );
1048 }
1049
1050 return $attachment_count > 50;
1051 }
1052
1053 /**
1054 * Check if the website has more than 100 posts and over 10 are over a year old.
1055 *
1056 * @return bool
1057 */
1058 private function has_old_posts() {
1059 if ( $this->debug ) {
1060 return true;
1061 }
1062
1063 $posts_count = get_transient( 'tsk_posts_count' );
1064
1065 // Create a new WP_Query object to get all posts
1066 $args = array(
1067 'post_type' => 'post',
1068 'posts_per_page' => 101, //phpcs:ignore WordPress.WP.PostsPerPage.posts_per_page_posts_per_page
1069 'fields' => 'ids',
1070 'no_found_rows' => true,
1071 );
1072
1073 if ( false === $posts_count ) {
1074 $query = new \WP_Query( $args );
1075 $total_posts = $query->post_count;
1076 wp_reset_postdata();
1077
1078 // Count the number of posts older than 1 year
1079 $one_year_ago = gmdate( 'Y-m-d H:i:s', strtotime( '-1 year' ) );
1080 $args['date_query'] = array(
1081 array(
1082 'before' => $one_year_ago,
1083 'inclusive' => true,
1084 ),
1085 );
1086
1087 $query = new \WP_Query( $args );
1088 $old_posts = $query->post_count;
1089 wp_reset_postdata();
1090
1091 $posts_count = array(
1092 'total_posts' => $total_posts,
1093 'old_posts' => $old_posts,
1094 );
1095
1096 set_transient( 'tsk_posts_count', $posts_count, DAY_IN_SECONDS );
1097 }
1098
1099 // Check if there are more than 100 posts and more than 10 old posts
1100 return $posts_count['total_posts'] > 100 && $posts_count['old_posts'] > 10;
1101 }
1102
1103 /**
1104 * Check if should load Woo promos.
1105 *
1106 * @return bool
1107 */
1108 private function load_woo_promos() {
1109 $this->woo_promos = array(
1110 'ppom' => array(
1111 'title' => Loader::$labels['promotions']['woo']['ppom_title'],
1112 'description' => Loader::$labels['promotions']['woo']['ppom_desc'],
1113 'icon' => '<svg width="25" height="25" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1800 1800"><path d="M241.023,324.818c0.252,0,0.505,0.035,0.758,0.035h465.68c17.266,0,31.256-13.99,31.256-31.252 c0-17.262-13.99-31.247-31.256-31.247H351.021h-109.24c-17.258,0-31.252,13.985-31.252,31.247 C210.529,310.605,224.121,324.412,241.023,324.818z"/><path d="M210.529,450.306c0,17.257,13.994,31.252,31.252,31.252h769.451c17.262,0,31.256-13.995,31.256-31.252 c0-17.266-13.994-31.252-31.256-31.252H241.781C224.523,419.054,210.529,433.04,210.529,450.306z"/><path d="M1011.232,575.751H241.781c-8.149,0-15.549,3.147-21.116,8.261c-6.213,5.712-10.136,13.879-10.136,22.987 c0,17.262,13.994,31.26,31.252,31.26h769.451c17.262,0,31.256-13.999,31.256-31.26c0-9.108-3.923-17.275-10.141-22.987 C1026.781,578.898,1019.386,575.751,1011.232,575.751z"/><path d="M1011.232,732.461H241.781c-17.258,0-31.252,13.99-31.252,31.247c0,17.262,13.994,31.257,31.252,31.257 h769.451c17.262,0,31.256-13.995,31.256-31.257C1042.488,746.451,1028.494,732.461,1011.232,732.461z"/><path d="M1011.232,889.157H241.781c-8.149,0-15.549,3.147-21.116,8.261c-6.213,5.713-10.136,13.879-10.136,22.987 c0,17.257,13.994,31.261,31.252,31.261h769.451c17.262,0,31.256-14.004,31.256-31.261c0-9.108-3.923-17.274-10.141-22.987 C1026.781,892.305,1019.386,889.157,1011.232,889.157z"/><path d="M1011.232,1045.867H241.781c-17.258,0-31.252,13.99-31.252,31.243c0,17.271,13.994,31.265,31.252,31.265 h769.451c17.262,0,31.256-13.994,31.256-31.265C1042.488,1059.857,1028.494,1045.867,1011.232,1045.867z"/><path d="M1011.232,1202.576H241.781c-17.258,0-31.252,13.995-31.252,31.252c0,17.258,13.994,31.252,31.252,31.252 h769.451c17.262,0,31.256-13.994,31.256-31.252C1042.488,1216.571,1028.494,1202.576,1011.232,1202.576z"/><path d="M1011.232,1359.273H241.781c-8.149,0-15.549,3.151-21.116,8.265c-6.213,5.713-10.136,13.875-10.136,22.987 c0,17.258,13.994,31.261,31.252,31.261h769.451c17.262,0,31.256-14.003,31.256-31.261c0-9.112-3.923-17.274-10.141-22.987 C1026.781,1362.425,1019.386,1359.273,1011.232,1359.273z"/><path d="M1233.542,251.228l-49.851-45.109L1052.136,87.076l-59.185-53.554c-5.293-4.792-11.947-7.421-18.786-7.836 h-3.49H83.676c-45.688,0-82.858,37.375-82.858,83.316v1583.612c0,45.94,37.17,83.316,82.858,83.316h1078.562 c45.68,0,82.845-37.376,82.845-83.316V277.08v-3.182C1244.646,264.73,1240.261,256.589,1233.542,251.228z M1003.117,125.864 l131.119,118.657h-131.119V125.864z M1183.691,1692.613c0,12.094-9.622,21.926-21.454,21.926H83.676 c-11.836,0-21.467-9.832-21.467-21.926V109.001c0-12.089,9.631-21.925,21.467-21.925h857.857V275.38 c0,17.052,13.785,30.862,30.786,30.862h211.372V1692.613z"/><path d="M1798.578,180.737c-7.049-88.305-81.114-158.02-171.205-158.02c-0.004,0-0.004,0-0.004,0 c-45.889,0-89.033,17.874-121.479,50.32c-29.18,29.175-46.519,67.005-49.73,107.699h-0.586v13.609c0,0.06-0.005,0.115-0.005,0.175 c0,0.026,0.005,0.056,0.005,0.082l-0.005,1369.26h0.197c0.557,5.404,2.522,10.731,6.047,15.373l141.135,185.91 c5.803,7.648,14.851,12.136,24.447,12.136c9.601-0.004,18.646-4.496,24.447-12.14l141.093-185.897 c3.528-4.65,5.494-9.982,6.051-15.391h0.197V180.737H1798.578z M1549.299,116.448c20.854-20.855,48.578-32.339,78.07-32.339h0.004 c50.24,0,92.746,33.723,106.076,79.718h-212.19C1526.358,146.098,1535.896,129.852,1549.299,116.448z M1595.372,1502.468 l-78.413,0.005l0.005-1260.345h220.828v1260.336h-81.103l0.009-1016.486l-61.335,0.004L1595.372,1502.468z M1627.382,1695.821 l-100.171-131.963l200.338-0.004L1627.382,1695.821z"/></svg>',
1114 'has_install' => true,
1115 'link' => wp_nonce_url(
1116 add_query_arg(
1117 array(
1118 'action' => 'install-plugin',
1119 'plugin' => 'woocommerce-product-addon',
1120 ),
1121 admin_url( 'update.php' )
1122 ),
1123 'install-plugin_woocommerce-product-addon'
1124 ),
1125 ),
1126 'sparks-wishlist' => array(
1127 'title' => Loader::$labels['promotions']['woo']['spark_title1'],
1128 'description' => Loader::$labels['promotions']['woo']['spark_desc1'],
1129 'icon' => '<svg width="25" height="25" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/SVG" aria-hidden="true"><path d="M60 21.25H57.5V40.125H60V21.25Z"></path><path d="M2.5 40H0V8.75C0 6.625 1.625 5 3.75 5H25V7.5H3.75C3 7.5 2.5 8 2.5 8.75V40Z"></path><path d="M56.25 51.25H3.75C1.625 51.25 0 49.625 0 47.5V42.5H25V45H2.5V47.5C2.5 48.25 3 48.75 3.75 48.75H56.25C57 48.75 57.5 48.25 57.5 47.5V43.75H60V47.5C60 49.625 58.375 51.25 56.25 51.25Z"></path><path d="M23.75 58.75H21.25V57.25L22.5 51.125V50H25V51.5L23.75 57.625V58.75Z"></path><path d="M38.75 58.75H36.25V57.625L35 51.25V50H37.5V51.125L38.75 57.5V58.75Z"></path><path d="M41.25 57.5H18.75V60H41.25V57.5Z"></path><path d="M56.25 32.5H43.75C41.625 32.5 40 30.875 40 28.75V3.75C40 1.625 41.625 0 43.75 0H56.25C58.375 0 60 1.625 60 3.75V28.75C60 30.875 58.375 32.5 56.25 32.5ZM43.75 2.5C43 2.5 42.5 3 42.5 3.75V28.75C42.5 29.5 43 30 43.75 30H56.25C57 30 57.5 29.5 57.5 28.75V3.75C57.5 3 57 2.5 56.25 2.5H43.75Z"></path><path d="M50 27.5C50.6904 27.5 51.25 26.9404 51.25 26.25C51.25 25.5596 50.6904 25 50 25C49.3096 25 48.75 25.5596 48.75 26.25C48.75 26.9404 49.3096 27.5 50 27.5Z"></path><path d="M51.25 45H31.25C29.125 45 27.5 43.375 27.5 41.25V8.75C27.5 6.625 29.125 5 31.25 5H37.5V7.5H31.25C30.5 7.5 30 8 30 8.75V41.25C30 42 30.5 42.5 31.25 42.5H51.25C52 42.5 52.5 42 52.5 41.25V35H55V41.25C55 43.375 53.375 45 51.25 45Z"></path><path d="M41.25 40C41.9404 40 42.5 39.4404 42.5 38.75C42.5 38.0596 41.9404 37.5 41.25 37.5C40.5596 37.5 40 38.0596 40 38.75C40 39.4404 40.5596 40 41.25 40Z"></path><path d="M21.75 40H18.25L13.25 35H11.75L6.75 40H0V37.5H5.75L10.75 32.5H14.25L19.25 37.5H20.75L52.875 5.375L54.625 7.125L21.75 40Z"></path><path d="M55 11.25H52.5V7.5H48.75V5H55V11.25Z"></path><defs><clip-path id="clip0"><rect width="60" height="60" fill="white"></rect></clip-path></defs></svg>',
1130 'link' => tsdk_utmify( 'https://themeisle.com/plugins/sparks-for-woocommerce/', 'promo', 'products-tabs' ),
1131 ),
1132 'sparks-announcement' => array(
1133 'title' => Loader::$labels['promotions']['woo']['spark_title2'],
1134 'description' => Loader::$labels['promotions']['woo']['spark_desc2'],
1135 'icon' => '<svg width="25" height="25" viewBox="0 0 60 61" fill="none" xmlns="http://www.w3.org/2000/SVG" aria-hidden="true"><path d="M30 8.89282C29.6685 8.89282 29.3505 8.76113 29.1161 8.52671C28.8817 8.29228 28.75 7.97434 28.75 7.64282V1.39282C28.75 1.0613 28.8817 0.743359 29.1161 0.508939C29.3505 0.274518 29.6685 0.142822 30 0.142822C30.3315 0.142822 30.6495 0.274518 30.8839 0.508939C31.1183 0.743359 31.25 1.0613 31.25 1.39282V7.64282C31.25 7.97434 31.1183 8.29228 30.8839 8.52671C30.6495 8.76113 30.3315 8.89282 30 8.89282Z"></path><path d="M30 21.9105L26.25 18.1605V7.82598L26.9409 7.47992C27.8914 7.00723 28.9385 6.76123 30 6.76123C31.0615 6.76123 32.1086 7.00723 33.0591 7.47992L33.75 7.82598V18.1605L30 21.9105ZM28.75 17.1253L30 18.3753L31.25 17.1253V9.44219C30.4344 9.19928 29.5656 9.19928 28.75 9.44219V17.1253Z"></path><path d="M60 60.1428H0V22.6428H17.5C17.8315 22.6428 18.1495 22.7745 18.3839 23.0089C18.6183 23.2434 18.75 23.5613 18.75 23.8928C18.75 24.2243 18.6183 24.5423 18.3839 24.7767C18.1495 25.0111 17.8315 25.1428 17.5 25.1428H2.5V57.6428H57.5V25.1428H42.5C42.1685 25.1428 41.8505 25.0111 41.6161 24.7767C41.3817 24.5423 41.25 24.2243 41.25 23.8928C41.25 23.5613 41.3817 23.2434 41.6161 23.0089C41.8505 22.7745 42.1685 22.6428 42.5 22.6428H60V60.1428Z"></path><path d="M11.2493 53.8933C11.0421 53.8929 10.8383 53.841 10.6561 53.7424C10.474 53.6438 10.3191 53.5015 10.2055 53.3283C10.0919 53.1551 10.0231 52.9564 10.0052 52.75C9.98727 52.5436 10.0209 52.336 10.103 52.1458L26.353 14.6459C26.4182 14.4953 26.5125 14.359 26.6304 14.2448C26.7483 14.1306 26.8876 14.0408 27.0402 13.9804C27.1928 13.9201 27.3559 13.8903 27.52 13.893C27.6841 13.8956 27.8461 13.9306 27.9967 13.9958C28.1473 14.0611 28.2836 14.1553 28.3978 14.2732C28.5119 14.3912 28.6018 14.5304 28.6621 14.683C28.7225 14.8357 28.7522 14.9987 28.7496 15.1628C28.7469 15.3269 28.712 15.4889 28.6467 15.6395L12.3967 53.1395C12.2999 53.3634 12.1397 53.5541 11.9358 53.6881C11.7319 53.822 11.4932 53.8934 11.2493 53.8933Z"></path><path d="M48.7505 53.8935C48.5065 53.8935 48.2679 53.8222 48.064 53.6883C47.8601 53.5543 47.6999 53.3637 47.603 53.1398L31.353 15.6398C31.2212 15.3356 31.2157 14.9915 31.3376 14.6833C31.4595 14.375 31.6989 14.1278 32.003 13.9961C32.3072 13.8643 32.6513 13.8588 32.9595 13.9807C33.2678 14.1026 33.515 14.3419 33.6467 14.6461L49.8967 52.1461C49.9789 52.3363 50.0125 52.5439 49.9946 52.7503C49.9767 52.9566 49.9078 53.1553 49.7942 53.3285C49.6806 53.5018 49.5258 53.6441 49.3436 53.7427C49.1614 53.8413 48.9576 53.8932 48.7505 53.8936V53.8935Z"></path><path d="M30 33.8928C29.6685 33.8928 29.3505 33.7611 29.1161 33.5267C28.8817 33.2923 28.75 32.9743 28.75 32.6428V25.1428C28.75 24.8113 28.8817 24.4934 29.1161 24.2589C29.3505 24.0245 29.6685 23.8928 30 23.8928C30.3315 23.8928 30.6495 24.0245 30.8839 24.2589C31.1183 24.4934 31.25 24.8113 31.25 25.1428V32.6428C31.25 32.9743 31.1183 33.2923 30.8839 33.5267C30.6495 33.7611 30.3315 33.8928 30 33.8928Z"></path><path d="M45 30.1428H15C14.6685 30.1428 14.3505 30.0111 14.1161 29.7767C13.8817 29.5423 13.75 29.2243 13.75 28.8928C13.75 28.5613 13.8817 28.2434 14.1161 28.0089C14.3505 27.7745 14.6685 27.6428 15 27.6428H45C45.3315 27.6428 45.6495 27.7745 45.8839 28.0089C46.1183 28.2434 46.25 28.5613 46.25 28.8928C46.25 29.2243 46.1183 29.5423 45.8839 29.7767C45.6495 30.0111 45.3315 30.1428 45 30.1428Z"></path><defs><clip-path id="clip0"><rect width="60" height="60" fill="white" transform="translate(0 0.142822)"></rect></clip-path></defs></svg>',
1136 'link' => tsdk_utmify( 'https://themeisle.com/plugins/sparks-for-woocommerce/', 'promo', 'products-tabs' ),
1137 ),
1138 'sparks-product-review' => array(
1139 'title' => Loader::$labels['promotions']['woo']['spark_title3'],
1140 'description' => Loader::$labels['promotions']['woo']['spark_desc3'],
1141 'icon' => '<svg width="25" height="25" viewBox="0 0 60 61" fill="none" xmlns="http://www.w3.org/2000/SVG" aria-hidden="true"><path d="M58.75 54.1797H1.25C1.08584 54.1797 0.923271 54.1474 0.771595 54.0846C0.619919 54.0218 0.482103 53.9297 0.366021 53.8137C0.24994 53.6976 0.157867 53.5598 0.0950637 53.4081C0.0322604 53.2564 -4.26571e-05 53.0939 4.22759e-08 52.9297V6.67969C-4.26571e-05 6.51552 0.0322604 6.35296 0.0950637 6.20128C0.157867 6.04961 0.24994 5.91179 0.366021 5.79571C0.482103 5.67963 0.619919 5.58755 0.771595 5.52475C0.923271 5.46195 1.08584 5.42964 1.25 5.42969H58.75C58.9142 5.42964 59.0767 5.46195 59.2284 5.52475C59.3801 5.58755 59.5179 5.67963 59.634 5.79571C59.7501 5.91179 59.8421 6.04961 59.9049 6.20128C59.9677 6.35296 60 6.51552 60 6.67969V52.9297C60 53.0939 59.9677 53.2564 59.9049 53.4081C59.8421 53.5598 59.7501 53.6976 59.634 53.8137C59.5179 53.9297 59.3801 54.0218 59.2284 54.0846C59.0767 54.1474 58.9142 54.1797 58.75 54.1797ZM2.5 51.6797H57.5V7.92969H2.5V51.6797Z"></path><path d="M6.25 15.4297C6.94036 15.4297 7.5 14.87 7.5 14.1797C7.5 13.4893 6.94036 12.9297 6.25 12.9297C5.55964 12.9297 5 13.4893 5 14.1797C5 14.87 5.55964 15.4297 6.25 15.4297Z"></path><path d="M10 15.4297C10.6904 15.4297 11.25 14.87 11.25 14.1797C11.25 13.4893 10.6904 12.9297 10 12.9297C9.30964 12.9297 8.75 13.4893 8.75 14.1797C8.75 14.87 9.30964 15.4297 10 15.4297Z"></path><path d="M13.75 15.4297C14.4404 15.4297 15 14.87 15 14.1797C15 13.4893 14.4404 12.9297 13.75 12.9297C13.0596 12.9297 12.5 13.4893 12.5 14.1797C12.5 14.87 13.0596 15.4297 13.75 15.4297Z"></path><path d="M58.75 15.4297H18.75C18.4185 15.4297 18.1005 15.298 17.8661 15.0636C17.6317 14.8292 17.5 14.5112 17.5 14.1797C17.5 13.8482 17.6317 13.5302 17.8661 13.2958C18.1005 13.0614 18.4185 12.9297 18.75 12.9297H58.75C59.0815 12.9297 59.3995 13.0614 59.6339 13.2958C59.8683 13.5302 60 13.8482 60 14.1797C60 14.5112 59.8683 14.8292 59.6339 15.0636C59.3995 15.298 59.0815 15.4297 58.75 15.4297Z"></path><path d="M28.7502 37.9297C28.4187 37.9295 28.1009 37.7978 27.8664 37.5634L24.4289 34.1259C24.198 33.8908 24.0693 33.574 24.0708 33.2445C24.0723 32.915 24.2039 32.5994 24.4369 32.3664C24.6699 32.1334 24.9855 32.0018 25.315 32.0003C25.6445 31.9988 25.9613 32.1275 26.1964 32.3584L28.6977 34.8597L38.8588 23.4522C38.968 23.3296 39.1002 23.2298 39.2479 23.1583C39.3957 23.0869 39.5561 23.0452 39.7199 23.0358C39.8838 23.0263 40.0479 23.0492 40.2029 23.1032C40.3579 23.1571 40.5008 23.2411 40.6233 23.3503C40.7459 23.4594 40.8457 23.5917 40.9172 23.7394C40.9886 23.8872 41.0303 24.0476 41.0397 24.2114C41.0492 24.3753 41.0263 24.5394 40.9723 24.6944C40.9184 24.8494 40.8344 24.9922 40.7253 25.1148L29.6834 37.511C29.5702 37.6382 29.4322 37.7409 29.2779 37.8129C29.1237 37.8849 28.9563 37.9247 28.7862 37.9298L28.7502 37.9297Z"></path><path d="M29.977 44.1812C28.3217 44.1775 26.6876 43.8085 25.1912 43.1007C23.6948 42.3928 22.3731 41.3635 21.3203 40.0861C20.2675 38.8087 19.5095 37.3148 19.1004 35.7108C18.6913 34.1068 18.6413 32.4322 18.9537 30.8067C19.2662 29.1811 19.9335 27.6445 20.9081 26.3065C21.8827 24.9684 23.1406 23.862 24.592 23.0659C26.0433 22.2699 27.6525 21.804 29.3046 21.7013C30.9568 21.5987 32.6113 21.8619 34.15 22.4722C34.4579 22.5949 34.7044 22.8349 34.8354 23.1393C34.9663 23.4438 34.9709 23.7878 34.8482 24.0957C34.7255 24.4036 34.4856 24.6501 34.1811 24.7811C33.8766 24.912 33.5326 24.9166 33.2247 24.7939C31.44 24.0862 29.472 23.985 27.6241 24.5059C25.7762 25.0269 24.1508 26.141 22.9985 27.6767C21.8462 29.2124 21.2308 31.0844 21.2473 33.0043C21.2637 34.9242 21.9111 36.7854 23.0895 38.3011C24.268 39.8168 25.9122 40.903 27.7688 41.3922C29.6254 41.8813 31.5913 41.7464 33.3637 41.0082C35.136 40.27 36.6164 38.9694 37.5768 37.3069C38.5372 35.6444 38.9242 33.7122 38.6782 31.8081C38.6568 31.6451 38.6678 31.4795 38.7104 31.3208C38.7531 31.1621 38.8267 31.0133 38.927 30.8831C39.0272 30.7528 39.1522 30.6436 39.2947 30.5617C39.4373 30.4798 39.5945 30.4268 39.7575 30.4058C39.9206 30.3848 40.0861 30.3961 40.2448 30.4391C40.4034 30.4822 40.552 30.5561 40.682 30.6566C40.8121 30.7572 40.921 30.8824 41.0026 31.0251C41.0842 31.1678 41.1368 31.3252 41.1574 31.4883C41.3469 32.9535 41.2459 34.4417 40.8602 35.8679C40.4745 37.294 39.8116 38.6303 38.9094 39.8002C38.0072 40.9702 36.8834 41.9509 35.6021 42.6865C34.3208 43.4221 32.9071 43.898 31.4419 44.0872C30.9561 44.1494 30.4668 44.1807 29.977 44.1812Z"></path><defs><clip-path id="clip0"><rect width="60" height="60" fill="white" transform="translate(0 0.429688)"></rect></clip-path></defs></svg>',
1142 'link' => tsdk_utmify( 'https://themeisle.com/plugins/sparks-for-woocommerce/', 'promo', 'products-tabs' ),
1143 ),
1144 );
1145
1146 // Check if $this-promotions isn't empty and has one of the items to load.
1147 $can_load = ! empty( $this->promotions ) && count( array_intersect( $this->promotions, array_keys( $this->woo_promos ) ) ) > 0;
1148
1149 if ( ! $can_load && ! $this->debug ) {
1150 return;
1151 }
1152
1153 add_action(
1154 'woocommerce_product_data_tabs',
1155 function ( $tabs ) {
1156 $tabs['tisdk-suggestions'] = array(
1157 'label' => Loader::$labels['promotions']['woo']['title'],
1158 'target' => 'tisdk_suggestions',
1159 'class' => array(),
1160 'priority' => 1000,
1161 );
1162
1163 return $tabs;
1164 }
1165 );
1166
1167 add_action( 'woocommerce_product_data_panels', array( $this, 'woocommerce_tab_content' ) );
1168 }
1169
1170 /**
1171 * WooCommerce Tab Content.
1172 */
1173 public function woocommerce_tab_content() {
1174 // Filter content based on if the key exists in $this->promotions array.
1175 $content = array_filter(
1176 $this->woo_promos,
1177 function ( $key ) {
1178 return in_array( $key, $this->promotions, true );
1179 },
1180 ARRAY_FILTER_USE_KEY
1181 );
1182
1183 // Display CSS
1184 self::render_woo_tabs_css();
1185
1186 self::render_notice_dismiss_ajax();
1187 ?>
1188
1189 <div id="tisdk_suggestions" class="panel woocommerce_options_panel hidden">
1190 <div class="tisdk-suggestions-header">
1191 <h4><?php echo esc_html( Loader::$labels['promotions']['woo']['title2'] ); ?></h4>
1192 </div>
1193 <div class="tisdk-suggestions-content">
1194 <?php foreach ( $content as $key => $item ) : ?>
1195 <div class="tisdk-suggestion" id="<?php echo esc_attr( $key ); ?>">
1196 <?php if ( isset( $item['icon'] ) ) : ?>
1197 <div class="tisdk-suggestion-icon">
1198 <?php echo $item['icon']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1199 </div>
1200 <?php endif; ?>
1201 <div class="tisdk-suggestion-content">
1202 <h4><?php echo esc_html( $item['title'] ); ?></h4>
1203 <p><?php echo esc_html( $item['description'] ); ?></p>
1204 </div>
1205 <div class="tisdk-suggestion-cta">
1206 <a href="<?php echo esc_url( $item['link'] ); ?>" target="blank" class="button">
1207 <?php echo( ( isset( $item['has_install'] ) && $item['has_install'] ) ? esc_html( Loader::$labels['promotions']['woo']['cta_install'] ) : esc_html( Loader::$labels['promotions']['woo']['learn_more'] ) ); ?>
1208 </a>
1209 <a class="suggestion-dismiss"
1210 title="<?php echo esc_attr( Loader::$labels['promotions']['woo']['dismiss'] ); ?>"
1211 href="#"></a>
1212 </div>
1213 </div>
1214 <?php endforeach; ?>
1215 </div>
1216 </div>
1217 <?php
1218 }
1219
1220 /**
1221 * CSS for WooCommerce Tabs
1222 */
1223 public static function render_woo_tabs_css() {
1224 $icon = 'M208 88.286c0-10 6.286-21.714 17.715-21.714 11.142 0 17.714 11.714 17.714 21.714 0 10.285-6.572 21.714-17.714 21.714C214.286 110 208 98.571 208 88.286zm304 160c0 36.001-11.429 102.286-36.286 129.714-22.858 24.858-87.428 61.143-120.857 70.572l-1.143.286v32.571c0 16.286-12.572 30.571-29.143 30.571-10 0-19.429-5.714-24.572-14.286-5.427 8.572-14.856 14.286-24.856 14.286-10 0-19.429-5.714-24.858-14.286-5.142 8.572-14.571 14.286-24.57 14.286-10.286 0-19.429-5.714-24.858-14.286-5.143 8.572-14.571 14.286-24.571 14.286-18.857 0-29.429-15.714-29.429-32.857-16.286 12.285-35.715 19.428-56.571 19.428-22 0-43.429-8.285-60.286-22.857 10.285-.286 20.571-2.286 30.285-5.714-20.857-5.714-39.428-18.857-52-36.286 21.37 4.645 46.209 1.673 67.143-11.143-22-22-56.571-58.857-68.572-87.428C1.143 321.714 0 303.714 0 289.429c0-49.714 20.286-160 86.286-160 10.571 0 18.857 4.858 23.143 14.857a158.792 158.792 0 0 1 12-15.428c2-2.572 5.714-5.429 7.143-8.286 7.999-12.571 11.714-21.142 21.714-34C182.571 45.428 232 17.143 285.143 17.143c6 0 12 .285 17.714 1.143C313.714 6.571 328.857 0 344.572 0c14.571 0 29.714 6 40 16.286.857.858 1.428 2.286 1.428 3.428 0 3.714-10.285 13.429-12.857 16.286 4.286 1.429 15.714 6.858 15.714 12 0 2.857-2.857 5.143-4.571 7.143 31.429 27.714 49.429 67.143 56.286 108 4.286-5.143 10.285-8.572 17.143-8.572 10.571 0 20.857 7.144 28.571 14.001C507.143 187.143 512 221.714 512 248.286zM188 89.428c0 18.286 12.571 37.143 32.286 37.143 19.714 0 32.285-18.857 32.285-37.143 0-18-12.571-36.857-32.285-36.857-19.715 0-32.286 18.858-32.286 36.857zM237.714 194c0-19.714 3.714-39.143 8.571-58.286-52.039 79.534-13.531 184.571 68.858 184.571 21.428 0 42.571-7.714 60-20 2-7.429 3.714-14.857 3.714-22.572 0-14.286-6.286-21.428-20.572-21.428-4.571 0-9.143.857-13.429 1.714-63.343 12.668-107.142 3.669-107.142-63.999zm-41.142 254.858c0-11.143-8.858-20.857-20.286-20.857-11.429 0-20 9.715-20 20.857v32.571c0 11.143 8.571 21.142 20 21.142 11.428 0 20.286-9.715 20.286-21.142v-32.571zm49.143 0c0-11.143-8.572-20.857-20-20.857-11.429 0-20.286 9.715-20.286 20.857v32.571c0 11.143 8.857 21.142 20.286 21.142 11.428 0 20-10 20-21.142v-32.571zm49.713 0c0-11.143-8.857-20.857-20.285-20.857-11.429 0-20.286 9.715-20.286 20.857v32.571c0 11.143 8.857 21.142 20.286 21.142 11.428 0 20.285-9.715 20.285-21.142v-32.571zm49.715 0c0-11.143-8.857-20.857-20.286-20.857-11.428 0-20.286 9.715-20.286 20.857v32.571c0 11.143 8.858 21.142 20.286 21.142 11.429 0 20.286-10 20.286-21.142v-32.571zM421.714 286c-30.857 59.142-90.285 102.572-158.571 102.572-96.571 0-160.571-84.572-160.571-176.572 0-16.857 2-33.429 6-49.714-20 33.715-29.714 72.572-29.714 111.429 0 60.286 24.857 121.715 71.429 160.857 5.143-9.714 14.857-16.286 26-16.286 10 0 19.428 5.714 24.571 14.286 5.429-8.571 14.571-14.286 24.858-14.286 10 0 19.428 5.714 24.571 14.286 5.429-8.571 14.857-14.286 24.858-14.286 10 0 19.428 5.714 24.857 14.286 5.143-8.571 14.571-14.286 24.572-14.286 10.857 0 20.857 6.572 25.714 16 43.427-36.286 68.569-92 71.426-148.286zm10.572-99.714c0-53.714-34.571-105.714-92.572-105.714-30.285 0-58.571 15.143-78.857 36.857C240.862 183.812 233.41 254 302.286 254c28.805 0 97.357-28.538 84.286 36.857 28.857-26 45.714-65.714 45.714-104.571z';
1225
1226 ?>
1227 <style>
1228 .tisdk-suggestions_options a {
1229 display: flex !important;
1230 align-items: center;
1231 }
1232
1233 .tisdk-suggestions_options a::before {
1234 content: url("data:image/svg+xml,%3Csvg fill='%23135e96' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='<?php echo esc_attr( $icon ); ?>'/%3E%3C/svg%3E") !important;
1235 min-width: 13px;
1236 max-width: 13px;
1237 }
1238
1239 .tisdk-suggestions_options.active a::before {
1240 content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='<?php echo esc_attr( $icon ); ?>'/%3E%3C/svg%3E") !important;
1241 }
1242
1243 .tisdk-suggestions-header {
1244 padding: 1em 1.5em;
1245 border-bottom: 1px solid #eee;
1246 }
1247
1248 .tisdk-suggestions-header h4 {
1249 font-size: 1.1em;
1250 margin: 0;
1251 }
1252
1253 .tisdk-suggestion {
1254 display: flex;
1255 align-items: center;
1256 flex-direction: row;
1257 padding: 1em 1.5em;
1258 }
1259
1260 .tisdk-suggestion-icon {
1261 height: 40px;
1262 margin: 0;
1263 margin-right: 0px;
1264 margin-right: 1.5em;
1265 flex: 0 0 40px;
1266 background: #966ccf;
1267 display: flex;
1268 justify-content: center;
1269 border-radius: 100%;
1270 align-items: center;
1271 padding: 5px;
1272 }
1273
1274 .tisdk-suggestion-icon svg {
1275 fill: #fff;
1276 }
1277
1278 .tisdk-suggestion-content {
1279 flex: 1 1 60%;
1280 }
1281
1282 .tisdk-suggestion-content h4 {
1283 margin: 0;
1284 }
1285
1286 .tisdk-suggestion-content p {
1287 margin: 0;
1288 margin-top: 4px;
1289 padding: 0;
1290 line-height: 1.5;
1291 }
1292
1293 .tisdk-suggestion-cta {
1294 flex: 1 1 30%;
1295 min-width: 160px;
1296 text-align: right;
1297 }
1298
1299 .tisdk-suggestion-cta .button {
1300 display: inline-block;
1301 min-width: 120px;
1302 text-align: center;
1303 margin: 0;
1304 }
1305
1306 .tisdk-suggestion-cta .suggestion-dismiss {
1307 position: relative;
1308 top: 5px;
1309 right: auto;
1310 margin-left: 1em;
1311 text-decoration: none;
1312 }
1313 </style>
1314 <?php
1315 }
1316
1317 /**
1318 * JS for Dismissing Notice
1319 */
1320 public static function render_notice_dismiss_ajax() {
1321 ?>
1322 <script>
1323 jQuery(document).ready(function ($) {
1324 // AJAX request to update the option value
1325 $('.tisdk-suggestion .suggestion-dismiss').click(function (e) {
1326 e.preventDefault();
1327 var suggestion = $(this).closest('.tisdk-suggestion');
1328 var value = suggestion.attr('id');
1329
1330 var nonce = '<?php echo esc_attr( wp_create_nonce( 'tisdk_update_option' ) ); ?>';
1331
1332 $.ajax({
1333 url: window.ajaxurl,
1334 type: 'POST',
1335 data: {
1336 action: 'tisdk_update_option',
1337 value,
1338 nonce
1339 },
1340 complete() {
1341 suggestion.remove();
1342
1343 // If element with .tisdk-suggestions-content has no children, hide the whole panel. Skip if the selector doesn't exist.
1344 if ($('.tisdk-suggestions-content').length && !$('.tisdk-suggestions-content').children().length) {
1345 $('.tisdk-suggestions_options').remove();
1346 $('#tisdk_suggestions').remove();
1347 $('.general_options').addClass('active');
1348 $('#general_product_data').css('display', 'block');
1349 }
1350 }
1351 });
1352 });
1353 });
1354 </script>
1355 <?php
1356 }
1357
1358 /**
1359 * Update the option value using AJAX
1360 */
1361 public function dismiss_promotion() {
1362 if ( ! isset( $_POST['nonce'] ) || ! isset( $_POST['value'] ) ) {
1363 $response = array(
1364 'success' => false,
1365 'message' => 'Missing nonce or value.',
1366 );
1367 wp_send_json( $response );
1368 wp_die();
1369 }
1370
1371 $nonce = sanitize_text_field( $_POST['nonce'] );
1372 $value = sanitize_text_field( $_POST['value'] );
1373
1374 if ( ! wp_verify_nonce( $nonce, 'tisdk_update_option' ) ) {
1375 $response = array(
1376 'success' => false,
1377 'message' => 'Invalid nonce.',
1378 );
1379 wp_send_json( $response );
1380 wp_die();
1381 }
1382
1383 $options = get_option( $this->option_main );
1384 $options = json_decode( $options, true );
1385
1386 $options[ $value ] = time();
1387
1388 update_option( $this->option_main, wp_json_encode( $options ) );
1389
1390 $response = array(
1391 'success' => true,
1392 );
1393
1394 wp_send_json( $response );
1395 wp_die();
1396 }
1397
1398 /**
1399 * Check if the user has a support page.
1400 */
1401 public function has_support_page() {
1402 $transient_name = 'tisdk_has_support_page';
1403 $has_support = get_transient( $transient_name );
1404
1405 if ( false === $has_support ) {
1406 global $wpdb;
1407
1408 // We use %i escape identifier that was added in WP 6.2.0, hence need to ignore PHPCS warning.
1409 // We only show this notice to users on higher version as that is the minimum for Hyve as well.
1410 $query = $wpdb->get_var( //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1411 $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
1412 'SELECT ID FROM %i WHERE post_type = %s AND post_status = %s AND post_title LIKE %s LIMIT 1', // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.UnsupportedPlaceholder
1413 $wpdb->posts,
1414 'page',
1415 'publish',
1416 '%support%'
1417 )
1418 );
1419
1420 $has_support = $query ? 'yes' : 'no';
1421
1422 set_transient( $transient_name, $has_support, 7 * DAY_IN_SECONDS );
1423 }
1424
1425 return 'yes' === $has_support;
1426 }
1427
1428 /**
1429 * Check if the user has a donate page.
1430 */
1431 public function has_donate_page() {
1432 $transient_name = 'tisdk_has_donate_page';
1433 $has_donate = get_transient( $transient_name );
1434
1435 if ( false === $has_donate ) {
1436 global $wpdb;
1437
1438 $query = $wpdb->get_var( //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1439 $wpdb->prepare(
1440 'SELECT ID FROM ' . $wpdb->posts . ' WHERE post_type = %s AND post_status = %s AND post_title LIKE %s LIMIT 1',
1441 'page',
1442 'publish',
1443 '%donate%'
1444 )
1445 );
1446
1447 $has_donate = $query ? 'yes' : 'no';
1448
1449 set_transient( $transient_name, $has_donate, 7 * DAY_IN_SECONDS );
1450 }
1451
1452 return 'yes' === $has_donate;
1453 }
1454
1455 /**
1456 * Check if the tagline contains LMS related keywords.
1457 *
1458 * @return bool True if the tagline contains LMS-related keywords, false otherwise.
1459 */
1460 public function has_lms_tagline() {
1461 $tagline = strtolower( get_bloginfo( 'description' ) );
1462 $lms_keywords = array( 'learning', 'courses' );
1463
1464 foreach ( $lms_keywords as $keyword ) {
1465 if ( strpos( $tagline, $keyword ) !== false ) {
1466 return true;
1467 }
1468 }
1469
1470 return false;
1471 }
1472 }
1473