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

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

362 lines 10.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 ThemeisleSDK\Common\Abstract_Module;
17 use ThemeisleSDK\Loader;
18 use ThemeisleSDK\Product;
19
20 /**
21 * Announcement module for the ThemeIsle SDK.
22 */
23 class Announcements extends Abstract_Module {
24
25 /**
26 * Holds the timeline for the announcements.
27 *
28 * @var array
29 */
30 private static $timeline = array(
31 'black_friday' => array(
32 'start' => '2024-11-25 00:00:00',
33 'end' => '2024-12-03 23:59:59',
34 'rendered' => false,
35 ),
36 );
37
38 /**
39 * Holds the option prefix for the announcements.
40 *
41 * This is used to store the dismiss date for each announcement.
42 *
43 * @var string
44 */
45 public $option_prefix = 'themeisle_sdk_announcement_';
46
47 /**
48 * Holds the time for the current request.
49 *
50 * @var string
51 */
52 public $time = '';
53
54 /**
55 * Check if the module can be loaded.
56 *
57 * @param Product $product Product data.
58 *
59 * @return bool
60 */
61 public function can_load( $product ) {
62 if ( $this->is_from_partner( $product ) ) {
63 return false;
64 }
65
66 return true;
67 }
68
69 /**
70 * Load the module for the selected product.
71 *
72 * @param Product $product Product data.
73 *
74 * @return void
75 */
76 public function load( $product ) {
77 if ( ! current_user_can( 'install_plugins' ) ) {
78 return;
79 }
80
81 $this->product = $product;
82
83 add_action( 'admin_init', array( $this, 'load_announcements' ) );
84 add_filter( 'themeisle_sdk_active_announcements', array( $this, 'get_active_announcements' ) );
85 add_filter( 'themeisle_sdk_announcements', array( $this, 'get_announcements_for_plugins' ) );
86 }
87
88 /**
89 * Load all valid announcements.
90 *
91 * @return void
92 */
93 public function load_announcements() {
94 $active = $this->get_active_announcements();
95
96 if ( empty( $active ) ) {
97 return;
98 }
99
100 foreach ( $active as $announcement ) {
101
102 $method = $announcement . '_notice_render';
103
104 if ( method_exists( $this, $method ) ) {
105 add_action( 'admin_notices', array( $this, $method ) );
106 }
107 }
108
109 // Load the ajax handler.
110 add_action( 'wp_ajax_themeisle_sdk_dismiss_announcement', array( $this, 'disable_notification_ajax' ) );
111 }
112
113 /**
114 * Get all active announcements.
115 *
116 * @return array List of active announcements.
117 */
118 public function get_active_announcements() {
119 $active = array();
120
121 foreach ( self::$timeline as $announcement_slug => $dates ) {
122 if ( $this->is_active( $dates ) && $this->can_show( $announcement_slug, $dates ) ) {
123 $active[] = $announcement_slug;
124 }
125 }
126
127 return $active;
128 }
129
130 /**
131 * Get all announcements along with plugin specific data.
132 *
133 * @return array List of announcements.
134 */
135 public function get_announcements_for_plugins() {
136
137 $announcements = array();
138
139 foreach ( self::$timeline as $announcement => $dates ) {
140 $announcements[ $announcement ] = $dates;
141
142 if ( false !== strpos( $announcement, 'black_friday' ) ) {
143 $announcements[ $announcement ]['active'] = $this->is_active( $dates );
144
145 // Dashboard banners URLs.
146 $announcements[ $announcement ]['feedzy_dashboard_url'] = tsdk_utmify( 'https://themeisle.com/plugins/feedzy-rss-feeds/blackfriday/', 'bfcm24', 'dashboard' );
147 $announcements[ $announcement ]['neve_dashboard_url'] = tsdk_utmify( 'https://themeisle.com/themes/neve/blackfriday/', 'bfcm24', 'dashboard' );
148 $announcements[ $announcement ]['otter_dashboard_url'] = tsdk_utmify( 'https://themeisle.com/plugins/otter-blocks/blackfriday/', 'bfcm24', 'dashboard' );
149
150 // Customizer banners URLs.
151 $announcements[ $announcement ]['hestia_customizer_url'] = tsdk_utmify( 'https://themeisle.com/black-friday/', 'bfcm24', 'hestiacustomizer' );
152 $announcements[ $announcement ]['neve_customizer_url'] = tsdk_utmify( 'https://themeisle.com/black-friday/', 'bfcm24', 'nevecustomizer' );
153
154 // Banners urgency text.
155 $remaining_time = $this->get_remaining_time_for_event( $dates['end'] );
156 $announcements[ $announcement ]['remaining_time'] = $remaining_time;
157 $announcements[ $announcement ]['urgency_text'] = ! empty( $remaining_time ) ? sprintf( Loader::$labels['announcements']['hurry_up'], $remaining_time ) : '';
158 }
159 }
160
161 return apply_filters( 'themeisle_sdk_announcements_data', $announcements );
162 }
163
164 /**
165 * Get the announcement data.
166 *
167 * @param string $announcement The announcement to get the data for.
168 *
169 * @return array
170 */
171 public function get_announcement_data( $announcement ) {
172 return ! empty( $announcement ) && is_string( $announcement ) && isset( self::$timeline[ $announcement ] ) ? self::$timeline[ $announcement ] : array();
173 }
174
175 /**
176 * Check if the announcement has an active timeline.
177 *
178 * @param array $dates The announcement to check.
179 *
180 * @return bool
181 */
182 public function is_active( $dates ) {
183
184 if ( empty( $this->time ) ) {
185 $this->time = current_time( 'Y-m-d' );
186 }
187
188 $start = isset( $dates['start'] ) ? $dates['start'] : null;
189 $end = isset( $dates['end'] ) ? $dates['end'] : null;
190
191 if ( $start && $end ) {
192 return $start <= $this->time && $this->time <= $end;
193 } elseif ( $start ) {
194 return $this->time >= $start;
195 } elseif ( $end ) {
196 return $this->time <= $end;
197 }
198
199 return false;
200 }
201
202 /**
203 * Get the remaining time for the event in a human readable format.
204 *
205 * @param string $end_date The end date for event.
206 *
207 * @return string Remaining time for the event.
208 */
209 public function get_remaining_time_for_event( $end_date ) {
210 if ( empty( $end_date ) || ! is_string( $end_date ) ) {
211 return '';
212 }
213
214 return human_time_diff( time(), strtotime( $end_date ) );
215
216 }
217
218 /**
219 * Check if the announcement can be shown.
220 *
221 * @param string $announcement_slug The announcement to check.
222 * @param array $dates The announcement to check.
223 *
224 * @return bool
225 */
226 public function can_show( $announcement_slug, $dates ) {
227 $dismiss_date = get_option( $this->option_prefix . $announcement_slug, false );
228
229 if ( false === $dismiss_date ) {
230 return true;
231 }
232
233 // If the start date is after the dismiss date, show the notice.
234 $start = isset( $dates['start'] ) ? $dates['start'] : null;
235 if ( $start && $dismiss_date < $start ) {
236 return true;
237 }
238
239 return false;
240 }
241
242 /**
243 * Disable the notification via ajax.
244 *
245 * @return void
246 */
247 public function disable_notification_ajax() {
248 if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'dismiss_themeisle_event_notice' ) ) {
249 wp_die( 'Invalid nonce! Refresh the page and try again.' );
250 }
251
252 if ( ! isset( $_POST['announcement'] ) || ! is_string( $_POST['announcement'] ) ) {
253 wp_die( 'Invalid announcement! Refresh the page and try again.' );
254 }
255
256 $announcement = sanitize_key( $_POST['announcement'] );
257
258 update_option( $this->option_prefix . $announcement, current_time( 'Y-m-d' ) );
259 wp_die( 'success' );
260 }
261
262 /**
263 * Render the Black Friday notice.
264 *
265 * @return void
266 */
267 public function black_friday_notice_render() {
268
269 // Prevent the notice from being rendered twice.
270 if ( self::$timeline['black_friday']['rendered'] ) {
271 return;
272 }
273 self::$timeline['black_friday']['rendered'] = true;
274
275 $product_names = array();
276
277 foreach ( Loader::get_products() as $product ) {
278 $slug = $product->get_slug();
279
280 // Do not add if the contains the string 'pro'.
281 if ( strpos( $slug, 'pro' ) !== false ) {
282 continue;
283 }
284
285 $product_names[] = $product->get_name();
286 }
287
288 // Randomize the products and get only 4.
289 shuffle( $product_names );
290 $product_names = array_slice( $product_names, 0, 4 );
291
292 ?>
293 <style>
294 .themeisle-sale {
295 display: flex;
296 }
297 </style>
298 <div class="themeisle-sale notice notice-info is-dismissible" data-announcement="black_friday">
299 <img src="<?php echo esc_url_raw( $this->get_sdk_uri() . 'assets/images/themeisle-logo.svg' ); ?>"/>
300 <p>
301 <strong><?php echo esc_html( Loader::$labels['announcements']['sale_live'] ); ?> ></strong>
302 - <?php echo sprintf( esc_html( Loader::$labels['announcements']['max_savings'] ), esc_html( implode( ', ', $product_names ) ) ); ?>
303 .
304 <a href="<?php echo esc_url_raw( tsdk_utmify( 'https://themeisle.com/blackfriday/', 'bfcm24', 'globalnotice' ) ); ?>"
305 target="_blank"><?php echo esc_html( Loader::$labels['announcements']['learn_more'] ); ?>></a>
306 <span class="themeisle-sale-error"></span>
307 </p>
308 </div>
309 <script type="text/javascript" data-origin="themeisle-sdk">
310 window.document.addEventListener('DOMContentLoaded', () => {
311 const observer = new MutationObserver((mutationsList, observer) => {
312 for (let mutation of mutationsList) {
313 if (mutation.type === 'childList') {
314 const container = document.querySelector('.themeisle-sale.notice');
315 const button = container?.querySelector('button');
316 if (button) {
317 button.addEventListener('click', e => {
318 e.preventDefault();
319 fetch('<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>', {
320 method: 'POST',
321 headers: {
322 'Content-Type': 'application/x-www-form-urlencoded'
323 },
324 body: new URLSearchParams({
325 action: 'themeisle_sdk_dismiss_announcement',
326 nonce: '<?php echo esc_attr( wp_create_nonce( 'dismiss_themeisle_event_notice' ) ); ?>',
327 announcement: container.dataset.announcement
328 })
329 })
330 .then(response => response.text())
331 .then(response => {
332 if (!response?.includes('success')) {
333 document.querySelector('.themeisle-sale-error').innerHTML = response;
334 return;
335 }
336
337 document.querySelectorAll('.themeisle-sale.notice').forEach(el => {
338 el.classList.add('hidden');
339 setTimeout(() => {
340 el.remove();
341 }, 800);
342 });
343 })
344 .catch(error => {
345 console.error('Error:', error);
346 document.querySelector('.themeisle-sale-error').innerHTML = error;
347 });
348 });
349 observer.disconnect();
350 break;
351 }
352 }
353 }
354 });
355
356 observer.observe(document.body, {childList: true, subtree: true});
357 });
358 </script>
359 <?php
360 }
361 }
362