sss
This commit is contained in:
@@ -9,5 +9,16 @@ declare(strict_types=1);
|
|||||||
// Force scope flag so ApiKernel can limit available actions if needed
|
// Force scope flag so ApiKernel can limit available actions if needed
|
||||||
$_GET['scope'] = $_GET['scope'] ?? 'external';
|
$_GET['scope'] = $_GET['scope'] ?? 'external';
|
||||||
|
|
||||||
|
// Map /external/render requests to the correct ApiKernel action when no action is given
|
||||||
|
$reqPath = parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH);
|
||||||
|
if (
|
||||||
|
empty($_GET['action'])
|
||||||
|
&& empty($_POST['action'])
|
||||||
|
&& is_string($reqPath)
|
||||||
|
&& preg_match('~^/external/render/?$~', $reqPath)
|
||||||
|
) {
|
||||||
|
$_POST['action'] = 'external.render';
|
||||||
|
}
|
||||||
|
|
||||||
// Re-use the existing kernel bootstrap
|
// Re-use the existing kernel bootstrap
|
||||||
require_once __DIR__ . '/../public/api.php';
|
require_once __DIR__ . '/../public/api.php';
|
||||||
|
|||||||
@@ -734,6 +734,79 @@ class ApiKernel
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function handleExternalRender(): void
|
||||||
|
{
|
||||||
|
$token = trim((string)($this->in['token'] ?? ''));
|
||||||
|
if ($token === '') {
|
||||||
|
$this->fail('Token required', null, 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
$settingsTable = $this->customerSettingsTable();
|
||||||
|
$stmt = $this->pdo->prepare("SELECT `customer_id` FROM `$settingsTable` WHERE `external_api_token` = :t LIMIT 1");
|
||||||
|
$stmt->execute([':t' => $token]);
|
||||||
|
$row = $stmt->fetch();
|
||||||
|
$customerId = (int)($row['customer_id'] ?? 0);
|
||||||
|
if ($customerId <= 0) {
|
||||||
|
$this->fail('Invalid token', null, 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$templatesTable = $this->tableMap['templates'] ?? null;
|
||||||
|
if (!$templatesTable || !$this->tableExists($templatesTable)) {
|
||||||
|
$this->fail('Templates table not available', null, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
[$idCol, $allCols] = $this->resolveIdCol('templates');
|
||||||
|
$nameCol = $this->conf['columns']['templates']['name'] ?? ($this->firstExisting($allCols, ['name']) ?: $idCol);
|
||||||
|
|
||||||
|
$templateKey = $this->val($this->in, ['template', 'template_id', 'id', 'name'], '');
|
||||||
|
$templateId = is_numeric($templateKey) ? (int)$templateKey : null;
|
||||||
|
|
||||||
|
$where = "WHERE `customer_id` = :cid ";
|
||||||
|
$params = [':cid' => $customerId];
|
||||||
|
if ($templateId !== null && $templateId > 0) {
|
||||||
|
$where .= "AND `$idCol` = :id ";
|
||||||
|
$params[':id'] = $templateId;
|
||||||
|
} else {
|
||||||
|
$name = trim((string)$templateKey);
|
||||||
|
if ($name === '') {
|
||||||
|
$this->fail('template required', null, 422);
|
||||||
|
}
|
||||||
|
$where .= "AND `$nameCol` = :name ";
|
||||||
|
$params[':name'] = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = "SELECT * FROM `$templatesTable` $where LIMIT 1";
|
||||||
|
$stmt = $this->pdo->prepare($sql);
|
||||||
|
foreach ($params as $k => $v) {
|
||||||
|
$stmt->bindValue($k, $v, is_int($v) ? PDO::PARAM_INT : PDO::PARAM_STR);
|
||||||
|
}
|
||||||
|
$stmt->execute();
|
||||||
|
$tpl = $stmt->fetch();
|
||||||
|
if (!$tpl) {
|
||||||
|
$this->fail('Template not found', ['template' => $templateKey], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$htmlCol = $this->resolveHtmlColumn($allCols, 'templates');
|
||||||
|
$html = ($htmlCol && isset($tpl[$htmlCol])) ? (string)$tpl[$htmlCol] : '';
|
||||||
|
if ($html === '' && !empty($tpl['json_content'])) {
|
||||||
|
$html = '<p>(Dieses Template enthält noch keine HTML-Inhalte.)</p>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$auth = ['id' => $customerId, 'customer_id' => $customerId];
|
||||||
|
$cache = [];
|
||||||
|
$stack = [];
|
||||||
|
$html = $this->renderHtmlWithReferences($html, $auth, $cache, $stack);
|
||||||
|
$html = $this->replacePlaceholders($html, (array)($this->in['placeholders'] ?? []));
|
||||||
|
$html = $this->prepareEmailHtml($html);
|
||||||
|
|
||||||
|
$this->respond([
|
||||||
|
'ok' => true,
|
||||||
|
'template_id' => (int)($tpl[$idCol] ?? 0),
|
||||||
|
'name' => $tpl[$nameCol] ?? null,
|
||||||
|
'html' => $html,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
private function prepareEmailHtml(string $html): string
|
private function prepareEmailHtml(string $html): string
|
||||||
{
|
{
|
||||||
$html = trim($html);
|
$html = trim($html);
|
||||||
@@ -753,6 +826,27 @@ class ApiKernel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function replacePlaceholders(string $html, array $placeholders): string
|
||||||
|
{
|
||||||
|
if ($html === '' || !$placeholders) {
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
$map = [];
|
||||||
|
foreach ($placeholders as $key => $value) {
|
||||||
|
if (is_array($value) || is_object($value)) continue;
|
||||||
|
$value = (string)$value;
|
||||||
|
$trimmedKey = trim((string)$key);
|
||||||
|
if ($trimmedKey === '') continue;
|
||||||
|
$map['{{' . $trimmedKey . '}}'] = $value;
|
||||||
|
$map['{{ ' . $trimmedKey . ' }}'] = $value;
|
||||||
|
$map['[[' . $trimmedKey . ']]'] = $value;
|
||||||
|
$map['[[ ' . $trimmedKey . ' ]]'] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $map ? strtr($html, $map) : $html;
|
||||||
|
}
|
||||||
|
|
||||||
private function dispatchTestMail(string $to, string $subject, string $html, ?array $sender = null): bool
|
private function dispatchTestMail(string $to, string $subject, string $html, ?array $sender = null): bool
|
||||||
{
|
{
|
||||||
if (!function_exists('mail')) {
|
if (!function_exists('mail')) {
|
||||||
@@ -814,6 +908,9 @@ class ApiKernel
|
|||||||
switch ($this->action) {
|
switch ($this->action) {
|
||||||
case 'health':
|
case 'health':
|
||||||
$this->respond(['ok' => true, 'time' => date('c')]);
|
$this->respond(['ok' => true, 'time' => date('c')]);
|
||||||
|
case 'external.render':
|
||||||
|
$this->handleExternalRender();
|
||||||
|
break;
|
||||||
|
|
||||||
/* ---------- AUTH ---------- */
|
/* ---------- AUTH ---------- */
|
||||||
case 'auth.login':
|
case 'auth.login':
|
||||||
|
|||||||
Reference in New Issue
Block a user