Teren-app/app/Services/Documents/TokenValueResolver.php

95 lines
3.7 KiB
PHP

<?php
namespace App\Services\Documents;
use App\Models\Contract;
use App\Models\DocumentTemplate;
use App\Models\User;
class TokenValueResolver
{
/**
* Resolve tokens to values.
* Returns array with keys: values (resolved token=>value) and unresolved (list of tokens not resolved / not allowed)
* Policy determines whether invalid tokens throw (fail) or are collected (blank|keep).
*
* @return array{values:array<string,string>,unresolved:array<int,string>}
*/
public function resolve(array $tokens, DocumentTemplate $template, Contract $contract, User $user, string $policy = 'fail'): array
{
$values = [];
$unresolved = [];
// Retrieve whitelist from DB settings (if present) and merge with config baseline (config acts as baseline; DB can add or override entity arrays)
$settingsWhitelist = app(\App\Services\Documents\DocumentSettings::class)->get()->whitelist ?? [];
$configWhitelist = config('documents.whitelist', []);
// Merge preserving DB additions/overrides
$globalWhitelist = array_replace($configWhitelist, $settingsWhitelist);
// Always treat globally whitelisted entities as available, even if legacy template does not list them
if ($template->entities && is_array($template->entities)) {
$templateEntities = array_values(array_unique(array_merge($template->entities, array_keys($globalWhitelist))));
} else {
$templateEntities = array_keys($globalWhitelist);
}
foreach ($tokens as $token) {
[$entity,$attr] = explode('.', $token, 2);
if ($entity === 'generation') {
$values[$token] = $this->generationAttribute($attr, $user);
continue;
}
if (! in_array($entity, $templateEntities, true)) {
if ($policy === 'fail') {
throw new \RuntimeException("Nedovoljen entiteta token: $entity");
}
$unresolved[] = $token;
continue;
}
$allowed = ($template->columns[$entity] ?? []) ?: ($globalWhitelist[$entity] ?? []);
if (! in_array($attr, $allowed, true)) {
if ($policy === 'fail') {
throw new \RuntimeException("Nedovoljen stolpec token: $token");
}
$unresolved[] = $token;
continue;
}
$values[$token] = $this->entityAttribute($entity, $attr, $contract) ?? '';
}
return ['values' => $values, 'unresolved' => array_values(array_unique($unresolved))];
}
private function generationAttribute(string $attr, User $user): string
{
return match ($attr) {
'timestamp' => (string) now()->timestamp,
'date' => now()->toDateString(), // raw ISO; formatting applied later
'user_name' => $user->name ?? 'Uporabnik',
default => ''
};
}
private function entityAttribute(string $entity, string $attr, Contract $contract): ?string
{
switch ($entity) {
case 'contract':
return (string) ($contract->{$attr} ?? '');
case 'client_case':
return (string) optional($contract->clientCase)->{$attr};
case 'client':
return (string) optional(optional($contract->clientCase)->client)->{$attr};
case 'person':
$person = optional(optional($contract->clientCase)->person);
return (string) $person->{$attr};
case 'account':
$account = optional($contract->account);
return (string) $account->{$attr};
default:
return '';
}
}
}