PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / 1.2.21
VikAppointments Services Booking Calendar v1.2.21
1.2.21 1.2.20 trunk 1.2.17 1.2.18 1.2.19
vikappointments / admin / helpers / html / admin.php
vikappointments / admin / helpers / html Last commit date
admin.php 5 days ago index.html 5 days ago inspector.php 5 days ago mediamanager.php 5 days ago scripts.php 5 days ago
admin.php
1708 lines
1 <?php
2 /**
3 * @package VikAppointments
4 * @subpackage core
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 * VikAppointments HTML admin helper.
16 *
17 * @since 1.7
18 */
19 abstract class VAPHtmlAdmin
20 {
21 /**
22 * Method to sort a column in a grid.
23 *
24 * @param string $title The link title.
25 * @param string $order The order field for the column.
26 * @param string $direction The current direction.
27 * @param string $selected The selected ordering.
28 * @param string $task An optional task override.
29 * @param string $new_direction An optional direction for the new column.
30 * @param string $tip An optional text shown as tooltip title instead of $title.
31 * @param string $form An optional form selector.
32 *
33 * @return string
34 */
35 public static function sort($title, $order, $direction = 'asc', $selected = '', $task = null, $new_direction = 'asc', $tip = '', $form = null)
36 {
37 if (!$tip && preg_match("/ordering$/i", $order))
38 {
39 // force "Ordering" as tooltip in order to avoid
40 // display the HTML of the icon
41 $tip = 'JGRID_HEADING_ORDERING';
42 }
43
44 // render grid HTML
45 $html = JHtml::fetch('grid.sort', $title, $order, $direction, $selected, $task, $new_direction, $tip, $form);
46
47 // turn off tooltip or popover
48 $html = preg_replace("/\bhas(?:Tooltip|Popover)\b/", '', $html);
49
50 return $html;
51 }
52
53 /**
54 * Method to sort a column in a grid without using a native function.
55 *
56 * @param string $title The link title.
57 * @param string $order The order field for the column.
58 * @param string $direction The current direction.
59 * @param string $selected The selected ordering.
60 * @param string $new_direction An optional direction for the new column.
61 *
62 * @return string
63 */
64 public static function customsort($title, $order, $direction = 'asc', $selected = '', $new_direction = 'asc')
65 {
66 // use sort to get HTML
67 $html = static::sort($title, $order, $direction, $selected, $new_direction);
68
69 if ($order == $selected)
70 {
71 // in case the ordering was already selected, reverse direction
72 $direction = $direction == 'asc' ? 'desc' : 'asc';
73 }
74 else
75 {
76 // in case the ordering is not selected, use the default new direction
77 $direction = $new_direction;
78 }
79
80 // replace onclick attribute with the specified ordering data
81 $html = preg_replace("/\bonclick=\"(.*?)\"/i", 'data-order-col="' . $order . '" data-order-dir="' . $direction . '"', $html);
82
83 return $html;
84 }
85
86 /**
87 * Returns a list of supported groups.
88 *
89 * @param integer $type The group type (1 for services, 2 for employees).
90 * @param mixed $blank True to include an empty option. Use a string to
91 * specify the placeholder of the empty option.
92 *
93 * @return array A list of groups.
94 */
95 public static function groups($type, $blank = false)
96 {
97 $options = array();
98
99 if ($blank !== false)
100 {
101 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTGROUP');
102
103 $options[] = JHtml::fetch('select.option', '', $blank);
104 }
105
106 $dbo = JFactory::getDbo();
107
108 $q = $dbo->getQuery(true);
109 $q->select($dbo->qn(array('id', 'name')));
110 $q->order($dbo->qn('ordering') . ' ASC');
111
112 if ($type == 1)
113 {
114 $q->from($dbo->qn('#__vikappointments_group'));
115 }
116 else
117 {
118 $q->from($dbo->qn('#__vikappointments_employee_group'));
119 }
120
121 $dbo->setQuery($q);
122
123 foreach ($dbo->loadObjectList() as $group)
124 {
125 $options[] = JHtml::fetch('select.option', $group->id, $group->name);
126 }
127
128 return $options;
129 }
130
131 /**
132 * Returns a list of supported employees.
133 *
134 * @param boolean $strict True to fetch only the published employees.
135 * @param mixed $blank True to include an empty option. Use a string to
136 * specify the placeholder of the empty option.
137 * @param boolean $group True to group the options by status.
138 *
139 * @return array A list of employees.
140 */
141 public static function employees($strict = false, $blank = false, $group = false)
142 {
143 $options = array();
144
145 if ($blank !== false)
146 {
147 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTEMPLOYEE');
148
149 $options[] = JHtml::fetch('select.option', '', $blank);
150
151 if ($group)
152 {
153 $options[0] = array($options[0]);
154 }
155 }
156
157 $no_group = JText::translate('VAPSERVICENOGROUP');
158
159 $dbo = JFactory::getDbo();
160
161 $q = $dbo->getQuery(true);
162 $q->select($dbo->qn(array('e.id', 'e.nickname')));
163 $q->from($dbo->qn('#__vikappointments_employee', 'e'));
164
165 if ($group)
166 {
167 $q->select($dbo->qn('g.name', 'group_name'));
168 $q->leftjoin($dbo->qn('#__vikappointments_employee_group', 'g') . ' ON ' . $dbo->qn('g.id') . ' = ' . $dbo->qn('e.id_group'));
169 // sort employees by group first
170 $q->order($dbo->qn('g.ordering') . ' ASC');
171 }
172
173 $q->order($dbo->qn('e.nickname') . ' ASC');
174
175 if ($strict)
176 {
177 $q->where($dbo->qn('e.listable') . ' = 1');
178 }
179
180 $dbo->setQuery($q);
181
182 foreach ($dbo->loadObjectList() as $employee)
183 {
184 $opt = JHtml::fetch('select.option', $employee->id, $employee->nickname);
185
186 if ($group)
187 {
188 // create group key
189 $key = $employee->group_name ? $employee->group_name : $no_group;
190
191 // create group if not exists
192 if (!isset($options[$key]))
193 {
194 $options[$key] = array();
195 }
196
197 // add within group
198 $options[$key][] = $opt;
199 }
200 else
201 {
202 // add at first level
203 $options[] = $opt;
204 }
205 }
206
207 if ($group && isset($options[$no_group]))
208 {
209 // always move employees without group at the end of the list
210 $tmp = $options[$no_group];
211 unset($options[$no_group]);
212 $options[$no_group] = $tmp;
213 }
214
215 return $options;
216 }
217
218 /**
219 * Returns a list of supported services.
220 *
221 * @param boolean $strict True to fetch only the published services.
222 * @param mixed $blank True to include an empty option. Use a string to
223 * specify the placeholder of the empty option.
224 * @param boolean $group True to group the options by status.
225 *
226 * @return array A list of services.
227 */
228 public static function services($strict = false, $blank = false, $group = false)
229 {
230 $options = array();
231
232 if ($blank !== false)
233 {
234 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTSERVICE');
235
236 $options[] = JHtml::fetch('select.option', '', $blank);
237
238 if ($group)
239 {
240 $options[0] = array($options[0]);
241 }
242 }
243
244 $no_group = JText::translate('VAPSERVICENOGROUP');
245
246 $dbo = JFactory::getDbo();
247
248 $q = $dbo->getQuery(true);
249 $q->select($dbo->qn(array('s.id', 's.name')));
250 $q->from($dbo->qn('#__vikappointments_service', 's'));
251
252 if ($group)
253 {
254 $q->select($dbo->qn('g.name', 'group_name'));
255 $q->leftjoin($dbo->qn('#__vikappointments_group', 'g') . ' ON ' . $dbo->qn('g.id') . ' = ' . $dbo->qn('s.id_group'));
256 // sort services by group first
257 $q->order($dbo->qn('g.ordering') . ' ASC');
258 $q->order($dbo->qn('s.ordering') . ' ASC');
259 }
260 else
261 {
262 $q->order($dbo->qn('s.name') . ' ASC');
263 }
264
265 if ($strict)
266 {
267 $q->where($dbo->qn('s.published') . ' = 1');
268 }
269
270 $dbo->setQuery($q);
271
272 foreach ($dbo->loadObjectList() as $service)
273 {
274 $opt = JHtml::fetch('select.option', $service->id, $service->name);
275
276 if ($group)
277 {
278 // create group key
279 $key = $service->group_name ? $service->group_name : $no_group;
280
281 // create group if not exists
282 if (!isset($options[$key]))
283 {
284 $options[$key] = array();
285 }
286
287 // add within group
288 $options[$key][] = $opt;
289 }
290 else
291 {
292 // add at first level
293 $options[] = $opt;
294 }
295 }
296
297 if ($group && isset($options[$no_group]))
298 {
299 // always move services without group at the end of the list
300 $tmp = $options[$no_group];
301 unset($options[$no_group]);
302 $options[$no_group] = $tmp;
303 }
304
305 return $options;
306 }
307
308 /**
309 * Returns a list of supported option groups.
310 *
311 * @param mixed $blank True to include an empty option. Use a string to
312 * specify the placeholder of the empty option.
313 *
314 * @return array A list of option groups.
315 */
316 public static function optiongroups($blank = false)
317 {
318 $options = array();
319
320 if ($blank !== false)
321 {
322 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTGROUP');
323
324 $options[] = JHtml::fetch('select.option', '', $blank);
325 }
326
327 $dbo = JFactory::getDbo();
328
329 $q = $dbo->getQuery(true)
330 ->select($dbo->qn(array('id', 'name')))
331 ->from($dbo->qn('#__vikappointments_option_group'))
332 ->order($dbo->qn('ordering') . ' ASC');
333
334 $dbo->setQuery($q);
335
336 foreach ($dbo->loadObjectList() as $group)
337 {
338 $options[] = JHtml::fetch('select.option', $group->id, $group->name);
339 }
340
341 return $options;
342 }
343
344 /**
345 * Returns a list of supported options.
346 *
347 * @param boolean $strict True to fetch only the published options.
348 * @param mixed $blank True to include an empty option. Use a string to
349 * specify the placeholder of the empty option.
350 * @param boolean $group True to group the options by status.
351 * @param mixed $id_ser An optional ID to load only the options assigned
352 * to the given service.
353 *
354 * @return array A list of options.
355 */
356 public static function options($strict = false, $blank = false, $group = false, $id_ser = null)
357 {
358 $options = array();
359
360 if ($blank !== false)
361 {
362 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTOPTION');
363
364 $options[] = JHtml::fetch('select.option', '', $blank);
365
366 if ($group)
367 {
368 $options[0] = array($options[0]);
369 }
370 }
371
372 $dbo = JFactory::getDbo();
373
374 $q = $dbo->getQuery(true);
375 $q->select($dbo->qn(array('o.id', 'o.name', 'o.published')));
376 $q->from($dbo->qn('#__vikappointments_option', 'o'));
377
378 if ($id_ser)
379 {
380 // filter the options by service
381 $q->from($dbo->qn('#__vikappointments_ser_opt_assoc', 'a'));
382 $q->where($dbo->qn('a.id_option') . ' = ' . $dbo->qn('o.id'));
383 $q->where($dbo->qn('a.id_service') . ' = ' . (int) $id_ser);
384 }
385
386 if ($group)
387 {
388 // take published items first when we need to group them
389 $q->order($dbo->qn('o.published') . ' DESC');
390 }
391
392 $q->order($dbo->qn('o.ordering') . ' ASC');
393
394 if ($strict)
395 {
396 $q->where($dbo->qn('o.published') . ' = 1');
397 }
398
399 $dbo->setQuery($q);
400
401 foreach ($dbo->loadObjectList() as $option)
402 {
403 $opt = JHtml::fetch('select.option', $option->id, $option->name);
404
405 if ($group)
406 {
407 // create group key
408 $key = JText::translate($option->published ? 'JPUBLISHED' : 'JUNPUBLISHED');
409
410 // create status group if not exists
411 if (!isset($options[$key]))
412 {
413 $options[$key] = array();
414 }
415
416 // add within group
417 $options[$key][] = $opt;
418 }
419 else
420 {
421 // add at first level
422 $options[] = $opt;
423 }
424 }
425
426 return $options;
427 }
428
429 /**
430 * Returns a list of supported locations.
431 *
432 * @param mixed $id_employee The ID of the locations owner. Use null to ignore
433 * this filter.
434 * @param mixed $blank True to include an empty option. Use a string to
435 * specify the placeholder of the empty option.
436 * @param boolean $group True to group the locations by status.
437 *
438 * @return array A list of locations.
439 */
440 public static function locations($id_employee = 0, $blank = false, $group = false)
441 {
442 $options = array();
443
444 if ($blank !== false)
445 {
446 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTLOCATION');
447
448 $options[] = JHtml::fetch('select.option', '', $blank);
449
450 if ($group)
451 {
452 $options[0] = array($options[0]);
453 }
454 }
455
456 $dbo = JFactory::getDbo();
457
458 // get employee/global locations
459
460 $q = $dbo->getQuery(true);
461
462 $q->select('l.*')
463 ->from($dbo->qn('#__vikappointments_employee_location', 'l'));
464
465 $q->select($dbo->qn(array('c.country_name', 'c.country_2_code')))
466 ->leftjoin($dbo->qn('#__vikappointments_countries', 'c') . ' ON ' . $dbo->qn('c.id') . ' = ' . $dbo->qn('l.id_country'));
467
468 $q->select($dbo->qn(array('s.state_name', 'state_2_code')))
469 ->leftjoin($dbo->qn('#__vikappointments_states', 's') . ' ON ' . $dbo->qn('s.id') . ' = ' . $dbo->qn('l.id_state'));
470
471 $q->select($dbo->qn(array('ci.city_name', 'ci.city_2_code')))
472 ->leftjoin($dbo->qn('#__vikappointments_cities', 'ci') . ' ON ' . $dbo->qn('ci.id') . ' = ' . $dbo->qn('l.id_city'));
473
474 if ($id_employee !== null)
475 {
476 $q->where(array(
477 $dbo->qn('l.id_employee') . ' = ' . (int) $id_employee,
478 $dbo->qn('l.id_employee') . ' <= 0',
479 ), 'OR');
480 }
481
482 // load first the locations of the employee
483 $q->order($dbo->qn('l.id_employee') . ' DESC');
484 $q->order($dbo->qn('l.name') . ' ASC');
485
486 $dbo->setQuery($q);
487
488 foreach ($dbo->loadObjectList() as $l)
489 {
490 $code = $l->city_name;
491
492 if (empty($code))
493 {
494 $code = $l->state_2_code;
495
496 if (empty($code))
497 {
498 $code = $l->country_2_code;
499 }
500 }
501
502 // create dropdown option
503 $opt = JHtml::fetch('select.option', $l->id, $l->name . " ({$l->address}, {$code})");
504
505 if ($group)
506 {
507 // create group key
508 $key = $l->id_employee > 0 ? 0 : JText::translate('VAPMENUTITLEHEADER3');
509
510 // create group if not exists
511 if (!isset($options[$key]))
512 {
513 $options[$key] = array();
514 }
515
516 // add within group
517 $options[$key][] = $opt;
518 }
519 else
520 {
521 // add at first level
522 $options[] = $opt;
523 }
524 }
525
526 return $options;
527 }
528
529 /**
530 * Returns a list of supported packages groups.
531 *
532 * @param mixed $blank True to include an empty option. Use a string to
533 * specify the placeholder of the empty option.
534 *
535 * @return array A list of packages groups.
536 */
537 public static function packgroups($blank = false)
538 {
539 $options = array();
540
541 if ($blank !== false)
542 {
543 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTGROUP');
544
545 $options[] = JHtml::fetch('select.option', '', $blank);
546 }
547
548 $dbo = JFactory::getDbo();
549
550 $q = $dbo->getQuery(true)
551 ->select($dbo->qn(array('id', 'title')))
552 ->from($dbo->qn('#__vikappointments_package_group'))
553 ->order($dbo->qn('ordering') . ' ASC');
554
555 $dbo->setQuery($q);
556
557 foreach ($dbo->loadObjectList() as $group)
558 {
559 $options[] = JHtml::fetch('select.option', $group->id, $group->title);
560 }
561
562 return $options;
563 }
564
565 /**
566 * Returns a list of supported packages.
567 *
568 * @param boolean $strict True to fetch only the published packages.
569 * @param mixed $blank True to include an empty option. Use a string to
570 * specify the placeholder of the empty option.
571 * @param boolean $group True to group the packages.
572 *
573 * @return array A list of packages.
574 */
575 public static function packages($strict = false, $blank = false, $group = false)
576 {
577 $options = array();
578
579 if ($blank !== false)
580 {
581 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTPACKAGE');
582
583 $options[] = JHtml::fetch('select.option', '', $blank);
584
585 if ($group)
586 {
587 $options[0] = array($options[0]);
588 }
589 }
590
591 $no_group = JText::translate('VAPSERVICENOGROUP');
592
593 $dbo = JFactory::getDbo();
594 $config = VAPFactory::getConfig();
595
596 $q = $dbo->getQuery(true);
597 $q->select($dbo->qn(array('p.id', 'p.name', 'p.price', 'p.num_app', 'p.validity')));
598 $q->from($dbo->qn('#__vikappointments_package', 'p'));
599
600 if ($group)
601 {
602 $q->select($dbo->qn('g.title', 'group_name'));
603 $q->leftjoin($dbo->qn('#__vikappointments_package_group', 'g') . ' ON ' . $dbo->qn('g.id') . ' = ' . $dbo->qn('p.id_group'));
604 // sort packages by group first
605 $q->order($dbo->qn('g.ordering') . ' ASC');
606 }
607
608 $q->order($dbo->qn('p.ordering') . ' ASC');
609
610 if ($strict)
611 {
612 $q->where($dbo->qn('p.published') . ' = 1');
613 }
614
615 $dbo->setQuery($q);
616
617 foreach ($dbo->loadObjectList() as $package)
618 {
619 $opt = JHtml::fetch('select.option', $package->id, $package->name);
620
621 // include package cost and appointments
622 $opt->price = $package->price;
623 $opt->num_app = $package->num_app;
624 $opt->validity = $package->validity ? JHtml::fetch('date', '+' . $package->validity . ' days', $config->get('dateformat') . ' ' . $config->get('timeformat')) : '';
625
626 // build option data
627 $opt->data = 'data-price="' . $opt->price . '" data-num-app="' . $opt->num_app . '" data-validity="' . $opt->validity . '"';
628
629 if ($group)
630 {
631 // create group key
632 $key = $package->group_name ? $package->group_name : $no_group;
633
634 // create group if not exists
635 if (!isset($options[$key]))
636 {
637 $options[$key] = array();
638 }
639
640 // add within group
641 $options[$key][] = $opt;
642 }
643 else
644 {
645 // add at first level
646 $options[] = $opt;
647 }
648 }
649
650 if ($group && isset($options[$no_group]))
651 {
652 // always move packages without group at the end of the list
653 $tmp = $options[$no_group];
654 unset($options[$no_group]);
655 $options[$no_group] = $tmp;
656 }
657
658 return $options;
659 }
660
661 /**
662 * Returns a list of supported countries.
663 *
664 * @param string $pk The column to use as value.
665 * @param mixed $blank True to include an empty option. Use a string to
666 * specify the placeholder of the empty option.
667 *
668 * @return array A list of countries.
669 */
670 public static function countries($pk = 'id', $blank = false)
671 {
672 $options = array();
673
674 if ($blank !== false)
675 {
676 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTCOUNTRY');
677
678 $options[] = JHtml::fetch('select.option', '', $blank);
679 }
680
681 // iterate published countries
682 foreach (VAPLocations::getCountries('country_name') as $country)
683 {
684 // fetch option value
685 $value = isset($country[$pk]) ? $country[$pk] : $country['id'];
686
687 $options[] = JHtml::fetch('select.option', $value, $country['country_name']);
688 }
689
690 return $options;
691 }
692
693 /**
694 * Returns a list of supported states.
695 *
696 * @param integer $country The country to which the states belong.
697 * @param string $pk The column to use as value.
698 * @param mixed $blank True to include an empty option. Use a string to
699 * specify the placeholder of the empty option.
700 *
701 * @return array A list of states.
702 */
703 public static function states($country, $pk = 'id', $blank = false)
704 {
705 $options = array();
706
707 if ($blank !== false)
708 {
709 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTSTATE');
710
711 $options[] = JHtml::fetch('select.option', '', $blank);
712 }
713
714 if ($country > 0)
715 {
716 // iterate published states
717 foreach (VAPLocations::getStates($country, 'state_name') as $state)
718 {
719 // fetch option value
720 $value = isset($state[$pk]) ? $state[$pk] : $state['id'];
721
722 $options[] = JHtml::fetch('select.option', $value, $state['state_name']);
723 }
724 }
725
726 return $options;
727 }
728
729 /**
730 * Returns a list of supported cities.
731 *
732 * @param integer $state The state to which the cities belong.
733 * @param string $pk The column to use as value.
734 * @param mixed $blank True to include an empty option. Use a string to
735 * specify the placeholder of the empty option.
736 *
737 * @return array A list of cities.
738 */
739 public static function cities($state, $pk = 'id', $blank = false)
740 {
741 $options = array();
742
743 if ($blank !== false)
744 {
745 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTCITY');
746
747 $options[] = JHtml::fetch('select.option', '', $blank);
748 }
749
750 if ($state > 0)
751 {
752 // iterate published cities
753 foreach (VAPLocations::getCities($state, 'city_name') as $city)
754 {
755 // fetch option value
756 $value = isset($city[$pk]) ? $city[$pk] : $city['id'];
757
758 $options[] = JHtml::fetch('select.option', $value, $city['city_name']);
759 }
760 }
761
762 return $options;
763 }
764
765 /**
766 * Returns a list of supported coupon groups.
767 *
768 * @param mixed $blank True to include an empty option. Use a string to
769 * specify the placeholder of the empty option.
770 *
771 * @return array A list of coupon groups.
772 */
773 public static function coupongroups($blank = false)
774 {
775 $options = array();
776
777 if ($blank !== false)
778 {
779 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTGROUP');
780
781 $options[] = JHtml::fetch('select.option', '', $blank);
782 }
783
784 $dbo = JFactory::getDbo();
785
786 $q = $dbo->getQuery(true)
787 ->select($dbo->qn(array('id', 'name')))
788 ->from($dbo->qn('#__vikappointments_coupon_group'))
789 ->order($dbo->qn('ordering') . ' ASC');
790
791 $dbo->setQuery($q);
792
793 foreach ($dbo->loadObjectList() as $group)
794 {
795 $options[] = JHtml::fetch('select.option', $group->id, $group->name);
796 }
797
798 return $options;
799 }
800
801 /**
802 * Returns a list of supported coupon codes.
803 *
804 * @param mixed $blank True to include an empty option. Use a string to
805 * specify the placeholder of the empty option.
806 * @param boolean $group True to group the coupons.
807 * @param mixed $applicable The section to which the coupons are applicable.
808 *
809 * @return array A list of coupons.
810 */
811 public static function coupons($blank = false, $group = false, $applicable = null)
812 {
813 $options = array();
814
815 if ($blank !== false)
816 {
817 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTCOUPON');
818
819 $options[] = JHtml::fetch('select.option', '', $blank);
820
821 if ($group)
822 {
823 $options[0] = array($options[0]);
824 }
825 }
826
827 $no_group = JText::translate('VAPSERVICENOGROUP');
828 $currency = VAPFactory::getCurrency();
829
830 $dbo = JFactory::getDbo();
831
832 $q = $dbo->getQuery(true);
833 $q->select($dbo->qn(array('c.code', 'c.percentot', 'c.value')));
834 $q->from($dbo->qn('#__vikappointments_coupon', 'c'));
835
836 if ($group)
837 {
838 $q->select($dbo->qn('g.name', 'group_name'));
839 $q->leftjoin($dbo->qn('#__vikappointments_coupon_group', 'g') . ' ON ' . $dbo->qn('g.id') . ' = ' . $dbo->qn('c.id_group'));
840 // sort coupons by group first
841 $q->order($dbo->qn('g.ordering') . ' ASC');
842 }
843
844 if ($applicable)
845 {
846 // restrict to applicable group only
847 $q->where(array(
848 $dbo->qn('c.applicable') . ' IS NULL',
849 $dbo->qn('c.applicable') . ' = ' . $dbo->q(''),
850 $dbo->qn('c.applicable') . ' = ' . $dbo->q($applicable),
851 ), 'OR');
852 }
853
854 $q->order($dbo->qn('c.id') . ' ASC');
855
856 $dbo->setQuery($q);
857
858 foreach ($dbo->loadObjectList() as $coupon)
859 {
860 if ($coupon->value <= 0)
861 {
862 $sfx = '';
863 }
864 else if ($coupon->percentot == 1)
865 {
866 $sfx = ' (' . $coupon->value . '%)';
867 }
868 else
869 {
870 $sfx = ' (' . $currency->format($coupon->value) . ')';
871 }
872
873 $opt = JHtml::fetch('select.option', $coupon->code, $coupon->code . $sfx);
874
875 if ($group)
876 {
877 // create group key
878 $key = $coupon->group_name ? $coupon->group_name : $no_group;
879
880 // create group if not exists
881 if (!isset($options[$key]))
882 {
883 $options[$key] = array();
884 }
885
886 // add within group
887 $options[$key][] = $opt;
888 }
889 else
890 {
891 // add at first level
892 $options[] = $opt;
893 }
894 }
895
896 if ($group && isset($options[$no_group]))
897 {
898 // always move coupons without group at the end of the list
899 $tmp = $options[$no_group];
900 unset($options[$no_group]);
901 $options[$no_group] = $tmp;
902 }
903
904 return $options;
905 }
906
907 /**
908 * Returns a list of supported status codes for the given group.
909 *
910 * @param string $group The group to look for (appointments, packages or subscriptions).
911 * @param mixed $blank True to include an empty option. Use a string to specify the
912 * placeholder of the blank option.
913 *
914 * @return array A list of status codes.
915 */
916 public static function statuscodes($group = 'appointments', $blank = false)
917 {
918 $options = array();
919
920 if ($blank !== false)
921 {
922 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTSTATUS');
923
924 $options[] = JHtml::fetch('select.option', '', $blank);
925 }
926
927 $where = array();
928
929 if ($group)
930 {
931 // filter only when a group is specified
932 $where[$group] = 1;
933 }
934
935 // search status codes
936 $codes = JHtml::fetch('vaphtml.status.find', array('code', 'name'), $where);
937
938 // create list
939 foreach ($codes as $code)
940 {
941 // avoid displaying duplicate status codes in case of missing group
942 $options[$code->code] = JHtml::fetch('select.option', $code->code, $code->name);
943 }
944
945 return array_values($options);
946 }
947
948 /**
949 * Returns a list of supported taxes.
950 *
951 * @param mixed $blank True to include an empty option. Use a string to specify the
952 * placeholder of the blank option.
953 *
954 * @return array A list of taxes.
955 */
956 public static function taxes($blank = false)
957 {
958 $options = array();
959
960 if ($blank !== false)
961 {
962 $blank = is_string($blank) ? $blank : JText::translate('JGLOBAL_SELECT_AN_OPTION');
963
964 $options[] = JHtml::fetch('select.option', '', $blank);
965 }
966
967 $dbo = JFactory::getDbo();
968
969 $q = $dbo->getQuery(true)
970 ->select($dbo->qn(array('id', 'name')))
971 ->from($dbo->qn('#__vikappointments_tax'))
972 ->order($dbo->qn('name') . ' ASC');
973
974 $dbo->setQuery($q);
975
976 // create list
977 foreach ($dbo->loadObjectList() as $tax)
978 {
979 $options[] = JHtml::fetch('select.option', $tax->id, $tax->name);
980 }
981
982 return $options;
983 }
984
985 /**
986 * Returns a list of supported payment gateways for the given type.
987 *
988 * @param string $type The group to look for (appointments, packages or subscriptions).
989 * @param mixed $blank True to include an empty option. Use a string to specify the
990 * placeholder of the blank option.
991 * @param boolean $group True to group the payments by status.
992 *
993 * @return array A list of payment gateways.
994 */
995 public static function payments($type = 'appointments', $blank = false, $group = false)
996 {
997 $options = array();
998
999 if ($blank !== false)
1000 {
1001 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTPAYMENT');
1002
1003 $options[] = JHtml::fetch('select.option', '', $blank);
1004
1005 if ($group)
1006 {
1007 $options[0] = array($options[0]);
1008 }
1009 }
1010
1011 $dbo = JFactory::getDbo();
1012
1013 $q = $dbo->getQuery(true);
1014 $q->select($dbo->qn(array('id', 'name', 'published', 'charge')));
1015 $q->from($dbo->qn('#__vikappointments_gpayments'));
1016 $q->where($dbo->qn('id_employee') . ' <= 0');
1017
1018 if ($type && $type !== '*')
1019 {
1020 if ($type == 'appointments')
1021 {
1022 // allowed for appointments
1023 $q->where($dbo->qn('appointments') . ' = 1');
1024 }
1025 else
1026 {
1027 // allowed for packages
1028 $q->where($dbo->qn('subscr') . ' = 1');
1029 }
1030 }
1031
1032 if ($group)
1033 {
1034 // take published items first when we need to group them
1035 $q->order($dbo->qn('published') . ' DESC');
1036 }
1037
1038 $q->order($dbo->qn('ordering') . ' ASC');
1039
1040 $dbo->setQuery($q);
1041
1042 foreach ($dbo->loadObjectList() as $payment)
1043 {
1044 $opt = JHtml::fetch('select.option', $payment->id, $payment->name);
1045
1046 // include payment charge too
1047 $opt->charge = $payment->charge;
1048 $opt->dataCharge = 'data-charge="' . $payment->charge . '"';
1049
1050 if ($group)
1051 {
1052 // create group key
1053 $key = JText::translate($payment->published ? 'JPUBLISHED' : 'JUNPUBLISHED');
1054
1055 // create status group if not exists
1056 if (!isset($options[$key]))
1057 {
1058 $options[$key] = array();
1059 }
1060
1061 // add within group
1062 $options[$key][] = $opt;
1063 }
1064 else
1065 {
1066 // add at first level
1067 $options[] = $opt;
1068 }
1069 }
1070
1071 return $options;
1072 }
1073
1074 /**
1075 * Returns a list of supported subscriptions.
1076 *
1077 * @param integer $category The category to fetch (0 for customers, 1 for employees).
1078 * @param mixed $blank True to include an empty option. Use a string to specify the
1079 * placeholder of the blank option.
1080 * @param boolean $group True to group the subscriptions by status.
1081 *
1082 * @return array A list of subscriptions.
1083 */
1084 public static function subscriptions($category = 0, $blank = false, $group = false)
1085 {
1086 $options = array();
1087
1088 if ($blank !== false)
1089 {
1090 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTSUBSCR');
1091
1092 $options[] = JHtml::fetch('select.option', '', $blank);
1093
1094 if ($group)
1095 {
1096 $options[0] = array($options[0]);
1097 }
1098 }
1099
1100 $dbo = JFactory::getDbo();
1101
1102 $q = $dbo->getQuery(true);
1103 $q->select($dbo->qn(array('id', 'name', 'published', 'price')));
1104 $q->from($dbo->qn('#__vikappointments_subscription'));
1105 $q->where($dbo->qn('group') . ' = ' . (int) $category);
1106
1107 if ($group)
1108 {
1109 // take published items first when we need to group them
1110 $q->order($dbo->qn('published') . ' DESC');
1111 }
1112
1113 $q->order($dbo->qn('ordering') . ' ASC');
1114
1115 $dbo->setQuery($q);
1116
1117 foreach ($dbo->loadObjectList() as $subscr)
1118 {
1119 $opt = JHtml::fetch('select.option', $subscr->id, $subscr->name);
1120
1121 // include subscription price too
1122 $opt->price = $subscr->price;
1123 $opt->data = 'data-price="' . $subscr->price . '"';
1124
1125 if ($group)
1126 {
1127 // create group key
1128 $key = JText::translate($subscr->published ? 'JPUBLISHED' : 'JUNPUBLISHED');
1129
1130 // create status group if not exists
1131 if (!isset($options[$key]))
1132 {
1133 $options[$key] = array();
1134 }
1135
1136 // add within group
1137 $options[$key][] = $opt;
1138 }
1139 else
1140 {
1141 // add at first level
1142 $options[] = $opt;
1143 }
1144 }
1145
1146 return $options;
1147 }
1148
1149 /**
1150 * Returns a list of supported tags.
1151 *
1152 * @param boolean $blank True to include an empty option.
1153 *
1154 * @return array A list of logins.
1155 */
1156 public static function tags($group = null, $blank = false)
1157 {
1158 $options = array();
1159
1160 if ($blank)
1161 {
1162 $options[] = JHtml::fetch('select.option', '', JText::translate('VAPFILTERSELECTTAG'));
1163 }
1164
1165 $dbo = JFactory::getDbo();
1166
1167 $q = $dbo->getQuery(true)
1168 ->select('t.*')
1169 ->select($dbo->qn('t.id', 'value'))
1170 ->select($dbo->qn('t.name', 'text'))
1171 ->from($dbo->qn('#__vikappointments_tag', 't'))
1172 ->order($dbo->qn('t.ordering') . ' ASC');
1173
1174 if ($group)
1175 {
1176 $q->where($dbo->qn('t.group') . ' = ' . $dbo->q($group));
1177 }
1178
1179 $dbo->setQuery($q);
1180 $options = array_merge($options, $dbo->loadObjectList());
1181
1182 return $options;
1183 }
1184
1185 /**
1186 * Returns a list of supported payment gateways.
1187 *
1188 * @param boolean $blank True to include an empty option. Use a string to specify the
1189 * placeholder of the blank option.
1190 *
1191 * @return array A list of drivers.
1192 */
1193 public static function paymentdrivers($blank = false)
1194 {
1195 // get payment drivers
1196 $files = VAPApplication::getInstance()->getPaymentDrivers();
1197
1198 $options = array();
1199
1200 if ($blank !== false)
1201 {
1202 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTFILE');
1203
1204 $options[] = JHtml::fetch('select.option', '', $blank);
1205 }
1206
1207 foreach ($files as $file)
1208 {
1209 // get file name
1210 $value = basename($file);
1211 // strip file extension
1212 $text = preg_replace("/\.php$/", '', $value);
1213 // capitalize driver name
1214 $text = ucwords(str_replace('_', ' ', $text));
1215
1216 $options[] = JHtml::fetch('select.option', $value, $text);
1217 }
1218
1219 return $options;
1220 }
1221
1222 /**
1223 * Returns a list of supported SMS providers.
1224 *
1225 * @param boolean $blank True to include an empty option. Use a string to specify the
1226 * placeholder of the blank option.
1227 *
1228 * @return array A list of drivers.
1229 */
1230 public static function smsdrivers($blank = false)
1231 {
1232 // get SMS drivers
1233 $files = VAPApplication::getInstance()->getSmsDrivers();
1234
1235 $options = array();
1236
1237 if ($blank !== false)
1238 {
1239 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTFILE');
1240
1241 $options[] = JHtml::fetch('select.option', '', $blank);
1242 }
1243
1244 foreach ($files as $file)
1245 {
1246 // get file name
1247 $value = basename($file);
1248 // strip file extension
1249 $text = preg_replace("/\.php$/", '', $value);
1250 // capitalize driver name
1251 $text = ucwords(str_replace('_', ' ', $text));
1252
1253 $options[] = JHtml::fetch('select.option', $value, $text);
1254 }
1255
1256 return $options;
1257 }
1258
1259 /**
1260 * Returns a list of created cron jobs.
1261 *
1262 * @param mixed $blank True to include an empty option. Use a string to specify the
1263 * placeholder of the blank option.
1264 * @param boolean $group True to group the cron jobs by status.
1265 *
1266 * @return array A list of cron jobs.
1267 */
1268 public static function cronjobs($blank = false, $group = false)
1269 {
1270 $options = array();
1271
1272 if ($blank !== false)
1273 {
1274 $blank = is_string($blank) ? $blank : JText::translate('JGLOBAL_SELECT_AN_OPTION');
1275
1276 $options[] = JHtml::fetch('select.option', '', $blank);
1277
1278 if ($group)
1279 {
1280 $options[0] = array($options[0]);
1281 }
1282 }
1283
1284 $dbo = JFactory::getDbo();
1285
1286 $q = $dbo->getQuery(true);
1287 $q->select($dbo->qn(array('id', 'name', 'published')));
1288 $q->from($dbo->qn('#__vikappointments_cronjob'));
1289
1290 if ($group)
1291 {
1292 // take published items first when we need to group them
1293 $q->order($dbo->qn('published') . ' DESC');
1294 }
1295
1296 $q->order($dbo->qn('name') . ' ASC');
1297
1298 $dbo->setQuery($q);
1299
1300 foreach ($dbo->loadObjectList() as $job)
1301 {
1302 $opt = JHtml::fetch('select.option', $job->id, $job->name);
1303
1304 if ($group)
1305 {
1306 // create group key
1307 $key = JText::translate($job->published ? 'JPUBLISHED' : 'JUNPUBLISHED');
1308
1309 // create status group if not exists
1310 if (!isset($options[$key]))
1311 {
1312 $options[$key] = array();
1313 }
1314
1315 // add within group
1316 $options[$key][] = $opt;
1317 }
1318 else
1319 {
1320 // add at first level
1321 $options[] = $opt;
1322 }
1323 }
1324
1325 return $options;
1326 }
1327
1328 /**
1329 * Returns a list of supported cron job drivers.
1330 *
1331 * @param boolean $blank True to include an empty option. Use a string to specify the
1332 * placeholder of the blank option.
1333 *
1334 * @return array A list of drivers.
1335 */
1336 public static function crondrivers($blank = false)
1337 {
1338 // load cron framework
1339 VikAppointments::loadCronLibrary();
1340
1341 $drivers = array();
1342
1343 // load all drivers
1344 foreach (VAPCronDispatcher::includeAll() as $file => $cron)
1345 {
1346 $drivers[$file] = $cron;
1347 }
1348
1349 // sort by ascending name
1350 uasort($drivers, function($a, $b)
1351 {
1352 return strcasecmp($a->title(), $b->title());
1353 });
1354
1355 $options = array();
1356
1357 if ($blank !== false)
1358 {
1359 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTFILE');
1360
1361 $options[] = JHtml::fetch('select.option', '', $blank);
1362 }
1363
1364 // create options list
1365 foreach ($drivers as $file => $cron)
1366 {
1367 $opt = JHtml::fetch('select.option', $file, $cron->title());
1368 // register description too
1369 $opt->description = $cron->description();
1370
1371 $options[] = $opt;
1372 }
1373
1374 return $options;
1375 }
1376
1377 /**
1378 * Returns a list of supported e-mail templates.
1379 *
1380 * @param boolean $blank True to include an empty option. Use a string to specify the
1381 * placeholder of the blank option.
1382 *
1383 * @return array A list of files.
1384 */
1385 public static function mailtemplates($blank = false)
1386 {
1387 // get all existing template files
1388 $all_tmpl_files = glob(VAPHELPERS . DIRECTORY_SEPARATOR . 'mail_tmpls' . DIRECTORY_SEPARATOR . '*.php');
1389
1390 $options = array();
1391
1392 if ($blank !== false)
1393 {
1394 $blank = is_string($blank) ? $blank : JText::translate('VAPFILTERSELECTFILE');
1395
1396 $options[] = JHtml::fetch('select.option', '', $blank);
1397 }
1398
1399 foreach ($all_tmpl_files as $file)
1400 {
1401 $filename = basename($file);
1402
1403 // remove file extension
1404 $name = preg_replace("/\.php$/i", '', $filename);
1405 // remove ending "_mail_tmpl"
1406 $name = preg_replace("/_?e?mail_?tmpl$/i", '', $name);
1407 // replace dashes and underscores with spaces
1408 $name = preg_replace("/[-_]+/", ' ', $name);
1409 // capitalize words
1410 $name = ucwords(strtolower($name));
1411
1412 $opt = JHtml::fetch('select.option', $filename, $name);
1413
1414 // include file path
1415 $opt->file = $file;
1416
1417 $options[] = $opt;
1418 }
1419
1420 return $options;
1421 }
1422
1423 /**
1424 * Returns a list of supported API logins.
1425 *
1426 * @param boolean $blank True to include an empty option.
1427 *
1428 * @return array A list of logins.
1429 */
1430 public static function apilogins($blank = false)
1431 {
1432 $options = array();
1433
1434 if ($blank)
1435 {
1436 $options[] = JHtml::fetch('select.option', '', JText::translate('VAPFILTERSELECTAPP'));
1437 }
1438
1439 $dbo = JFactory::getDbo();
1440
1441 $q = $dbo->getQuery(true)
1442 ->select($dbo->qn('l.application'))
1443 ->select($dbo->qn('l.username'))
1444 ->select($dbo->qn('l.password'))
1445 ->from($dbo->qn('#__vikappointments_api_login', 'l'))
1446 ->where($dbo->qn('l.active') . ' = 1');
1447
1448 $dbo->setQuery($q);
1449
1450 foreach ($dbo->loadObjectList() as $r)
1451 {
1452 if ($r->application)
1453 {
1454 $text = $r->application . ' : ' . $r->username;
1455 }
1456 else
1457 {
1458 $text = $r->username;
1459 }
1460
1461 $value = $r->username . ';' . $r->password;
1462
1463 $options[] = JHtml::fetch('select.option', $value, $text);
1464 }
1465
1466 return $options;
1467 }
1468
1469 /**
1470 * Returns a list of supported models.
1471 *
1472 * @param boolean $blank True to include an empty option.
1473 *
1474 * @return array A list of models.
1475 */
1476 public static function models($usepath = true, $blank = false)
1477 {
1478 $options = array();
1479
1480 if ($blank)
1481 {
1482 $options[] = JHtml::fetch('select.option', '', JText::translate('VAPFILTERSELECTFILE'));
1483 }
1484
1485 foreach (glob(VAPADMIN . DIRECTORY_SEPARATOR . 'models' . DIRECTORY_SEPARATOR . '*.php') as $path)
1486 {
1487 // take only the file name and remove file extension
1488 $text = preg_replace("/\.php$/", '', basename($path));
1489
1490 if ($usepath)
1491 {
1492 // use file path as value
1493 $value = $path;
1494 }
1495 else
1496 {
1497 // use model name as value
1498 $value = $text;
1499 }
1500
1501 $options[] = JHtml::fetch('select.option', $value, $text);
1502 }
1503
1504 return $options;
1505 }
1506
1507 /**
1508 * Returns the HTML of the handle used to rearrange the table rows.
1509 * FontAwesome is required in order to display the handle icon.
1510 *
1511 * @param integer $ordering The ordering value.
1512 * @param boolean $canEdit True if the user is allowed to edit the ordering.
1513 * @param boolean $canOrder True if the table is currently sorted by "ordering" column.
1514 * @param boolean $input True if the ordering input should be included in the body.
1515 *
1516 * @return string The HTML of the handle.
1517 */
1518 public static function sorthandle($ordering, $canEdit = true, $canOrder = true, $input = true)
1519 {
1520 $icon_class = $icon_title = '';
1521
1522 if (!$canEdit)
1523 {
1524 $icon_class = ' inactive';
1525 }
1526 else if (!$canOrder)
1527 {
1528 $icon_class = ' inactive tip-top hasTooltip';
1529 $icon_title = JText::translate('JORDERINGDISABLED');
1530 }
1531
1532 $html = '<span class="sortable-handler' . $icon_class . '" title="' . $icon_title . '">
1533 <i class="fas fa-ellipsis-v medium-big" aria-hidden="true"></i>
1534 </span>';
1535
1536 if ($canEdit && $canOrder && $input)
1537 {
1538 $html .= '<input type="hidden" name="order[]" value="' . $ordering . '" />';
1539 }
1540
1541 return $html;
1542 }
1543
1544 /**
1545 * Returns a HTML block representing the status of an image.
1546 *
1547 * @param string $image The relative path of the image.
1548 * @param boolean $preview True to enable the preview (only if image exists).
1549 *
1550 * @return string The resulting HTML.
1551 */
1552 public static function imagestatus($image, $preview = true)
1553 {
1554 if (empty($image))
1555 {
1556 // image not uploaded
1557 $status = 2;
1558 $icon = 'fas fa-image no';
1559 }
1560 else if (!is_file(VAPMEDIA . DIRECTORY_SEPARATOR . $image))
1561 {
1562 // image not found
1563 $status = 0;
1564 $icon = 'fas fa-eye-slash no';
1565 }
1566 else
1567 {
1568 // image ok
1569 $status = 1;
1570 $icon = 'fas fa-image ok';
1571 }
1572
1573 $title = JText::translate('VAPIMAGESTATUS' . $status);
1574
1575 // create HTML icon status
1576 $html = '<i class="' . $icon . ' big-2x" title="' . htmlspecialchars($title) . '"></i>';
1577
1578 if ($status == 1 && $preview)
1579 {
1580 // wrap icon within a link to support preview
1581 $html = '<a href="' . VAPMEDIA_URI . $image . '" class="modal" target="_blank">' . $html . '</a>';
1582 }
1583
1584 return $html;
1585 }
1586
1587 /**
1588 * Creates an action link to display and toggle the status of a column.
1589 *
1590 * @param mixed $state The current state of the column or an array/object
1591 * holding the state and the publishing dates (start, end).
1592 * @param mixed $id An optional record ID.
1593 * @param string $task The task to reach to perform the status change.
1594 * @param mixed $can The user permissions. Leave null to auto-detect.
1595 * @param array $args An associative array used to extend the query string.
1596 * @param string $title An optional title to attach to the state icon.
1597 *
1598 * @return string The resulting HTML.
1599 */
1600 public static function stateaction($state, $id = null, $task = null, $can = null, array $args = array(), $title = '')
1601 {
1602 if ($task && is_null($can))
1603 {
1604 // retrieve permissions
1605 $can = JFactory::getUser()->authorise('core.edit.state', 'com_vikappointments');
1606 }
1607
1608 // check if we have an object
1609 if (is_array($state) || is_object($state))
1610 {
1611 $data = new JObject($state);
1612
1613 // try to extract state and publishing dates
1614 $state = $data->get('state', 0);
1615 $start = $data->get('start', null);
1616 $end = $data->get('end', null);
1617 }
1618 else
1619 {
1620 $start = $end = null;
1621 }
1622
1623 // fetch class status
1624 if ($state)
1625 {
1626 // published
1627 $state_class = 'fas fa-check-circle ok';
1628
1629 $now = JFactory::getDate()->toSql();
1630
1631 // check whether the start publishing is in the future
1632 if (!VAPDateHelper::isNull($start) && $now < $start)
1633 {
1634 // not yet started
1635 $state_class = 'fas fa-minus-circle warn';
1636 // override title
1637 $start = JHtml::fetch('date', $start, 'DATE_FORMAT_LC3');
1638 $title = JText::sprintf('VAP_PUBL_START_ON', $start);
1639 }
1640 else if (!VAPDateHelper::isNull($end) && $now > $end)
1641 {
1642 // expired
1643 $state_class = 'fas fa-minus-circle warn';
1644 // override title
1645 $end = JHtml::fetch('date', $end, 'DATE_FORMAT_LC3');
1646 $title = JText::sprintf('VAP_PUBL_END_ON', $end);
1647 }
1648 }
1649 else
1650 {
1651 // unpublished
1652 $state_class = 'fas fa-dot-circle no';
1653 }
1654
1655 $class = $state_class . ' big';
1656
1657 if ($title)
1658 {
1659 // define title attribute
1660 $title = ' title="' . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '"';
1661 $class .= ' hasTooltip';
1662 }
1663
1664 // create badge icon
1665 $html = '<i class="' . $class . '"' . $title . '></i>';
1666
1667 if ($can && $task && $id)
1668 {
1669 // create action URL
1670 $url = 'index.php?option=com_vikappointments&task=';
1671
1672 if (preg_match("/(^|\.)publish$/i", $task))
1673 {
1674 // we are using the native "publish" and "unpublish" tasks
1675 if ($state)
1676 {
1677 // replace "publish" with "unpublish"
1678 $task = preg_replace("/(^|\.)publish$/i", '$1unpublish', $task);
1679 }
1680
1681 $url .= $task;
1682 }
1683 else
1684 {
1685 // we are using a custom task, so we need to defin the new state
1686 $url .= $task . '&state=' . ($state ? 0 : 1);
1687 }
1688
1689 // append record ID
1690 $url .= '&cid[]=' . $id;
1691
1692 if ($args)
1693 {
1694 // extend the query string with the given parameters
1695 $url .= '&' . http_build_query($args);
1696 }
1697
1698 // append CSRF token
1699 $url = VAPApplication::getInstance()->addUrlCSRF($url, $xhtml = true);
1700
1701 // wrap badge within a link to implement status change
1702 $html = '<a href="' . $url . '">' . $html . '</a>';
1703 }
1704
1705 return $html;
1706 }
1707 }
1708