source: spip-zone/_core_/plugins/svp/plugins/preparer_sql_plugin.php

Last change on this file was 115696, checked in by eric@…, 6 months ago

SVP Typologie gère maintenant toute la typologie des plugins, soit les catégories et les tags. Aussi, contrairement à ce qui a été prévu dans les commits précédents on supprime toute manipulation des catégories et des tags dans SVP :

  • les colonnes tags et categorie sont supprimées de spip_plugins
  • le chargement du XML considère encore l'attribut ou la balise categorie par souci de compatibilité mais ne le renvoie pas.
  • il ne reste plus que les API d'affichage qui utilisent la catégorie comme filtre mais qui fonctionnent très bien sans et ne sont utilisés que par Plugins SPIP. Ces API seront revus dans un prochain commit.

Cette version de SVP qui inaugure une branche 2.0 est totalement compatible avec les sites de production fonctionnant en mode runtime mais est incomptaible avec Plugins SPIP.

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