c62f1f6571c57dfb43f27937a84f107ddc7f79dd
[lhc/web/www.git] / www / plugins-dist / svp / plugins / preparer_sql_plugin.php
1 <?php
2
3 /**
4 * Fichier permettant de calculer les données SQL à insérer
5 * à partir d'une arbre de description originaire d'un plugin.xml
6 *
7 * @plugin SVP pour SPIP
8 * @license GPL
9 * @package SPIP\SVP\Plugins
10 **/
11
12 if (!defined('_ECRIRE_INC_VERSION')) {
13 return;
14 }
15
16 /**
17 * Pour une description de plugin donnée (issue de la dtd de plugin.xml),
18 * prépare les données à installer en bdd
19 *
20 * Les données sont parfois sérialisées, parfois transcodées, parfois compilées
21 * pour tenir compte des spécificités de cette DTD et du stockage en bdd.
22 *
23 * @uses compiler_branches_spip()
24 * @param array $plugin
25 * Description de plugin
26 * @return array
27 * Couples clés => valeurs de description du paquet
28 **/
29 function plugins_preparer_sql_plugin($plugin) {
30 include_spip('inc/svp_outiller');
31
32 $champs = array();
33 if (!$plugin) {
34 return $champs;
35 }
36
37 // On initialise les champs ne necessitant aucune transformation
38 $champs['categorie'] = (isset($plugin['categorie']) and $plugin['categorie']) ? $plugin['categorie'] : '';
39 $champs['etat'] = (isset($plugin['etat']) and $plugin['etat']) ? $plugin['etat'] : '';
40 $champs['version'] = $plugin['version'] ? normaliser_version($plugin['version']) : '';
41 $champs['version_base'] = (isset($plugin['schema']) and $plugin['schema']) ? $plugin['schema'] : '';
42
43 // Renommage de certains champs
44 $champs['logo'] = (isset($plugin['logo']) and $plugin['logo']) ? $plugin['logo'] : '';
45 $champs['lien_doc'] = (isset($plugin['documentation']) and $plugin['documentation']) ? normaliser_lien($plugin['documentation']) : '';
46 // On passe le prefixe en lettres majuscules comme ce qui est fait dans SPIP
47 // Ainsi les valeurs dans la table spip_plugins coincideront avec celles de la meta plugin
48 $champs['prefixe'] = strtoupper($plugin['prefix']);
49
50 // Indicateurs d'etat numerique (pour simplifier la recherche des maj de STP)
51 static $num = array('stable' => 4, 'test' => 3, 'dev' => 2, 'experimental' => 1);
52 $champs['etatnum'] = (isset($plugin['etat']) and isset($num[$plugin['etat']])) ? $num[$plugin['etat']] : 0;
53
54 // Tags : liste de mots-cles
55 $champs['tags'] = (isset($plugin['tags']) and $plugin['tags']) ? serialize($plugin['tags']) : '';
56
57 // On passe en utf-8 avec le bon charset les champs pouvant contenir des entites html
58 $champs['description'] = entite2charset($plugin['description'], 'utf-8');
59
60 // Traitement des auteurs, credits, licences et copyright
61 // -- on extrait les auteurs, licences et copyrights sous forme de tableaux
62 // -- depuis le commit 18294 du core la balise auteur est renvoyee sous forme de tableau mais
63 // contient toujours qu'un seul index
64 $balise_auteur = entite2charset($plugin['auteur'][0], 'utf-8');
65 $auteurs = normaliser_auteur_licence($balise_auteur, 'auteur');
66 $balise_licence = isset($plugin['licence'][0]) ? entite2charset($plugin['licence'][0], 'utf-8') : '';
67 $licences = normaliser_auteur_licence($balise_licence, 'licence');
68 // -- on merge les tableaux recuperes dans auteur et licence
69 $champs['auteur'] = $champs['licence'] = $champs['copyright'] = '';
70 if ($t = array_merge($auteurs['auteur'], $licences['auteur'])) {
71 $champs['auteur'] = serialize($t);
72 }
73 if ($t = array_merge($auteurs['licence'], $licences['licence'])) {
74 $champs['licence'] = serialize($t);
75 }
76 if ($t = array_merge($auteurs['copyright'], $licences['copyright'])) {
77 $champs['copyright'] = serialize($t);
78 }
79
80 // Extrait d'un nom et un slogan normalises
81 // Slogan : si vide on ne fait plus rien de special, on traitera ça a l'affichage
82 $champs['slogan'] = $plugin['slogan'] ? entite2charset($plugin['slogan'], 'utf-8') : '';
83 // Nom : on repere dans le nom du plugin un chiffre en fin de nom
84 // et on l'ampute de ce numero pour le normaliser
85 // et on passe tout en unicode avec le charset du site
86 $champs['nom'] = trim(entite2charset($plugin['nom'], 'utf-8'));
87
88 // Extraction de la compatibilite SPIP et construction de la liste des branches spip supportees
89 $champs['compatibilite_spip'] = ($plugin['compatibilite']) ? $plugin['compatibilite'] : '';
90 $champs['branches_spip'] = ($plugin['compatibilite']) ? compiler_branches_spip($plugin['compatibilite']) : '';
91
92 // Construction du tableau des dependances necessite, lib et utilise
93 $dependances['necessite'] = $plugin['necessite'];
94 $dependances['librairie'] = $plugin['lib'];
95 $dependances['utilise'] = $plugin['utilise'];
96 $champs['dependances'] = serialize($dependances);
97
98 // Calculer le champ 'procure' (tableau sérialisé prefixe => version)
99 $champs['procure'] = '';
100 if (!empty($plugin['procure'][0])) {
101 $champs['procure'] = array();
102 foreach ($plugin['procure'][0] as $procure) {
103 $p = strtoupper($procure['nom']);
104 if (
105 !isset($champs['procure'][$p])
106 or spip_version_compare($procure['version'], $champs['procure'][$p], '>')
107 ) {
108 $champs['procure'][$p] = $procure['version'];
109 }
110 }
111 $champs['procure'] = serialize($champs['procure']);
112 }
113
114 // Champs non supportes par la DTD plugin et ne pouvant etre deduits d'autres balises
115 $champs['lien_demo'] = '';
116 $champs['lien_dev'] = '';
117 $champs['credit'] = '';
118
119 return $champs;
120 }
121
122
123 /**
124 * Normalise un nom issu d'un plugin.xml
125 *
126 * @todo Supprimer cette fonction qui ne sert nulle part ?
127 *
128 * @uses extraire_trads()
129 *
130 * @param string $nom
131 * Le nom
132 * @param string $langue
133 * La langue à extraire
134 * @param bool $supprimer_numero
135 * Supprimer les numéros ?
136 * @return string
137 * Le nom
138 **/
139 function normaliser_nom($nom, $langue = '', $supprimer_numero = true) {
140 include_spip('inc/texte');
141
142 // On extrait les traductions de l'eventuel multi
143 // Si le nom n'est pas un multi alors le tableau renvoye est de la forme '' => 'nom'
144 $noms = extraire_trads(str_replace(array('<multi>', '</multi>'), array(), $nom, $nbr_replace));
145 $multi = ($nbr_replace > 0 and !$langue) ? true : false;
146
147 $nouveau_nom = '';
148 foreach ($noms as $_lang => $_nom) {
149 $_nom = trim($_nom);
150 if (!$_lang) {
151 $_lang = _LANGUE_PAR_DEFAUT;
152 }
153 if ($supprimer_numero) {
154 $nbr_matches = preg_match(',(.+)(\s+[\d._]*)$,Um', $_nom, $matches);
155 } else {
156 $nbr_matches = 0;
157 }
158 if (!$langue or $langue == $_lang or count($noms) == 1) {
159 $nouveau_nom .= (($multi) ? '[' . $_lang . ']' : '') .
160 (($nbr_matches > 0) ? trim($matches[1]) : $_nom);
161 }
162 }
163
164 if ($nouveau_nom) // On renvoie un nouveau nom multi ou pas sans la valeur de la branche
165 {
166 $nouveau_nom = (($multi) ? '<multi>' : '') . $nouveau_nom . (($multi) ? '</multi>' : '');
167 }
168
169 return $nouveau_nom;
170 }
171
172
173 /**
174 * Normalise un lien issu d'un plugin.xml
175 *
176 * Éliminer les textes superflus dans les liens (raccourcis [XXX->http...])
177 * et normaliser l'esperluete pour éviter l'erreur d'entité indéfinie
178 *
179 * @param string $url
180 * URL à normaliser
181 * @return string
182 * URL normalisée
183 */
184 function normaliser_lien($url) {
185 if (!preg_match(',https?://[^]\s]+,', $url, $r)) {
186 return '';
187 }
188 $url = str_replace('&', '&amp;', str_replace('&amp;', '&', $r[0]));
189
190 return $url;
191 }
192
193
194 /**
195 * Normalise un auteur ou une licence issue d'un plugin.xml
196 *
197 * - Élimination des multi (exclus dans la nouvelle version)
198 * - Transformation en attribut des balises A
199 * - Interprétation des balises BR et LI et de la virgule et du
200 * espace+tiret comme séparateurs
201 *
202 * @uses _RACCOURCI_LIEN
203 *
204 * @param string $texte
205 * Texte de la balise
206 * @param string $balise
207 * Nom de la balise (auteur | licence)
208 * @return array
209 * Tableau listant les auteurs, licences et copyright trouvés
210 */
211 function normaliser_auteur_licence($texte, $balise) {
212 include_spip('inc/filtres');
213 include_spip('inc/lien');
214 include_spip('inc/svp_outiller');
215
216 // On extrait le multi si besoin et on selectionne la traduction francaise
217 $t = normaliser_multi($texte);
218
219 $res = array('auteur' => array(), 'licence' => array(), 'copyright' => array());
220 foreach (preg_split('@(<br */?>)|<li>|,|\s-|\n_*\s*|&amp;| & | et @', $t[_LANGUE_PAR_DEFAUT]) as $v) {
221 // On detecte d'abord si le bloc texte en cours contient un eventuel copyright
222 // -- cela generera une balise copyright et non auteur
223 $copy = '';
224 if (preg_match('/(?:\&#169;|©|copyright|\(c\)|&copy;)[\s:]*([\d-]+)/i', $v, $r)) {
225 $copy = trim($r[1]);
226 $v = str_replace($r[0], '', $v);
227 $res['copyright'][] = $copy;
228 }
229
230 // On detecte ensuite un lien eventuel d'un auteur
231 // -- soit sous la forme d'une href d'une ancre
232 // -- soit sous la forme d'un raccourci SPIP
233 // Dans les deux cas on garde preferentiellement le contenu de l'ancre ou du raccourci
234 // si il existe
235 $href = $mail = '';
236 if (preg_match('@<a[^>]*href=(\W)(.*?)\1[^>]*>(.*?)</a>@', $v, $r)) {
237 $href = $r[2];
238 $v = str_replace($r[0], $r[3], $v);
239 } elseif (preg_match(_RACCOURCI_LIEN, $v, $r)) {
240 if (preg_match('/([^\w\d._-]*)(([\w\d._-]+)@([\w\d.-]+))/', $r[4], $m)) {
241 $mail = $r[4];
242 } else {
243 $href = $r[4];
244 }
245 $v = ($r[1]) ? $r[1] : str_replace($r[0], '', $v);
246 } else {
247 $href = '';
248 }
249
250 // On detecte ensuite un mail eventuel
251 if (!$mail and preg_match('/([^\w\d._-]*)(([\w\d._-]+)@([\w\d.-]+))/', $v, $r)) {
252 $mail = $r[2];
253 $v = str_replace($r[2], '', $v);
254 if (!$v) {
255 // On considere alors que la premiere partie du mail peut faire office de nom d'auteur
256 if (preg_match('/(([\w\d_-]+)[.]([\w\d_-]+))@/', $r[2], $s)) {
257 $v = ucfirst($s[2]) . ' ' . ucfirst($s[3]);
258 } else {
259 $v = ucfirst($r[3]);
260 }
261 }
262 }
263
264 // On detecte aussi si le bloc texte en cours contient une eventuelle licence
265 // -- cela generera une balise licence et non auteur
266 // cette heuristique n'est pas deterministe car la phrase de licence n'est pas connue
267 $licence = array();
268 if (preg_match('/\b((gnu|free|creative\s+common|cc)*[\/|\s|-]*(apache|lgpl|agpl|gpl|fdl|mit|bsd|art\s+|attribution|by)(\s+licence|\-sharealike|-nc-nd|-nc-sa|-sa|-nc|-nd)*\s*v*(\d*[\.\d+]*))\b/i',
269 $v, $r)) {
270 if ($licence = definir_licence($r[2], $r[3], $r[4], $r[5])) {
271 $res['licence'][] = $licence;
272 }
273 }
274
275 // On finalise la balise auteur ou licence si on a pas trouve de licence prioritaire
276 if ($href) {
277 $href = !preg_match(',https?://,', $href, $matches) ? "http://" . $href : $href;
278 }
279 $v = trim(textebrut($v));
280 if ((strlen($v) > 2) and !$licence) {
281 if ($balise == 'auteur') {
282 $res['auteur'][] = array('nom' => $v, 'url' => $href, 'mail' => $mail);
283 } else {
284 $res['licence'][] = array('nom' => $v, 'url' => $href);
285 }
286 }
287 }
288
289 return $res;
290 }
291
292
293 /**
294 * Expanse les multi en un tableau de textes complets, un par langue
295 *
296 * @uses _EXTRAIRE_MULTI
297 * @param string $texte
298 * Le texte
299 * @return array
300 * Texte expansé par code de langue : couples (code de langue => texte)
301 */
302 function normaliser_multi($texte) {
303 include_spip('inc/filtres');
304
305 if (!preg_match_all(_EXTRAIRE_MULTI, $texte, $regs, PREG_SET_ORDER)) {
306 return array(_LANGUE_PAR_DEFAUT => $texte);
307 }
308 $trads = array();
309 foreach ($regs as $reg) {
310 foreach (extraire_trads($reg[1]) as $k => $v) {
311 // Si le code de langue n'est pas précisé dans le multi c'est donc la langue par défaut
312 $lang = ($k) ? $k : _LANGUE_PAR_DEFAUT;
313 $trads[$lang] = str_replace($reg[0], $v, isset($trads[$k]) ? $trads[$k] : $texte);
314 }
315 }
316
317 return $trads;
318 }