6109b30dc544f1629996f36864330443b4f21eab
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
6 * Copyright (c) 2001-2016 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
14 * Fonctions pour concaténer plusieurs fichiers en un
16 * @package SPIP\Compresseur\Concatener
18 if (!defined("_ECRIRE_INC_VERSION")) {
24 * Concaténer en un seul une liste de fichier,
25 * avec appels de callback sur chaque fichier,
26 * puis sur le fichier final
28 * Gestion d'un cache : le fichier concaténé n'est produit que si il n'existe pas
29 * pour la liste de fichiers fournis en entrée
33 * Liste des fichiers à concatener, chaque entrée sour la forme html=>fichier
34 * - string $key : html d'insertion du fichier dans la page
35 * - string|array $fichier : chemin du fichier, ou tableau (page,argument) si c'est un squelette
36 * @param string $format
37 * js ou css utilisé pour l'extension du fichier de sortie
38 * @param array $callbacks
39 * Tableau de fonctions à appeler :
40 * - each_pre : fonction de préparation à appeler sur le contenu de chaque fichier
41 * - each_min : fonction de minification à appeler sur le contenu de chaque fichier
42 * - all_min : fonction de minification à appeler sur le contenu concatene complet, en fin de traitement
44 * Tableau a 2 entrées retournant le nom du fichier et des commentaires HTML à insérer dans la page initiale
46 function concatener_fichiers($files, $format = 'js', $callbacks = array()) {
48 if (!is_array($files) && $files) {
49 $files = array($files);
52 $callback_min = isset($callbacks['each_min']) ?
$callbacks['each_min'] : 'concatener_callback_identite';
53 $callback_pre = isset($callbacks['each_pre']) ?
$callbacks['each_pre'] : '';
54 $url_base = self('&');
56 // on trie la liste de files pour calculer le nom
57 // necessaire pour retomber sur le meme fichier
58 // si on renome une url a la volee pour enlever le var_mode=recalcul
59 // mais attention, il faut garder l'ordre initial pour la minification elle meme !
60 $dir = sous_repertoire(_DIR_VAR
, 'cache-' . $format);
61 $nom = $dir . md5(serialize($files) . serialize($callbacks)) . ".$format";
63 (defined('_VAR_MODE') and _VAR_MODE
== 'recalcul')
70 foreach ($files as $key => $file) {
71 if (!is_array($file)) {
74 // enlever le timestamp si besoin
75 $file = preg_replace(",[?].+$,", '', $file);
77 // preparer le fichier si necessaire
79 $file = $callback_pre($file);
82 lire_fichier($file, $contenu);
85 if (!isset($file[1])) {
88 $comm = _SPIP_PAGE
. "=$file[0]"
89 . (strlen($file[1]) ?
"($file[1])" : '');
90 parse_str($file[1], $contexte);
91 $contenu = recuperer_fond($file[0], $contexte);
93 // preparer le contenu si necessaire
95 $contenu = $callback_pre($contenu,
96 url_absolue(_DIR_RESTREINT ?
generer_url_public($file[0], $file[1]) : $url_base));
98 // enlever le var_mode si present pour retrouver la css minifiee standard
99 if (strpos($file[1], 'var_mode') !== false) {
104 $key = preg_replace(',(&(amp;)?)?var_mode=[^&\'"]*,', '', $key);
105 $file[1] = preg_replace(',&?var_mode=[^&\'"]*,', '', $file[1]);
106 if (!strlen($file[1])) {
109 $files2 = array_replace_key($files2, $old_key, $key, $file);
112 // passer la balise html initiale en second argument
113 $fichier .= "/* $comm */\n" . $callback_min($contenu, $key) . "\n\n";
115 $total +
= strlen($contenu);
118 // calcul du % de compactage
119 $pc = intval(1000 * strlen($fichier) / $total) / 10;
120 $comms = "compact [\n\t" . join("\n\t", $comms) . "\n] $pc%";
121 $fichier = "/* $comms */\n\n" . $fichier;
123 // si on a nettoye des &var_mode=recalcul : mettre a jour le nom
124 // on ecrit pas dans le nom initial, qui est de toute facon recherche qu'en cas de recalcul
128 $nom = $dir . md5(serialize($files) . serialize($callbacks)) . ".$format";
132 $final_callback = (isset($callbacks['all_min']) ?
$callbacks['all_min'] : false);
133 if ($final_callback) {
134 unset($callbacks['all_min']);
135 $nom_tmp = $dir . md5(serialize($files) . serialize($callbacks)) . ".$format";
138 ecrire_fichier($nom_tmp, $fichier, true);
139 clearstatcache(true, $nom_tmp);
140 // ecrire une version .gz pour content-negociation par apache, cf. [11539]
141 ecrire_fichier("$nom_tmp.gz", $fichier, true);
143 if ($final_callback) {
144 // closure compiler ou autre super-compresseurs
145 // a appliquer sur le fichier final
146 $encore = $final_callback($nom_tmp, $nom);
147 // si echec, on se contente de la compression sans cette callback
148 if ($encore !== $nom) {
150 ecrire_fichier($nom, $fichier, true);
151 clearstatcache(true, $nom);
152 // ecrire une version .gz pour content-negociation par apache, cf. [11539]
153 ecrire_fichier("$nom.gz", $fichier, true);
161 // Le commentaire detaille n'apparait qu'au recalcul, pour debug
162 return array($nom, (isset($comms) and $comms) ?
"<!-- $comms -->\n" : '');
166 * Une callback pour la minification par défaut
168 * Mais justement, par défaut on ne minifie rien !
170 * @param string $contenu Contenu à minifier
171 * @return string Contenu à minifier
173 function &concatener_callback_identite(&$contenu) {
178 * Une callback pour ?
180 * @param array $tableau
182 * @param string $orig_key
183 * Index dont on cherche la valeur actuelle
184 * @param string $new_key
185 * Nouvel index que l'on veut voir affecter de la valeur de la clé d'origine
186 * @param mixed $new_value
187 * Si rempli, la nouvelle clé prend cette valeur à la place
188 * de la valeur de la clé d'origine
192 function &array_replace_key($tableau, $orig_key, $new_key, $new_value = null) {
194 foreach ($tableau as $k => $v) {
195 if ($k == $orig_key) {
197 if (!is_null($new_value)) {