Source of file MailerService.php
Size: 27,238 Bytes - Last Modified: 2023-11-16T22:56:03+01:00
/home/websites/teicee/packagist/site/phpdoc/conf/../vendor/teicee/mail-bundle/src/Service/MailerService.php
| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663 | <?phpnamespace TIC\MailBundle\Service; use Doctrine\ORM\EntityManagerInterface; #use Symfony\Component\Mailer\MailerInterface;use Symfony\Component\Mailer\Transport\TransportInterface; use Symfony\Component\Routing\RouterInterface; use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Component\HttpFoundation\RequestStack; use Twig\Loader\ArrayLoader; use Symfony\Component\Mime\Email; use Symfony\Component\Mime\Address; use Symfony\Component\Mailer\SentMessage; use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use TIC\MailBundle\Entity\Template; use TIC\MailBundle\Entity\Maillog; /** * Service d'envoi de notifications par email. * Utilisation du transport mailer Symfony et Twig d'après les modèles définis dans le bundle. */class MailerService {protected $em; # protected $mailer;protected $transport; protected $router; protected $translator; protected $requestStack; protected $config; protected $locales; protected $locale_orig; public $locale; public $twig; protected $lastError; // conserve le dernier message d'erreur protected $lastEvent; // conserve l'id de la dernière entrée du journal const ConfKeys = ['maillog','smsdomain','fromdomains','fromname','fromaddr','return','admins','locales','formats']; public function __construct( EntityManagerInterface $em, # MailerInterface $mailer,TransportInterface $transport, RouterInterface $router, TranslatorInterface $translator, RequestStack $requestStack, array $config) { $this->em = $em; # $this->mailer = $mailer;$this->transport = $transport; $this->router = $router; $this->translator = $translator; $this->requestStack = $requestStack; $this->config = \array_merge(\array_fill_keys(self::ConfKeys, null), $config); $this->initLocale(); // détection et backup de la locale en cours } /** * Initialise la locale pour la génération des messages (auto ou forcé). * * @param string $locale Spécifie la locale à utiliser (optionnel) * @return string Retourne la valeur de la locale configurée */public function initLocale(string $locale = null): ?string { // récupération de la locale en cours par défaut if ($locale === null) { $request = $this->requestStack->getCurrentRequest(); if (\is_object($request)) $locale = $request->getLocale(); # if ($locale === null) $locale = $this->container->getParameter('kernel.default_locale');if ($this->locale_orig === null) $this->locale_orig = $locale; } // màj de la locale pour les filtres I18n (trans...) if ($locale !== null) $this->translator->setLocale($locale); return $this->locale = $locale; } /** * Réinitialise l'environnement avec la locale d'origine (auto ou forcé). * * @param string $locale Spécifie la locale à restaurer (optionnel) */public function restoreLocale(string $locale = null): void { if ($locale === null) $locale = $this->locale_orig; if ($locale !== null) { // màj de la locale pour les filtres Intl (localizeddate...) \Symfony\Component\Intl\Locale::setDefault($locale); // màj de la locale pour les filtres I18n (trans...) $this->translator->setLocale($locale); } } /** * Définition de l'environnement Twig (contenus des templates & ajout des extensions utiles). * @TODO transformations/adaptations dans les contenus des templates ? * * @param array $contents Contenus des vues twig pour 'subject', 'bodyText', 'bodyHtml' et 'bodySms' */protected function initTwig(array $contents): void { // vérification que les 4 vues twig attendues existent (vide par défaut) foreach (array('subject', 'bodyText', 'bodyHtml', 'bodySms') as $view) { if (! isset($contents[$view])) $contents[$view] = ''; } // création de l'environnement twig avec les contenus $this->twig = new \Twig\Environment(new ArrayLoader($contents)); // ajout des extensions twig utilisables $this->twig->addExtension(new \Twig\Extra\Intl\IntlExtension()); # $this->twig->addExtension(new \Twig\Extensions\Extension\I18n());# $this->twig->addExtension(new \Twig\Extensions\Extension\Text()); $this->twig->addExtension(new \Symfony\Bridge\Twig\Extension\TranslationExtension($this->translator)); $this->twig->addExtension(new \Symfony\Bridge\Twig\Extension\RoutingExtension($this->router->getGenerator())); # $this->twig->addExtension(new \Symfony\Bridge\Twig\Extension\AssetExtension($this->container->get('assets.packages')));# $this->twig->addExtension(new \Symfony\Bridge\Twig\Extension\HttpFoundationExtension($this->requestStack)); // TIC Core extensions $this->twig->addExtension(new \TIC\TwigBundle\Extension\DatetimeExtension()); $this->twig->addExtension(new \TIC\TwigBundle\Extension\FormatExtension()); # $this->twig->addExtension(new \TIC\TwigBundle\Extension\RouterExtension()); // màj de la locale pour les filtres Intl (localizeddate...) \Symfony\Component\Intl\Locale::setDefault($this->locale); } /** * Préparation d'un message à envoyer (objet Symfony Email & environnement Twig). * * @param string $ref Référence du modèle de notification (cf tic_mail.templates dans services.yaml) * @param string|array $to Adresses mail des destinataires (chaine avec virgule en séparateur acceptée) * @param string|array $pjs Pièces-jointes (chemin ou structure {'name':, 'type':, 'data':}, seul ou en liste) * @param string $locale Spécifie la locale à utiliser (optionnel) * @param boolean $sms Indique s'il s'agit d'un envoi par SMS plutôt que par SMTP * @return Email $message Instance du message (Symfony Email) initialisée selon le modèle de notification * (ou null si aucun modèle de notification correspondant actif ou exception) */public function prepare(string $ref, mixed $to = array(), mixed $pjs = array(), string $locale = null, bool $sms = false): ?Email { $this->lastError = null; $this->lastEvent = null; $message = null; try { // nouvelle instance de message $message = new Email(); $message->getHeaders()->addTextHeader('X-TIC-Template', $ref); // recherche du modèle de notification $template = $this->em->getRepository(Template::class)->findOneByRef($ref); if (! \is_object($template)) return null; if (! $template->getEnabled()) return null; // initialisation de l'environnement twig if ($locale !== null) $this->initLocale($locale); $this->initTwig($template->getContents($this->locale)); // nom et adresse de l'expéditeur (bdd sinon parameters) $sender = $template->getSender(); if (! empty($sender) && \preg_match('/^("?([^"]+)"?\s+)?<?\s*([^\s<@]+@[^@>\s]+)\s*>?$/', $sender, $match)) { $from_name = isset($match[1]) ? $match[2] : null; $from_addr = $match[3]; } else { $from_name = $this->config['fromname']; $from_addr = $this->config['fromaddr']; } $message->from(($from_name === null) ? $from_addr : new Address($from_addr, $from_name)); // spécification d'une adresse de retour $return = $template->getReturn(); if (empty($return)) $return = $this->config['return']; if (! empty($return)) $message->returnPath($return); // ajout des destinataires $this->addDest($message, $to, false, $sms); // ajout des destinataires en copie cachée (sauf envoi sms) if (empty($sms)) { // copie aux administrateurs ? if ($template->getBccAdmins()) $this->addDest($message, $this->config['admins'], true); // copies supplémentaires ? $this->addDest($message, $template->getBccMore(), true); } // attachement de l'éventuelle pièce jointe if (empty($sms)) { if (! \is_array($pjs) || isset($pjs['data'])) $pjs = array($pjs); foreach ($pjs as $pj) $this->attach($message, $pj); } return $message; } catch (\Exception $e) { $this->logger($ref, $message, -3, $e->getMessage(), $sms); return null; } } /** * Indique les informations de l'expéditeur sur un message. * (adresse du "From:" et "Return-Path:" préservée si le domaine du $sender n'est pas dans $config['fromdomains']) * * @param Email $message Instance du message (Symfony Email) auquel ajouter les destinataires * @param string $sender Adresse de l'expéditeur à utiliser (peut contenir une partie "nom" devant) */public function setSender(Email &$message, string $sender): void { if (! \preg_match('/^("?([^"]+)"?\s+)?<?\s*([^\s<@]+@[^@>\s]+)\s*>?$/', $sender, $match)) return; $from_name = isset($match[1]) ? $match[2] : ""; $from_addr = $match[3]; list($from_user, $from_host) = \explode('@', $from_addr . '@'); // domaine connu : utilisation totale de l'expéditeur en remplacement (entêtes "From:" et "Return-Path:") if (\is_array($this->config['fromdomains']) && \in_array(\strtolower($from_host), $this->config['fromdomains'])) { $message->from(new Address($from_addr, $from_name)); $message->returnPath($from_addr); } // domaine autre : remplace uniquement la partie "nom" du "From:" (mais pas l'adresse) et ajout sur "Reply-to:" else { $message->replyTo(new Address($from_addr, $from_name)); $from_orig = \current($message->getFrom()); if ($from_orig) $message->from(new Address($from_orig->getAddress(), empty($from_name) ? $from_user : $from_name)); } } /** * Ajout de destinataires sur un message. * @see https://symfony.com/doc/current/mailer.html#email-addresses * * @param Email $message Instance du message (Symfony Email) auquel ajouter les destinataires * @param array|string $dest Liste d'adresses email (si chaine, virgule en séparateur) * @param boolean $bcc Ajout des destinataires en copie cachée (Bcc, sinon To) * @param boolean $sms Destinataires pour SMS (numéros de téléphone avec nom de domaine spécial) */public function addDest(Email &$message, mixed $dest, bool $bcc = false, bool $sms = false): void { if ($dest === null) return; if (! \is_array($dest)) $dest = \explode(',', $dest); if ($sms) $smsdomain = $this->config['smsdomain']; foreach ($dest as $addr) { $addr = \trim($addr); if ($sms) $addr = \preg_replace('/[^\d\w\.\-@]/', '', \preg_replace('/^\+/', 'p', $addr)); if ($addr === '') continue; if (isset($smsdomain) && (\strpos($addr, '@') === FALSE)) $addr.= '@' . $smsdomain; if ($bcc) $message->addBcc($addr); else $message->addTo($addr); } } /** * Ajout d'un fichier en pièce-jointe d'un message. * @see https://symfony.com/doc/current/mailer.html#file-attachments * * @param Email $message Instance du message (Symfony Email) à compléter * @param array|string $pj Pièce-jointe (structure {'name':, 'type':, 'data':} ou simple chemin) */public function attach(Email &$message, mixed $pj): void { if (\is_array($pj)) { $message->attach( $pj['data'], $pj['name'], $pj['type'] ); } elseif (! empty($pj)) { $message->attachFromPath($pj, null, 'application/octet-stream'); } } /** * Détection des images intégrées en base64 dans du contenu HTML pour extraction et conversion en attachements). * @see https://symfony.com/doc/current/mailer.html#embedding-images * * @param Email $message Instance du message (Symfony Email) à compléter * @param string $html Contenu HTML à analyser pour traiter les images à extraire et attacher * @return string Contenu HTML avec les tag <img> modifiés (data base 64 => cid interne) */public function embedBase64HtmlImages(Email &$message, string $html): string { if (empty($html)) return ''; $cache_img = array(); return preg_replace_callback( '|<img([^>]*) src="data:image/(\w+);base64,([a-zA-Z0-9/+]+=*)"|i', function($matches) use ($message, &$cache_img){ $sign = \md5($matches[3]); if (! \array_key_exists($sign, $cache_img)) { $type = $matches[2]; $name = \sprintf('internal_img_%03d.%s', \count($cache_img) + 1, $type); $message->embed(\base64_decode($matches[3]), $name, 'image/'.$type); $cache_img[$sign] = $name; } return \sprintf('<img%s src="%s"', $matches[1], $cache_img[$sign]); }, $html ); } /** * Composition du contenu textuel d'un message (rendu des vues Twig). * @see https://symfony.com/doc/current/mailer.html#message-contents * * @param Email $message Instance du message (Symfony Email) à compléter * @param array $data Liste clé/valeur pour les substitutions des templates * @param string $ref Référence du modèle de notification (pour info dans les logs ; false pour désactiver les logs) * @return boolean Vrai en cas de succès, faux si une exception a été attrapée */public function compose(Email &$message, array $data = array(), string $ref = null): bool { $this->lastError = null; $this->lastEvent = null; try { // génération du sujet $subject = $this->twig->render('subject', $data); $subject = \html_entity_decode($subject, ENT_QUOTES, 'UTF-8'); $message->subject($subject); // liste des formats autorisés par la configuration (HTML et TEXT par défaut) $formats = $this->config['formats']; if (empty($formats)) $formats = array('HTML', 'TEXT'); // génération du contenu text/plain $bodyText = \in_array('TEXT', $formats) ? $this->twig->render('bodyText', $data) : ''; $bodyText = \html_entity_decode($bodyText, ENT_QUOTES, 'UTF-8'); // génération du contenu text/html (avec conversion des tags img base64 en attachements) $bodyHtml = \in_array('HTML', $formats) ? $this->twig->render('bodyHtml', $data) : ''; $bodyHtml = $this->embedBase64HtmlImages($message, $bodyHtml); // intégration du ou des contenus multipart if (empty($bodyHtml)) { $message->text($bodyText); } else { $message->html($bodyHtml); if (! empty($bodyText)) $message->text($bodyText); } return true; } catch (\Exception $e) { $this->logger($ref, $message, -2, $e->getMessage(), false); return false; } } /** * Composition du contenu SMS d'un message (rendu des vues Twig). * * @param Email $message Instance du message (Symfony Email) à compléter * @param array $data Liste clé/valeur pour les substitutions des templates * @param string $ref Référence du modèle de notification (pour info dans les logs ; false pour désactiver les logs) * @return boolean Vrai en cas de succès, faux si une exception a été attrapée */public function composeSMS(Email &$message, array $data = array(), string $ref = null): bool { $this->lastError = null; $this->lastEvent = null; try { // vérification que le format SMS est autorisé par la configuration $formats = $this->config['formats']; if (! \in_array('SMS', $formats)) throw new \Exception("SMS format not available!"); // génération du sujet $subject = $this->twig->render('subject', $data); $subject = \html_entity_decode($subject, ENT_QUOTES, 'UTF-8'); $message->subject($subject); // génération du texte $bodySms = $this->twig->render('bodySms', $data); $bodySms = \html_entity_decode($bodySms, ENT_QUOTES, 'UTF-8'); $message->text($bodySms); return true; } catch (\Exception $e) { $this->logger($ref, $message, -2, $e->getMessage(), true); return false; } } /** * Envoi un message préparé. * @see https://symfony.com/doc/current/mailer.html#debugging-emails * * @param Email $message Instance du message (Symfony Email) à envoyer * @param mixed $ref Référence du modèle de notification (pour info dans les logs) * Null (défaut) pour la récupérer automatiquement d'après l'entête X-TIC-Template * False pour désactiver les logs en cas de succès (mais toujours sur Exception) * @param boolean $sms Indique s'il s'agit d'un envoi par SMS plutôt que par SMTP * @return integer Nombre de destinataires ou -1 si exception du TransportMailer */public function send(Email &$message, mixed $ref = null, bool $sms = false): int { $this->lastError = null; $this->lastEvent = null; try { # $this->mailer->send($message);$sentMessage = $this->transport->send($message); # dump($sentMessage->getDebug());$message->messageId = $sentMessage->getMessageId(); $rc = \count($sentMessage->getEnvelope()->getRecipients()); if ($ref !== false) $this->logger($ref, $message, $rc, null, $sms); } catch (TransportExceptionInterface $e) { # dump($e->getDebug());$rc = -1; $this->logger($ref, $message, $rc, $e->getMessage(), $sms); } catch (\Exception $e) { $rc = -1; $this->logger($ref, $message, $rc, $e->getMessage(), $sms); } return $rc; } /** * Préparation, composition puis envoi d'un message PLAIN et/ou HTML (méthode "combo"). * * @param string $ref Référence du modèle de notification (cf tic_mail.templates dans services.yaml) * @param string|array $to Adresses mail des destinataires (chaine avec virgule en séparateur acceptée) * @param array $data Liste clé/valeur pour les substitutions des templates (peut contenir 'locale') * @param string|array $pjs Pièces-jointes (chemin ou structure {'name':, 'type':, 'data':}, seul ou en liste) * @param boolean $return Si vrai retournera l'objet Symfony Email au lieu de tenter de l'envoyer * @param String $sender Adresse d'expéditeur (From, Reply-to ou Return-path selon $config['fromdomains']) * @return mixed Nombre de destinaires du message envoyé (peut être 0) ou objet Email généré * Null sur échec aux étapes "prepare" ou "compose" * False sur échec à l'envoi par le Transport Mailer */public function notify(string $ref, mixed $to = array(), array $data = array(), mixed $pjs = array(), bool $return = false, string $sender = null): mixed { $locale = \array_key_exists('locale', $data) ? $data['locale'] : null; // préparation... $message = $this->prepare($ref, $to, $pjs, $locale); if ($message === null) return null; // forcer les informations de l'expéditeur ? if ($sender !== null) $this->setSender($message, $sender); // composition... $rc = $this->compose($message, $data, $ref); if (! $rc) return null; $this->restoreLocale(); // retour ou envoi... if ($return) return $message; $rc = $this->send($message, $ref); return ($rc < 0) ? false : $rc; } /** * Préparation, composition puis envoi d'un message SMS (méthode "combo"). * * @param string $ref Référence du modèle de notification (cf tic_mail.templates dans services.yaml) * @param string|array $to Adresses mail des destinataires (chaine avec virgule en séparateur acceptée) * @param array $data Liste clé/valeur pour les substitutions des templates (peut contenir 'locale') * @param boolean $return Si vrai retournera l'objet Symfony Email au lieu de tenter de l'envoyer * @return mixed Nombre de destinaires du message envoyé (peut être 0) ou objet Email généré * Null sur échec aux étapes "prepare" ou "compose" * False sur échec à l'envoi par le Transport Mailer */public function notifySMS(string $ref, mixed $to = array(), array $data = array(), bool $return = false): mixed { $locale = \array_key_exists('locale', $data) ? $data['locale'] : null; // préparation... $message = $this->prepare($ref, $to, array(), $locale, true); if ($message === null) return null; // composition... $rc = $this->composeSMS($message, $data, $ref); if (! $rc) return null; $this->restoreLocale(); // retour ou envoi... if ($return) return $message; $rc = $this->send($message, $ref, true); return ($rc < 0) ? false : $rc; } /** * Préparation, composition puis envoi de messages pour chaque destinataire (méthode "combo"). * * @param string $ref Référence du modèle de notification (cf tic_mail.templates dans services.yaml) * @param string|array $to Adresses mail des destinataires (chaine avec virgule en séparateur acceptée) * @param array $data Liste clé/valeur pour les substitutions des templates * @param string|array $pjs Pièces-jointes (chemin ou structure {'name':, 'type':, 'data':}, seul ou en liste) * @return integer Nombre de messages envoyés (succès sur destinataire) * Null sur échec aux étapes "prepare" ou "compose" */public function batch(string $ref, mixed $to, array $data = array(), mixed $pjs = array()): ?int { $locale = \array_key_exists('locale', $data) ? $data['locale'] : null; // préparation... $message = $this->prepare($ref, null, $pjs, $locale); if ($message === null) return null; // composition... $rc = $this->compose($message, $data, $ref); if (! $rc) return null; $this->restoreLocale(); // envois... $counter = 0; if (! \is_array($to)) $to = \explode(',', $to); foreach ($to as $addr) { $addr = \trim($addr); if (empty($addr)) continue; $message->to($addr); $rc = $this->send($message, $ref); if ($rc >= 0) $counter++; } return $counter; } /** * Enregistrement dans le journal des envois (envoyé avec succès ou échec d'une étape). * * @param string $ref Référence du modèle de notification (par défaut récupéré depuis les entêtes) * @param Email $message Instance du message traité (Symfony Email) * @param integer $rc Nombre de destinataires si succès, code d'erreur négatif sur exception * @param string $error Message de l'exception en cas d'erreur * @param boolean $sms Indique s'il s'agit d'un envoi par SMS plutôt que par SMTP * @return integer Identifiant de l'objet Maillog généré */public function logger(?string $ref, Email $message = null, int $rc = null, string $error = null, bool $sms = false): ?int { $this->lastError = $error; $this->lastEvent = 0; try { if (! $this->config['maillog']) return null; if ($message instanceof Email) { // récupération de la ref du template dans les headers if ($ref === null) { $header = $message->getHeaders()->getHeaderBody('X-TIC-Template'); if ($header) $ref = $header->getValue(); } // récupération du contenu et de son type (plain|html|sms) if ($sms) { $contentBody = $message->getTextBody(); $contentType = 'text/sms'; } else { $contentBody = $message->getHtmlBody(); $contentType = 'text/html'; if (empty($contentBody)) { $contentBody = $message->getTextBody(); $contentType = 'text/plain'; } } $return = $message->getReturnPath(); $this->lastEvent = $this->em->getRepository(Maillog::class)->createEventLog(array( 'template' => $ref, 'locale' => $this->locale, 'returnPath' => isset($return) ? $return->getAddress() : null, 'mailFrom' => \array_map(function($a){ return $a->getAddress(); }, $message->getFrom()), 'mailRcpt' => \array_map(function($a){ return $a->getAddress(); }, $message->getTo()), 'mailBcc' => \array_map(function($a){ return $a->getAddress(); }, $message->getBcc()), 'subject' => $message->getSubject(), 'body' => $contentBody, 'contentType'=> $contentType, 'messageId' => isset($message->messageId) ? $message->messageId : null, 'sendCode' => $rc, 'errorMsg' => $error, )); } else { $this->lastEvent = $this->em->getRepository(Maillog::class)->createEventLog(array( 'template' => $ref, 'locale' => $this->locale, 'contentType'=> ($sms) ? 'text/sms' : '', 'sendCode' => $rc, 'errorMsg' => $error, )); } return $this->lastEvent; } catch (\Exception $e) { \printf("MAILER LOGGER FAILED: %s\n", $e->getMessage()); return null; } } /** * Retourne le message de la dernière erreur rencontrée (exception interceptée). * * @return string */public function getLastError() { return $this->lastError; } /** * Retourne l'entrée du journal correspondant au dernier envoi (uniquement son id par défaut). * * @param boolean Vrai pour obtenir l'entité complète ; Faux pour avoir une référence Doctrine. * @return integer|Maillog Clé primaire du Maillog, référence du Maillog ou objet Maillog */public function getLastEvent(bool $retrieve_entity = null): mixed { if (empty($this->lastEvent)) return null; if ($retrieve_entity === null) return $this->lastEvent; if (! $retrieve_entity) return $this->em->getReference(Maillog::class, $this->lastEvent); return $this->em->getRepository(Maillog::class)->find($this->lastEvent); } /** * Ajout dans une entité donnée de l'entrée du journal du dernier envoi (via méthode addMaillog ou addNotification). */public function logLastEvent(object &$entity): MailerService { $event = $this->getLastEvent(false); if ($event !== null) { foreach (array('addMaillog', 'addNotification') as $method) { if (! \method_exists($entity, $method)) continue; \call_user_func(array($entity, $method), $event); break; } } return $this; } /** * Retourne la liste des langues définies (gestion des messages multilingues). * Note: les locales possibles sont utilisées dans l'admin, mais pas à l'envoi. * * @return array Liste des locales possibles */public function getLocales(): array { if ($this->locales !== null) return $this->locales; // recherche dans les paramètres du bundle $this->locales = $this->config['locales']; if ($this->locales !== null) return $this->locales; // recherche dans les attributs de la requête $request = $this->requestStack->getCurrentRequest(); if ($request) $this->locales = $request->attributes->get('locales'); if ($this->locales !== null) return $this->locales; // recherche dans les données de la session # $session = $this->container->get('session');# if ($session) $this->locales = $session->get('locales');# if ($this->locales !== null) return $this->locales; // liste avec la locale par défaut en dernier recours $this->locales = array(); return $this->locales; } } |