1: <?php
2: namespace TIC\TwigBundle\Extension;
3:
4: use TIC\TwigBundle\Base\TICTwigExtension as BaseExtension;
5: use Symfony\Component\HttpKernel\KernelInterface;
6: use Twig\TwigFilter;
7:
8: /**
9: * Filtres et fonctions twig de formattage et conversions.
10: * https://symfony.com/doc/current/templating/twig_extension.html
11: */
12: class FilesExtension extends BaseExtension
13: {
14: private $appKernel;
15:
16: public function getFilters(): array
17: {
18: return [
19: new TwigFilter('filePath', [$this, 'filePathFilter'] ),
20: new TwigFilter('fileContent', [$this, 'fileContentFilter'] ),
21: new TwigFilter('b64image', [$this, 'b64imageFilter'] ),
22: ];
23: }
24:
25: public function __construct(KernelInterface $appKernel = null)
26: {
27: $this->appKernel = $appKernel;
28: }
29:
30: /**
31: * Retourne le chemin absolu sur le serveur d'un emplacement relatif.
32: *
33: * @param string $filepath Chemin relatif d'une ressource de bundle (commence par '@'),
34: * ou depuis la racine du projet Symfony (commence par '/')
35: * sinon depuis la racine web du projet (sous-dossier 'public' ?)
36: * @return string Chemin complet vers le fichier correspondant sur le serveur
37: */
38: public function filePathFilter(string $filepath): ?string
39: {
40: try {
41: switch (\substr($filepath, 0, 1)) {
42: // recherche du chemin de la ressource si filepath commence par un '@'
43: case '@' : return $this->appKernel->locateResource($filepath);
44: // recherche du chemin complet du fichier relatif à la racine du projet
45: case '/' : return $this->appKernel->getProjectDir() . $filepath;
46: // recherche du chemin complet du fichier relatif à la racine web (public ?)
47: default :
48: if (isset($_SERVER['SCRIPT_FILENAME'])) {
49: $root = \dirname($_SERVER['SCRIPT_FILENAME']);
50: } else {
51: // TODO: si autre que './public' (paramètre web_dir ?)
52: $root = $this->appKernel->getProjectDir() . '/public';
53: }
54: return $root . '/' . $filepath;
55: }
56: } catch (\Exception $e) {}
57: return null;
58: }
59:
60: /**
61: * Retourne le contenu d'un fichier.
62: *
63: * @param string $filepath Chemin relatif d'une ressource de bundle (commence par '@'),
64: * ou depuis la racine du projet Symfony (commence par '/')
65: * sinon depuis la racine web du projet (sous-dossier 'public' ?)
66: * @return string Le contenu du fichier correspondant au chemin donné
67: */
68: public function fileContentFilter($filepath): ?string
69: {
70: $fullpath = $this->filePathFilter($filepath);
71: return (isset($fullpath) && \file_exists($fullpath)) ? \file_get_contents($fullpath) : null;
72: }
73:
74: /**
75: * Retourne le contenu d'une image en base64 (avec l'entête 'data:' pour être embarqué dans une page html).
76: *
77: * @param string $filepath Chemin relatif d'une ressource de bundle (commence par '@'),
78: * ou depuis la racine du projet Symfony (commence par '/')
79: * sinon depuis la racine web du projet (sous-dossier 'public' ?)
80: * @return string Données d'une image 'inline' en base64 à insérer dans un attribut 'src'
81: */
82: public function b64imageFilter(string $filepath): string
83: {
84: $fullpath = $this->filePathFilter($filepath);
85:
86: // retourne l'image en base64 avec le préfixe 'data:' suivi du type mime
87: if (isset($fullpath) && \file_exists($fullpath)) {
88: $mime = \mime_content_type($fullpath);
89: return \sprintf('data:%s;base64,', $mime) . \base64_encode(\file_get_contents($fullpath));
90: }
91:
92: // à défaut, retourne le chemin demandé
93: return $filepath;
94: }
95:
96: }
97: