PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / trunk
VikAppointments Services Booking Calendar vtrunk
trunk 1.2.17 1.2.18 1.2.19
vikappointments / libraries / system / screen.php
vikappointments / libraries / system Last commit date
assets.php 1 month ago body.php 4 years ago builder.php 1 month ago cron.php 4 years ago feedback.php 4 years ago gutenberg.php 2 years ago install.php 1 month ago mce.php 4 years ago rssfeeds.php 5 months ago screen.php 4 years ago
screen.php
826 lines
1 <?php
2 /**
3 * @package VikAppointments - Libraries
4 * @subpackage system
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2021 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 /**
15 * Helper class to setup the WordPress Screen.
16 *
17 * @since 1.0
18 */
19 class VikAppointmentsScreen
20 {
21 /**
22 * The type of options to display.
23 * This property can be edited externally.
24 *
25 * @var boolean
26 */
27 public static $optionsType = null;
28
29 /**
30 * Creates the option section within the WP Screen for VikAppointments.
31 *
32 * @return void
33 */
34 public static function options()
35 {
36 $app = JFactory::getApplication();
37
38 // make sure we are in VikAppointments (back-end)
39 if (!$app->isAdmin() || $app->input->get('page') != 'vikappointments')
40 {
41 // abort
42 return;
43 }
44
45 // check if we should display screen options for listing pages
46 if (static::$optionsType == 'list')
47 {
48 // create pagination option
49 $args = array(
50 'label' => __('Number of items per page:'),
51 'default' => 20,
52 'option' => 'vikappointments_list_limit',
53 );
54
55 add_screen_option('per_page', $args);
56 }
57 }
58
59 /**
60 * Filters a screen option value before it is set.
61 *
62 * @param boolean $skip Whether to save or skip saving the screen option value. Default false.
63 * @param string $option The option name.
64 * @param mixed $value The option value.
65 *
66 * @return mixed Returning false to the filter will skip saving the current option.
67 */
68 public static function saveOption($skip, $option, $value)
69 {
70 switch ($option)
71 {
72 case 'vikappointments_list_limit':
73 // cannot have a value lower than 1
74 $value = max(array(1, (int) $value));
75 // refresh cached value
76 JFactory::getApplication()->setUserState('com_vikappointments.limit', $value);
77
78 return $value;
79 }
80
81 // skip otherwise
82 return $skip;
83 }
84
85 /**
86 * Creates the Help tabs within the WP Screen for VikAppointments.
87 *
88 * @param WP_Screen $screen The current screen instance.
89 *
90 * @return void
91 */
92 public static function help($screen = null)
93 {
94 $app = JFactory::getApplication();
95
96 // make sure we are in VikAppointments (back-end)
97 if (!$app->isAdmin() || $app->input->get('page') != 'vikappointments')
98 {
99 // abort
100 return;
101 }
102
103 // make sure $screen is a valid instance
104 if (!class_exists('WP_Screen') || !$screen instanceof WP_Screen)
105 {
106 if (VIKAPPOINTMENTS_DEBUG)
107 {
108 // trigger warning in case debug is enabled
109 trigger_error('Method ' . __METHOD__ . ' has been called too early', E_USER_WARNING);
110 }
111 // abort
112 return;
113 }
114
115 // extract view from request
116 $view = $app->input->get('view', null);
117
118 if (empty($view))
119 {
120 // no view, try to check 'task'
121 $view = $app->input->get('task', 'vikappointments');
122 }
123
124 // make sure the view is supported
125 if (!isset(static::$lookup[$view]))
126 {
127 // view not supported
128 return;
129 }
130
131 // check if we have a link to an existing item
132 if (is_string(static::$lookup[$view]))
133 {
134 // use the linked element
135 $view = static::$lookup[$view];
136 }
137
138 // check if the view documentation has been already cached
139 $doc = get_transient('vikappointments_screen_' . $view);
140
141 if (!$doc)
142 {
143 // evaluate if we should stop using HELP tabs after 3 failed attempts
144 $fail = (int) get_option('vikappointments_screen_failed_attempts', 0);
145
146 if ($fail >= 5)
147 {
148 // Do not proceed as we hit too many failure attempts contiguously.
149 // Reset 'vikappointments_screen_failed_attempts' option to restart using HELP tabs.
150 return;
151 }
152
153 // create POST arguments
154 $args = array(
155 'documentation_alias' => 'vik-appointments',
156 'lang' => substr(JFactory::getLanguage()->getTag(), 0, 2),
157 );
158
159 $args = array_merge($args, static::$lookup[$view]);
160
161 // build headers
162 $headers = array(
163 /**
164 * Always bypass SSL validation while reaching our end-point.
165 *
166 * @since 1.2
167 */
168 'sslverify' => false,
169 );
170
171 $http = new JHttp();
172
173 // make HTTP post
174 $response = $http->post('https://vikwp.com/index.php?option=com_vikhelpdesk&format=json', $args, $headers);
175
176 if ($response->code != 200)
177 {
178 // increase total number of failed attempts
179 update_option('vikappointments_screen_failed_attempts', $fail + 1);
180
181 return;
182 }
183
184 // try to decode JSON
185 $doc = json_decode($response->body);
186
187 if (!is_array($doc))
188 {
189 // increase total number of failed attempts
190 update_option('vikappointments_screen_failed_attempts', $fail + 1);
191
192 return;
193 }
194
195 // reset total number of failed attempts
196 update_option('vikappointments_screen_failed_attempts', 0);
197
198 // cache retrieved documentation (for one week only)
199 set_transient('vikappointments_screen_' . $view, json_encode($doc), WEEK_IN_SECONDS);
200 }
201 else
202 {
203 // JSON decode the cached documentation
204 $doc = json_decode($doc);
205 }
206
207 // iterate category sections
208 foreach ($doc as $i => $cat)
209 {
210 // add subcategory as help tab
211 $screen->add_help_tab(array(
212 'id' => 'vikappointments-' . $view . '-' . ($i + 1),
213 'title' => $cat->contentTitle,
214 'content' => $cat->content,
215 ));
216 }
217
218 // add help sidebar
219 $screen->set_help_sidebar(
220 '<p><strong>' . __('For more information:') . '</strong></p>' .
221 '<p><a href="https://vikwp.com/support/documentation/vik-appointments/" target="_blank">VikWP.com</a></p>'
222 );
223 }
224
225 /**
226 * Clears the cache for the specified view, if specified.
227 *
228 * @param string|null $view Clear the cache for the specified view (if specified)
229 * or for all the existing views.
230 *
231 * @return void
232 */
233 public static function clearCache($view = null)
234 {
235 if ($view)
236 {
237 delete_transient('vikappointments_screen_' . $view);
238 }
239 else
240 {
241 foreach (static::$lookup as $view => $args)
242 {
243 if (is_array($args))
244 {
245 delete_transient('vikappointments_screen_' . $view);
246 }
247 }
248
249 // delete settings too
250 delete_option('vikappointments_screen_failed_attempts');
251 delete_option('vikappointments_list_limit');
252 }
253 }
254
255 /**
256 * Lookup used to retrieve the arguments for the HTTP request.
257 *
258 * @var array
259 */
260 protected static $lookup = array(
261 ////////////////////////////////
262 /////////// DASHBOARD //////////
263 ////////////////////////////////
264
265 // dashboard
266 'vikappointments' => array(
267 'task' => 'documentation.category',
268 'category_name' => 'dashboard',
269 ),
270
271 ////////////////////////////////
272 ////////// MANAGEMENT //////////
273 ////////////////////////////////
274
275 // groups
276 'groups' => array(
277 'task' => 'documentation.subcategory',
278 'category_name' => 'management',
279 'subcategory_name' => 'groups',
280 ),
281 'managegroup' => 'groups',
282
283 // employees
284 'employees' => array(
285 'task' => 'documentation.subcategory',
286 'category_name' => 'management',
287 'subcategory_name' => 'employees',
288 // 'content_name' => 'employee',
289 'no_contents' => true,
290 ),
291
292 // edit employee
293 'manageemployee' => array(
294 'task' => 'documentation.subcategory',
295 'category_name' => 'management',
296 'subcategory_name' => 'employees',
297 'content_name' => array(
298 'employee',
299 'custom fields',
300 'working days',
301 ),
302 ),
303
304 // employee overrides
305 'emprates' => array(
306 'task' => 'documentation.subcategory',
307 'category_name' => 'management',
308 'subcategory_name' => 'employees',
309 'content_name' => 'overrides',
310 ),
311
312 // employee payments
313 'emppayments' => array(
314 'task' => 'documentation.subcategory',
315 'category_name' => 'management',
316 'subcategory_name' => 'employees',
317 'content_name' => 'payments',
318 ),
319
320 // employee payments
321 'emplocations' => array(
322 'task' => 'documentation.subcategory',
323 'category_name' => 'management',
324 'subcategory_name' => 'employees',
325 'content_name' => 'locations',
326 ),
327 'manageemplocation' => 'emplocations',
328
329 // employee reports
330 'reportsemp' => array(
331 'task' => 'documentation.subcategory',
332 'category_name' => 'management',
333 'subcategory_name' => 'employees',
334 'content_name' => 'reports',
335 ),
336
337 // services
338 'services' => array(
339 'task' => 'documentation.subcategory',
340 'category_name' => 'management',
341 'subcategory_name' => 'services',
342 'content_name' => array(
343 'special rates',
344 ),
345 ),
346
347 // edit service
348 'manageservice' => array(
349 'task' => 'documentation.subcategory',
350 'category_name' => 'management',
351 'subcategory_name' => 'services',
352 'content_name' => array(
353 'service',
354 'assignments',
355 'metadata',
356 ),
357 ),
358
359 // service working days
360 'serworkdays' => array(
361 'task' => 'documentation.subcategory',
362 'category_name' => 'management',
363 'subcategory_name' => 'services',
364 'content_name' => 'working days',
365 ),
366
367 // service rates
368 'rates' => array(
369 'task' => 'documentation.subcategory',
370 'category_name' => 'management',
371 'subcategory_name' => 'services',
372 'content_name' => array(
373 'special rates',
374 'rate fields',
375 'rates debug',
376 ),
377 ),
378 'managerate' => 'rates',
379
380 // options
381 'options' => array(
382 'task' => 'documentation.subcategory',
383 'category_name' => 'management',
384 'subcategory_name' => 'options',
385 'no_contents' => true,
386 ),
387
388 // edit option
389 'manageoption' => array(
390 'task' => 'documentation.subcategory',
391 'category_name' => 'management',
392 'subcategory_name' => 'options',
393 ),
394
395 // locations
396 'locations' => array(
397 'task' => 'documentation.subcategory',
398 'category_name' => 'management',
399 'subcategory_name' => 'locations',
400 'no_contents' => true,
401 ),
402
403 // edit location
404 'managelocation' => array(
405 'task' => 'documentation.subcategory',
406 'category_name' => 'management',
407 'subcategory_name' => 'locations',
408 ),
409
410 // packages groups
411 'packgroups' => array(
412 'task' => 'documentation.subcategory',
413 'category_name' => 'management',
414 'subcategory_name' => 'packages',
415 'content_name' => 'packages groups',
416 ),
417 'managepackgroup' => 'packgroups',
418
419 // packages products
420 'packages' => array(
421 'task' => 'documentation.subcategory',
422 'category_name' => 'management',
423 'subcategory_name' => 'packages',
424 'no_contents' => true,
425 ),
426
427 // edit package
428 'managepackage' => array(
429 'task' => 'documentation.subcategory',
430 'category_name' => 'management',
431 'subcategory_name' => 'packages',
432 'content_name' => 'packages content',
433 ),
434
435 // packages orders
436 'packorders' => array(
437 'task' => 'documentation.subcategory',
438 'category_name' => 'management',
439 'subcategory_name' => 'packages',
440 'content_name' => 'packages orders',
441 ),
442 'managepackorder' => 'packorders',
443
444 ////////////////////////////////
445 ///////// APPOINTMENTS /////////
446 ////////////////////////////////
447
448 // reservations
449 'reservations' => array(
450 'task' => 'documentation.subcategory',
451 'category_name' => 'appointments',
452 'subcategory_name' => 'reservations',
453 'content_name' => array(
454 'single & multiple appointments',
455 'sms notifications',
456 'invoices',
457 ),
458 ),
459
460 // edit reservation
461 'managereservation' => array(
462 'task' => 'documentation.subcategory',
463 'category_name' => 'appointments',
464 'subcategory_name' => 'reservations',
465 'content_name' => array(
466 'reservation',
467 'order statuses',
468 ),
469 ),
470
471 // make recurrence
472 'makerecurrence' => array(
473 'task' => 'documentation.subcategory',
474 'category_name' => 'appointments',
475 'subcategory_name' => 'reservations',
476 'content_name' => 'make recurrence',
477 ),
478
479 // export reservations
480 'exportres' => array(
481 'task' => 'documentation.subcategory',
482 'category_name' => 'appointments',
483 'subcategory_name' => 'reservations',
484 'content_name' => 'export',
485 ),
486
487 // closures
488 'manageclosure' => array(
489 'task' => 'documentation.subcategory',
490 'category_name' => 'appointments',
491 'subcategory_name' => 'reservations',
492 'content_name' => 'closures',
493 ),
494
495 // waiting list
496 'waitinglist' => array(
497 'task' => 'documentation.subcategory',
498 'category_name' => 'appointments',
499 'subcategory_name' => 'waiting list',
500 'no_contents' => true,
501 ),
502
503 // edit waiting list
504 'managewaiting' => array(
505 'task' => 'documentation.subcategory',
506 'category_name' => 'appointments',
507 'subcategory_name' => 'waiting list',
508 ),
509
510 // customers
511 'customers' => array(
512 'task' => 'documentation.subcategory',
513 'category_name' => 'appointments',
514 'subcategory_name' => 'customers',
515 'content_name' => array(
516 'customers',
517 'import',
518 'export',
519 'sms notifications',
520 ),
521 ),
522
523 // edit customer
524 'managecustomer' => array(
525 'task' => 'documentation.subcategory',
526 'category_name' => 'appointments',
527 'subcategory_name' => 'customers',
528 'content_name' => array(
529 'customers',
530 'user credit',
531 ),
532 ),
533
534 // coupons
535 'coupons' => array(
536 'task' => 'documentation.subcategory',
537 'category_name' => 'appointments',
538 'subcategory_name' => 'coupons',
539 'content_name' => array(
540 'import',
541 'export',
542 ),
543 ),
544
545 // edit coupon
546 'managecoupon' => array(
547 'task' => 'documentation.subcategory',
548 'category_name' => 'appointments',
549 'subcategory_name' => 'coupons',
550 'content_name' => 'coupon',
551 ),
552
553 // coupon groups
554 'coupongroups' => array(
555 'task' => 'documentation.subcategory',
556 'category_name' => 'appointments',
557 'subcategory_name' => 'coupons',
558 'content_name' => 'groups',
559 ),
560 'managecoupongroup' => 'coupongroups',
561
562 // calendar
563 'calendar' => array(
564 'task' => 'documentation.subcategory',
565 'category_name' => 'appointments',
566 'subcategory_name' => 'calendar',
567 'content_name' => 'reports',
568 ),
569 'reportsall' => 'calendar',
570
571 // daily calendar
572 'caldays' => array(
573 'task' => 'documentation.subcategory',
574 'category_name' => 'appointments',
575 'subcategory_name' => 'calendar',
576 'content_name' => 'daily view',
577 ),
578
579 ////////////////////////////////
580 //////////// PORTAL ////////////
581 ////////////////////////////////
582
583 // countries
584 'countries' => array(
585 'task' => 'documentation.subcategory',
586 'category_name' => 'portal',
587 'subcategory_name' => 'countries',
588 'no_contents' => true,
589 ),
590
591 // edit country
592 'managecountry' => array(
593 'task' => 'documentation.subcategory',
594 'category_name' => 'portal',
595 'subcategory_name' => 'countries',
596 'content_name' => 'countries',
597 ),
598
599 // states
600 'states' => array(
601 'task' => 'documentation.subcategory',
602 'category_name' => 'portal',
603 'subcategory_name' => 'countries',
604 'content_name' => 'states',
605 ),
606 'managestate' => 'states',
607
608 // cities
609 'cities' => array(
610 'task' => 'documentation.subcategory',
611 'category_name' => 'portal',
612 'subcategory_name' => 'countries',
613 'content_name' => 'cities',
614 ),
615 'managecity' => 'cities',
616
617 // reviews
618 'revs' => array(
619 'task' => 'documentation.subcategory',
620 'category_name' => 'portal',
621 'subcategory_name' => 'reviews',
622 'no_contents' => true,
623 ),
624
625 // edit review
626 'managerev' => array(
627 'task' => 'documentation.subcategory',
628 'category_name' => 'portal',
629 'subcategory_name' => 'reviews',
630 ),
631
632 // subscriptions
633 'subscriptions' => array(
634 'task' => 'documentation.subcategory',
635 'category_name' => 'portal',
636 'subcategory_name' => 'subscriptions',
637 'no_contents' => true,
638 ),
639
640 // edit subscription
641 'managesubscription' => array(
642 'task' => 'documentation.subcategory',
643 'category_name' => 'portal',
644 'subcategory_name' => 'subscriptions',
645 ),
646
647 // subscription orders
648 'subscrorders' => array(
649 'task' => 'documentation.subcategory',
650 'category_name' => 'portal',
651 'subcategory_name' => 'subscription orders',
652 'content_name' => 'employees overview',
653 ),
654
655 // edit subscription order
656 'managesubscrorder' => array(
657 'task' => 'documentation.subcategory',
658 'category_name' => 'portal',
659 'subcategory_name' => 'subscription orders',
660 'content_name' => 'subscription orders content',
661 ),
662
663 ////////////////////////////////
664 //////////// GLOBAL ////////////
665 ////////////////////////////////
666
667 // custom fields
668 'customf' => array(
669 'task' => 'documentation.subcategory',
670 'category_name' => 'global',
671 'subcategory_name' => 'custom fields',
672 'content_name' => array(
673 'rules',
674 'override custom fields',
675 ),
676 ),
677
678 // edit custom field
679 'managecustomf' => array(
680 'task' => 'documentation.subcategory',
681 'category_name' => 'global',
682 'subcategory_name' => 'custom fields',
683 'content_name' => array(
684 'custom field',
685 'text type',
686 'textarea type',
687 'number type',
688 'date type',
689 'select type',
690 'checkbox type',
691 'file type',
692 'separator type',
693 'rules',
694 ),
695 ),
696
697 // payments
698 'payments' => array(
699 'task' => 'documentation.subcategory',
700 'category_name' => 'global',
701 'subcategory_name' => 'payments',
702 'no_contents' => true,
703 ),
704
705 // edit payment
706 'managepayment' => array(
707 'task' => 'documentation.subcategory',
708 'category_name' => 'global',
709 'subcategory_name' => 'payments',
710 ),
711
712 // invoices
713 'invfiles' => array(
714 'task' => 'documentation.subcategory',
715 'category_name' => 'global',
716 'subcategory_name' => 'invoices archive',
717 ),
718
719 // media manager
720 'media' => array(
721 'task' => 'documentation.subcategory',
722 'category_name' => 'global',
723 'subcategory_name' => 'media manager',
724 'content_name' => 'analyze media',
725 ),
726
727 // new media
728 'managemedia' => array(
729 'task' => 'documentation.subcategory',
730 'category_name' => 'global',
731 'subcategory_name' => 'media manager',
732 'content_name' => array(
733 'upload',
734 'quick upload',
735 ),
736 ),
737
738 // cron jobs
739 'cronjobs' => array(
740 'task' => 'documentation.subcategory',
741 'category_name' => 'global',
742 'subcategory_name' => 'cron jobs',
743 ),
744
745 ////////////////////////////////
746 ///////// CONFIGURATION ////////
747 ////////////////////////////////
748
749 // configuration > global
750 'editconfig' => array(
751 'task' => 'documentation.subcategory',
752 'category_name' => 'configuration',
753 'subcategory_name' => 'global',
754 ),
755
756 // configuration > employees
757 'editconfigemp' => array(
758 'task' => 'documentation.subcategory',
759 'category_name' => 'configuration',
760 'subcategory_name' => 'employees',
761 ),
762
763 // configuration > closing days
764 'editconfigcldays' => array(
765 'task' => 'documentation.subcategory',
766 'category_name' => 'configuration',
767 'subcategory_name' => 'closing days',
768 ),
769
770 // configuration > closing days
771 'editconfigsmsapi' => array(
772 'task' => 'documentation.subcategory',
773 'category_name' => 'configuration',
774 'subcategory_name' => 'sms apis',
775 ),
776
777 // configuration > closing days
778 'editconfigcron' => array(
779 'task' => 'documentation.subcategory',
780 'category_name' => 'configuration',
781 'subcategory_name' => 'cron jobs',
782 ),
783
784 // mail custom text
785 'mailtextcust' => array(
786 'task' => 'documentation.subcategory',
787 'category_name' => 'global',
788 'subcategory_name' => 'e-mail custom text',
789 'no_contents' => true,
790 ),
791
792 // mail custom text
793 'managemailtext' => array(
794 'task' => 'documentation.subcategory',
795 'category_name' => 'global',
796 'subcategory_name' => 'e-mail custom text',
797 ),
798
799 // conversion codes
800 'conversions' => array(
801 'task' => 'documentation.subcategory',
802 'category_name' => 'global',
803 'subcategory_name' => 'conversion codes',
804 'no_contents' => true,
805 ),
806
807 // edit conversion code
808 'manageconversion' => array(
809 'task' => 'documentation.subcategory',
810 'category_name' => 'global',
811 'subcategory_name' => 'conversion codes',
812 ),
813 );
814 }
815
816 /**
817 * In case VikAppointments displayed the menu, we are probably
818 * visiting a page with a list. For this reason, we should alter
819 * the VikAppointmentsScreen::$optionsType to display a specific
820 * screen options form.
821 */
822 add_action('vikappointments_before_build_menu', function()
823 {
824 VikAppointmentsScreen::$optionsType = 'list';
825 });
826