156 lines
5.8 KiB
PHP
156 lines
5.8 KiB
PHP
<?php
|
|
|
|
namespace App\Signature;
|
|
|
|
use App\Models\Assignment;
|
|
use App\Models\Campaign;
|
|
use App\Models\DirectoryUser;
|
|
use App\Models\EditableField;
|
|
use App\Models\SharedMailbox;
|
|
use App\Models\Template;
|
|
|
|
/**
|
|
* Calcule la signature d'un agent pour un contexte de rédaction donné.
|
|
* Tout est lu dans la base locale (synchro Graph) : aucun appel Graph en direct.
|
|
*/
|
|
final class SignatureBuilder
|
|
{
|
|
public function __construct(
|
|
private readonly TemplateRenderer $renderer,
|
|
private readonly TemplateSelector $selector,
|
|
) {}
|
|
|
|
/**
|
|
* @param string $context new | reply | forward | appointment
|
|
* @param string|null $mailbox adresse émettrice (boîte partagée éventuelle)
|
|
* @return array{html:string, variant:string, template:string}|null
|
|
*/
|
|
public function build(DirectoryUser $user, string $context, ?string $mailbox = null): ?array
|
|
{
|
|
$shared = $this->sharedMailbox($user, $mailbox);
|
|
$template = $shared?->template ?? $this->templateFor($user);
|
|
if (! $template) {
|
|
return null;
|
|
}
|
|
|
|
$variant = $this->variant($user, $context);
|
|
if ($variant === 'none') {
|
|
return ['html' => '', 'variant' => 'none', 'template' => $template->name];
|
|
}
|
|
|
|
$source = $variant === 'short' ? ($template->html_short ?: $template->html_full) : $template->html_full;
|
|
if (! $source) {
|
|
return null;
|
|
}
|
|
|
|
$vars = $this->variables($user, $variant);
|
|
|
|
if ($shared) {
|
|
// Boîte partagée : ses propres coordonnées, l'agent seulement si l'admin l'a choisi.
|
|
$vars['boite_nom'] = $shared->display_name;
|
|
$vars['boite_email'] = $shared->address;
|
|
$vars['email'] = $shared->address;
|
|
if (! $shared->include_sender) {
|
|
foreach (['prenom', 'nom', 'nom_complet', 'fonction', 'mobile'] as $k) {
|
|
$vars[$k] = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
return [
|
|
'html' => $this->renderer->render($source, $vars),
|
|
'variant' => $variant,
|
|
'template' => $template->name,
|
|
];
|
|
}
|
|
|
|
/** Variables d'un agent (attributs Entra + surcharges autorisées + bannière en variante complète). */
|
|
public function variables(DirectoryUser $user, string $variant = 'full'): array
|
|
{
|
|
$vars = VariableMap::build($user->getAttributes(), $this->allowedOverrides($user));
|
|
$vars['banniere'] = $variant === 'full' ? $this->bannerHtml($user) : '';
|
|
$vars['site_url'] = config('signature.public_url');
|
|
|
|
return $vars;
|
|
}
|
|
|
|
/** Aperçu d'un HTML brut (brouillon en cours d'édition) pour un agent donné. */
|
|
public function preview(DirectoryUser $user, string $source, string $variant = 'full'): string
|
|
{
|
|
return $this->renderer->render($source, $this->variables($user, $variant));
|
|
}
|
|
|
|
public function templateFor(DirectoryUser $user): ?Template
|
|
{
|
|
$assignments = Assignment::query()
|
|
->where('tenant_id', $user->tenant_id)
|
|
->get(['id', 'template_id', 'directory_group_id', 'priority'])
|
|
->map(fn ($a) => [
|
|
'id' => $a->id,
|
|
'template_id' => $a->template_id,
|
|
'group_id' => $a->directory_group_id,
|
|
'priority' => $a->priority,
|
|
])->all();
|
|
|
|
$default = Template::where('tenant_id', $user->tenant_id)->where('is_default', true)->value('id');
|
|
$id = $this->selector->select($assignments, $user->groups()->pluck('directory_groups.id')->all(), $default);
|
|
|
|
return $id ? Template::whereNotNull('html_full')->find($id) : null;
|
|
}
|
|
|
|
private function variant(DirectoryUser $user, string $context): string
|
|
{
|
|
if ($context !== 'reply' && $context !== 'forward') {
|
|
return 'full';
|
|
}
|
|
$pref = $user->preference?->reply_variant ?? config('signature.default_reply_variant', 'short');
|
|
|
|
return in_array($pref, ['short', 'full', 'none'], true) ? $pref : 'short';
|
|
}
|
|
|
|
/** Surcharges saisies par l'agent, limitées aux champs que l'admin a ouverts. */
|
|
private function allowedOverrides(DirectoryUser $user): array
|
|
{
|
|
$enabled = EditableField::where('tenant_id', $user->tenant_id)->where('enabled', true)->pluck('field')->all();
|
|
|
|
return $user->overrides()->whereIn('field', $enabled)->pluck('value', 'field')->all();
|
|
}
|
|
|
|
private function sharedMailbox(DirectoryUser $user, ?string $mailbox): ?SharedMailbox
|
|
{
|
|
if (! $mailbox) {
|
|
return null;
|
|
}
|
|
$mailbox = strtolower($mailbox);
|
|
if ($mailbox === strtolower((string) $user->mail) || $mailbox === strtolower((string) $user->user_principal_name)) {
|
|
return null;
|
|
}
|
|
|
|
return SharedMailbox::with('template')->where('tenant_id', $user->tenant_id)->where('address', $mailbox)->first();
|
|
}
|
|
|
|
private function bannerHtml(DirectoryUser $user): string
|
|
{
|
|
$groupIds = $user->groups()->pluck('directory_groups.id')->all();
|
|
|
|
$campaign = Campaign::running()
|
|
->where('tenant_id', $user->tenant_id)
|
|
->where(fn ($q) => $q->whereDoesntHave('groups')
|
|
->orWhereHas('groups', fn ($g) => $g->whereIn('directory_groups.id', $groupIds)))
|
|
->orderByDesc('priority')->orderBy('id')
|
|
->first();
|
|
|
|
if (! $campaign) {
|
|
return '';
|
|
}
|
|
|
|
$src = htmlspecialchars(config('signature.public_url').'/img/'.ltrim($campaign->image_path, '/'), ENT_QUOTES);
|
|
$alt = htmlspecialchars($campaign->alt_text, ENT_QUOTES);
|
|
$img = "<img src=\"{$src}\" alt=\"{$alt}\" width=\"600\" style=\"display:block;max-width:100%;height:auto;border:0\">";
|
|
|
|
return $campaign->link_url
|
|
? '<a href="'.htmlspecialchars($campaign->link_url, ENT_QUOTES).'">'.$img.'</a>'
|
|
: $img;
|
|
}
|
|
}
|