PluginProbe ʕ •ᴥ•ʔ
Starter Sites & Templates by Neve / 1.4.1
Starter Sites & Templates by Neve v1.4.1
1.4.1 1.4.0 1.3.0 1.2.29 1.2.28 1.2.6 1.2.7 1.2.8 1.2.9 trunk 1.0.10 1.0.11 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 1.1.20 1.1.21 1.1.22 1.1.23 1.1.24 1.1.25 1.1.26 1.1.27 1.1.28 1.1.29 1.1.3 1.1.30 1.1.31 1.1.32 1.1.33 1.1.34 1.1.35 1.1.36 1.1.37 1.1.38 1.1.39 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.3 1.2.4 1.2.5
templates-patterns-collection / vendor / codeinwp / themeisle-sdk / src / Modules / Announcements.php
templates-patterns-collection / vendor / codeinwp / themeisle-sdk / src / Modules Last commit date
About_us.php 3 weeks ago Abstract_Migration.php 2 months ago Announcements.php 2 months ago Compatibilities.php 2 years ago Dashboard_widget.php 3 weeks ago Featured_plugins.php 1 month ago Float_widget.php 1 year ago Licenser.php 2 months ago Logger.php 10 months ago Migrator.php 2 months ago Notification.php 3 years ago Promotions.php 3 weeks ago Recommendation.php 3 years ago Review.php 1 year ago Rollback.php 1 year ago Script_loader.php 1 year ago Translate.php 5 years ago Translations.php 1 year ago Uninstall_feedback.php 3 days ago Welcome.php 2 years ago
Announcements.php
547 lines
1 <?php
2 /**
3 * File responsible for announcements.
4 *
5 * This is used to display information about limited events, such as Black Friday.
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 3.3.0
12 */
13
14 namespace ThemeisleSDK\Modules;
15
16 use DateTime;
17 use ThemeisleSDK\Common\Abstract_Module;
18 use ThemeisleSDK\Loader;
19 use ThemeisleSDK\Product;
20
21 /**
22 * Announcement module for the ThemeIsle SDK.
23 */
24 class Announcements extends Abstract_Module {
25
26 const SALE_DURATION_BLACK_FRIDAY = '+7 days'; // DateTime modifier. (Include Cyber Monday)
27 const MINIMUM_INSTALL_AGE = 3 * DAY_IN_SECONDS;
28
29 /**
30 * Mark if the notice was already loaded.
31 *
32 * @var boolean
33 */
34 private static $notice_loaded = false;
35
36 /**
37 * Mark if the plugin meta link was already loaded.
38 *
39 * @var boolean
40 */
41 private static $meta_link_loaded = false;
42
43 /**
44 * The product to be used.
45 *
46 * @var string
47 */
48 private static $current_product = '';
49
50 /**
51 * Check if the module can be loaded.
52 *
53 * @param Product $product Product data.
54 *
55 * @return bool
56 */
57 public function can_load( $product ) {
58 if ( $this->is_from_partner( $product ) ) {
59 return false;
60 }
61
62 return true;
63 }
64
65 /**
66 * Load the module for the selected product.
67 *
68 * @param Product $product Product data.
69 *
70 * @return void
71 */
72 public function load( $product ) {
73 $this->product = $product;
74
75 add_filter(
76 'themeisle_sdk_is_black_friday_sale',
77 function( $is_black_friday ) {
78 return $this->is_black_friday_sale( $this->get_current_date() );
79 }
80 );
81
82 add_action( 'admin_menu', array( $this, 'load_announcements' ), 9 );
83 add_action( 'wp_ajax_themeisle_sdk_dismiss_black_friday_notice', array( $this, 'disable_notification_ajax' ) );
84 }
85
86 /**
87 * Load all valid announcements.
88 *
89 * @return void
90 */
91 public function load_announcements() {
92 $current_date = $this->get_current_date();
93 if ( ! $this->is_black_friday_sale( $current_date ) ) {
94 return;
95 }
96
97 if ( self::MINIMUM_INSTALL_AGE > ( $current_date->getTimestamp() - $this->product->get_install_time() ) ) {
98 return;
99 }
100
101 add_action( 'admin_notices', array( $this, 'black_friday_notice_render' ) );
102
103 add_action(
104 'themeisle_internal_page',
105 function( $plugin, $page_slug ) {
106 self::$current_product = $plugin;
107 },
108 10,
109 2
110 );
111
112 add_filter( 'plugin_row_meta', array( $this, 'add_plugin_meta_links' ), 10, 2 );
113 add_filter( $this->product->get_key() . '_about_us_metadata', array( $this, 'override_about_us_metadata' ), 100 );
114 }
115
116 /**
117 * Get the remaining time for the event in a human-readable format.
118 *
119 * @param DateTime $end_date The end date for event.
120 *
121 * @return string Remaining time for the event.
122 */
123 public function get_remaining_time_for_event( $end_date ) {
124 return human_time_diff( $this->get_current_date()->getTimestamp(), $end_date->getTimestamp() );
125 }
126
127 /**
128 * Check if the announcement can be shown.
129 *
130 * @param DateTime $current_date The announcement to check.
131 * @param int $user_id The user id to show the notice.
132 *
133 * @return bool
134 */
135 public function can_show_notice( $current_date, $user_id ) {
136 $current_year = $current_date->format( 'Y' );
137 $user_notice_dismiss_timestamp = get_user_meta( $user_id, 'themeisle_sdk_dismissed_notice_black_friday', true );
138
139 if ( empty( $user_notice_dismiss_timestamp ) ) {
140 return true;
141 }
142
143 $dismissed_year = wp_date( 'Y', $user_notice_dismiss_timestamp );
144
145 return $current_year !== $dismissed_year;
146 }
147
148 /**
149 * Calculate the start date for Black Friday based on the year of the given date.
150 *
151 * Black Friday is the day after the Thanksgiving and the sale starts on the Monday of that week.
152 *
153 * @param DateTime $date The current date object, used to determine the year.
154 * @return DateTime The start date of Black Friday for the given year.
155 */
156 public function get_start_date( $date ) {
157 $year = $date->format( 'Y' );
158 $black_friday = new DateTime( "last friday of november {$year}" );
159
160 $sale_start = clone $black_friday;
161 $sale_start->modify( 'monday this week' );
162 $sale_start->setTime( 0, 0 );
163
164 return $sale_start;
165 }
166
167 /**
168 * Calculate the event end date.
169 *
170 * @param DateTime $start_date The start date.
171 * @return DateTime The end date.
172 */
173 public function get_end_date( $start_date ) {
174 $black_friday_end = clone $start_date;
175 $black_friday_end->modify( self::SALE_DURATION_BLACK_FRIDAY );
176 $black_friday_end->setTime( 23, 59, 59 );
177 return $black_friday_end;
178 }
179
180 /**
181 * Check if the current date falls within the Black Friday sale period.
182 *
183 * @param DateTime $current_date The date to check.
184 * @return bool True if the date is within the Black Friday sale period, false otherwise.
185 */
186 public function is_black_friday_sale( $current_date ) {
187 $black_friday_start_date = $this->get_start_date( $current_date );
188 $black_friday_end = $this->get_end_date( $black_friday_start_date );
189 return $black_friday_start_date <= $current_date && $current_date <= $black_friday_end;
190 }
191
192 /**
193 * Get the notice data.
194 *
195 * @return array The notice data.
196 */
197 public function get_notice_data() {
198 $time_left_label = $this->get_remaining_time_for_event( $this->get_end_date( $this->get_start_date( $this->get_current_date() ) ) );
199 $time_left_label = sprintf( Loader::$labels['announcements']['time_left'], $time_left_label );
200
201 $utm_location = 'globalnotice';
202 if ( ! empty( $this->product ) ) {
203 $utm_location = $this->product->get_friendly_name();
204 }
205
206 $sale_title = Loader::$labels['announcements']['black_friday'];
207 $sale_url = tsdk_translate_link( tsdk_utmify( 'https://themeisle.com/blackfriday/', 'bfcm26', $utm_location ) );
208
209 $current_year = $this->get_current_date()->format( 'Y' );
210 $sale_message = sprintf( Loader::$labels['announcements']['max_savings'], $current_year );
211
212 return array(
213 'title' => $sale_title,
214 'sale_url' => $sale_url,
215 'message' => $sale_message,
216 'time_left' => $time_left_label,
217 );
218 }
219
220 /**
221 * Render the Black Friday notice.
222 *
223 * @return void
224 */
225 public function black_friday_notice_render() {
226
227 // Prevent the notice from being rendered twice.
228 if ( self::$notice_loaded ) {
229 return;
230 }
231 self::$notice_loaded = true;
232
233 $current_user_id = get_current_user_id();
234
235 if ( ! $this->can_show_notice( $this->get_current_date(), $current_user_id ) ) {
236 return;
237 }
238
239 $all_configs = apply_filters( 'themeisle_sdk_blackfriday_data', array( 'default' => $this->get_notice_data() ) );
240
241 if ( empty( $all_configs ) || ! is_array( $all_configs ) ) {
242 return;
243 }
244
245 $data = isset( $all_configs['default'] ) ? $all_configs['default'] : $this->get_notice_data();
246 $products = Loader::get_products();
247 $current_time = $this->get_current_date()->getTimestamp();
248 $can_show = false;
249
250 // Check if we have products that are eligible to show the notice with the default data. If the product provide its own config, use it.
251 foreach ( $products as $product ) {
252 $slug = $product->get_slug();
253
254 if ( self::MINIMUM_INSTALL_AGE < ( $current_time - $product->get_install_time() ) ) {
255 $can_show = true;
256
257 if ( isset( $all_configs[ $slug ] ) && ! empty( $all_configs[ $slug ] ) && is_array( $all_configs[ $slug ] ) ) {
258 $data = $all_configs[ $slug ];
259
260 if ( self::$current_product === $slug ) {
261 $data = $all_configs[ $slug ];
262 break;
263 }
264 }
265 }
266 }
267
268 if ( ! $can_show ) {
269 return;
270 }
271
272 $displayed_on_internal_page = 0 < did_action( 'themeisle_internal_page' );
273
274 $title = ! empty( $data['title'] ) ? $data['title'] : Loader::$labels['announcements']['black_friday'];
275 $time_left_label = ! empty( $data['time_left'] ) ? $data['time_left'] : '';
276 $message = ! empty( $data['message'] ) ? $data['message'] : '';
277 $logo_url = ! empty( $data['logo_url'] ) ? $data['logo_url'] : $this->get_sdk_uri() . 'assets/images/themeisle-logo.png';
278 $cta_label = ! empty( $data['cta_label'] ) ? $data['cta_label'] : Loader::$labels['announcements']['notice_link_label'];
279 $sale_url = ! empty( $data['sale_url'] ) ? $data['sale_url'] : '';
280 $hide_other_notices = ! empty( $data['hide_other_notices'] ) ? $data['hide_other_notices'] : $displayed_on_internal_page;
281 $dismiss_notice_url = wp_nonce_url(
282 add_query_arg(
283 array( 'action' => 'themeisle_sdk_dismiss_black_friday_notice' ),
284 admin_url( 'admin-ajax.php' )
285 ),
286 'dismiss_themeisle_event_notice'
287 );
288
289 if ( empty( $sale_url ) ) {
290 return;
291 }
292
293 if ( ! current_user_can( 'install_plugins' ) ) {
294 $sale_url = remove_query_arg( 'lkey', $sale_url );
295 }
296
297 ?>
298 <style>
299 .themeisle-sale {
300 border-left-color: #0466CB;
301 }
302 .themeisle-sale :is(.themeisle-sale-title, p) {
303 margin: 0;
304 }
305 .themeisle-sale-container {
306 display: flex;
307 align-items: center;
308 padding: 0.5rem 0;
309 gap: 0.5rem;
310 padding-right: 10px;
311 }
312 .themeisle-sale-content {
313 display: flex;
314 flex-direction: column;
315 gap: 0.2rem;
316 }
317 .themeisle-sale a {
318 text-decoration: none;
319 }
320 .themeisle-sale p a {
321 margin-left: 1rem;
322 padding: 7px 12px;
323 border-radius: 4px;
324 background: #0466CB;
325 color: white;
326 font-weight: 700;
327 }
328 .themeisle-sale-dismiss {
329 padding-top: 5px;
330 }
331 .themeisle-sale-dismiss span {
332 color: #787c82;
333 font-size: 16px;
334 }
335 .notice.themeisle-sale {
336 padding: 0;
337 }
338 .themeisle-sale-logo {
339 display: flex;
340 justify-content: center;
341 align-items: center;
342 margin-left: 5px;
343 }
344 .themeisle-sale-time-left {
345 margin-left: 5px;
346 padding: 3px 5px;
347 border-radius: 4px;
348 background-color: #dfdfdf;
349 font-weight: 600;
350 font-size: x-small;
351 line-height: 1;
352 }
353 .themeisle-sale-title {
354 font-size: 14px;
355 display: flex;
356 align-items: center;
357 }
358 .themeisle-sale-action {
359 flex-grow: 1;
360 display: flex;
361 justify-content: flex-end;
362 }
363 <?php if ( $hide_other_notices ) : ?>
364 .notice:not(.themeisle-sale) {
365 display: none;
366 }
367 <?php endif; ?>
368 </style>
369 <div class="themeisle-sale notice notice-info" data-event-slug="black_friday">
370 <div class="themeisle-sale-container">
371 <div class="themeisle-sale-logo">
372 <img
373 width="45"
374 src="<?php echo esc_url( $logo_url ); ?>"
375 />
376 </div>
377 <div class="themeisle-sale-content">
378 <h4 class="themeisle-sale-title">
379 <?php echo esc_html( $title ); ?>
380 <span class="themeisle-sale-time-left">
381 <?php echo esc_html( $time_left_label ); ?>
382 </span>
383 </h4>
384 <p>
385 <?php echo wp_kses_post( $message ); ?>
386 </p>
387 </div>
388 <div class="themeisle-sale-action">
389 <a
390 href="<?php echo esc_url( $sale_url ); ?>"
391 target="_blank"
392 class="button button-primary themeisle-sale-button"
393 >
394 <?php echo esc_html( $cta_label ); ?>
395 </a>
396 </div>
397 <a href="<?php echo esc_url( $dismiss_notice_url ); ?>" class="themeisle-sale-dismiss">
398 <span class="dashicons dashicons-dismiss"></span>
399 </a>
400 </div>
401 </div>
402 <script>
403 // Note: Some plugins use React and the content is ready after the `DOMContentLoaded` event. Use this function to reposition the notice after components have rendered.
404 window.tsdk_reposition_notice = function() {
405 const bannerRoot = document.getElementById('tsdk_banner');
406 const saleNotice = document.querySelector('.themeisle-sale');
407 if ( ! bannerRoot || ! saleNotice ) {
408 return;
409 }
410
411 bannerRoot.appendChild(saleNotice);
412 };
413
414 document.addEventListener( 'DOMContentLoaded', function() {
415 window.tsdk_reposition_notice();
416 } );
417 </script>
418 <?php
419 }
420
421 /**
422 * Disable the notification via ajax.
423 *
424 * @return void
425 */
426 public function disable_notification_ajax() {
427 check_ajax_referer( 'dismiss_themeisle_event_notice' );
428
429 update_user_meta( get_current_user_id(), 'themeisle_sdk_dismissed_notice_black_friday', $this->get_current_date()->getTimestamp() );
430
431 $return_page_url = wp_get_referer();
432 if ( empty( $return_page_url ) ) {
433 $return_page_url = admin_url();
434 }
435
436 wp_safe_redirect( $return_page_url );
437 exit;
438 }
439
440 /**
441 * Add the plugin meta links.
442 *
443 * @param array<string, string> $links The plugin meta links.
444 * @param string $plugin_file The plugin file.
445 * @return array<string, string> The plugin meta links.
446 */
447 public function add_plugin_meta_links( $links, $plugin_file ) {
448 if ( self::$meta_link_loaded ) {
449 return $links;
450 }
451
452 if ( $plugin_file !== plugin_basename( $this->product->get_basefile() ) ) {
453 return $links;
454 }
455
456 $configs = apply_filters( 'themeisle_sdk_blackfriday_data', array( 'default' => $this->get_notice_data() ) );
457
458 if ( empty( $configs ) || ! is_array( $configs ) ) {
459 return $links;
460 }
461
462 $current_slug = $this->product->get_slug();
463 $data = isset( $configs[ $current_slug ] ) && ! empty( $configs[ $current_slug ] ) && is_array( $configs[ $current_slug ] ) ? $configs[ $current_slug ] : array();
464
465 $plugin_meta_message = '';
466 $plugin_meta_url = '';
467
468 if ( isset( $data['plugin_meta_targets'] ) && ! empty( $data['plugin_meta_targets'] ) && ! in_array( $current_slug, $data['plugin_meta_targets'] ) ) {
469 return $links; // The current configuration is for another plugins.
470 }
471
472 $plugin_meta_message = ! empty( $data['plugin_meta_message'] ) ? $data['plugin_meta_message'] : '';
473 $plugin_meta_url = ! empty( $data['sale_url'] ) ? $data['sale_url'] : '';
474
475 if ( empty( $plugin_meta_url ) || empty( $plugin_meta_message ) ) {
476
477 // Check if a configuration is in another plugin.
478 $products = Loader::get_products();
479 foreach ( $products as $product ) {
480 $slug = $product->get_slug();
481
482 if ( $slug === $current_slug || ! isset( $configs[ $slug ] ) || empty( $configs[ $slug ] ) || ! is_array( $configs[ $slug ] ) ) {
483 continue;
484 }
485
486 if ( ! empty( $configs[ $slug ]['plugin_meta_targets'] ) && in_array( $current_slug, $configs[ $slug ]['plugin_meta_targets'] ) ) {
487 $plugin_meta_message = ! empty( $configs[ $slug ]['plugin_meta_message'] ) ? $configs[ $slug ]['plugin_meta_message'] : '';
488 $plugin_meta_url = ! empty( $configs[ $slug ]['sale_url'] ) ? $configs[ $slug ]['sale_url'] : '';
489 break;
490 }
491 }
492 }
493
494 if ( empty( $plugin_meta_url ) || empty( $plugin_meta_message ) ) {
495 return $links;
496 }
497
498 $links[] = sprintf( '<a class="themeisle-sale-plugin-meta-link" style="color: red;" href="%s" target="_blank">%s</a>', esc_url( $plugin_meta_url ), esc_html( $plugin_meta_message ) );
499
500 self::$meta_link_loaded = true;
501
502 return $links;
503 }
504
505 /**
506 * Override the About Us upgrade menu during Black Friday.
507 *
508 * Registered dynamically during admin_menu when sale is active.
509 * Only applies if About_Us module is loaded for the product.
510 *
511 * @param array<string, mixed> $about_data About Us metadata.
512 *
513 * @return array<string, mixed>
514 */
515 public function override_about_us_metadata( $about_data ) {
516 if ( ! $this->is_black_friday_sale( $this->get_current_date() ) ) {
517 return $about_data;
518 }
519
520 if ( empty( $about_data ) || ! is_array( $about_data ) ) {
521 return $about_data;
522 }
523
524 if ( empty( $about_data['has_upgrade_menu'] ) || true !== $about_data['has_upgrade_menu'] ) {
525 return $about_data;
526 }
527
528 $configs = apply_filters( 'themeisle_sdk_blackfriday_data', array( 'default' => $this->get_notice_data() ) );
529
530 $current_slug = $this->product->get_slug();
531 if ( ! isset( $configs[ $current_slug ] ) || empty( $configs[ $current_slug ] ) || ! is_array( $configs[ $current_slug ] ) ) {
532 return $about_data;
533 }
534
535 $config = $configs[ $current_slug ];
536
537 if ( empty( $config['upgrade_menu_text'] ) || empty( $config['sale_url'] ) ) {
538 return $about_data;
539 }
540
541 $about_data['upgrade_text'] = $config['upgrade_menu_text'];
542 $about_data['upgrade_link'] = $config['sale_url'];
543
544 return $about_data;
545 }
546 }
547