PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.65
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.65
51.1.86 51.1.84 51.1.85 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 All 40 releases
king-addons / includes / widgets / Sticky_Contact_Bar / Sticky_Contact_Bar.php

Sticky_Contact_Bar.php in King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder 51.1.65, at includes/widgets/Sticky_Contact_Bar/Sticky_Contact_Bar.php

842 lines 27.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Sticky Contact Bar 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\Icons_Manager;
15 use Elementor\Repeater;
16 use Elementor\Widget_Base;
17
18 if (!defined('ABSPATH')) {
19 exit;
20 }
21
22 /**
23 * Renders a sticky contact bar with quick-action channels.
24 */
25 class Sticky_Contact_Bar extends Widget_Base
26 {
27 /**
28 * Widget slug.
29 *
30 * @return string
31 */
32 public function get_name(): string
33 {
34 return 'king-addons-sticky-contact-bar';
35 }
36
37 /**
38 * Widget title.
39 *
40 * @return string
41 */
42 public function get_title(): string
43 {
44 return esc_html__('Sticky Contact Bar', 'king-addons');
45 }
46
47 /**
48 * Widget icon.
49 *
50 * @return string
51 */
52 public function get_icon(): string
53 {
54 return 'king-addons-icon king-addons-sticky-contact-bar';
55 }
56
57 /**
58 * Style dependencies.
59 *
60 * @return array<int, string>
61 */
62 public function get_style_depends(): array
63 {
64 return [
65 KING_ADDONS_ASSETS_UNIQUE_KEY . '-sticky-contact-bar-style',
66 ];
67 }
68
69 /**
70 * Script dependencies.
71 *
72 * @return array<int, string>
73 */
74 public function get_script_depends(): array
75 {
76 return [
77 KING_ADDONS_ASSETS_UNIQUE_KEY . '-sticky-contact-bar-script',
78 ];
79 }
80
81 /**
82 * Categories.
83 *
84 * @return array<int, string>
85 */
86 public function get_categories(): array
87 {
88 return ['king-addons'];
89 }
90
91 /**
92 * Keywords.
93 *
94 * @return array<int, string>
95 */
96 public function get_keywords(): array
97 {
98 return ['contact', 'sticky', 'whatsapp', 'telegram', 'messenger'];
99 }
100
101 public function get_custom_help_url()
102 {
103 return 'mailto:[email protected]?subject=Bug Report - King Addons&body=Please describe the issue';
104 }
105
106 /**
107 * Register controls.
108 *
109 * @return void
110 */
111 public function register_controls(): void
112 {
113 $this->register_content_controls();
114 $this->register_style_controls();
115 $this->register_pro_notice_controls();
116 }
117
118 /**
119 * Render widget output.
120 *
121 * @return void
122 */
123 public function render(): void
124 {
125 $settings = $this->get_settings_for_display();
126 $channels = $this->prepare_channels($settings['kng_channels'] ?? []);
127
128 if (empty($channels)) {
129 return;
130 }
131
132 $attrs = $this->get_wrapper_attributes($settings);
133 ?>
134 <div class="king-addons-sticky-contact-bar" <?php echo $attrs; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
135 <?php if (($settings['kng_show_status'] ?? 'yes') === 'yes') : ?>
136 <div class="king-addons-sticky-contact-bar__status" role="status" aria-live="polite">
137 <span class="king-addons-sticky-contact-bar__dot" aria-hidden="true"></span>
138 <span class="king-addons-sticky-contact-bar__status-text">
139 <?php echo esc_html($settings['kng_status_online_label'] ?? esc_html__('We are online', 'king-addons')); ?>
140 </span>
141 </div>
142 <?php endif; ?>
143
144 <?php if (!empty($settings['kng_title']) && ($settings['kng_show_labels'] ?? 'yes') === 'yes') : ?>
145 <div class="king-addons-sticky-contact-bar__title">
146 <?php echo esc_html($settings['kng_title']); ?>
147 </div>
148 <?php endif; ?>
149
150 <div class="king-addons-sticky-contact-bar__list">
151 <?php foreach ($channels as $channel) : ?>
152 <?php
153 $rel = $channel['is_external'] ? 'noopener noreferrer' : 'nofollow';
154 ?>
155 <a
156 class="king-addons-sticky-contact-bar__item"
157 data-availability="<?php echo esc_attr($channel['availability']); ?>"
158 data-channel="<?php echo esc_attr($channel['type']); ?>"
159 data-device="<?php echo esc_attr($channel['device']); ?>"
160 href="<?php echo esc_url($channel['url']); ?>"
161 <?php echo $channel['is_external'] ? 'target="_blank"' : ''; ?>
162 rel="<?php echo esc_attr($rel); ?>"
163 >
164 <?php if (!empty($channel['icon'])) : ?>
165 <span class="king-addons-sticky-contact-bar__icon">
166 <?php Icons_Manager::render_icon($channel['icon'], ['aria-hidden' => 'true']); ?>
167 </span>
168 <?php endif; ?>
169 <?php if (($settings['kng_show_labels'] ?? 'yes') === 'yes') : ?>
170 <span class="king-addons-sticky-contact-bar__label">
171 <?php echo esc_html($channel['label']); ?>
172 </span>
173 <?php endif; ?>
174 </a>
175 <?php endforeach; ?>
176 </div>
177 </div>
178 <?php
179 }
180
181 /**
182 * Content controls.
183 *
184 * @param bool $is_pro Whether pro controls are needed.
185 *
186 * @return void
187 */
188 public function register_content_controls(bool $is_pro = false): void
189 {
190 $this->start_controls_section(
191 'kng_content_section',
192 [
193 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Content', 'king-addons'),
194 'tab' => Controls_Manager::TAB_CONTENT,
195 ]
196 );
197
198 $this->add_control(
199 'kng_title',
200 [
201 'label' => esc_html__('Helper Label', 'king-addons'),
202 'type' => Controls_Manager::TEXT,
203 'default' => esc_html__('Need quick help?', 'king-addons'),
204 'description' => esc_html__('Shown above channels when labels are enabled.', 'king-addons'),
205 ]
206 );
207
208 $this->add_control(
209 'kng_status_default',
210 [
211 'label' => esc_html__('Default Status', 'king-addons'),
212 'type' => Controls_Manager::SELECT,
213 'default' => 'online',
214 'options' => [
215 'online' => esc_html__('Online', 'king-addons'),
216 'offline' => esc_html__('Offline', 'king-addons'),
217 ],
218 ]
219 );
220
221 $this->add_control(
222 'kng_status_online_label',
223 [
224 'label' => esc_html__('Online Text', 'king-addons'),
225 'type' => Controls_Manager::TEXT,
226 'default' => esc_html__('We are online', 'king-addons'),
227 ]
228 );
229
230 $this->add_control(
231 'kng_status_offline_label',
232 [
233 'label' => esc_html__('Offline Text', 'king-addons'),
234 'type' => Controls_Manager::TEXT,
235 'default' => esc_html__('We respond soon', 'king-addons'),
236 ]
237 );
238
239 $this->add_control(
240 'kng_show_status',
241 [
242 'label' => esc_html__('Show Status', 'king-addons'),
243 'type' => Controls_Manager::SWITCHER,
244 'return_value' => 'yes',
245 'default' => 'yes',
246 ]
247 );
248
249 $this->add_control(
250 'kng_show_labels',
251 [
252 'label' => esc_html__('Show Channel Labels', 'king-addons'),
253 'type' => Controls_Manager::SWITCHER,
254 'return_value' => 'yes',
255 'default' => 'yes',
256 ]
257 );
258
259 $repeater = new Repeater();
260
261 $repeater->add_control(
262 'kng_channel_label',
263 [
264 'label' => esc_html__('Label', 'king-addons'),
265 'type' => Controls_Manager::TEXT,
266 'default' => esc_html__('WhatsApp', 'king-addons'),
267 ]
268 );
269
270 $repeater->add_control(
271 'kng_channel_type',
272 [
273 'label' => esc_html__('Channel', 'king-addons'),
274 'type' => Controls_Manager::SELECT,
275 'default' => 'whatsapp',
276 'options' => [
277 'whatsapp' => esc_html__('WhatsApp', 'king-addons'),
278 'telegram' => esc_html__('Telegram', 'king-addons'),
279 'messenger' => esc_html__('Facebook Messenger', 'king-addons'),
280 'phone' => esc_html__('Phone', 'king-addons'),
281 'email' => esc_html__('Email', 'king-addons'),
282 'link' => esc_html__('Custom Link', 'king-addons'),
283 ],
284 ]
285 );
286
287 $repeater->add_control(
288 'kng_channel_value',
289 [
290 'label' => esc_html__('Destination', 'king-addons'),
291 'type' => Controls_Manager::TEXT,
292 'placeholder' => esc_html__('Phone, @username, or email', 'king-addons'),
293 ]
294 );
295
296 $repeater->add_control(
297 'kng_channel_message',
298 [
299 'label' => esc_html__('Prefill Message', 'king-addons'),
300 'type' => Controls_Manager::TEXT,
301 'placeholder' => esc_html__('Used for WhatsApp/Telegram', 'king-addons'),
302 'condition' => [
303 'kng_channel_type' => ['whatsapp', 'telegram'],
304 ],
305 ]
306 );
307
308 $repeater->add_control(
309 'kng_channel_url',
310 [
311 'label' => esc_html__('Custom URL', 'king-addons'),
312 'type' => Controls_Manager::URL,
313 'placeholder' => esc_html__('https://', 'king-addons'),
314 'condition' => [
315 'kng_channel_type' => 'link',
316 ],
317 ]
318 );
319
320 $repeater->add_control(
321 'kng_channel_icon',
322 [
323 'label' => esc_html__('Icon', 'king-addons'),
324 'type' => Controls_Manager::ICONS,
325 'fa4compatibility' => 'icon',
326 ]
327 );
328
329 $availability_options = [
330 'always' => esc_html__('Always show', 'king-addons'),
331 'online' => esc_html__('Show when online', 'king-addons'),
332 ];
333
334 if ($is_pro) {
335 $availability_options['offline'] = esc_html__('Show when offline', 'king-addons');
336 }
337
338 $repeater->add_control(
339 'kng_channel_availability',
340 [
341 'label' => esc_html__('Visibility', 'king-addons'),
342 'type' => Controls_Manager::SELECT,
343 'default' => 'always',
344 'options' => $availability_options,
345 ]
346 );
347
348 if ($is_pro) {
349 $repeater->add_control(
350 'kng_channel_device',
351 [
352 'label' => esc_html__('Device', 'king-addons'),
353 'type' => Controls_Manager::SELECT,
354 'default' => 'all',
355 'options' => [
356 'all' => esc_html__('All devices', 'king-addons'),
357 'desktop' => esc_html__('Desktop only', 'king-addons'),
358 'mobile' => esc_html__('Mobile only', 'king-addons'),
359 ],
360 ]
361 );
362 }
363
364 $repeater->add_control(
365 'kng_channel_new_tab',
366 [
367 'label' => esc_html__('Open in new tab', 'king-addons'),
368 'type' => Controls_Manager::SWITCHER,
369 'return_value' => 'yes',
370 'default' => 'yes',
371 ]
372 );
373
374 $this->add_control(
375 'kng_channels',
376 [
377 'label' => esc_html__('Channels', 'king-addons'),
378 'type' => Controls_Manager::REPEATER,
379 'fields' => $repeater->get_controls(),
380 'default' => [
381 [
382 'kng_channel_label' => esc_html__('WhatsApp', 'king-addons'),
383 'kng_channel_type' => 'whatsapp',
384 'kng_channel_value' => '+1 800 555 1234',
385 'kng_channel_message' => esc_html__('Hi! I need assistance.', 'king-addons'),
386 'kng_channel_new_tab' => 'yes',
387 'kng_channel_availability' => 'always',
388 ],
389 [
390 'kng_channel_label' => esc_html__('Call us', 'king-addons'),
391 'kng_channel_type' => 'phone',
392 'kng_channel_value' => '+1 800 555 9876',
393 'kng_channel_new_tab' => 'yes',
394 'kng_channel_availability' => 'always',
395 ],
396 [
397 'kng_channel_label' => esc_html__('Telegram', 'king-addons'),
398 'kng_channel_type' => 'telegram',
399 'kng_channel_value' => 'kingaddons',
400 'kng_channel_message' => esc_html__('Hello! I have a question.', 'king-addons'),
401 'kng_channel_new_tab' => 'yes',
402 'kng_channel_availability' => 'online',
403 ],
404 ],
405 'title_field' => '{{ kng_channel_label }}',
406 ]
407 );
408
409 $this->end_controls_section();
410
411 $this->start_controls_section(
412 'kng_layout_section',
413 [
414 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Layout', 'king-addons'),
415 'tab' => Controls_Manager::TAB_CONTENT,
416 ]
417 );
418
419 $this->add_control(
420 'kng_edge',
421 [
422 'label' => esc_html__('Edge', 'king-addons'),
423 'type' => Controls_Manager::SELECT,
424 'default' => 'right',
425 'options' => [
426 'right' => esc_html__('Right', 'king-addons'),
427 'left' => esc_html__('Left', 'king-addons'),
428 ],
429 ]
430 );
431
432 $this->add_control(
433 'kng_vertical_position',
434 [
435 'label' => esc_html__('Vertical Alignment', 'king-addons'),
436 'type' => Controls_Manager::SELECT,
437 'default' => 'middle',
438 'options' => [
439 'top' => esc_html__('Top', 'king-addons'),
440 'middle' => esc_html__('Middle', 'king-addons'),
441 'bottom' => esc_html__('Bottom', 'king-addons'),
442 ],
443 ]
444 );
445
446 $this->add_responsive_control(
447 'kng_offset',
448 [
449 'label' => esc_html__('Offset', 'king-addons'),
450 'type' => Controls_Manager::SLIDER,
451 'size_units' => ['px'],
452 'range' => [
453 'px' => [
454 'min' => 0,
455 'max' => 400,
456 ],
457 ],
458 'default' => [
459 'size' => 120,
460 'unit' => 'px',
461 ],
462 ]
463 );
464
465 $this->add_responsive_control(
466 'kng_gap',
467 [
468 'label' => esc_html__('Items Gap', 'king-addons'),
469 'type' => Controls_Manager::SLIDER,
470 'size_units' => ['px'],
471 'range' => [
472 'px' => [
473 'min' => 0,
474 'max' => 40,
475 ],
476 ],
477 'default' => [
478 'size' => 10,
479 'unit' => 'px',
480 ],
481 'selectors' => [
482 '{{WRAPPER}} .king-addons-sticky-contact-bar__list' => 'gap: {{SIZE}}{{UNIT}};',
483 ],
484 ]
485 );
486
487 $this->end_controls_section();
488 }
489
490 /**
491 * Style controls.
492 *
493 * @return void
494 */
495 public function register_style_controls(): void
496 {
497 $this->start_controls_section(
498 'kng_style_box_section',
499 [
500 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Box', 'king-addons'),
501 'tab' => Controls_Manager::TAB_STYLE,
502 ]
503 );
504
505 $this->add_control(
506 'kng_box_background',
507 [
508 'label' => esc_html__('Background', 'king-addons'),
509 'type' => Controls_Manager::COLOR,
510 'selectors' => [
511 '{{WRAPPER}} .king-addons-sticky-contact-bar' => 'background-color: {{VALUE}};',
512 ],
513 ]
514 );
515
516 $this->add_responsive_control(
517 'kng_box_padding',
518 [
519 'label' => esc_html__('Padding', 'king-addons'),
520 'type' => Controls_Manager::DIMENSIONS,
521 'size_units' => ['px', 'em'],
522 'selectors' => [
523 '{{WRAPPER}} .king-addons-sticky-contact-bar' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
524 ],
525 ]
526 );
527
528 $this->add_control(
529 'kng_box_radius',
530 [
531 'label' => esc_html__('Border Radius', 'king-addons'),
532 'type' => Controls_Manager::SLIDER,
533 'size_units' => ['px', '%'],
534 'range' => [
535 'px' => ['min' => 0, 'max' => 80],
536 '%' => ['min' => 0, 'max' => 50],
537 ],
538 'selectors' => [
539 '{{WRAPPER}} .king-addons-sticky-contact-bar' => 'border-radius: {{SIZE}}{{UNIT}};',
540 ],
541 ]
542 );
543
544 $this->add_group_control(
545 Group_Control_Border::get_type(),
546 [
547 'name' => 'kng_box_border',
548 'selector' => '{{WRAPPER}} .king-addons-sticky-contact-bar',
549 ]
550 );
551
552 $this->add_group_control(
553 Group_Control_Box_Shadow::get_type(),
554 [
555 'name' => 'kng_box_shadow',
556 'selector' => '{{WRAPPER}} .king-addons-sticky-contact-bar',
557 ]
558 );
559
560 $this->end_controls_section();
561
562 $this->start_controls_section(
563 'kng_style_status_section',
564 [
565 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Status', 'king-addons'),
566 'tab' => Controls_Manager::TAB_STYLE,
567 ]
568 );
569
570 $this->add_group_control(
571 Group_Control_Typography::get_type(),
572 [
573 'name' => 'kng_status_typography',
574 'selector' => '{{WRAPPER}} .king-addons-sticky-contact-bar__status-text, {{WRAPPER}} .king-addons-sticky-contact-bar__title',
575 ]
576 );
577
578 $this->add_control(
579 'kng_status_color',
580 [
581 'label' => esc_html__('Text Color', 'king-addons'),
582 'type' => Controls_Manager::COLOR,
583 'selectors' => [
584 '{{WRAPPER}} .king-addons-sticky-contact-bar__status-text' => 'color: {{VALUE}};',
585 '{{WRAPPER}} .king-addons-sticky-contact-bar__title' => 'color: {{VALUE}};',
586 ],
587 ]
588 );
589
590 $this->add_control(
591 'kng_status_dot_online',
592 [
593 'label' => esc_html__('Dot Color (Online)', 'king-addons'),
594 'type' => Controls_Manager::COLOR,
595 'selectors' => [
596 '{{WRAPPER}} .king-addons-sticky-contact-bar__dot' => 'background-color: {{VALUE}};',
597 ],
598 ]
599 );
600
601 $this->add_control(
602 'kng_status_dot_offline',
603 [
604 'label' => esc_html__('Dot Color (Offline)', 'king-addons'),
605 'type' => Controls_Manager::COLOR,
606 'selectors' => [
607 '{{WRAPPER}} .king-addons-sticky-contact-bar.is-offline .king-addons-sticky-contact-bar__dot' => 'background-color: {{VALUE}};',
608 ],
609 ]
610 );
611
612 $this->end_controls_section();
613
614 $this->start_controls_section(
615 'kng_style_items_section',
616 [
617 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Channels', 'king-addons'),
618 'tab' => Controls_Manager::TAB_STYLE,
619 ]
620 );
621
622 $this->add_group_control(
623 Group_Control_Typography::get_type(),
624 [
625 'name' => 'kng_item_typography',
626 'selector' => '{{WRAPPER}} .king-addons-sticky-contact-bar__label',
627 ]
628 );
629
630 $this->add_control(
631 'kng_item_color',
632 [
633 'label' => esc_html__('Text Color', 'king-addons'),
634 'type' => Controls_Manager::COLOR,
635 'selectors' => [
636 '{{WRAPPER}} .king-addons-sticky-contact-bar__item' => 'color: {{VALUE}};',
637 ],
638 ]
639 );
640
641 $this->add_control(
642 'kng_item_bg',
643 [
644 'label' => esc_html__('Background', 'king-addons'),
645 'type' => Controls_Manager::COLOR,
646 'selectors' => [
647 '{{WRAPPER}} .king-addons-sticky-contact-bar__item' => 'background-color: {{VALUE}};',
648 ],
649 ]
650 );
651
652 $this->add_control(
653 'kng_item_bg_hover',
654 [
655 'label' => esc_html__('Hover Background', 'king-addons'),
656 'type' => Controls_Manager::COLOR,
657 'selectors' => [
658 '{{WRAPPER}} .king-addons-sticky-contact-bar__item:hover' => 'background-color: {{VALUE}};',
659 ],
660 ]
661 );
662
663 $this->add_control(
664 'kng_item_radius',
665 [
666 'label' => esc_html__('Item Radius', 'king-addons'),
667 'type' => Controls_Manager::SLIDER,
668 'size_units' => ['px', '%'],
669 'range' => [
670 'px' => ['min' => 0, 'max' => 40],
671 '%' => ['min' => 0, 'max' => 50],
672 ],
673 'selectors' => [
674 '{{WRAPPER}} .king-addons-sticky-contact-bar__item' => 'border-radius: {{SIZE}}{{UNIT}};',
675 ],
676 ]
677 );
678
679 $this->add_group_control(
680 Group_Control_Border::get_type(),
681 [
682 'name' => 'kng_item_border',
683 'selector' => '{{WRAPPER}} .king-addons-sticky-contact-bar__item',
684 ]
685 );
686
687 $this->end_controls_section();
688 }
689
690 /**
691 * Render pro upsell section.
692 *
693 * @return void
694 */
695 public function register_pro_notice_controls(): void
696 {
697 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
698 Core::renderProFeaturesSection($this, '', Controls_Manager::RAW_HTML, 'sticky-contact-bar', [
699 'Schedule-based online/offline states',
700 'UTM-aware availability (campaign-specific)',
701 'Per-channel visibility rules and offline presets',
702 'Device-aware multi-channel bar with status indicator',
703 ]);
704 }
705 }
706
707 /**
708 * Build wrapper attributes.
709 *
710 * @param array<string, mixed> $settings Settings.
711 *
712 * @return string
713 */
714 public function get_wrapper_attributes(array $settings): string
715 {
716 $attrs = [
717 'data-position' => $settings['kng_edge'] ?? 'right',
718 'data-align' => $settings['kng_vertical_position'] ?? 'middle',
719 'data-offset' => isset($settings['kng_offset']['size']) ? (string) $settings['kng_offset']['size'] : '120',
720 'data-status-default' => $settings['kng_status_default'] ?? 'online',
721 'data-online-label' => $settings['kng_status_online_label'] ?? esc_html__('We are online', 'king-addons'),
722 'data-offline-label' => $settings['kng_status_offline_label'] ?? esc_html__('We respond soon', 'king-addons'),
723 'data-show-labels' => (($settings['kng_show_labels'] ?? 'yes') === 'yes') ? 'yes' : 'no',
724 'data-schedule-active' => 'no',
725 'data-schedule-start' => '',
726 'data-schedule-end' => '',
727 'data-timezone-offset' => '0',
728 'data-utm-key' => '',
729 'data-utm-value' => '',
730 'data-utm-state' => '',
731 ];
732
733 return $this->compile_attributes($attrs);
734 }
735
736 /**
737 * Compile attribute array to string.
738 *
739 * @param array<string, string> $attrs Attributes.
740 *
741 * @return string
742 */
743 public function compile_attributes(array $attrs): string
744 {
745 $compiled = [];
746 foreach ($attrs as $key => $value) {
747 $compiled[] = esc_attr($key) . '="' . esc_attr((string) $value) . '"';
748 }
749
750 return implode(' ', $compiled);
751 }
752
753 /**
754 * Prepare channels data.
755 *
756 * @param array<int, array<string, mixed>> $channels Channels.
757 *
758 * @return array<int, array<string, mixed>>
759 */
760 public function prepare_channels(array $channels): array
761 {
762 $prepared = [];
763
764 foreach ($channels as $channel) {
765 $label = trim($channel['kng_channel_label'] ?? '');
766 $type = $channel['kng_channel_type'] ?? '';
767 if ($label === '' || $type === '') {
768 continue;
769 }
770
771 $url = $this->build_channel_url($channel);
772 if ($url === '') {
773 continue;
774 }
775
776 $prepared[] = [
777 'label' => $label,
778 'type' => $type,
779 'url' => $url,
780 'icon' => $channel['kng_channel_icon'] ?? [],
781 'availability' => $channel['kng_channel_availability'] ?? 'always',
782 'device' => $channel['kng_channel_device'] ?? 'all',
783 'is_external' => ($channel['kng_channel_new_tab'] ?? '') === 'yes',
784 ];
785 }
786
787 return $prepared;
788 }
789
790 /**
791 * Build URL for a channel.
792 *
793 * @param array<string, mixed> $channel Channel data.
794 *
795 * @return string
796 */
797 public function build_channel_url(array $channel): string
798 {
799 $type = $channel['kng_channel_type'] ?? '';
800 $value = trim($channel['kng_channel_value'] ?? '');
801 $message = trim($channel['kng_channel_message'] ?? '');
802
803 if ($type === 'link') {
804 return $channel['kng_channel_url']['url'] ?? '';
805 }
806
807 if ($value === '') {
808 return '';
809 }
810
811 switch ($type) {
812 case 'whatsapp':
813 $number = preg_replace('/[^0-9]/', '', $value);
814 $url = 'https://wa.me/' . rawurlencode($number);
815 if ($message !== '') {
816 $url .= '?text=' . rawurlencode($message);
817 }
818 return $url;
819 case 'telegram':
820 $username = ltrim($value, '@');
821 $url = 'https://t.me/' . rawurlencode($username);
822 if ($message !== '') {
823 $url .= '?text=' . rawurlencode($message);
824 }
825 return $url;
826 case 'messenger':
827 $page = ltrim($value, '/');
828 return 'https://m.me/' . rawurlencode($page);
829 case 'phone':
830 return 'tel:' . rawurlencode(preg_replace('/\s+/', '', $value));
831 case 'email':
832 return 'mailto:' . rawurlencode($value);
833 default:
834 return '';
835 }
836 }
837 }
838
839
840
841
842