feat: complete production backend integration
This commit is contained in:
@@ -1,14 +1,18 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
final class DirectAdminVacationApi
|
||||
class DirectAdminVacationApi
|
||||
{
|
||||
public function __construct(private string $directadminBinary = '/usr/local/directadmin/directadmin')
|
||||
/** @var callable|null */
|
||||
private $request;
|
||||
|
||||
public function __construct(private string $daBinary = '/usr/local/bin/da', ?callable $request = null)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/** @param array<string,mixed> $rule @return array<string,string> */
|
||||
public function buildSavePayload(string $email, array $rule): array
|
||||
public function buildSavePayload(string $email, array $rule, bool $exists = true): array
|
||||
{
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
throw new InvalidArgumentException('Invalid mailbox email');
|
||||
@@ -16,20 +20,46 @@ final class DirectAdminVacationApi
|
||||
[$local, $domain] = explode('@', strtolower($email), 2);
|
||||
[$startDate, $startTime] = $this->splitPeriod((string)($rule['start_value'] ?? ''));
|
||||
[$endDate, $endTime] = $this->splitPeriod((string)($rule['end_value'] ?? ''));
|
||||
[$startYear, $startMonth, $startDay] = explode('-', $startDate);
|
||||
[$endYear, $endMonth, $endDay] = explode('-', $endDate);
|
||||
return [
|
||||
'action' => 'modify',
|
||||
'action' => $exists ? 'modify' : 'create',
|
||||
'domain' => $domain,
|
||||
'user' => $local,
|
||||
'email' => $email,
|
||||
'text' => (string)($rule['body'] ?? ''),
|
||||
'subject' => (string)($rule['subject'] ?? ''),
|
||||
'startdate' => $startDate,
|
||||
'starttime' => $startTime,
|
||||
'enddate' => $endDate,
|
||||
'startyear' => $startYear,
|
||||
'startmonth' => $startMonth,
|
||||
'startday' => $startDay,
|
||||
'endtime' => $endTime,
|
||||
'endyear' => $endYear,
|
||||
'endmonth' => $endMonth,
|
||||
'endday' => $endDay,
|
||||
'create' => $exists ? '' : 'Create',
|
||||
];
|
||||
}
|
||||
|
||||
/** @param array<string,mixed> $rule */
|
||||
public function saveVacation(string $owner, string $email, array $rule, bool $exists): void
|
||||
{
|
||||
$this->requestAsUser($owner, 'CMD_API_EMAIL_VACATION', $this->buildSavePayload($email, $rule, $exists));
|
||||
}
|
||||
|
||||
public function deleteVacation(string $owner, string $email): void
|
||||
{
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
throw new InvalidArgumentException('Invalid mailbox email');
|
||||
}
|
||||
[$local, $domain] = explode('@', strtolower($email), 2);
|
||||
$this->requestAsUser($owner, 'CMD_API_EMAIL_VACATION', [
|
||||
'action' => 'delete',
|
||||
'domain' => $domain,
|
||||
'select0' => $local,
|
||||
]);
|
||||
}
|
||||
|
||||
/** @return array{0:string,1:string} */
|
||||
private function splitPeriod(string $value): array
|
||||
{
|
||||
@@ -38,4 +68,58 @@ final class DirectAdminVacationApi
|
||||
}
|
||||
return [$m[1], $m[2]];
|
||||
}
|
||||
|
||||
/** @param array<string,string> $payload */
|
||||
private function requestAsUser(string $owner, string $endpoint, array $payload): void
|
||||
{
|
||||
if (!preg_match('/^[A-Za-z0-9._-]+$/', $owner)) {
|
||||
throw new InvalidArgumentException('Invalid DirectAdmin owner');
|
||||
}
|
||||
if ($this->request !== null) {
|
||||
$result = call_user_func($this->request, $owner, $endpoint, $payload);
|
||||
if ($result === false) {
|
||||
throw new RuntimeException('DirectAdmin API request failed');
|
||||
}
|
||||
return;
|
||||
}
|
||||
$baseUrl = $this->apiUrl($owner);
|
||||
$url = rtrim($baseUrl, '/') . '/' . $endpoint;
|
||||
$args = ['curl', '-fsS', '-X', 'POST'];
|
||||
foreach ($payload as $key => $value) {
|
||||
$args[] = '--data-urlencode';
|
||||
$args[] = $key . '=' . $value;
|
||||
}
|
||||
$args[] = $url;
|
||||
$this->run($args, '');
|
||||
}
|
||||
|
||||
private function apiUrl(string $owner): string
|
||||
{
|
||||
$output = $this->run([$this->daBinary, 'api-url', '--user=' . $owner], '');
|
||||
$url = trim($output);
|
||||
if ($url === '' || !preg_match('#^https?://#', $url)) {
|
||||
throw new RuntimeException('Cannot determine DirectAdmin API URL for user');
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
/** @param string[] $args */
|
||||
private function run(array $args, string $stdin): string
|
||||
{
|
||||
$process = proc_open($args, [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $pipes);
|
||||
if (!is_resource($process)) {
|
||||
throw new RuntimeException('Cannot start DirectAdmin API command');
|
||||
}
|
||||
fwrite($pipes[0], $stdin);
|
||||
fclose($pipes[0]);
|
||||
$stdout = stream_get_contents($pipes[1]) ?: '';
|
||||
$stderr = stream_get_contents($pipes[2]) ?: '';
|
||||
fclose($pipes[1]);
|
||||
fclose($pipes[2]);
|
||||
$code = proc_close($process);
|
||||
if ($code !== 0) {
|
||||
throw new RuntimeException('DirectAdmin API command failed: ' . trim($stderr));
|
||||
}
|
||||
return $stdout;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user