Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
WhatsAppBusinessTemplateOptions
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
2 / 2
15
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 forNotification
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
14
1<?php
2
3declare(strict_types=1);
4/**
5 * SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
6 * SPDX-License-Identifier: AGPL-3.0-or-later
7 */
8
9namespace OCA\Libresign\Service\Notification;
10
11use OCP\IAppConfig;
12
13/**
14 * LibreSign owns positional UTILITY template values and their order.
15 *
16 * Configure both app-config values whatsapp_business_template_name and
17 * whatsapp_business_template_language to opt in to structured delivery.
18 * Otherwise preserve the existing one-body-value gateway behavior.
19 * {{1}} holds one-line notification text; {{2}} holds the action URL.
20 */
21final class WhatsAppBusinessTemplateOptions {
22    public function __construct(
23        private IAppConfig $appConfig,
24    ) {
25    }
26
27    /** @return array<string, mixed> */
28    public function forNotification(string $text, string $url): array {
29        $name = trim($this->appConfig->getValueString('libresign', 'whatsapp_business_template_name', ''));
30        $language = trim($this->appConfig->getValueString('libresign', 'whatsapp_business_template_language', ''));
31        if ($name === '' && $language === '') {
32            return [];
33        }
34        if ($name === '' || $language === '') {
35            throw new \InvalidArgumentException('WhatsApp Business template name and language are both required.');
36        }
37        if (preg_match('/^[a-z0-9_]{1,128}$/D', $name) !== 1
38            || preg_match('/^[A-Za-z0-9_-]{2,32}$/D', $language) !== 1) {
39            throw new \InvalidArgumentException('Invalid WhatsApp Business template configuration.');
40        }
41        if (!filter_var($url, FILTER_VALIDATE_URL) || parse_url($url, PHP_URL_SCHEME) !== 'https'
42            || parse_url($url, PHP_URL_USER) !== null || parse_url($url, PHP_URL_PASS) !== null) {
43            throw new \InvalidArgumentException('WhatsApp Business requires an absolute HTTPS action URL.');
44        }
45        $normalized = preg_replace('/\s+/u', ' ', trim($text));
46        if ($normalized === null || $normalized === '' || mb_strlen($normalized, 'UTF-8') > 1024) {
47            throw new \InvalidArgumentException('Invalid WhatsApp Business notification text.');
48        }
49        return [
50            'template_name' => $name,
51            'template_language' => $language,
52            'template_category' => 'UTILITY',
53            'body_parameters' => [$normalized, $url],
54            'expected_body_parameter_count' => 2,
55        ];
56    }
57}