PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.27
Booktics – Appointment Booking Calendar for Service Businesses v1.0.27
1.0.29 1.0.28 1.0.27 1.0.26 1.0.25 1.0.24 1.0.23 1.0.22 1.0.21 1.0.20 1.0.19 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.2 1.0.3 All 31 releases
booktics / vendor / arraytics / plugin-notice-sdk / src / Notice.php

Notice.php in Booktics – Appointment Booking Calendar for Service Businesses 1.0.27, at vendor/arraytics/plugin-notice-sdk/src/Notice.php

543 lines 14.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Arraytics\PluginNotice;
4
5 class Notice
6 {
7 /**
8 * Singleton instance of the Notice class.
9 *
10 * @var self|null
11 */
12 protected static $instance;
13
14 /**
15 * Plugin version (set from main plugin).
16 *
17 * @var string
18 */
19 protected $version = '1.0.0'; // default fallback
20
21 /**
22 * Unique identifier for the notice.
23 *
24 * @var string
25 */
26 protected $notice_id;
27
28 /**
29 * Text domain of the plugin.
30 *
31 * @var string
32 */
33 protected $text_domain;
34
35 /**
36 * Unique ID used internally.
37 *
38 * @var string
39 */
40 protected $unique_id;
41
42 /**
43 * Additional CSS classes for the notice container.
44 *
45 * @var string
46 */
47 protected $class = '';
48
49 /**
50 * Default button configuration.
51 *
52 * @var array
53 */
54 protected $button;
55
56 /**
57 * Size-specific settings (currently unused).
58 *
59 * @var array
60 */
61 protected $size = [];
62
63 /**
64 * List of buttons added to the notice.
65 *
66 * @var array
67 */
68 protected $buttons = [];
69
70 /**
71 * Title of the notice.
72 *
73 * @var string
74 */
75 protected $title = '';
76
77 /**
78 * Message body of the notice.
79 *
80 * @var string
81 */
82 protected $message = '';
83
84 /**
85 * URL of the left-side logo image.
86 *
87 * @var string
88 */
89 protected $logo = '';
90
91 /**
92 * Whether the notice container should have gutter (padding).
93 *
94 * @var string
95 */
96 protected $gutter = '';
97
98 /**
99 * Inline style for the logo image.
100 *
101 * @var string
102 */
103 protected $logo_style = '';
104
105 /**
106 * Dismissible type: false, 'user', or 'global'.
107 *
108 * @var string|bool
109 */
110 protected $dismissible = false;
111
112 /**
113 * Expiration time in seconds for the dismissible notice.
114 *
115 * @var int
116 */
117 protected $expired_time = 1;
118
119 /**
120 * Raw HTML content to override default markup.
121 *
122 * @var string
123 */
124 protected $html = '';
125
126 /**
127 * Get an instance of the Notice class.
128 *
129 * @param string|null $text_domain
130 * @param string|null $unique_id
131 * @return self|false
132 */
133 public static function instance($text_domain = null, $unique_id = null)
134 {
135 if (!$text_domain) {
136 return false;
137 }
138 self::$instance = new self();
139 return self::$instance->config($text_domain, $unique_id ?: uniqid());
140 }
141
142 /**
143 * Initialize the dismiss AJAX and enqueue scripts.
144 *
145 * @return void
146 */
147 public static function init()
148 {
149 static $initialized = false;
150
151 // Prevent multiple initializations
152 if ( $initialized ) {
153 return;
154 }
155
156 add_action('wp_ajax_wpmet-notices', [__CLASS__, 'dismiss_ajax_call']);
157 add_action( 'admin_head', [ __CLASS__, 'enqueue_scripts' ] );
158
159 $initialized = true;
160 }
161
162 /**
163 * Enqueue comparison scripts and styles
164 *
165 * @return void
166 */
167 public static function enqueue_scripts()
168 {
169 ?>
170 <script>
171 jQuery(document).ready(function ($) {
172 $( '.wpmet-notice.is-dismissible' ).on( 'click', '.notice-dismiss', function() {
173 var _this = $( this ).parents('.wpmet-notice').eq(0);
174 var notice_id = _this.attr( 'id' ) || '';
175 var expired_time = _this.attr( 'expired_time' ) || '';
176 var dismissible = _this.attr( 'dismissible' ) || '';
177 var nonce = '<?php echo wp_create_nonce( 'wpmet-notices' ); ?>';
178
179 _this.hide();
180
181 $.ajax({
182 url: ajaxurl,
183 type: 'POST',
184 data: {
185 action: 'wpmet-notices',
186 notice_id: notice_id,
187 dismissible: dismissible,
188 expired_time: expired_time,
189 nonce: nonce
190 },
191 });
192 });
193 });
194 </script>
195 <style>
196 .wpmet-notice { margin-bottom: 15px; padding: 0 !important; display: flex; align-items: center; }
197 .wpmet-notice .notice-right-container { margin: .7rem .8rem .8rem; }
198 .notice-container-full-width { width: 100% !important; }
199
200 .wpmet-notice.no-gutter { padding: 0 !important; border-width: 0 !important; }
201 .wpmet-notice.no-gutter .notice-right-container { padding: 0 !important; margin: 0 !important; }
202
203 .notice-right-container .notice-vert-space { margin-bottom: .8rem; }
204 .notice-right-container .notice-vert-space:last-child,
205 .notice-right-container .notice-vert-space:only-child { margin-bottom: 0; }
206
207 .wpmet-notice .notice-logo { padding: 3px; max-width: 110px; max-height: 110px; }
208 .wpmet-notice .plugin-notice-href img { max-width: 100%; height: auto; }
209
210 .wpmet-notice-button { text-decoration: none; }
211 .wpmet-notice-button > i { margin-right: 3px; }
212 .wpmet-notice-button .notice-icon { display: inline-block; }
213 .wpmet-notice-button .notice-icon:before { vertical-align: middle !important; margin-top: -1px; }
214
215 .wpmet-notice .notice-main-title { color: #1d2327; font-size: 1.2rem; }
216 </style>
217 <?php
218 }
219
220 /**
221 * Configure basic properties of the notice.
222 *
223 * @param string $text_domain
224 * @param string $unique_id
225 * @return $this
226 */
227 public function config($text_domain, $unique_id)
228 {
229 $this->text_domain = $text_domain;
230 $this->unique_id = $unique_id;
231 $this->notice_id = "$text_domain-$unique_id";
232 $this->dismissible = false;
233 $this->expired_time = 1;
234
235 $this->button = [
236 'default_class' => 'button',
237 'class' => 'button-secondary',
238 'text' => 'Button',
239 'url' => '#',
240 'icon' => '',
241 ];
242
243 return $this;
244 }
245
246 /**
247 * Set additional CSS classes.
248 *
249 * @param string $classname
250 * @return $this
251 */
252 public function set_class($classname = '')
253 {
254 $this->class .= $classname;
255 return $this;
256 }
257
258 /**
259 * Set the notice type.
260 *
261 * @param string $type
262 * @return $this
263 */
264 public function set_type($type = '')
265 {
266 $this->class .= " notice-$type";
267 return $this;
268 }
269
270 /**
271 * Add a button to the notice.
272 *
273 * @param array $button
274 * @return $this
275 */
276 public function set_button($button = [])
277 {
278 $this->buttons[] = array_merge($this->button, $button);
279 return $this;
280 }
281
282 /**
283 * Set a custom ID for the notice.
284 *
285 * @param string $id
286 * @return $this
287 */
288 public function set_id($id)
289 {
290 $this->notice_id = $id;
291 return $this;
292 }
293
294 /**
295 * Set the title of the notice.
296 *
297 * @param string $title
298 * @return $this
299 */
300 public function set_title($title = '')
301 {
302 $this->title .= $title;
303 return $this;
304 }
305
306 /**
307 * Set the message of the notice.
308 *
309 * @param string $message
310 * @return $this
311 */
312 public function set_message($message = '')
313 {
314 $this->message .= $message;
315 return $this;
316 }
317
318 /**
319 * Enable or disable gutter spacing.
320 *
321 * @param bool $gutter
322 * @return $this
323 */
324 public function set_gutter($gutter = true)
325 {
326 $this->gutter = $gutter;
327 $this->class .= $gutter ? '' : ' no-gutter';
328 return $this;
329 }
330
331 /**
332 * Set logo and style.
333 *
334 * @param string $logo
335 * @param string $logo_style
336 * @return $this
337 */
338 public function set_logo($logo = '', $logo_style = '')
339 {
340 $this->logo = $logo;
341 $this->logo_style = $logo_style;
342 return $this;
343 }
344
345 /**
346 * Set custom HTML content.
347 *
348 * @param string $html
349 * @return $this
350 */
351 public function set_html($html = '')
352 {
353 $this->html .= $html;
354 return $this;
355 }
356
357 /**
358 * Configure dismiss behavior.
359 *
360 * @param string $scope 'user' or 'global'
361 * @param int $time Expiry time in seconds
362 * @return $this
363 */
364 public function set_dismiss($scope = 'global', $time = 604800)
365 {
366 $this->dismissible = $scope;
367 $this->expired_time = $time;
368 return $this;
369 }
370
371 /**
372 * Get the compiled data for rendering.
373 *
374 * @return array
375 */
376 public function get_data()
377 {
378 return [
379 'message' => $this->message,
380 'title' => $this->title,
381 'buttons' => $this->buttons,
382 'class' => $this->class,
383 'html' => $this->html,
384 ];
385 }
386
387 /**
388 * Add the notice to the WordPress admin_notices hook.
389 *
390 * @return void
391 */
392 public function call()
393 {
394 add_action('admin_notices', [$this, 'get_notice']);
395 }
396
397 /**
398 * Display the notice HTML based on conditions.
399 *
400 * @return void
401 */
402 public function get_notice()
403 {
404 switch ($this->dismissible) {
405 case 'user':
406 $expired = get_user_meta(get_current_user_id(), $this->notice_id, true);
407 break;
408 case 'global':
409 $expired = get_transient($this->notice_id);
410 break;
411 default:
412 $expired = '';
413 break;
414 }
415
416 global $notice_list;
417 $notice_list = isset($notice_list) ? $notice_list : [];
418
419 if (!isset($notice_list[$this->notice_id]) && (false === $expired || empty($expired))) {
420 $notice_list[$this->notice_id] = __FILE__;
421 $this->generate_html();
422 }
423 }
424
425 /**
426 * Render the HTML for the notice.
427 *
428 * @return void
429 */
430 public function generate_html()
431 {
432 ?>
433 <div
434 id="<?php echo esc_attr($this->notice_id); ?>"
435 class="notice wpmet-notice notice-<?php echo esc_attr($this->notice_id . ' ' . $this->class); ?> <?php echo $this->dismissible === false ? '' : 'is-dismissible'; ?>"
436 expired_time="<?php echo esc_attr($this->expired_time); ?>"
437 dismissible="<?php echo esc_attr($this->dismissible); ?>"
438 >
439 <?php if (!empty($this->logo)) : ?>
440 <img class="notice-logo" style="<?php echo esc_attr($this->logo_style); ?>" src="<?php echo esc_url($this->logo); ?>" />
441 <?php endif; ?>
442
443 <div class="notice-right-container <?php echo empty($this->logo) ? 'notice-container-full-width' : ''; ?>">
444 <?php if (empty($this->html)) : ?>
445 <?php if (!empty($this->title)) : ?>
446 <div class="notice-main-title notice-vert-space"><?php echo esc_html($this->title); ?></div>
447 <?php endif; ?>
448
449 <div class="notice-message notice-vert-space">
450 <?php echo wp_kses_post($this->message); ?>
451 </div>
452
453 <?php if (!empty($this->buttons)) : ?>
454 <div class="button-container notice-vert-space">
455 <?php foreach ($this->buttons as $button) : ?>
456 <a id="<?php echo isset($button['id']) ? esc_attr($button['id']) : ''; ?>"
457 href="<?php echo esc_url($button['url']); ?>"
458 class="wpmet-notice-button <?php echo esc_attr($button['class']); ?>">
459 <?php if (!empty($button['icon'])) : ?>
460 <i class="notice-icon <?php echo esc_attr($button['icon']); ?>"></i>
461 <?php endif; ?>
462 <?php echo esc_html($button['text']); ?>
463 </a>&nbsp;
464 <?php endforeach; ?>
465 </div>
466 <?php endif; ?>
467 <?php else : ?>
468 <?php echo wp_kses_post($this->html); ?>
469 <?php endif; ?>
470 </div>
471
472 <?php if ($this->dismissible !== false) : ?>
473 <button type="button" class="notice-dismiss">
474 <span class="screen-reader-text">x#dismiss</span>
475 </button>
476 <?php endif; ?>
477
478 <div style="clear:both"></div>
479 </div>
480 <?php
481 }
482
483 /**
484 * Handle AJAX dismissal request.
485 *
486 * @return void
487 */
488 public static function dismiss_ajax_call()
489 {
490 $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
491 if (empty($nonce) || !wp_verify_nonce($nonce, 'wpmet-notices')) {
492 wp_send_json_error();
493 }
494
495 $notice_id = isset($_POST['notice_id']) ? sanitize_text_field(wp_unslash($_POST['notice_id'])) : '';
496 $dismissible = isset($_POST['dismissible']) ? sanitize_text_field(wp_unslash($_POST['dismissible'])) : '';
497 $expired = isset($_POST['expired_time']) ? (int) sanitize_text_field(wp_unslash($_POST['expired_time'])) : 0;
498
499 if ($notice_id) {
500 if ($dismissible === 'user') {
501 update_user_meta(get_current_user_id(), $notice_id, true);
502 } else {
503 set_transient($notice_id, true, $expired);
504 }
505 wp_send_json_success();
506 }
507
508 wp_send_json_error();
509 }
510
511 /**
512 * Set the plugin version dynamically.
513 *
514 * @param string $version
515 * @return $this
516 */
517 public function set_version($version)
518 {
519 $this->version = $version;
520 return $this;
521 }
522
523 /**
524 * Get plugin version.
525 *
526 * @return string
527 */
528 public function get_version()
529 {
530 return $this->version;
531 }
532
533 /**
534 * Get file location of this script.
535 *
536 * @return string
537 */
538 public function get_script_location()
539 {
540 return __FILE__;
541 }
542 }
543