c62f1f6571c57dfb43f27937a84f107ddc7f79dd
4 * Fichier permettant de calculer les données SQL à insérer
5 * à partir d'une arbre de description originaire d'un plugin.xml
7 * @plugin SVP pour SPIP
9 * @package SPIP\SVP\Plugins
12 if (!defined('_ECRIRE_INC_VERSION')) {
17 * Pour une description de plugin donnée (issue de la dtd de plugin.xml),
18 * prépare les données à installer en bdd
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.
23 * @uses compiler_branches_spip()
24 * @param array $plugin
25 * Description de plugin
27 * Couples clés => valeurs de description du paquet
29 function plugins_preparer_sql_plugin($plugin) {
30 include_spip('inc/svp_outiller');
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'] : '';
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']);
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;
54 // Tags : liste de mots-cles
55 $champs['tags'] = (isset($plugin['tags']) and $plugin['tags']) ?
serialize($plugin['tags']) : '';
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');
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);
73 if ($t = array_merge($auteurs['licence'], $licences['licence'])) {
74 $champs['licence'] = serialize($t);
76 if ($t = array_merge($auteurs['copyright'], $licences['copyright'])) {
77 $champs['copyright'] = serialize($t);
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'));
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']) : '';
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);
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']);
105 !isset($champs['procure'][$p])
106 or spip_version_compare($procure['version'], $champs['procure'][$p], '>')
108 $champs['procure'][$p] = $procure['version'];
111 $champs['procure'] = serialize($champs['procure']);
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'] = '';
124 * Normalise un nom issu d'un plugin.xml
126 * @todo Supprimer cette fonction qui ne sert nulle part ?
128 * @uses extraire_trads()
132 * @param string $langue
133 * La langue à extraire
134 * @param bool $supprimer_numero
135 * Supprimer les numéros ?
139 function normaliser_nom($nom, $langue = '', $supprimer_numero = true) {
140 include_spip('inc/texte');
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;
148 foreach ($noms as $_lang => $_nom) {
151 $_lang = _LANGUE_PAR_DEFAUT
;
153 if ($supprimer_numero) {
154 $nbr_matches = preg_match(',(.+)(\s+[\d._]*)$,Um', $_nom, $matches);
158 if (!$langue or $langue == $_lang or count($noms) == 1) {
159 $nouveau_nom .= (($multi) ?
'[' . $_lang . ']' : '') .
160 (($nbr_matches > 0) ?
trim($matches[1]) : $_nom);
164 if ($nouveau_nom) // On renvoie un nouveau nom multi ou pas sans la valeur de la branche
166 $nouveau_nom = (($multi) ?
'<multi>' : '') . $nouveau_nom . (($multi) ?
'</multi>' : '');
174 * Normalise un lien issu d'un plugin.xml
176 * Éliminer les textes superflus dans les liens (raccourcis [XXX->http...])
177 * et normaliser l'esperluete pour éviter l'erreur d'entité indéfinie
184 function normaliser_lien($url) {
185 if (!preg_match(',https?://[^]\s]+,', $url, $r)) {
188 $url = str_replace('&', '&', str_replace('&', '&', $r[0]));
195 * Normalise un auteur ou une licence issue d'un plugin.xml
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
202 * @uses _RACCOURCI_LIEN
204 * @param string $texte
206 * @param string $balise
207 * Nom de la balise (auteur | licence)
209 * Tableau listant les auteurs, licences et copyright trouvés
211 function normaliser_auteur_licence($texte, $balise) {
212 include_spip('inc/filtres');
213 include_spip('inc/lien');
214 include_spip('inc/svp_outiller');
216 // On extrait le multi si besoin et on selectionne la traduction francaise
217 $t = normaliser_multi($texte);
219 $res = array('auteur' => array(), 'licence' => array(), 'copyright' => array());
220 foreach (preg_split('@(<br */?>)|<li>|,|\s-|\n_*\s*|&| & | 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
224 if (preg_match('/(?:\©|¬©|copyright|\(c\)|©)[\s:]*([\d-]+)/i', $v, $r)) {
226 $v = str_replace($r[0], '', $v);
227 $res['copyright'][] = $copy;
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
236 if (preg_match('@<a[^>]*href=(\W)(.*?)\1[^>]*>(.*?)</a>@', $v, $r)) {
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)) {
245 $v = ($r[1]) ?
$r[1] : str_replace($r[0], '', $v);
250 // On detecte ensuite un mail eventuel
251 if (!$mail and preg_match('/([^\w\d._-]*)(([\w\d._-]+)@([\w\d.-]+))/', $v, $r)) {
253 $v = str_replace($r[2], '', $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]);
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
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',
270 if ($licence = definir_licence($r[2], $r[3], $r[4], $r[5])) {
271 $res['licence'][] = $licence;
275 // On finalise la balise auteur ou licence si on a pas trouve de licence prioritaire
277 $href = !preg_match(',https?://,', $href, $matches) ?
"http://" . $href : $href;
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);
284 $res['licence'][] = array('nom' => $v, 'url' => $href);
294 * Expanse les multi en un tableau de textes complets, un par langue
296 * @uses _EXTRAIRE_MULTI
297 * @param string $texte
300 * Texte expansé par code de langue : couples (code de langue => texte)
302 function normaliser_multi($texte) {
303 include_spip('inc/filtres');
305 if (!preg_match_all(_EXTRAIRE_MULTI
, $texte, $regs, PREG_SET_ORDER
)) {
306 return array(_LANGUE_PAR_DEFAUT
=> $texte);
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);