Files
Moodle/classes/local/receipt/Client.php
T

111 lines
3.6 KiB
PHP

<?php
declare(strict_types=1);
namespace paygw_moneta\local\receipt;
use InvalidArgumentException;
/**
* Покупатель в чеке — объект `client` из `kassaspecification.pdf`: обязательно
* хотя бы одно из `email`/`phone`; при обоих чек уходит только на e-mail.
* `name` — ФИО покупателя, передаётся только вместе с контактом.
*
* @package paygw_moneta
* @copyright 2026 Moneta Labs {@link https://moneta.ru/}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
final class Client
{
public const NAME_MAX_LENGTH = 256;
public const EMAIL_MAX_LENGTH = 64;
/** По `kassaspecification.pdf` (принимающая сторона); JSON-схема Check URL даёт 13. */
public const PHONE_MAX_LENGTH = 19;
private function __construct(
public readonly ?string $name,
public readonly ?string $email,
public readonly ?string $phone,
) {}
/**
* Строит покупателя из «сырых» данных профиля; невалидные значения
* отбрасываются. Если у покупателя нет ни e-mail, ни телефона, подставляется
* `$fallbackEmail` — настройка «Email для чеков» (чек уходит продавцу, ФИО
* покупателя остаётся); без неё покупателя нет (`null`).
*/
public static function fromContacts(
?string $email,
?string $phone,
?string $name = null,
?string $fallbackEmail = null,
): ?self {
$email = self::normalizeEmail($email);
$phone = self::normalizePhone($phone);
if ($email === null && $phone === null) {
$email = self::normalizeEmail($fallbackEmail);
}
if ($email === null && $phone === null) {
return null;
}
return new self(self::normalizeName($name), $email, $phone);
}
/**
* @param array{name?: ?string, email?: ?string, phone?: ?string} $data
*/
public static function fromArray(array $data): self
{
$client = self::fromContacts($data['email'] ?? null, $data['phone'] ?? null, $data['name'] ?? null);
if ($client === null) {
throw new InvalidArgumentException('У покупателя нет ни e-mail, ни телефона.');
}
return $client;
}
/**
* @return array<string, string>
*/
public function toArray(): array
{
return array_filter(
['name' => $this->name, 'email' => $this->email, 'phone' => $this->phone],
static fn(?string $value): bool => $value !== null,
);
}
public static function normalizeEmail(?string $email): ?string
{
$email = trim((string) $email);
if (
$email === ''
|| strlen($email) > self::EMAIL_MAX_LENGTH
|| filter_var($email, FILTER_VALIDATE_EMAIL) === false
) {
return null;
}
return $email;
}
public static function normalizePhone(?string $phone): ?string
{
$digits = preg_replace('/[^0-9]/', '', (string) $phone) ?? '';
if ($digits === '' || strlen($digits) + 1 > self::PHONE_MAX_LENGTH) {
return null;
}
return '+' . $digits;
}
private static function normalizeName(?string $name): ?string
{
$name = ReceiptText::validate((string) $name, self::NAME_MAX_LENGTH);
return $name === '' ? null : $name;
}
}