Source of file DatatablesExtension.php
Size: 9,197 Bytes - Last Modified: 2023-11-16T22:56:02+01:00
/home/websites/teicee/packagist/site/phpdoc/conf/../vendor/teicee/twig-bundle/src/Extension/DatatablesExtension.php
| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 | <?phpnamespace TIC\TwigBundle\Extension; use TIC\TwigBundle\Base\TICTwigExtension as BaseExtension; use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Component\HttpFoundation\UrlHelper; use Twig\TwigFunction; /** * Filtres et fonctions twig pour générer des listes avec DataTables.js * https://symfony.com/doc/current/templating/twig_extension.html */class DatatablesExtension extends BaseExtension {public function getFunctions(): array { return [ new TwigFunction('dtFilters', [$this, 'dtFiltersFunction'], ['is_safe' => ['html']] ), new TwigFunction('dtGenerate', [$this, 'dtGenerateFunction'], ['is_safe' => ['html']] ), ]; } public function __construct(UrlHelper $urlHelper, TranslatorInterface $translator = null) { $this->urlHelper = $urlHelper; $this->translator = $translator; } /** * Génération du code HTML du conteneur des filtres de recherches (créés ensuite dynamiquement en JS). * * Classes possibles pour activer les filtres (à définir dans les headers) : * sel-filter, lsel-filter, csel-filter, isel-filter, * ltxt-filter, ctxt-filter, bool-filter, * min-filter, max-filter * * @param string $id * @param bool $noreset * @return string */public function dtFiltersFunction(string $id = null, bool $noreset = false): string { if (empty($id)) $id = "itemlist"; // TODO: html attr escape $buttons = ''; if (empty($noreset)) { // réinitialisation (suppression) des filtres $html = '<button id="%s-filters-reset" class="btn btn-secondary btn-sm dt-filters-reset" title="%s" type="button">%s</button>'; $buttons.= \sprintf($html, $id, $this->trans('btn.unfilter', true), $this->getIcon('bi-eraser-fill')); /* $('#{{ id }}-filters-reset').click( function(){ $('#{{ id }}-filters select option:selected').prop("selected", false).closest('select').change(); $('#{{ id }}-filters input[type="text"]').val("").change(); $('#{{ id }}_filter input[type="search"]').val("").trigger('search'); }); */} $html = '<div id="%s-filters" class="form-group d-none dt-filters"><label>%s</label> :%s</div>'; return \sprintf($html, $id, \htmlspecialchars($this->trans('widget.datatable.filters')), $buttons); } /** * Génération du code JavaScript pour initialiser DataTables sur une table HTML. * * Liste des options disponibles : * - id (default 'itemlist') : Valeur de l'attribut 'id' de l'objet HTML à transformer * - orders (default 1) : Numéro(s) des colonnes pour le tri (sens inversé si négatif) ex: "-1,2" * - persist (default false) : * - filters (default false) : * - search (default false) : Si faux mais option "filters" vrai, vrai forcé mais avec input masqué * - paging (default false) : * - info (default false) : * - buttons (default false) : Si true affichage de la zone avec la liste définie par défaut, si faux liste vide * - responsive (default false) : * - select (default false) : ["info"=>false] sinon ["style"=>'multi'] ou ["style"=>'os',"selector"=>'td:first-child'] * - ajax (default false) : URL * # phPrefix (default '– ') : Préfixe du libellé (placeholder) pour génération des filtres (ex '• ') * # selOpts (default []) : Spécification des choix à utiliser pour les filtres select * # defaults (default []) : Valeurs de filtre par défaut pour les colonnes (dans l'ordre) * # fnPost (default false) : Nom d'une fonction JS à exécuter en fin d'initialisation * - options (default []) : Hachage d'autres options JS à passer dans la configuration de DataTables * * @param array $options Liste d'options pour paramétrer la construction * @return string Code JS d'initialisation de DataTables sur l'objet HTML spécifié */public function dtGenerateFunction(array $options = []): string { // application des options par défaut de la fonction Twig $options+= array( 'id' => "itemlist", 'orders' => "1", // deviendra : [ [0,"asc"] ] 'persist' => false, 'filters' => false, 'search' => false, 'paging' => false, 'info' => false, 'buttons' => false, 'responsive' => false, 'select' => false, 'ajax' => false, # 'phPrefix' => "– ",# 'selOpts' => [],# 'defaults' => [],# 'fnPost' => false,'options' => [], ); // liste des boutons : array ou string avec virgules, true => défaut, false => aucun (liste vide) if (\is_string($options['buttons'])) $options['buttons'] = \explode(",", \str_replace(' ', '', $options['buttons'])); if (empty($options['buttons'])) $options['buttons'] = []; // génération des options pour le constructeur JS de DataTable $jsopts = array( 'order' => $this->makeOrders( $options['orders'] ), 'applyFilter' => (bool)$options['filters'], 'stateSave' => (bool)$options['persist'], 'searching' => (bool)$options['filters'] || (bool)$options['search'], 'paging' => (bool)$options['paging'], 'info' => (bool)$options['info'], 'buttons' => $options['buttons'], 'select' => empty($options['select']) ? ["info" => false] : $options['select'], 'responsive' => (bool)$options['responsive'], 'dom' => $this->makeLayout($options['search'], $options['paging'], ! empty($options['buttons'])), 'language' => [ "url" => $this->findLanguageURL() ], ); if ($options['ajax']) $jsopts+= array( 'ajax' => [ "type" => "POST", "url" => $options['ajax'] ], 'serverSide' => true, 'processing' => true, // utilise "r" dans le layout "dom" pour indiquer le traitement en cours ); foreach ($options['options'] as $key => $val) $jsopts[ $key ] = $val; # dump($options, $jsopts);return \sprintf("var dt_%s = $('#%s').DataTable(%s);", $options['id'], $options['id'], \json_encode($jsopts)); } /** * Construction de l'option "orders" de DataTable à partir d'un (ou plusieurs) entier(s). * * Exemples : * "-1" => [ [0,"desc"] ] * [-1,2] => [ [0,"desc"], [1,"asc"] ] * "1,-3" => [ [0,"asc"], [2,"desc"] ] * * @param mixed $orders Numéro(s) des colonnes, négatif pour tri inverse (liste ou chaine avec virgule) * @return array Liste de critères de tri (couples index de colonne et sens) */protected function makeOrders(mixed $orders = 0): array { $option = []; if (! \is_array($orders)) $orders = \explode(',', $orders); foreach ($orders as $order) { if (! ($order = \intval($order))) continue; $option[] = [ \abs($order) - 1, ($order < 0) ? "desc" : "asc" ]; } return $option; } /** * Construction de l'option "dom" de DataTable selon les fonctionnalités à afficher. * * "i" informations (nb affichés/total) * "l" [paging] sélecteur nb d'éléments par page * "p" [paging] navigation sur les numéros de pages * "f" [search] filtre de recherche global * "B" [button] boutons d'action (exports, print...) * * @param bool $search Option de recherche globale activée ? * @param bool $paging Option de pagination de la liste activée ? * @return string Chaine indiquant les blocs et classes de mise en page */protected function makeLayout(bool $search = false, bool $paging = false, bool $buttons = false): string { $top = "'row tic-dt-top d-print-none'"; $lst = "'row tic-dt-lst'<'col-sm-12'tr>"; $end = "'row tic-dt-end'"; if ($paging) { if ($search) { if ($buttons) $top.= "<'col-md-6 col-lg-4'l>" . "<'col-md-6 col-lg-4 order-lg-last'f>" . "<'col-lg-4 text-center'B>"; else $top.= "<'col-md-6'l>" . "<'col-md-6'f>"; } else { if ($buttons) $top.= "<'col-md-6'l>" . "<'col-md-6'B>"; else $top.= "<'col-sm-12'l>"; } } else { if ($search) { if ($buttons) $top.= "<'col-md-6'B>" . "<'col-md-6'f>"; else $top.= "<'col-sm-12'f>"; } else { if ($buttons) $top.= "<'col-sm-12'B>"; else $top.= ""; } } $end.= empty($paging) ? "<'col-sm-12'i>" : "<'col-sm-5'i><'col-sm-7'p>"; return \sprintf('<%s><%s><%s>', $top, $lst, $end); } /** * Retourne l'URL du fichier JSON des traductions à charger en AJAX. * * @param string $locale Locale des traductions souhaitées (courante par défaut) * @return string URL absolue vers le fichier JSON de traductions de Datatables */protected function findLanguageURL(?string $locale = null): string { $url = $this->urlHelper->getAbsoluteUrl("/bundles/tictwig/datatables/i18n/"); if ($locale === null) $locale = \Locale::getDefault(); $locale = \substr(\strtolower($locale), 0, 2); switch ($locale) { case 'fr' : $file = "fr_fr.json"; break; case 'de' : $file = "de_de.json"; break; case 'it' : $file = "it_it.json"; break; case 'es' : $file = "es_es.json"; break; case 'en' : $file = "en-en.json"; break; default : $file = "en-en.json"; } return $url . $file; } } |