Files
orderPRO/src/Modules/Sms/SmsTemplateRepository.php
Jacek Pyziak 522c94a434 feat(124): sms templates CRUD + order picker
- Nowa tabela sms_templates (name + body + is_active) + minimalny CRUD.
- /settings/sms-templates: lista + formularz z paleta zmiennych (pill chips).
- Wydzielono Sms\SmsVariableResolver ze wspolna logika placeholderow;
  Email\VariableResolver staje sie cienka fasada — EmailSendingService bez zmian.
- Dropdown "Wybierz szablon" w zakladce SMS na /orders/{id} z fetch
  GET /orders/{id}/sms/template + OrderProAlerts.confirm przy nadpisaniu.
- Stopka SMSPLANET dalej doklejana wylacznie przez SmsConversationService
  (Phase 122 contract preserved).
- Sidebar Ustawien: nowy link "Szablony SMS".

Migration: 20260512_000112_create_sms_templates.sql (CREATE TABLE).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:37:51 +02:00

122 lines
3.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Modules\Sms;
use App\Core\Http\ToggleableRepositoryTrait;
use PDO;
use RuntimeException;
final class SmsTemplateRepository
{
use ToggleableRepositoryTrait;
public function __construct(
private readonly PDO $pdo
) {
}
/**
* @return list<array<string, mixed>>
*/
public function listAll(): array
{
$statement = $this->pdo->prepare(
'SELECT id, name, body, is_active, created_at, updated_at
FROM sms_templates
ORDER BY name ASC'
);
$statement->execute();
$rows = $statement->fetchAll(PDO::FETCH_ASSOC);
return is_array($rows) ? $rows : [];
}
/**
* @return list<array<string, mixed>>
*/
public function listActive(): array
{
$statement = $this->pdo->prepare(
'SELECT id, name, body
FROM sms_templates
WHERE is_active = 1
ORDER BY name ASC'
);
$statement->execute();
$rows = $statement->fetchAll(PDO::FETCH_ASSOC);
return is_array($rows) ? $rows : [];
}
/**
* @return array<string, mixed>|null
*/
public function findById(int $id): ?array
{
$statement = $this->pdo->prepare(
'SELECT id, name, body, is_active, created_at, updated_at
FROM sms_templates
WHERE id = :id'
);
$statement->execute(['id' => $id]);
$row = $statement->fetch(PDO::FETCH_ASSOC);
return is_array($row) ? $row : null;
}
/**
* @param array<string, mixed> $data
*/
public function save(array $data): int
{
$name = trim((string) ($data['name'] ?? ''));
$body = (string) ($data['body'] ?? '');
if ($name === '') {
throw new RuntimeException('Nazwa szablonu jest wymagana.');
}
if (trim($body) === '') {
throw new RuntimeException('Tresc szablonu jest wymagana.');
}
$id = isset($data['id']) && $data['id'] !== '' ? (int) $data['id'] : null;
$params = [
'name' => $name,
'body' => $body,
'is_active' => isset($data['is_active']) && $data['is_active'] ? 1 : 0,
];
if ($id !== null) {
$params['id'] = $id;
$statement = $this->pdo->prepare(
'UPDATE sms_templates
SET name = :name, body = :body, is_active = :is_active
WHERE id = :id'
);
$statement->execute($params);
return $id;
}
$statement = $this->pdo->prepare(
'INSERT INTO sms_templates (name, body, is_active)
VALUES (:name, :body, :is_active)'
);
$statement->execute($params);
return (int) $this->pdo->lastInsertId();
}
public function delete(int $id): void
{
$statement = $this->pdo->prepare('DELETE FROM sms_templates WHERE id = :id');
$statement->execute(['id' => $id]);
}
public function toggleStatus(int $id): void
{
$this->toggleActive('sms_templates', $id);
}
}