source: spip-zone/_plugins_/svp/inc/svp_depoter.php @ 43277

Last change on this file since 43277 was 43277, checked in by eric@…, 9 years ago

On désactive la gestion des logos actuelle qui ne fonctionne pas.
En attente d'une solution...

  • Property svn:eol-style set to native
File size: 35.1 KB
Line 
1<?php
2
3if (!defined("_ECRIRE_INC_VERSION")) return;
4include_spip('inc/plugin');
5
6// ----------------------- Traitements des depots ---------------------------------
7
8/**
9 * Teste la validite d'une url d'un depot de paquets
10 *
11 * @param string $url
12 * @return boolean
13 */
14
15// $url => url du fichier xml de description du depot
16function svp_verifier_adresse_depot($url){
17        include_spip('inc/distant');
18        return (!$xml = recuperer_page($url)) ? false : true;
19}
20
21
22/**
23 * Ajout du depot et de ses extensions dans la base de donnees
24 *
25 * @param string $url
26 * @return boolean
27 */
28
29// $url         => url du fichier xml de description du depot
30// $erreur      => message d'erreur a afficher
31function svp_ajouter_depot($url, &$erreur=''){
32        // On considere que l'url a deja ete validee (correcte et nouveau depot)
33        $url = trim($url);
34
35        // Lire les donnees d'un depot de paquets
36        $infos = svp_xml_parse_depot($url);
37        if (!$infos) {
38                $erreur = _T('svp:message_nok_xml_non_conforme', array('fichier' => $url));
39                return false;
40        }
41       
42        // Ajout du depot dans la table spip_depots. Les compteurs de paquets et de plugins
43        // sont mis a jour apres le traitement des paquets
44        $champs = array('titre' => filtrer_entites($infos['depot']['titre']), 
45                                        'descriptif' => filtrer_entites($infos['depot']['descriptif']),
46                                        'type' => $infos['depot']['type'],
47                                        'url_serveur' => $infos['depot']['url_serveur'],
48                                        'url_archives' => $infos['depot']['url_archives'],
49                                        'xml_paquets'=> $url,
50                                        'sha_paquets'=> sha1_file($url));
51        $id_depot = sql_insertq('spip_depots', $champs);
52               
53        // Ajout des paquets dans spip_paquets et actualisation des plugins dans spip_plugins
54        $ok = svp_actualiser_paquets($id_depot, $infos['paquets'], $nb_paquets, $nb_plugins, $nb_autres);
55        if (!$ok OR ($nb_paquets == 0)) {
56                // Si une erreur s'est produite, on supprime le depot deja insere
57                sql_delete('spip_depots','id_depot='.sql_quote($id_depot));
58                if (!ok)
59                        $erreur = _T('svp:message_nok_xml_non_conforme', array('fichier' => $url));
60                else
61                        $erreur = _T('svp:message_nok_aucun_paquet_ajoute', array('url' => $url));
62                return false;
63        }
64
65        // On met à jour le nombre de paquets et de plugins du depot maintenant !
66        sql_updateq('spip_depots',
67                                array('nbr_paquets'=> $nb_paquets, 'nbr_plugins'=> $nb_plugins, 'nbr_autres'=> $nb_autres),
68                                'id_depot=' . sql_quote($id_depot));
69       
70        return true;
71}
72
73/**
74 * Suppression du depot et de ses extensions dans la base de donnees
75 *
76 * @param int $id
77 * @return boolean
78 */
79
80// $id  => id_depot de l'objet depot dans la table spip_depots
81function svp_supprimer_depot($id){
82        $id = intval($id);
83       
84        // Pas de depot a cet id ?
85        if (!$id_depot = sql_getfetsel('id_depot', 'spip_depots', 'id_depot='. sql_quote($id)) ){
86                return false;
87        }
88
89        // on calcule les versions max des plugins heberges par le depot
90        $vmax =array();
91        if ($resultats = sql_select('id_plugin, version', 'spip_paquets', 'id_depot='. sql_quote($id))) {
92                while ($paquet = sql_fetch($resultats)) {
93                        $id_plugin = $paquet['id_plugin'];
94                        if (!isset($vmax[$id_plugin])
95                        OR (spip_version_compare($vmax[$id_plugin], $paquet['version'], '<'))) 
96                                $vmax[$id_plugin] = $paquet['version'];
97                }
98        }
99
100        // On supprime les paquets heberges par le depot
101        sql_delete('spip_paquets','id_depot='.sql_quote($id_depot));
102
103        // On supprime ensuite :
104        // - les liens des plugins avec le depot (table spip_depots_plugins)
105        // - les plugins dont aucun paquet n'est encore heberge par un depot restant (table spip_plugins)
106        // - et on met a zero la vmax des plugins ayant vu leur paquet vmax supprime
107        svp_nettoyer_apres_suppression($id_depot, $vmax);
108
109        // On supprime le depot lui-meme
110        sql_delete('spip_depots','id_depot='.sql_quote($id_depot));
111        return true;
112}
113
114
115function svp_nettoyer_apres_suppression($id_depot, $vmax) {
116
117        // On rapatrie la liste des plugins du depot qui servira apres qu'on ait supprime les liens
118        // de la table spip_depots_plugins
119        $liens = sql_allfetsel('id_plugin', 'spip_depots_plugins', 'id_depot='.sql_quote($id_depot));
120        $plugins_depot = array_map('reset', $liens);
121
122        // On peut donc supprimer tous ces liens *plugins-depots* du depot
123        sql_delete('spip_depots_plugins', 'id_depot='.sql_quote($id_depot));
124
125        // On verifie pour chaque plugin concerne par la disparition de paquets si c'est la version
126        // la plus elevee qui a ete supprimee.
127        // Si oui, on positionne le vmax a 0, ce qui permettra de remettre a jour le plugin systematiquement
128        // a la prochaine actualisation.
129        // Cette operation est necessaire car on n'impose pas que les informations du plugin soient identiques
130        // pour chaque paquet !!!
131        if ($resultats = sql_select('id_plugin, vmax', 'spip_plugins', sql_in('id_plugin', $plugins_depot))) {
132                while ($plugin = sql_fetch($resultats)) {
133                        if (spip_version_compare($plugin['vmax'], $vmax[$plugin['id_plugin']], '='))
134                                sql_updateq('spip_plugins',     array('vmax' => '0.0'), 'id_plugin=' . sql_quote($plugin['id_plugin']));
135                }
136        }
137
138        // Maintenant on calcule la liste des plugins du depot qui ne sont pas heberges
139        // par un autre depot => donc a supprimer
140        // - Liste de tous les plugins encore lies a un autre depot
141        $liens = sql_allfetsel('id_plugin', 'spip_depots_plugins');
142        $autres_plugins = array_map('reset', $liens);
143        // - L'intersection des deux tableaux renvoie les plugins a supprimer   
144        $plugins_a_supprimer = array_diff($plugins_depot, $autres_plugins);
145
146        // On supprimer les plugins identifies
147        sql_delete('spip_plugins', sql_in('id_plugin', $plugins_a_supprimer)); 
148       
149        return true;
150}
151
152
153/**
154 * Actualisation des plugins d'un depot deja cree.
155 * @param int $id
156 * @return boolean
157 */
158
159// $id  => id_depot de l'objet depot dans la table spip_depots
160function svp_actualiser_depot($id){
161        $id = intval($id);
162       
163        // pas de depot a cet id ?
164        if (!$depot = sql_fetsel('*', 'spip_depots', 'id_depot='. sql_quote($id)) ){
165                return false;
166        }
167
168        $sha = sha1_file($depot['xml_paquets']);
169        if ($depot['sha_paquets'] == $sha) {
170                // Le fichier n'a pas change (meme sha1) alors on ne fait qu'actualiser la date
171                // de mise a jour du depot en mettant a jour *inutilement* le sha1
172                spip_log('>> AVERTISSEMENT : aucune modification du fichier XML, actualisation non declenchee - id_depot = ' . $depot['id_depot'], 'svp');
173                sql_replace('spip_depots', array_diff_key($depot, array('maj' => '')));
174        }
175        else {
176                // Le fichier a bien change il faut actualiser tout le depot
177                $infos = svp_xml_parse_depot($depot['xml_paquets']);
178                if (!$infos)
179                        return false;
180       
181                // On actualise les paquets dans spip_paquets uniquement car le depot n'est
182                // mis a jour que par le formulaire d'edition d'un depot.
183                // Lors de la mise a jour des paquets, les plugins aussi sont actualises
184                $ok = svp_actualiser_paquets($depot['id_depot'], $infos['paquets'], 
185                                                                        $nb_paquets, $nb_plugins, $nb_autres);
186                if ($ok) {
187                        // On met à jour le nombre de paquets et de plugins du depot ainsi que le nouveau sha1
188                        // ce qui aura pour effet d'actualiser la date de mise a jour
189                        sql_updateq('spip_depots', 
190                                                array('nbr_paquets'=> $nb_paquets, 'nbr_plugins'=> $nb_plugins, 'nbr_autres'=> $nb_autres, 'sha_paquets'=> $sha),
191                                                'id_depot=' . sql_quote($depot['id_depot']));
192                }
193        }
194       
195        return true;
196}
197
198
199/**
200 * Actualisation de la table des paquets pour le depot choisi
201 *
202 * @param int $id_depot
203 * @param array $paquets
204 * @param int &$nb_paquets
205 * @param int &$nb_plugins
206 * @param int &$nb_autres
207 * @return boolean
208 */
209
210// $id_depot    => Id du depot dans la table spip_depots
211// $paquets             => Tableau des paquets extrait du fichier xml
212//                                 L'index est le nom de l'archive (xxxx.zip) et le contenu est
213//                                 un tableau à deux entrées :
214//                                      - ['plugin'] le tableau des infos du plugin
215//                                      - ['file'] le nom de l'archive .zip
216// &$nb_paquets => Nombre de paquets reellement inseres dans la base renvoye a l'appelant
217// &$nb_plugins => Nombre de plugins parmi les paquets inseres
218// &$nb_autres  => Nombre de contributions non issues de plugin parmi les paquets inseres
219function svp_actualiser_paquets($id_depot, $paquets, &$nb_paquets, &$nb_plugins, &$nb_autres) {
220
221        // Initialisation des compteurs
222        $nb_paquets = 0;
223        $nb_plugins = 0;
224        $nb_autres = 0;
225       
226        // Si aucun depot ou aucun paquet on renvoie une erreur
227        if ((!$id_depot) OR (!is_array($paquets)))
228                return false;
229               
230        // On initialise l'url de base des logos du depot et son type afin de calculer l'url complete de chaque logo
231        // A REVOIR COMPLETEMENT !!!!
232        $depot = sql_fetsel('url_archives, type', 'spip_depots', 'id_depot=' . sql_quote($id_depot));
233       
234        // Initialisation du tableau des id de paquets crees ou mis a jour pour le depot concerne
235        $ids_a_supprimer = array();
236        $versions_a_supprimer = array();
237        $ids = sql_allfetsel('id_paquet, id_plugin, version', 'spip_paquets', array('id_depot='. sql_quote($id_depot)));
238        foreach ($ids as $_ids) {
239                $ids_a_supprimer[$_ids['id_paquet']] = $_ids['id_plugin'];
240                $versions_a_supprimer[$_ids['id_paquet']] = $_ids['version'];
241        }
242
243        // On met a jour ou on cree chaque paquet a partir du contenu du fichier xml
244        // On ne fait pas cas de la compatibilite avec la version de SPIP installee
245        // car l'operation doit permettre de collecter tous les paquets
246        foreach ($paquets as $_archive => $_infos) {
247                $insert_paquet = array();
248                // On initialise les informations specifiques au paquet :
249                // l'id du depot et les infos de l'archive
250                $insert_paquet['id_depot'] = $id_depot;
251                $insert_paquet['nom_archive'] = $_archive;
252                $insert_paquet['nbo_archive'] = $_infos['size'];
253                $insert_paquet['maj_archive'] = date('Y-m-d H:i:s', $_infos['date']);
254                $insert_paquet['src_archive'] = $_infos['source'];
255                $insert_paquet['date_modif'] = $_infos['last_commit'];
256
257                // On verifie si le paquet est celui d'un plugin ou pas
258                if ($champs = svp_remplir_champs_sql($_infos['plugin'])) {
259                        $paquet_plugin = true;
260                        // On complete les informations du paquet et du plugin
261                        $insert_paquet = array_merge($insert_paquet, $champs['paquet']);
262                        $insert_plugin = $champs['plugin'];
263                        // On construit l'url complete du logo
264                        // A REVOIR COMPLETEMENT !!!
265                        if ($insert_paquet['logo'])
266                                $insert_paquet['logo'] = $depot['url_archives'] . '/'
267                                                                           . $insert_paquet['src_archive'] . '/'
268                                                                           . $insert_paquet['logo'];
269
270                        // On loge l'absence de categorie ou une categorie erronee et on positionne la categorie
271                        // par defaut "aucune"
272                        // Provisoire tant que la DTD n'est pas en fonction
273                        if (!$insert_plugin['categorie']) {
274                                spip_log("Categorie absente dans le paquet issu de <". $insert_paquet['src_archive'] . 
275                                                "> du depot <" . $insert_paquet['id_depot'] . ">\n", 'svp_paquets');
276                                $insert_plugin['categorie'] = 'aucune';
277                        }
278                        else {
279                                $svp_categories = unserialize($GLOBALS['meta']['svp_categories']);
280                                if (!in_array($insert_plugin['categorie'], $svp_categories)) {
281                                        spip_log("Categorie &#107;" . $insert_plugin['categorie'] . "&#108; incorrecte dans le paquet issu de <". $insert_paquet['src_archive'] . 
282                                                        "> du depot <" . $insert_paquet['id_depot'] . ">\n", 'svp_paquets');
283                                        $insert_plugin['categorie'] = 'aucune';
284                                }
285                        }
286                }
287                else {
288                        $paquet_plugin = false;
289                }
290                // On teste l'existence du paquet dans la base avec les champs id_depot, nom_archive et src_archive
291                // pour etre sur de l'unicite.
292                // - si le paquet existe on ne fait qu'un update
293                // - sinon on insere le paquet
294                if (!$paquet = sql_fetsel('*', 'spip_paquets', array('id_depot='. sql_quote($insert_paquet['id_depot']),
295                                                                                                                        'nom_archive='. sql_quote($insert_paquet['nom_archive']),
296                                                                                                                        'src_archive='. sql_quote($insert_paquet['src_archive'])))) {
297                        // Le paquet n'existe pas encore en base de donnees
298                        // ------------------------------------------------
299                       
300                        // On positionne la date de creation a celle du dernier commit ce qui est bien le cas
301                        $insert_paquet['date_crea'] = $insert_paquet['date_modif'];
302
303                        // Les collisions ne sont possibles que si on ajoute un nouveau paquet
304                        $collision = false;
305
306                        if ($paquet_plugin) {
307                                // On est en presence d'un PLUGIN
308                                // ------------------------------
309                                // On evite les doublons de paquet
310                                // Pour determiner un doublon on verifie actuellement :
311                                // - le prefixe
312                                // - la version du paquet et de la base
313                                // - l'etat
314                                // - et on exclu les themes car leur prefixe est toujours = a "theme"
315                                $where = array('t1.id_plugin=t2.id_plugin',
316                                                't1.version=' . sql_quote($insert_paquet['version']),
317                                                't1.version_base=' . sql_quote($insert_paquet['version_base']),
318                                                't1.etatnum=' . sql_quote($insert_paquet['etatnum']),
319                                                't2.prefixe=' . sql_quote($insert_plugin['prefixe']));
320                                if (($insert_plugin['prefixe'] == _SVP_PREFIXE_PLUGIN_THEME)
321                                OR (!$id_paquet = sql_getfetsel('t1.id_paquet', 'spip_paquets AS t1, spip_plugins AS t2', $where))) {
322                                        // On traite d'abord le plugin du paquet pour recuperer l'id_plugin
323                                        // On rajoute le plugin dans la table spip_plugins si celui-ci n'y est pas encore ou on recupere
324                                        // l'id si il existe deja et on le met a jour si la version du paquet est plus elevee
325                                        if (!$plugin = sql_fetsel('id_plugin, vmax', 'spip_plugins',
326                                                array('prefixe=' . sql_quote($insert_plugin['prefixe'])))) {
327                                                $id_plugin = sql_insertq('spip_plugins', 
328                                                                                                array_merge($insert_plugin, array('vmax' => $insert_paquet['version'])));
329                                        }
330                                        else {
331                                                $id_plugin = $plugin['id_plugin'];
332                                                if (spip_version_compare($plugin['vmax'], $insert_paquet['version'], '<='))
333                                                        sql_updateq('spip_plugins',
334                                                                                array_merge($insert_plugin, array('vmax' => $insert_paquet['version'])),
335                                                                                'id_plugin=' . sql_quote($id_plugin));
336                                        }
337       
338                                        // On traite maintenant le paquet connaissant l'id du plugin
339                                        $insert_paquet['id_plugin'] = $id_plugin;
340                                        sql_insertq('spip_paquets', $insert_paquet);
341       
342                                        // On rajoute le plugin comme heberge par le depot si celui-ci n'est pas encore
343                                        // enregistre comme tel
344                                        if (!sql_countsel('spip_depots_plugins',
345                                                array('id_plugin=' . sql_quote($id_plugin),
346                                                        'id_depot=' . sql_quote($id_depot)))) {
347                                                sql_insertq('spip_depots_plugins', array('id_depot' => $id_depot, 'id_plugin' => $id_plugin));
348                                        }
349                                }
350                                else
351                                        $collision = true;
352                        }
353                        else {
354                                // On est en presence d'une CONTRIBUTION NON PLUGIN
355                                // ------------------------------------------------
356                                $where = array(
357                                                't1.id_depot=' . sql_quote($insert_paquet['id_depot']),
358                                                't1.nom_archive=' . sql_quote($insert_paquet['nom_archive']));
359                                if (!$id_paquet = sql_getfetsel('t1.id_paquet', 'spip_paquets AS t1', $where)) {
360                                        // Ce n'est pas un plugin, donc id_plugin=0 et toutes les infos plugin sont nulles
361                                        $insert_paquet['id_plugin'] = 0;
362                                        sql_insertq('spip_paquets', $insert_paquet);
363                                }
364                                else
365                                        $collision = true;
366                        }
367                        // On loge le paquet ayant ete refuse dans un fichier a part afin de les verifier
368                        // apres coup
369                        if ($collision AND _SVP_LOG_PAQUETS) {
370                                spip_log("Collision avec le paquet <". $insert_paquet['nom_archive'] . 
371                                                " / " . $insert_paquet['src_archive'] . "> du depot <" . $insert_paquet['id_depot'] . ">\n", 'svp_paquets');
372                        }
373                }
374                else {
375                        // Le paquet existe deja en base de donnees
376                        // ----------------------------------------
377                       
378                        // On met a jour le paquet en premier lieu qu'il soit un plugin ou une contribution
379                        sql_updateq('spip_paquets', $insert_paquet,
380                                                'id_paquet=' . sql_quote($paquet['id_paquet']));
381
382                        // Ensuite, si on est en presence d'un plugin, on le met a jour si le paquet est de version
383                        // plus elevee ou egale (on gere ainsi les oublis d'incrementation)
384                        if ($paquet_plugin) {
385                                if ($vmax = sql_getfetsel('vmax', 'spip_plugins', array('id_plugin=' . sql_quote($paquet['id_plugin']))))
386                                        if (spip_version_compare($vmax, $insert_paquet['version'], '<='))
387                                                sql_updateq('spip_plugins',
388                                                                        array_merge($insert_plugin, array('vmax' => $insert_paquet['version'])),
389                                                                        'id_plugin=' . sql_quote($paquet['id_plugin']));
390                        }
391                               
392                        // On ne change rien sur la table spip_depots_plugins, c'est inutile
393
394                        // On retire le paquet mis a jour de la liste des paquets a supprimer a la fin de l'actualisation
395                        if (isset($ids_a_supprimer[$paquet['id_paquet']])) {
396                                unset($ids_a_supprimer[$paquet['id_paquet']]);
397                                unset($versions_a_supprimer[$paquet['id_paquet']]);
398                        }
399                }
400        }
401       
402        // Il faut maintenant nettoyer la liste des paquets et plugins qui ont disparus du depot
403        if (count($ids_a_supprimer) > 0)
404                svp_nettoyer_apres_actualisation($id_depot, $ids_a_supprimer, $versions_a_supprimer);
405       
406        // Calcul des compteurs de paquets, plugins et contributions
407        $nb_paquets = sql_countsel('spip_paquets', 'id_depot=' . sql_quote($id_depot));
408        $nb_plugins = sql_countsel('spip_depots_plugins', 'id_depot=' . sql_quote($id_depot));
409        $nb_autres = sql_countsel('spip_paquets', array('id_depot=' . sql_quote($id_depot), 'id_plugin=0'));
410       
411        return true;
412}
413
414
415function svp_nettoyer_apres_actualisation($id_depot, $ids_a_supprimer, $versions_a_supprimer) {
416
417        // Si on rentre dans cette fonction c'est que le tableau des paquets a supprimer est non vide
418        // On prepare :
419        // - la liste des paquets a supprimer
420        // - la liste des plugins a verifier
421        // - la liste des versions max pour les plugins a verifier
422        $paquets_a_supprimer = array();
423        $ids_plugin = array();
424        $vmax = array();
425        foreach ($ids_a_supprimer as $_id_paquet => $_id_plugin) {
426                $paquets_a_supprimer[] = $_id_paquet;
427                if (!in_array($_id_plugin, $ids_plugin) AND ($_id_plugin != 0)) {
428                        $ids_plugin[] = $_id_plugin;
429                        if (!isset($vmax[$id_plugin])
430                        OR (spip_version_compare($vmax[$id_plugin], $versions_a_supprimer[$_id_paquet], '<'))) 
431                                $vmax[$_id_plugin] = $versions_a_supprimer[$_id_paquet];
432                }
433        }
434
435        // On supprime les paquets inutiles
436        sql_delete('spip_paquets', sql_in('id_paquet', $paquets_a_supprimer));
437
438        // On verifie pour chaque plugin concerne par la disparition de paquets si c'est la version
439        // la plus elevee qui a ete supprimee.
440        // Si oui, on positionne le vmax a 0, ce qui permettra de remettre a jour le plugin systematiquement
441        // a la prochaine actualisation.
442        // Cette operation est necessaire car on n'impose pas que les informations du plugin soient identiques
443        // pour chaque paquet !!!
444        if ($resultats = sql_select('id_plugin, vmax', 'spip_plugins', sql_in('id_plugin', $ids_plugin))) {
445                while ($plugin = sql_fetch($resultats)) {
446                        if (spip_version_compare($plugin['vmax'], $vmax[$plugin['id_plugin']], '='))
447                                sql_updateq('spip_plugins',     array('vmax' => '0.0'), 'id_plugin=' . sql_quote($plugin['id_plugin']));
448                }
449        }
450
451        if ($ids_plugin) {
452                // On cherche pour chaque plugin de la liste si un paquet existe encore dans le meme depot
453                // Si aucun autre paquet n'existe on peut supprimer le plugin de la table spip_depots_plugins
454                if ($resultats = sql_select('id_plugin', 'spip_paquets', 
455                                                                        array('id_depot=' . sql_quote($id_depot), sql_in('id_plugin', $ids_plugin)))) {
456                        while ($paquet = sql_fetch($resultats)) {
457                                $cle = array_search($paquet['id_plugin'], $ids_plugin);
458                                if ($cle !== false)
459                                        unset($ids_plugin[$cle]);
460                        }
461                }
462                if (count($ids_plugin) > 0) {
463                        // On supprime les liens des plugins n'etant plus heberges par le depot
464                        sql_delete('spip_depots_plugins', array('id_depot=' . sql_quote($id_depot), sql_in('id_plugin', $ids_plugin)));
465                               
466                        // Maintenant on verifie si les plugins supprimes sont encore heberges par d'autre depot
467                        // Si non, on peut supprimer le plugin lui-meme de la table spip_plugins
468                        $plugins_a_supprimer = $ids_plugin;
469                        if ($liens = sql_allfetsel('id_plugin', 'spip_depots_plugins', sql_in('id_plugin', $ids_plugin))) {
470                                $plugins_a_conserver = array_map('reset', $liens);
471                                // L'intersection des deux tableaux renvoie les plugins a supprimer     
472                                $plugins_a_supprimer = array_diff($ids_plugin, $plugins_a_conserver);
473                        }
474                       
475                        // On supprime les plugins identifies
476                        if ($plugins_a_supprimer)
477                                sql_delete('spip_plugins', sql_in('id_plugin', $plugins_a_supprimer));
478                }
479        }
480       
481        return true;
482}
483
484
485// Les archives xml sont deja applaties, pas la peine de se compliquer.
486function svp_remplir_champs_sql($p) {
487
488        if (!$p)
489                return array();
490
491        // On passe le prefixe en lettres majuscules comme ce qui est fait dans SPIP
492        // Ainsi les valeurs dans la table spip_plugins coincideront avec celles de la meta plugin
493        $p['prefix'] = strtoupper($p['prefix']);
494
495        // calcul du tableau de dependances
496        $dependances = array();
497        $v_spip = '';
498        if (is_array($p['necessite'])) {
499                foreach ($p['necessite'] as $c=>$n) {
500                        $p['necessite'][$c]['id'] = strtoupper($n['id']);
501                        if ($n['id'] == 'SPIP') {
502                                $v_spip = $n['version'];
503                        }
504                }
505                $dependances['necessite'] = $p['necessite'];
506        }
507       
508        if (is_array($p['utilise'])) {
509                foreach ($p['utilise'] as $c=>$n) {
510                        $p['utilise'][$c]['id'] = strtoupper($n['id']);
511                }
512                $dependances['utilise'] = $p['utilise'];
513        }
514
515        // Etat numerique (pour simplifier la recherche de maj)
516        $num = array('stable'=>4, 'test'=>3, 'dev'=>2, 'experimental'=>1);
517        $etatnum = isset($num[$p['etat']]) ? $num[$p['etat']] : 0;
518       
519        // On passe en utf-8 avec le bon charset les champs pouvant contenir des entites html
520        $p['description'] = unicode2charset(html2unicode($p['description']));
521        $p['slogan'] = unicode2charset(html2unicode($p['slogan']));
522        $p['nom'] = unicode2charset(html2unicode($p['nom']));
523        $p['auteur'] = unicode2charset(html2unicode($p['auteur']));
524        $p['licence'] = unicode2charset(html2unicode($p['licence']));
525
526        // Nom, slogan et branche
527        if ($p['prefix'] == _SVP_PREFIXE_PLUGIN_THEME) {
528                // Traitement specifique des themes qui aujourd'hui sont consideres comme des paquets
529                // d'un plugin unique de prefixe "theme"
530                $nom = _SVP_NOM_PLUGIN_THEME;
531                $slogan = _SVP_SLOGAN_PLUGIN_THEME;
532        }
533        else {
534                // Calcul *temporaire* de la nouvelles balise slogan si celle-ci n'est
535                // pas renseignee et de la balise nom. Ceci devrait etre temporaire jusqu'a la nouvelle ere
536                // glaciaire des plugins
537                // - Slogan     :       si vide alors on prend la premiere phrase de la description limitee a 255
538                $slogan = (!$p['slogan']) ? svp_remplir_slogan($p['description']) : $p['slogan'];
539                // - Nom :      on repere dans le nom du plugin un chiffre en fin de nom
540                //                      et on l'ampute de ce numero pour le normaliser
541                //                      et on passe tout en unicode avec le charset du site
542                $nom = svp_normaliser_nom($p['nom']);
543        }
544       
545        return array(
546                'plugin' => array(
547                        'prefixe' => $p['prefix'],
548                        'nom' => $nom,
549                        'slogan' => $slogan,
550                        'categorie' => $p['categorie'],
551                        'tags' => $p['tags']),
552                'paquet' => array(
553                        'logo' => $p['icon'],
554                        'description' => $p['description'],
555                        'auteur' => $p['auteur'],
556                        'version' => $p['version'],
557                        'version_base' => $p['version_base'],
558                        'version_spip' => $v_spip,
559                        'etat' => $p['etat'],
560                        'etatnum' => $etatnum,
561                        'licence' => $p['licence'],
562                        'lien' => $p['lien'],
563                        'dependances' => serialize($dependances))
564        );
565}
566
567function svp_remplir_slogan($description) {
568        include_spip('inc/texte');
569
570        // On extrait les traductions de l'eventuel multi
571        // Si le nom n'est pas un multi alors le tableau renvoye est de la forme '' => 'nom'
572        $descriptions = extraire_trads(str_replace(array('<multi>', '</multi>'), array(), $description, $nbr_replace));
573        $multi = ($nbr_replace > 0) ? true : false;
574
575        // On boucle sur chaque multi ou sur la chaine elle-meme en extrayant le slogan
576        // dans les differentes langues
577        $slogan = '';
578        foreach ($descriptions as $_lang => $_descr) {
579                $_descr = trim($_descr);
580                if (!$_lang)
581                        $_lang = 'fr';
582                $nbr_matches = preg_match(',^(.+)[.!?\r\n\f],Um', $_descr, $matches);
583                $slogan .= (($multi) ? '[' . $_lang . ']' : '') . 
584                                        (($nbr_matches > 0) ? trim($matches[1]) : couper($_descr, 150, ''));
585        }
586
587        if ($slogan)
588                // On renvoie un nouveau slogan multi ou pas
589                $slogan = (($multi) ? '<multi>' : '') . $slogan . (($multi) ? '</multi>' : '');
590
591        return $slogan;
592}
593
594function svp_normaliser_nom($nom) {
595        include_spip('inc/texte');
596
597        // On extrait les traductions de l'eventuel multi
598        // Si le nom n'est pas un multi alors le tableau renvoye est de la forme '' => 'nom'
599        $noms = extraire_trads(str_replace(array('<multi>', '</multi>'), array(), $nom, $nbr_replace));
600        $multi = ($nbr_replace > 0) ? true : false;
601       
602        $nouveau_nom = '';
603        foreach ($noms as $_lang => $_nom) {
604                $_nom = trim($_nom);
605                if (!$_lang)
606                        $_lang = 'fr';
607                $nbr_matches = preg_match(',(.+)(\s+[\d._]*)$,Um', $_nom, $matches);
608                $nouveau_nom .= (($multi) ? '[' . $_lang . ']' : '') . 
609                                                (($nbr_matches > 0) ? trim($matches[1]) : $_nom);
610        }
611       
612        if ($nouveau_nom)
613                // On renvoie un nouveau nom multi ou pas sans la valeur de la branche
614                $nouveau_nom = (($multi) ? '<multi>' : '') . $nouveau_nom . (($multi) ? '</multi>' : '');
615               
616        return $nouveau_nom;
617}
618
619
620// ----------------------- Analyses XML ---------------------------------
621
622// parse un fichier de source dont l'url est donnee
623// ce fichier est un fichier XML contenant <depot>...</depot>
624// et <archives>...</archives>
625function svp_xml_parse_depot($url){
626        include_spip('inc/xml');
627        include_spip('inc/distant');
628
629        // On lit le fichier xml
630        if (!$xml = recuperer_page($url)) {
631                return false;
632        }
633
634        // On enleve la balise doctype qui provoque une erreur "balise non fermee" lors du parsage
635        $xml = preg_replace('#<!DOCTYPE[^>]*>#','',$xml);
636
637        // Deux cas d'erreur de fichier non conforme
638        // - la syntaxe xml est incorrecte
639        // - aucun plugin dans le depot
640        // Si le bloc <depot> n'est pas renseigne on ne considere pas cela comme une erreur
641        $arbre = array();
642        if (!is_array($arbre = spip_xml_parse($xml)) OR !is_array($archives = $arbre['archives'][0])){
643                return false;
644        }
645
646        // On extrait les informations du depot si elles existent (balise <depot>)
647        $infos = array('depot' => array(), 'paquets' => array());
648        if (is_array($depot = $arbre['depot'][0]))
649                $infos['depot'] = svp_xml_aplatit_multiple(array('titre', 'descriptif', 'type', 'url_serveur', 'url_archives'), $depot);
650        if (!$infos['depot']['titre'])
651                $infos['depot']['titre'] = _T('svp:titre_nouveau_depot');
652        if (!$infos['depot']['type'])
653                $infos['depot']['type'] = 'svn';
654
655        // On extrait les informations de chaque plugin du depot (balise <archives>)
656        foreach ($archives as $z=>$c){
657                $c = $c[0];
658                // si fichier zip, on ajoute le paquet dans la liste
659                // - cas 1 : c'est un plugin donc on integre les infos du plugin
660                // - cas 2 : c'est une archive non plugin, pas d'infos autres que celles de l'archive
661                if ($url = $c['file'][0]) {
662                        if (is_array($c['plugin']))
663                                $plugin = svp_xml_parse_plugin($c['plugin'][0]);
664                        else
665                                $plugin = array();
666                        // On remplit les infos dans les deux cas
667                        $infos['paquets'][$url] = array(
668                                'plugin' => $plugin, 
669                                'file' => $url,
670                                'size' => $c['size'][0],
671                                'date' => $c['date'][0],        // c'est la date de generation du zip
672                                'source' => $c['source'][0],
673                                'last_commit' => $c['last_commit'][0]
674                        );
675                }
676        }
677       
678        return $infos;
679}
680
681
682// aplatit plusieurs cles d'un arbre xml dans un tableau
683// effectue un trim() au passage
684function svp_xml_aplatit_multiple($array, $arbre){
685        $a = array();
686        // array('uri','archive'=>'zip',...)
687        foreach ($array as $i=>$n){
688                if (is_string($i)) $cle = $i;
689                else $cle = $n;
690                $a[$n] = trim(spip_xml_aplatit($arbre[$cle]));
691        }
692        return $a;     
693}
694
695
696// parse un plugin.xml genere par spip_xml_parse()
697// en un tableau plus facilement utilisable
698// cette fonction doit permettre de mapper des changements
699// de syntaxe entre plugin.xml et step
700function svp_xml_parse_plugin($arbre){
701
702        if (!is_array($arbre)) 
703                return false;
704       
705        // on commence par les simples !
706        $plug_arbre = svp_xml_aplatit_multiple(
707                                array('nom','icon','auteur','licence','version','version_base','etat','slogan','categorie','tags',
708                                'description','lien','options','fonctions','prefix','install'), 
709                                $arbre);
710        $plug_arbre['prefix'] = strtolower($plug_arbre['prefix']);
711       
712        // on continue avec les plus complexes...       
713        // 1) balises avec attributs
714        foreach (array(
715                        'necessite'=>array('necessite', null),
716                        'utilise'=>array('utilise', null),
717                        'chemin'=>array('path', array('dir'=>'')))
718                                as $balise=>$p){
719                $params = $res = array();
720                // recherche de la balise et extraction des attributs
721                if (spip_xml_match_nodes(",^$balise,",$arbre, $res)){
722                        foreach(array_keys($res) as $tag){
723                                list($tag,$att) = spip_xml_decompose_tag($tag);
724                                $params[] = $att;
725                        }
726                } 
727                // valeur par defaut
728                else {
729                        if ($p[1]!==null)
730                                $params[] = $p[1];
731                }
732                $plug_arbre[$p[0]] = $params;           
733        }
734
735        return $plug_arbre;
736}
737
738
739// ----------------------- Recherches de plugins ---------------------------------
740
741function svp_rechercher_plugins_spip($phrase, $categorie, $etat, $depot, $version_spip='',
742                                                                        $exclusions=array(), $afficher_exclusions=false, $doublon=false, $tri='nom') {
743
744        include_spip('inc/rechercher');
745       
746        $plugins = array();
747        $scores = array();
748        $ids_paquets = array();
749
750        // On prepare l'utilisation de la recherche en base SPIP en la limitant aux tables spip_plugins
751        // et spip_paquets  si elle n'est pas vide
752        if ($phrase) {
753                $liste = liste_des_champs();
754                $tables = array('plugin' => $liste['plugin'], 'paquet' => $liste['paquet']);
755                $options = array('jointures' => true, 'score' => true);
756       
757                // On cherche dans tous les enregistrements de ces tables des correspondances les plugins qui
758                // correspondent a la phrase recherchee
759                // -- On obtient une liste d'id de plugins et d'id de paquets
760                $resultats = array('plugin' => array(), 'paquet' => array());
761                $resultats = recherche_en_base($phrase, $tables, $options);
762                // -- On prepare le tableau des scores avec les paquets trouves par la recherche
763                if ($resultats) {
764                        // -- On convertit les id de plugins en id de paquets
765                        $ids = array();
766                        if ($resultats['plugin']) {
767                                $ids_plugin = array_keys($resultats['plugin']);
768                                $where[] = sql_in('id_plugin', $ids_plugin);
769                                $ids = sql_allfetsel('id_paquet, id_plugin', 'spip_paquets', $where);
770                        }
771                        // -- On prepare les listes des id de paquet et des scores de ces memes paquets
772                        if ($resultats['paquet']) {
773                                $ids_paquets = array_keys($resultats['paquet']);
774                                foreach ($resultats['paquet'] as $_id => $_score) {
775                                        $scores[$_id] = intval($resultats['paquet'][$_id]['score']);
776                                }
777                        }
778                        // -- On merge les deux tableaux de paquets sans doublon en mettant a jour un tableau des scores
779                        foreach ($ids as $_ids) {
780                                $id_paquet = intval($_ids['id_paquet']);
781                                $id_plugin = intval($_ids['id_plugin']);
782                                if (array_search($id_paquet, $ids_paquets) === false) {
783                                        $ids_paquets[] = $id_paquet;
784                                        $scores[$id_paquet] = intval($resultats['plugin'][$id_plugin]['score']);
785                                }
786                                else {
787                                        $scores[$id_paquet] = intval($resultats['paquet'][$id_paquet]['score']) 
788                                                                                + intval($resultats['plugin'][$id_plugin]['score']);
789                                }
790                        }
791                }
792        }
793
794        // Maintenant, on continue la recherche en appliquant, sur la liste des id de paquets,
795        // les filtres complementaires : categorie, etat, exclusions et compatibilite spip
796        // si on a bien trouve des resultats precedemment ou si aucune phrase n'a ete saisie
797        // -- Preparation de la requete
798        if (!$phrase OR $resultats) {
799                $from = array('spip_plugins AS t1', 'spip_paquets AS t2', 'spip_depots AS t3');
800                $select = array('t1.nom AS nom', 't1.slogan AS slogan', 't1.prefixe AS prefixe', 't1.id_plugin AS id_plugin', 
801                                                't2.id_paquet AS id_paquet', 't2.description AS description', 't2.version_spip AS version_spip',
802                                                't2.auteur AS auteur', 't2.licence AS licence', 't2.etat AS etat',
803                                                't2.logo AS logo', 't2.version AS version', 't2.nom_archive AS nom_archive',
804                                                't3.url_archives AS url_archives', );
805                $where = array('t1.id_plugin=t2.id_plugin', 't2.id_depot=t3.id_depot');
806                if ($ids_paquets)
807                        $where[] = sql_in('t2.id_paquet', $ids_paquets);
808                if (($categorie) AND ($categorie != 'toute_categorie'))
809                        $where[] = 't1.categorie=' . sql_quote($categorie);
810                if (($etat) AND ($etat != 'tout_etat'))
811                        $where[] = 't2.etat=' . sql_quote($etat);
812                if (($depot) AND ($depot != 'tout_depot'))
813                        $where[] = 't2.id_depot=' . sql_quote($depot);
814                if ($exclusions AND !$afficher_exclusions)
815                        $where[] = sql_in('t2.id_plugin', $exclusions, 'NOT');
816       
817                if ($resultats = sql_select($select, $from, $where)) {
818                        while ($paquets = sql_fetch($resultats)) {
819                                $prefixe = $paquets['prefixe'];
820                                $version = $paquets['version'];
821                                $nom = extraire_multi($paquets['nom']);
822                                $slogan = extraire_multi($paquets['slogan']);
823                                $description = extraire_multi($paquets['description']);
824                                if (svp_verifier_compatibilite_spip($paquets['version_spip'], $version_spip)) {
825                                        // Le paquet remplit tous les criteres, on peut le selectionner
826                                        // -- on utilise uniquement la langue du site
827                                        $paquets['nom'] = $nom;
828                                        $paquets['slogan'] = $slogan;
829                                        $paquets['description'] = $description;
830                                        // -- on ajoute le score si on a bien saisi une phrase
831                                        if ($phrase)
832                                                $paquets['score'] = $scores[intval($paquets['id_paquet'])];
833                                        else
834                                                $paquets['score'] = 0;
835                                        // -- on construit l'url de l'archive
836                                        $paquets['url_archive'] = $paquets['url_archives'] . '/' . $paquets['nom_archive'];
837                                        // -- on gere les exclusions si elle doivent etre affichees
838                                        if ($afficher_exclusions AND in_array($paquets['id_plugin'], $exclusions))
839                                                $paquets['installe'] = true;
840                                        else
841                                                $paquets['installe'] = false;
842                                        // -- On traite les doublons (meme plugin, versions differentes)
843                                        if ($doublon)
844                                                // ajout systematique du paquet
845                                                $plugins[] = $paquets;
846                                        else {
847                                                // ajout
848                                                // - si pas encore trouve
849                                                // - ou si sa version est inferieure (on garde que la derniere version)
850                                                if (!$plugins[$prefixe]
851                                                OR ($plugins[$prefixe] AND spip_version_compare($plugins[$prefixe]['version'], $version, '<'))) {
852                                                        $plugins[$prefixe] = $paquets;
853                                                }
854                                        }
855                                }
856                        }
857                }
858               
859                // On trie le tableau par score décroissant ou nom croissant
860                $fonction = 'svp_trier_par_' . $tri;
861                if ($doublon)
862                        usort($plugins, $fonction);
863                else
864                        uasort($plugins, $fonction);
865        }
866       
867        return $plugins;
868}
869
870
871/**
872 * Recuperation des id des plugins a exclure car deja installes
873 *
874 * @return array
875 */
876function svp_lister_plugins_installes(){
877
878        $ids = array();
879
880        // On recupere la liste des plugins installes physiquement sur le site
881        // Pour l'instant ce n'est pas possible avec les fonctions natives de SPIP
882        // donc on se contente des plugins actifs
883        // - liste des prefixes en lettres majuscules des plugins actifs
884        include_spip('inc/plugin');
885        $plugins = liste_plugin_actifs();
886
887        // - liste des id de plugin correspondants
888        //   Il se peut que certains plugins ne soient pas trouves dans la bdd car aucun zip n'est disponible
889        //   (donc pas inclus dans archives.xml). C'est le cas des extensions du core
890        $ids = sql_allfetsel('id_plugin', 'spip_plugins', sql_in('prefixe', array_keys($plugins)));
891        $ids = array_map('reset', $ids);
892        $ids = array_map('intval', $ids);
893
894        return $ids;
895}
896
897
898/**
899 * Test de la compatibilite du plugin avec une version donnee de SPIP
900 *
901 * @return boolean
902 */
903function svp_verifier_compatibilite_spip($version, $version_spip) {
904        include_spip('inc/plugin');
905        if (!$version_spip)
906                $version_spip = $GLOBALS['spip_version_branche'].".".$GLOBALS['spip_version_code'];
907        return plugin_version_compatible($version, $version_spip);
908}
909
910
911/**
912 * Tri decroissant des resultats par score.
913 * Cette fonction est appelee par un usort ou uasort
914 *
915 * @return int
916 */
917function svp_trier_par_score($p1, $p2){
918        if ($p1['score'] == $p2['score']) 
919                $retour = 0;
920        else 
921                $retour = ($p1['score'] < $p2['score']) ? 1 : -1;
922        return $retour;
923}
924
925
926/**
927 * Tri croissant des resultats par nom.
928 * Si le nom est identique on classe par version decroissante
929 * Cette fonction est appelee par un usort ou uasort
930 *
931 * @return int
932 */
933function svp_trier_par_nom($p1, $p2){
934        $c1 = strcasecmp($p1['nom'], $p2['nom']);
935        if ($c1 == 0) {
936                $c2 = spip_version_compare($p1['version'], $p1['version'], '<');
937                $retour = ($c2) ? 1 : -1;
938        }
939        else 
940                $retour = ($c1 < 0) ? -1 : 1;
941        return $retour;
942}
943
944?>
Note: See TracBrowser for help on using the repository browser.