PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 3.6.0
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v3.6.0
3.6.0 3.5.3 3.5.2 3.5.1 3.5.0 3.4.8 3.4.7 3.4.6 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5.1 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.10 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.6.1 1.6.7 1.7.0 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.2 1.7.2.1 1.7.2.2 1.7.3 1.7.4 1.7.5 1.7.5.1 1.7.5.2 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.8.0 1.8.0.1 1.8.1 1.8.2 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.0.1 1.9.1 1.9.2 1.9.3 1.9.4 1.9.4.1 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.0.1 2.0.1 2.0.2 2.0.3 2.0.3.1 2.0.4 2.0.4.1 2.0.5 2.0.6 2.0.7 2.0.8 2.0.8.1 2.0.9 3.0.0 3.0.0.1 3.0.1 3.0.2 3.0.3 3.0.3.1 3.0.4 3.0.4.1 3.0.4.2 3.0.5 3.0.5.1 3.0.5.2 3.0.6 3.0.6.1 3.0.7.1 3.0.8 3.0.8.1 3.0.9 3.0.9.1 3.0.9.2 3.0.9.3 3.0.9.4 3.0.9.5 3.1.0 3.1.1 3.1.2 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.3.0 3.4.0 3.4.1 3.4.2 3.4.2.1 3.4.3 3.4.4 3.4.5 trunk 1.0 1.0.1 1.0.2 1.0.3
everest-forms / vendor / themegrill / themegrill-sdk / src / Modules / Announcements.php
everest-forms / vendor / themegrill / themegrill-sdk / src / Modules Last commit date
Announcements.php 6 months ago Licenser.php 2 months ago Logger.php 6 months ago Notification.php 6 months ago Rollback.php 6 months ago ScriptLoader.php 6 months ago UninstallFeedback.php 6 months ago Updater.php 2 months ago
Announcements.php
417 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 ThemeGrillSDK
8 * @subpackage Modules
9 * @copyright Copyright (c) 2025, ThemeGrill
10 * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
11 * @since 1.0.0
12 */
13
14 namespace ThemeGrillSDK\Modules;
15
16 use DateTime;
17 use ThemeGrillSDK\Common\AbstractModule;
18 use ThemeGrillSDK\Loader;
19 use ThemeGrillSDK\Product;
20
21 /**
22 * Announcement module for the ThemeGrill SDK.
23 */
24 class Announcements extends AbstractModule {
25
26 const SALE_DURATION_BLACK_FRIDAY = '+7 days'; // DateTime modifier. (Include Cyber Monday)
27
28 /**
29 * Mark if the notice was already loaded.
30 *
31 * @var boolean
32 */
33 private static $notice_loaded = false;
34
35 /**
36 * The product to be used.
37 *
38 * @var string
39 */
40 private static $current_product = '';
41
42 /**
43 * Check if the module can be loaded.
44 *
45 * @param Product $product Product data.
46 *
47 * @return bool
48 */
49 public function can_load( $product ) {
50 if ( $this->is_from_partner( $product ) ) {
51 return false;
52 }
53
54 return true;
55 }
56
57 /**
58 * Load the module for the selected product.
59 *
60 * @param Product $product Product data.
61 *
62 * @return void
63 */
64 public function load( $product ) {
65 $this->product = $product;
66
67 add_filter(
68 'themegrill_sdk_is_black_friday_sale',
69 function ( $is_black_friday ) {
70 return $this->is_black_friday_sale( $this->get_current_date() );
71 }
72 );
73
74 add_action( 'admin_init', array( $this, 'load_announcements' ) );
75 }
76
77 /**
78 * Load all valid announcements.
79 *
80 * @return void
81 */
82 public function load_announcements() {
83 if ( ! $this->is_black_friday_sale( $this->get_current_date() ) ) {
84 return;
85 }
86
87 add_action( 'admin_notices', array( $this, 'black_friday_notice_render' ) );
88 add_action( 'wp_ajax_themegrill_sdk_dismiss_black_friday_notice', array( $this, 'disable_notification_ajax' ) );
89 add_action(
90 'themegrill_internal_page',
91 function ( $plugin, $page_slug ) {
92 self::$current_product = $plugin;
93 },
94 10,
95 2
96 );
97 }
98
99
100
101 /**
102 * Get the remaining time for the event in a human-readable format.
103 *
104 * @param DateTime $end_date The end date for event.
105 *
106 * @return string Remaining time for the event.
107 */
108 public function get_remaining_time_for_event( $end_date ) {
109 return human_time_diff( $this->get_current_date()->getTimestamp(), $end_date->getTimestamp() );
110 }
111
112 /**
113 * Check if the announcement can be shown.
114 *
115 * @param DateTime $current_date The announcement to check.
116 * @param int $user_id The user id to show the notice.
117 *
118 * @return bool
119 */
120 public function can_show_notice( $current_date, $user_id ) {
121 $current_year = $current_date->format( 'Y' );
122 $user_notice_dismiss_timestamp = get_user_meta( $user_id, 'themegrill_sdk_dismissed_notice_black_friday', true );
123
124 if ( empty( $user_notice_dismiss_timestamp ) ) {
125 return true;
126 }
127
128 $dismissed_year = wp_date( 'Y', $user_notice_dismiss_timestamp );
129
130 return $current_year !== $dismissed_year;
131 }
132
133 /**
134 * Calculate the start date for Black Friday based on the year of the given date.
135 *
136 * Black Friday is the day after the Thanksgiving and the sale starts on the Monday of that week.
137 *
138 * @param DateTime $date The current date object, used to determine the year.
139 * @return DateTime The start date of Black Friday for the given year.
140 */
141 public function get_start_date( $date ) {
142 $year = $date->format( 'Y' );
143 $black_friday = new DateTime( "last friday of november {$year}" );
144
145 $sale_start = clone $black_friday;
146 $sale_start->modify( 'monday this week' );
147 $sale_start->setTime( 0, 0 );
148
149 return $sale_start;
150 }
151
152 /**
153 * Calculate the event end date.
154 *
155 * @param DateTime $start_date The start date.
156 * @return DateTime The end date.
157 */
158 public function get_end_date( $start_date ) {
159 $black_friday_end = clone $start_date;
160 $black_friday_end->modify( self::SALE_DURATION_BLACK_FRIDAY );
161 $black_friday_end->setTime( 23, 59, 59 );
162 return $black_friday_end;
163 }
164
165 /**
166 * Check if the current date falls within the Black Friday sale period.
167 *
168 * @param DateTime $current_date The date to check.
169 * @return bool True if the date is within the Black Friday sale period, false otherwise.
170 */
171 public function is_black_friday_sale( $current_date ) {
172 $black_friday_start_date = $this->get_start_date( $current_date );
173 $black_friday_end = $this->get_end_date( $black_friday_start_date );
174 return $black_friday_start_date <= $current_date && $current_date <= $black_friday_end;
175 }
176
177 /**
178 * Get the notice data.
179 *
180 * @return array The notice data.
181 */
182 public function get_notice_data() {
183 $time_left_label = $this->get_remaining_time_for_event( $this->get_end_date( $this->get_start_date( $this->get_current_date() ) ) );
184 $time_left_label = sprintf( Loader::$labels['announcements']['time_left'], $time_left_label );
185
186 $utm_location = 'globalnotice';
187 if ( ! empty( $this->product ) ) {
188 $utm_location = $this->product->get_friendly_name();
189 }
190
191 $sale_title = Loader::$labels['announcements']['black_friday'];
192 $sale_url = apply_filters( 'themegrill_sdk_announcements_sale_url', '' );
193 $sale_url = tgsdk_utmify(
194 apply_filters( 'themegrill_sdk_black_friday_url', 'https://themegrill.com/blackfriday/' ),
195 apply_filters( 'themegrill_sdk_black_friday_campaign_name', 'bfcm25' ),
196 $utm_location
197 );
198
199 $sale_message = sprintf( Loader::$labels['announcements']['max_savings'], '50%' );
200
201 return array(
202 'title' => $sale_title,
203 'sale_url' => $sale_url,
204 'message' => $sale_message,
205 'time_left' => $time_left_label,
206 );
207 }
208
209 /**
210 * Render the Black Friday notice.
211 *
212 * @return void
213 */
214 public function black_friday_notice_render() {
215
216 // Prevent the notice from being rendered twice.
217 if ( self::$notice_loaded ) {
218 return;
219 }
220 self::$notice_loaded = true;
221
222 $all_configs = apply_filters( 'themegrill_sdk_blackfriday_data', array( 'default' => $this->get_notice_data() ) );
223
224 if ( empty( $all_configs ) ) {
225 return;
226 }
227
228 $data = end( $all_configs );
229
230 if ( ! empty( self::$current_product ) && isset( $all_configs[ self::$current_product ] ) ) {
231 $data = $all_configs[ self::$current_product ];
232 }
233
234 if ( empty( $data ) || ! is_array( $data ) ) {
235 return;
236 }
237
238 $current_user_id = get_current_user_id();
239 $can_dismiss = true;
240
241 if ( ! empty( $data['dismiss'] ) ) {
242 $can_dismiss = $data['dismiss'];
243 } else {
244 // Disable by default if we are on a product page.
245 if ( 0 < did_action( 'themegrill_internal_page' ) ) {
246 $can_dismiss = false;
247 }
248 }
249
250 if ( $can_dismiss && ! $this->can_show_notice( $this->get_current_date(), $current_user_id ) ) {
251 return;
252 }
253
254 $sale_url = ! empty( $data['sale_url'] ) ? $data['sale_url'] : '';
255 $hide_other_notices = ! empty( $data['hide_other_notices'] ) ? $data['hide_other_notices'] : ! $can_dismiss;
256 $dismiss_notice_url = wp_nonce_url(
257 add_query_arg(
258 array( 'action' => 'themegrill_sdk_dismiss_black_friday_notice' ),
259 admin_url( 'admin-ajax.php' )
260 ),
261 'dismiss_themegrill_event_notice'
262 );
263
264 if ( empty( $sale_url ) ) {
265 return;
266 }
267
268 if ( ! current_user_can( 'install_plugins' ) ) {
269 $sale_url = remove_query_arg( 'lkey', $sale_url );
270 }
271
272 ?>
273 <style>
274 .themegrill-sale {
275 border-left-color: #0466CB;
276 }
277 .themegrill-sale :is(.themegrill-sale-title, p) {
278 margin: 0;
279 }
280 .themegrill-sale-container {
281 display: flex;
282 align-items: center;
283 padding: 0.5rem 0;
284 gap: 0.5rem;
285 padding-right: 10px;
286 }
287 .themegrill-sale-content {
288 display: flex;
289 flex-direction: column;
290 gap: 0.2rem;
291 }
292 .themegrill-sale a {
293 text-decoration: none;
294 }
295 .themegrill-sale p a {
296 margin-left: 1rem;
297 padding: 7px 12px;
298 border-radius: 4px;
299 background: #0466CB;
300 color: white;
301 font-weight: 700;
302 }
303 .themegrill-sale-dismiss {
304 padding-top: 5px;
305 }
306 .themegrill-sale-dismiss span {
307 color: #787c82;
308 font-size: 16px;
309 }
310 .notice.themegrill-sale {
311 padding: 0;
312 }
313 .themegrill-sale-logo {
314 display: flex;
315 justify-content: center;
316 align-items: center;
317 margin-left: 5px;
318 }
319 .themegrill-sale-time-left {
320 margin-left: 5px;
321 padding: 3px 5px;
322 border-radius: 4px;
323 background-color: #dfdfdf;
324 font-weight: 600;
325 font-size: x-small;
326 line-height: 1;
327 }
328 .themegrill-sale-title {
329 font-size: 14px;
330 display: flex;
331 align-items: center;
332 }
333 .themegrill-sale-action {
334 flex-grow: 1;
335 display: flex;
336 justify-content: flex-end;
337 }
338 <?php if ( $hide_other_notices ) : ?>
339 .notice:not(.themegrill-sale) {
340 display: none;
341 }
342 <?php endif; ?>
343 </style>
344 <div class="themegrill-sale notice notice-info" data-event-slug="black_friday">
345 <div class="themegrill-sale-container">
346 <div class="themegrill-sale-logo">
347 <img
348 width="45"
349 src="<?php echo esc_url( $this->get_sdk_uri() . 'assets/images/themegrill-logo.png' ); ?>"
350 />
351 </div>
352 <div class="themegrill-sale-content">
353 <h4 class="themegrill-sale-title">
354 <?php echo esc_html( $data['title'] ); ?>
355 <span class="themegrill-sale-time-left">
356 <?php echo esc_html( $data['time_left'] ); ?>
357 </span>
358 </h4>
359 <p>
360 <?php echo wp_kses_post( $data['message'] ); ?>
361 </p>
362 </div>
363 <div class="themegrill-sale-action">
364 <a
365 href="<?php echo esc_url( $sale_url ); ?>"
366 target="_blank"
367 class="button button-primary themegrill-sale-button"
368 >
369 <?php echo esc_html( Loader::$labels['announcements']['notice_link_label'] ); ?>
370 </a>
371 </div>
372 <?php if ( $can_dismiss ) : ?>
373 <a href="<?php echo esc_url( $dismiss_notice_url ); ?>" class="themegrill-sale-dismiss">
374 <span class="dashicons dashicons-dismiss"></span>
375 </a>
376 <?php endif; ?>
377 </div>
378 </div>
379 <script>
380 // 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.
381 window.tgsdk_reposition_notice = function() {
382 const bannerRoot = document.getElementById('tgsdk_banner');
383 const saleNotice = document.querySelector('.themegrill-sale');
384 if ( ! bannerRoot || ! saleNotice ) {
385 return;
386 }
387
388 bannerRoot.appendChild(saleNotice);
389 };
390
391 document.addEventListener( 'DOMContentLoaded', function() {
392 window.tgsdk_reposition_notice();
393 } );
394 </script>
395 <?php
396 }
397
398 /**
399 * Disable the notification via ajax.
400 *
401 * @return void
402 */
403 public function disable_notification_ajax() {
404 check_ajax_referer( 'dismiss_themegrill_event_notice' );
405
406 update_user_meta( get_current_user_id(), 'themegrill_sdk_dismissed_notice_black_friday', $this->get_current_date()->getTimestamp() );
407
408 $return_page_url = wp_get_referer();
409 if ( empty( $return_page_url ) ) {
410 $return_page_url = admin_url();
411 }
412
413 wp_safe_redirect( $return_page_url );
414 exit;
415 }
416 }
417