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));
$campaign = $variant === 'full' ? $this->campaignFor($user) : null;
$vars['banniere'] = $campaign ? $this->bannerHtml($campaign) : '';
$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();
}
/** Campagne dont la bannière s'affiche pour cet agent en ce moment (une seule par signature). */
public function campaignFor(DirectoryUser $user): ?Campaign
{
$running = Campaign::running()->where('tenant_id', $user->tenant_id)->with('groups:id')->get();
if ($running->isEmpty()) {
return null;
}
$id = $this->campaigns->select(
$running->map(fn (Campaign $c) => [
'id' => $c->id,
'priority' => $c->priority,
'group_ids' => $c->groups->pluck('id')->all(),
])->all(),
$user->groups()->pluck('directory_groups.id')->all(),
);
return $id ? $running->firstWhere('id', $id) : null;
}
/** HTML de la bannière d'une campagne : seul bloc injecté sans échappement, donc tout y est échappé ici. */
public function bannerHtml(Campaign $campaign): string
{
$path = implode('/', array_map('rawurlencode', explode('/', ltrim($campaign->image_path, '/'))));
$src = htmlspecialchars(config('signature.public_url').'/img/'.$path, ENT_QUOTES);
$alt = htmlspecialchars($campaign->alt_text, ENT_QUOTES);
$width = $campaign->displayWidth();
$img = "
";
// Lien : http(s) uniquement, même si la valeur a été écrite en base hors du back-office.
return preg_match('#^https?://#i', (string) $campaign->link_url)
? ''.$img.''
: $img;
}
}