PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.83
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.83
51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 51.1.46 51.1.47 51.1.49 All 37 releases
king-addons / includes / widgets / Event_Calendar / Event_Calendar.php

Event_Calendar.php in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.83, at includes/widgets/Event_Calendar/Event_Calendar.php

803 lines 25.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Event Calendar Widget (Free).
4 *
5 * @package King_Addons
6 */
7
8 namespace King_Addons;
9
10 use Elementor\Controls_Manager;
11 use Elementor\Group_Control_Border;
12 use Elementor\Group_Control_Box_Shadow;
13 use Elementor\Group_Control_Typography;
14 use Elementor\Repeater;
15 use Elementor\Widget_Base;
16
17 if (!defined('ABSPATH')) {
18 exit;
19 }
20
21 /**
22 * Renders an event calendar list.
23 */
24 class Event_Calendar extends Widget_Base
25 {
26 /**
27 * Widget slug.
28 *
29 * @return string
30 */
31 public function get_name(): string
32 {
33 return 'king-addons-event-calendar';
34 }
35
36 /**
37 * Widget title.
38 *
39 * @return string
40 */
41 public function get_title(): string
42 {
43 return esc_html__('Event Calendar', 'king-addons');
44 }
45
46 /**
47 * Widget icon.
48 *
49 * @return string
50 */
51 public function get_icon(): string
52 {
53 return 'king-addons-icon king-addons-event-calendar';
54 }
55
56 /**
57 * Style dependencies.
58 *
59 * @return array<int, string>
60 */
61 public function get_style_depends(): array
62 {
63 return [
64 KING_ADDONS_ASSETS_UNIQUE_KEY . '-event-calendar-style',
65 ];
66 }
67
68 /**
69 * Script dependencies.
70 *
71 * @return array<int, string>
72 */
73 public function get_script_depends(): array
74 {
75 return [
76 KING_ADDONS_ASSETS_UNIQUE_KEY . '-event-calendar-script',
77 ];
78 }
79
80 /**
81 * Categories.
82 *
83 * @return array<int, string>
84 */
85 public function get_categories(): array
86 {
87 return ['king-addons'];
88 }
89
90 /**
91 * Keywords.
92 *
93 * @return array<int, string>
94 */
95 public function get_keywords(): array
96 {
97 return ['event', 'calendar', 'schedule', 'list'];
98 }
99
100 public function get_custom_help_url()
101 {
102 return 'mailto:bug@kingaddons.com?subject=Bug Report - King Addons&body=Please describe the issue';
103 }
104
105 /**
106 * Register controls.
107 *
108 * @return void
109 */
110 public function register_controls(): void
111 {
112 $this->register_content_controls();
113 $this->register_layout_controls();
114 $this->register_style_card_controls();
115 $this->register_style_text_controls();
116 $this->register_style_badge_controls();
117 $this->register_pro_controls();
118 $this->register_pro_notice_controls();
119 }
120
121 /**
122 * Register Pro-only controls placeholder.
123 *
124 * The Pro version overrides this method to add premium controls without
125 * overriding the full `register_controls()` flow.
126 *
127 * @return void
128 */
129 public function register_pro_controls(): void
130 {
131 // Intentionally empty in Free.
132 }
133
134 /**
135 * Filter wrapper attributes for the widget output.
136 *
137 * @param array<string, string> $attributes Wrapper attributes.
138 * @param array<string, mixed> $settings Widget settings.
139 * @param array<int, array<string, mixed>> $events Events list.
140 *
141 * @return array<string, string>
142 */
143 public function filter_wrapper_attributes(array $attributes, array $settings, array $events): array
144 {
145 return $attributes;
146 }
147
148 /**
149 * Render Pro-only header content placeholder.
150 *
151 * @param array<string, mixed> $settings Widget settings.
152 * @param array<int, array<string, mixed>> $events Events list.
153 *
154 * @return void
155 */
156 public function render_pro_header(array $settings, array $events): void
157 {
158 // Intentionally empty in Free.
159 }
160
161 /**
162 * Render widget output.
163 *
164 * @return void
165 */
166 public function render(): void
167 {
168 $settings = $this->get_settings_for_display();
169 $events = $this->get_events($settings);
170
171 if (empty($events)) {
172 return;
173 }
174
175 $attributes = [
176 'class' => 'king-addons-event-calendar',
177 'data-has-filters' => 'no',
178 ];
179 $attributes = $this->filter_wrapper_attributes($attributes, $settings, $events);
180
181 $attr_pairs = [];
182 foreach ($attributes as $key => $value) {
183 $attr_pairs[] = esc_attr($key) . '="' . esc_attr($value) . '"';
184 }
185
186 ?>
187 <div <?php echo implode(' ', $attr_pairs); ?>>
188 <?php $this->render_pro_header($settings, $events); ?>
189 <div class="king-addons-event-calendar__list">
190 <?php foreach ($events as $event) : ?>
191 <?php $this->render_event($event, $settings); ?>
192 <?php endforeach; ?>
193 </div>
194 </div>
195 <?php
196 }
197
198 /**
199 * Content controls.
200 *
201 * @return void
202 */
203 protected function register_content_controls(): void
204 {
205 $this->start_controls_section(
206 'kng_events_section',
207 [
208 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Events', 'king-addons'),
209 'tab' => Controls_Manager::TAB_CONTENT,
210 ]
211 );
212
213 $repeater = new Repeater();
214
215 $repeater->add_control(
216 'kng_event_title',
217 [
218 'label' => esc_html__('Title', 'king-addons'),
219 'type' => Controls_Manager::TEXT,
220 'default' => esc_html__('Event title', 'king-addons'),
221 ]
222 );
223
224 $repeater->add_control(
225 'kng_event_date',
226 [
227 'label' => esc_html__('Start Date & Time', 'king-addons'),
228 'type' => Controls_Manager::DATE_TIME,
229 'picker_options' => ['enableTime' => true],
230 ]
231 );
232
233 $repeater->add_control(
234 'kng_event_end_date',
235 [
236 'label' => esc_html__('End Date & Time', 'king-addons'),
237 'type' => Controls_Manager::DATE_TIME,
238 'picker_options' => ['enableTime' => true],
239 ]
240 );
241
242 $repeater->add_control(
243 'kng_event_time_label',
244 [
245 'label' => esc_html__('Time Label', 'king-addons'),
246 'type' => Controls_Manager::TEXT,
247 'placeholder' => esc_html__('10:00 - 12:00', 'king-addons'),
248 ]
249 );
250
251 $repeater->add_control(
252 'kng_event_location',
253 [
254 'label' => esc_html__('Location', 'king-addons'),
255 'type' => Controls_Manager::TEXT,
256 'placeholder' => esc_html__('Main Hall', 'king-addons'),
257 ]
258 );
259
260 $repeater->add_control(
261 'kng_event_category',
262 [
263 'label' => esc_html__('Category', 'king-addons'),
264 'type' => Controls_Manager::TEXT,
265 'placeholder' => esc_html__('Conference', 'king-addons'),
266 ]
267 );
268
269 $repeater->add_control(
270 'kng_event_color',
271 [
272 'label' => esc_html__('Category Color', 'king-addons'),
273 'type' => Controls_Manager::COLOR,
274 ]
275 );
276
277 $repeater->add_control(
278 'kng_event_description',
279 [
280 'label' => esc_html__('Description', 'king-addons'),
281 'type' => Controls_Manager::TEXTAREA,
282 'rows' => 3,
283 ]
284 );
285
286 $repeater->add_control(
287 'kng_event_link',
288 [
289 'label' => esc_html__('Event Link', 'king-addons'),
290 'type' => Controls_Manager::URL,
291 'placeholder' => esc_html__('https://', 'king-addons'),
292 ]
293 );
294
295 $this->add_control(
296 'kng_events',
297 [
298 'label' => esc_html__('Events', 'king-addons'),
299 'type' => Controls_Manager::REPEATER,
300 'fields' => $repeater->get_controls(),
301 'default' => [],
302 ]
303 );
304
305 $this->add_control(
306 'kng_cta_text',
307 [
308 'label' => esc_html__('Button Text', 'king-addons'),
309 'type' => Controls_Manager::TEXT,
310 'default' => esc_html__('View details', 'king-addons'),
311 ]
312 );
313
314 $this->add_control(
315 'kng_show_button',
316 [
317 'label' => esc_html__('Show Button', 'king-addons'),
318 'type' => Controls_Manager::SWITCHER,
319 'return_value' => 'yes',
320 'default' => 'yes',
321 ]
322 );
323
324 $this->end_controls_section();
325 }
326
327 /**
328 * Layout controls.
329 *
330 * @return void
331 */
332 protected function register_layout_controls(): void
333 {
334 $this->start_controls_section(
335 'kng_layout_section',
336 [
337 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Layout', 'king-addons'),
338 'tab' => Controls_Manager::TAB_CONTENT,
339 ]
340 );
341
342 $this->add_control(
343 'kng_show_description',
344 [
345 'label' => esc_html__('Show Description', 'king-addons'),
346 'type' => Controls_Manager::SWITCHER,
347 'return_value' => 'yes',
348 'default' => 'yes',
349 ]
350 );
351
352 $this->add_control(
353 'kng_show_location',
354 [
355 'label' => esc_html__('Show Location', 'king-addons'),
356 'type' => Controls_Manager::SWITCHER,
357 'return_value' => 'yes',
358 'default' => 'yes',
359 ]
360 );
361
362 $this->add_control(
363 'kng_show_time',
364 [
365 'label' => esc_html__('Show Time', 'king-addons'),
366 'type' => Controls_Manager::SWITCHER,
367 'return_value' => 'yes',
368 'default' => 'yes',
369 ]
370 );
371
372 $this->end_controls_section();
373 }
374
375 /**
376 * Card style controls.
377 *
378 * @return void
379 */
380 protected function register_style_card_controls(): void
381 {
382 $this->start_controls_section(
383 'kng_style_card_section',
384 [
385 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Card', 'king-addons'),
386 'tab' => Controls_Manager::TAB_STYLE,
387 ]
388 );
389
390 $this->add_control(
391 'kng_card_bg',
392 [
393 'label' => esc_html__('Background', 'king-addons'),
394 'type' => Controls_Manager::COLOR,
395 'selectors' => [
396 '{{WRAPPER}} .king-addons-event-calendar__card' => 'background-color: {{VALUE}};',
397 ],
398 ]
399 );
400
401 $this->add_group_control(
402 Group_Control_Border::get_type(),
403 [
404 'name' => 'kng_card_border',
405 'selector' => '{{WRAPPER}} .king-addons-event-calendar__card',
406 ]
407 );
408
409 $this->add_control(
410 'kng_card_radius',
411 [
412 'label' => esc_html__('Border Radius', 'king-addons'),
413 'type' => Controls_Manager::SLIDER,
414 'size_units' => ['px', '%'],
415 'range' => [
416 'px' => ['min' => 0, 'max' => 40],
417 '%' => ['min' => 0, 'max' => 100],
418 ],
419 'selectors' => [
420 '{{WRAPPER}} .king-addons-event-calendar__card' => 'border-radius: {{SIZE}}{{UNIT}};',
421 ],
422 ]
423 );
424
425 $this->add_group_control(
426 Group_Control_Box_Shadow::get_type(),
427 [
428 'name' => 'kng_card_shadow',
429 'selector' => '{{WRAPPER}} .king-addons-event-calendar__card',
430 ]
431 );
432
433 $this->add_responsive_control(
434 'kng_card_padding',
435 [
436 'label' => esc_html__('Padding', 'king-addons'),
437 'type' => Controls_Manager::DIMENSIONS,
438 'size_units' => ['px', 'em'],
439 'selectors' => [
440 '{{WRAPPER}} .king-addons-event-calendar__card' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
441 ],
442 ]
443 );
444
445 $this->end_controls_section();
446 }
447
448 /**
449 * Text style controls.
450 *
451 * @return void
452 */
453 protected function register_style_text_controls(): void
454 {
455 $this->start_controls_section(
456 'kng_style_text_section',
457 [
458 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Text', 'king-addons'),
459 'tab' => Controls_Manager::TAB_STYLE,
460 ]
461 );
462
463 $this->add_group_control(
464 Group_Control_Typography::get_type(),
465 [
466 'name' => 'kng_title_typography',
467 'selector' => '{{WRAPPER}} .king-addons-event-calendar__title',
468 ]
469 );
470
471 $this->add_control(
472 'kng_title_color',
473 [
474 'label' => esc_html__('Title Color', 'king-addons'),
475 'type' => Controls_Manager::COLOR,
476 'selectors' => [
477 '{{WRAPPER}} .king-addons-event-calendar__title' => 'color: {{VALUE}};',
478 ],
479 ]
480 );
481
482 $this->add_group_control(
483 Group_Control_Typography::get_type(),
484 [
485 'name' => 'kng_meta_typography',
486 'selector' => '{{WRAPPER}} .king-addons-event-calendar__meta',
487 ]
488 );
489
490 $this->add_control(
491 'kng_meta_color',
492 [
493 'label' => esc_html__('Meta Color', 'king-addons'),
494 'type' => Controls_Manager::COLOR,
495 'selectors' => [
496 '{{WRAPPER}} .king-addons-event-calendar__meta' => 'color: {{VALUE}};',
497 ],
498 ]
499 );
500
501 $this->add_group_control(
502 Group_Control_Typography::get_type(),
503 [
504 'name' => 'kng_desc_typography',
505 'selector' => '{{WRAPPER}} .king-addons-event-calendar__description',
506 ]
507 );
508
509 $this->add_control(
510 'kng_desc_color',
511 [
512 'label' => esc_html__('Description Color', 'king-addons'),
513 'type' => Controls_Manager::COLOR,
514 'selectors' => [
515 '{{WRAPPER}} .king-addons-event-calendar__description' => 'color: {{VALUE}};',
516 ],
517 ]
518 );
519
520 $this->add_group_control(
521 Group_Control_Typography::get_type(),
522 [
523 'name' => 'kng_button_typography',
524 'selector' => '{{WRAPPER}} .king-addons-event-calendar__button',
525 ]
526 );
527
528 $this->add_control(
529 'kng_button_color',
530 [
531 'label' => esc_html__('Button Text Color', 'king-addons'),
532 'type' => Controls_Manager::COLOR,
533 'selectors' => [
534 '{{WRAPPER}} .king-addons-event-calendar__button' => 'color: {{VALUE}};',
535 ],
536 ]
537 );
538
539 $this->add_control(
540 'kng_button_bg',
541 [
542 'label' => esc_html__('Button Background', 'king-addons'),
543 'type' => Controls_Manager::COLOR,
544 'selectors' => [
545 '{{WRAPPER}} .king-addons-event-calendar__button' => 'background-color: {{VALUE}};',
546 ],
547 ]
548 );
549
550 $this->add_control(
551 'kng_button_radius',
552 [
553 'label' => esc_html__('Button Radius', 'king-addons'),
554 'type' => Controls_Manager::SLIDER,
555 'size_units' => ['px', '%'],
556 'range' => [
557 'px' => ['min' => 0, 'max' => 40],
558 '%' => ['min' => 0, 'max' => 100],
559 ],
560 'selectors' => [
561 '{{WRAPPER}} .king-addons-event-calendar__button' => 'border-radius: {{SIZE}}{{UNIT}};',
562 ],
563 ]
564 );
565
566 $this->end_controls_section();
567 }
568
569 /**
570 * Badge style controls.
571 *
572 * @return void
573 */
574 protected function register_style_badge_controls(): void
575 {
576 $this->start_controls_section(
577 'kng_style_badge_section',
578 [
579 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Date Badge', 'king-addons'),
580 'tab' => Controls_Manager::TAB_STYLE,
581 ]
582 );
583
584 $this->add_group_control(
585 Group_Control_Typography::get_type(),
586 [
587 'name' => 'kng_badge_typography',
588 'selector' => '{{WRAPPER}} .king-addons-event-calendar__badge',
589 ]
590 );
591
592 $this->add_control(
593 'kng_badge_text_color',
594 [
595 'label' => esc_html__('Text Color', 'king-addons'),
596 'type' => Controls_Manager::COLOR,
597 'selectors' => [
598 '{{WRAPPER}} .king-addons-event-calendar__badge' => 'color: {{VALUE}};',
599 ],
600 ]
601 );
602
603 $this->add_control(
604 'kng_badge_bg',
605 [
606 'label' => esc_html__('Background', 'king-addons'),
607 'type' => Controls_Manager::COLOR,
608 'selectors' => [
609 '{{WRAPPER}} .king-addons-event-calendar__badge' => 'background-color: {{VALUE}};',
610 ],
611 ]
612 );
613
614 $this->add_control(
615 'kng_badge_radius',
616 [
617 'label' => esc_html__('Radius', 'king-addons'),
618 'type' => Controls_Manager::SLIDER,
619 'size_units' => ['px', '%'],
620 'range' => [
621 'px' => ['min' => 0, 'max' => 30],
622 '%' => ['min' => 0, 'max' => 100],
623 ],
624 'selectors' => [
625 '{{WRAPPER}} .king-addons-event-calendar__badge' => 'border-radius: {{SIZE}}{{UNIT}};',
626 ],
627 ]
628 );
629
630 $this->end_controls_section();
631 }
632
633 /**
634 * Render pro notice.
635 *
636 * @return void
637 */
638 public function register_pro_notice_controls(): void
639 {
640 if (!king_addons_can_use_pro()) {
641 Core::renderProFeaturesSection($this, '', Controls_Manager::RAW_HTML, 'event-calendar', [
642 'Filters (category, search, upcoming only)',
643 'Date range filter and compact layout',
644 'Hover animations and category chips',
645 'Highlight ongoing events',
646 ]);
647 }
648 }
649
650 /**
651 * Get events parsed and sorted.
652 *
653 * @param array<string, mixed> $settings Settings.
654 *
655 * @return array<int, array<string, mixed>>
656 */
657 protected function get_events(array $settings): array
658 {
659 $events = [];
660 if (empty($settings['kng_events']) || !is_array($settings['kng_events'])) {
661 return $events;
662 }
663
664 foreach ($settings['kng_events'] as $item) {
665 $start = isset($item['kng_event_date']) ? strtotime((string) $item['kng_event_date']) : null;
666 $end = isset($item['kng_event_end_date']) ? strtotime((string) $item['kng_event_end_date']) : null;
667
668 $events[] = [
669 'title' => $item['kng_event_title'] ?? '',
670 'start' => $start,
671 'end' => $end,
672 'time_label' => $item['kng_event_time_label'] ?? '',
673 'location' => $item['kng_event_location'] ?? '',
674 'category' => $item['kng_event_category'] ?? '',
675 'color' => $item['kng_event_color'] ?? '',
676 'description' => $item['kng_event_description'] ?? '',
677 'link' => $item['kng_event_link'] ?? [],
678 ];
679 }
680
681 usort(
682 $events,
683 static function ($a, $b) {
684 return ($a['start'] ?? 0) <=> ($b['start'] ?? 0);
685 }
686 );
687
688 return $events;
689 }
690
691 /**
692 * Render single event card.
693 *
694 * @param array<string, mixed> $event Event data.
695 * @param array<string, mixed> $settings Settings.
696 *
697 * @return void
698 */
699 protected function render_event(array $event, array $settings): void
700 {
701 $this->render_event_base($event, $settings);
702 }
703
704 /**
705 * Render single event card base implementation.
706 *
707 * This method exists to allow the Pro version to extend event rendering
708 * without calling `parent::` methods.
709 *
710 * @param array<string, mixed> $event Event data.
711 * @param array<string, mixed> $settings Settings.
712 *
713 * @return void
714 */
715 protected function render_event_base(array $event, array $settings): void
716 {
717 $start_ts = $event['start'] ?? null;
718 $end_ts = $event['end'] ?? null;
719 $date_day = $start_ts ? date_i18n('d', $start_ts) : '';
720 $date_month = $start_ts ? date_i18n('M', $start_ts) : '';
721 $time_label = $event['time_label'] ?: ($start_ts ? date_i18n('H:i', $start_ts) : '');
722
723 $link = $event['link']['url'] ?? '';
724 $link_attrs = '';
725 if (!empty($link)) {
726 $is_external = !empty($event['link']['is_external']);
727 $nofollow = !empty($event['link']['nofollow']);
728 $rels = [];
729 if ($is_external) {
730 $rels[] = 'noopener';
731 $rels[] = 'noreferrer';
732 }
733 if ($nofollow) {
734 $rels[] = 'nofollow';
735 }
736 $rel_attr = !empty($rels) ? ' rel="' . esc_attr(implode(' ', array_unique($rels))) . '"' : '';
737 $target_attr = $is_external ? ' target="_blank"' : '';
738 $link_attrs = 'href="' . esc_url($link) . '"' . $target_attr . $rel_attr;
739 }
740
741 $item_classes = $event['item_classes'] ?? ['king-addons-event-calendar__item'];
742 $card_classes = $event['card_classes'] ?? ['king-addons-event-calendar__card'];
743 ?>
744 <article class="<?php echo esc_attr(implode(' ', $item_classes)); ?>"
745 data-date-start="<?php echo esc_attr($start_ts ?? ''); ?>"
746 data-date-end="<?php echo esc_attr($end_ts ?? ''); ?>"
747 data-category="<?php echo esc_attr($event['category']); ?>"
748 data-title="<?php echo esc_attr($event['title']); ?>">
749 <div class="<?php echo esc_attr(implode(' ', $card_classes)); ?>">
750 <div class="king-addons-event-calendar__badge" style="<?php echo $event['color'] ? 'background-color:' . esc_attr($event['color']) . ';' : ''; ?>">
751 <span class="king-addons-event-calendar__badge-day"><?php echo esc_html($date_day); ?></span>
752 <span class="king-addons-event-calendar__badge-month"><?php echo esc_html($date_month); ?></span>
753 </div>
754 <div class="king-addons-event-calendar__body">
755 <div class="king-addons-event-calendar__header">
756 <h3 class="king-addons-event-calendar__title"><?php echo esc_html($event['title']); ?></h3>
757 <?php if (!empty($event['category'])) : ?>
758 <span class="king-addons-event-calendar__chip" style="<?php echo $event['color'] ? 'color:' . esc_attr($event['color']) . ';border-color:' . esc_attr($event['color']) . ';' : ''; ?>">
759 <?php echo esc_html($event['category']); ?>
760 </span>
761 <?php endif; ?>
762 </div>
763 <div class="king-addons-event-calendar__meta">
764 <?php if (($settings['kng_show_time'] ?? 'yes') === 'yes' && ($time_label || $end_ts)) : ?>
765 <span class="king-addons-event-calendar__meta-item">
766 <?php echo esc_html($time_label); ?>
767 <?php if ($end_ts) : ?>
768 <?php echo ' - ' . esc_html(date_i18n('H:i', $end_ts)); ?>
769 <?php endif; ?>
770 </span>
771 <?php endif; ?>
772 <?php if (($settings['kng_show_location'] ?? 'yes') === 'yes' && !empty($event['location'])) : ?>
773 <span class="king-addons-event-calendar__meta-item">
774 <?php echo esc_html($event['location']); ?>
775 </span>
776 <?php endif; ?>
777 </div>
778 <?php if (($settings['kng_show_description'] ?? 'yes') === 'yes' && !empty($event['description'])) : ?>
779 <div class="king-addons-event-calendar__description">
780 <?php echo esc_html($event['description']); ?>
781 </div>
782 <?php endif; ?>
783 <?php if (($settings['kng_show_button'] ?? 'yes') === 'yes' && !empty($link_attrs)) : ?>
784 <div class="king-addons-event-calendar__actions">
785 <a class="king-addons-event-calendar__button" <?php echo $link_attrs; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
786 <?php echo esc_html($settings['kng_cta_text'] ?? esc_html__('View details', 'king-addons')); ?>
787 </a>
788 </div>
789 <?php endif; ?>
790 </div>
791 </div>
792 </article>
793 <?php
794 }
795 }
796
797
798
799
800
801
802
803