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

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

On crée enfin la bonne url pour le logo des paquets maintenant que smart-paquets les met à disposition.

  • Property svn:eol-style set to native
File size: 35.3 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                        // Le logo est maintenant disponible a la meme adresse que le zip et porte le nom du zip.
265                        // Son extension originale est conservee
266                        if ($insert_paquet['logo'])
267                                $insert_paquet['logo'] = $depot['url_archives'] . '/'
268                                                                           . basename($insert_paquet['nom_archive'], '.zip') . '.'
269                                                                           . pathinfo($insert_paquet['logo'], PATHINFO_EXTENSION);
270
271                        // On loge l'absence de categorie ou une categorie erronee et on positionne la categorie
272                        // par defaut "aucune"
273                        // Provisoire tant que la DTD n'est pas en fonction
274                        if (!$insert_plugin['categorie']) {
275                                spip_log("Categorie absente dans le paquet issu de <". $insert_paquet['src_archive'] . 
276                                                "> du depot <" . $insert_paquet['id_depot'] . ">\n", 'svp_paquets');
277                                $insert_plugin['categorie'] = 'aucune';
278                        }
279                        else {
280                                $svp_categories = unserialize($GLOBALS['meta']['svp_categories']);
281                                if (!in_array($insert_plugin['categorie'], $svp_categories)) {
282                                        spip_log("Categorie &#107;" . $insert_plugin['categorie'] . "&#108; incorrecte dans le paquet issu de <". $insert_paquet['src_archive'] . 
283                                                        "> du depot <" . $insert_paquet['id_depot'] . ">\n", 'svp_paquets');
284                                        $insert_plugin['categorie'] = 'aucune';
285                                }
286                        }
287                }
288                else {
289                        $paquet_plugin = false;
290                }
291                // On teste l'existence du paquet dans la base avec les champs id_depot, nom_archive et src_archive
292                // pour etre sur de l'unicite.
293                // - si le paquet existe on ne fait qu'un update
294                // - sinon on insere le paquet
295                if (!$paquet = sql_fetsel('*', 'spip_paquets', array('id_depot='. sql_quote($insert_paquet['id_depot']),
296                                                                                                                        'nom_archive='. sql_quote($insert_paquet['nom_archive']),
297                                                                                                                        'src_archive='. sql_quote($insert_paquet['src_archive'])))) {
298                        // Le paquet n'existe pas encore en base de donnees
299                        // ------------------------------------------------
300                       
301                        // On positionne la date de creation a celle du dernier commit ce qui est bien le cas
302                        $insert_paquet['date_crea'] = $insert_paquet['date_modif'];
303
304                        // Les collisions ne sont possibles que si on ajoute un nouveau paquet
305                        $collision = false;
306
307                        if ($paquet_plugin) {
308                                // On est en presence d'un PLUGIN
309                                // ------------------------------
310                                // On evite les doublons de paquet
311                                // Pour determiner un doublon on verifie actuellement :
312                                // - le prefixe
313                                // - la version du paquet et de la base
314                                // - l'etat
315                                // - et on exclu les themes car leur prefixe est toujours = a "theme"
316                                $where = array('t1.id_plugin=t2.id_plugin',
317                                                't1.version=' . sql_quote($insert_paquet['version']),
318                                                't1.version_base=' . sql_quote($insert_paquet['version_base']),
319                                                't1.etatnum=' . sql_quote($insert_paquet['etatnum']),
320                                                't2.prefixe=' . sql_quote($insert_plugin['prefixe']));
321                                if (($insert_plugin['prefixe'] == _SVP_PREFIXE_PLUGIN_THEME)
322                                OR (!$id_paquet = sql_getfetsel('t1.id_paquet', 'spip_paquets AS t1, spip_plugins AS t2', $where))) {
323                                        // On traite d'abord le plugin du paquet pour recuperer l'id_plugin
324                                        // On rajoute le plugin dans la table spip_plugins si celui-ci n'y est pas encore ou on recupere
325                                        // l'id si il existe deja et on le met a jour si la version du paquet est plus elevee
326                                        if (!$plugin = sql_fetsel('id_plugin, vmax', 'spip_plugins',
327                                                array('prefixe=' . sql_quote($insert_plugin['prefixe'])))) {
328                                                $id_plugin = sql_insertq('spip_plugins', 
329                                                                                                array_merge($insert_plugin, array('vmax' => $insert_paquet['version'])));
330                                        }
331                                        else {
332                                                $id_plugin = $plugin['id_plugin'];
333                                                if (spip_version_compare($plugin['vmax'], $insert_paquet['version'], '<='))
334                                                        sql_updateq('spip_plugins',
335                                                                                array_merge($insert_plugin, array('vmax' => $insert_paquet['version'])),
336                                                                                'id_plugin=' . sql_quote($id_plugin));
337                                        }
338       
339                                        // On traite maintenant le paquet connaissant l'id du plugin
340                                        $insert_paquet['id_plugin'] = $id_plugin;
341                                        sql_insertq('spip_paquets', $insert_paquet);
342       
343                                        // On rajoute le plugin comme heberge par le depot si celui-ci n'est pas encore
344                                        // enregistre comme tel
345                                        if (!sql_countsel('spip_depots_plugins',
346                                                array('id_plugin=' . sql_quote($id_plugin),
347                                                        'id_depot=' . sql_quote($id_depot)))) {
348                                                sql_insertq('spip_depots_plugins', array('id_depot' => $id_depot, 'id_plugin' => $id_plugin));
349                                        }
350                                }
351                                else
352                                        $collision = true;
353                        }
354                        else {
355                                // On est en presence d'une CONTRIBUTION NON PLUGIN
356                                // ------------------------------------------------
357                                $where = array(
358                                                't1.id_depot=' . sql_quote($insert_paquet['id_depot']),
359                                                't1.nom_archive=' . sql_quote($insert_paquet['nom_archive']));
360                                if (!$id_paquet = sql_getfetsel('t1.id_paquet', 'spip_paquets AS t1', $where)) {
361                                        // Ce n'est pas un plugin, donc id_plugin=0 et toutes les infos plugin sont nulles
362                                        $insert_paquet['id_plugin'] = 0;
363                                        sql_insertq('spip_paquets', $insert_paquet);
364                                }
365                                else
366                                        $collision = true;
367                        }
368                        // On loge le paquet ayant ete refuse dans un fichier a part afin de les verifier
369                        // apres coup
370                        if ($collision AND _SVP_LOG_PAQUETS) {
371                                spip_log("Collision avec le paquet <". $insert_paquet['nom_archive'] . 
372                                                " / " . $insert_paquet['src_archive'] . "> du depot <" . $insert_paquet['id_depot'] . ">\n", 'svp_paquets');
373                        }
374                }
375                else {
376                        // Le paquet existe deja en base de donnees
377                        // ----------------------------------------
378                       
379                        // On met a jour le paquet en premier lieu qu'il soit un plugin ou une contribution
380                        sql_updateq('spip_paquets', $insert_paquet,
381                                                'id_paquet=' . sql_quote($paquet['id_paquet']));
382
383                        // Ensuite, si on est en presence d'un plugin, on le met a jour si le paquet est de version
384                        // plus elevee ou egale (on gere ainsi les oublis d'incrementation)
385                        if ($paquet_plugin) {
386                                if ($vmax = sql_getfetsel('vmax', 'spip_plugins', array('id_plugin=' . sql_quote($paquet['id_plugin']))))
387                                        if (spip_version_compare($vmax, $insert_paquet['version'], '<='))
388                                                sql_updateq('spip_plugins',
389                                                                        array_merge($insert_plugin, array('vmax' => $insert_paquet['version'])),
390                                                                        'id_plugin=' . sql_quote($paquet['id_plugin']));
391                        }
392                               
393                        // On ne change rien sur la table spip_depots_plugins, c'est inutile
394
395                        // On retire le paquet mis a jour de la liste des paquets a supprimer a la fin de l'actualisation
396                        if (isset($ids_a_supprimer[$paquet['id_paquet']])) {
397                                unset($ids_a_supprimer[$paquet['id_paquet']]);
398                                unset($versions_a_supprimer[$paquet['id_paquet']]);
399                        }
400                }
401        }
402       
403        // Il faut maintenant nettoyer la liste des paquets et plugins qui ont disparus du depot
404        if (count($ids_a_supprimer) > 0)
405                svp_nettoyer_apres_actualisation($id_depot, $ids_a_supprimer, $versions_a_supprimer);
406       
407        // Calcul des compteurs de paquets, plugins et contributions
408        $nb_paquets = sql_countsel('spip_paquets', 'id_depot=' . sql_quote($id_depot));
409        $nb_plugins = sql_countsel('spip_depots_plugins', 'id_depot=' . sql_quote($id_depot));
410        $nb_autres = sql_countsel('spip_paquets', array('id_depot=' . sql_quote($id_depot), 'id_plugin=0'));
411       
412        return true;
413}
414
415
416function svp_nettoyer_apres_actualisation($id_depot, $ids_a_supprimer, $versions_a_supprimer) {
417
418        // Si on rentre dans cette fonction c'est que le tableau des paquets a supprimer est non vide
419        // On prepare :
420        // - la liste des paquets a supprimer
421        // - la liste des plugins a verifier
422        // - la liste des versions max pour les plugins a verifier
423        $paquets_a_supprimer = array();
424        $ids_plugin = array();
425        $vmax = array();
426        foreach ($ids_a_supprimer as $_id_paquet => $_id_plugin) {
427                $paquets_a_supprimer[] = $_id_paquet;
428                if (!in_array($_id_plugin, $ids_plugin) AND ($_id_plugin != 0)) {
429                        $ids_plugin[] = $_id_plugin;
430                        if (!isset($vmax[$id_plugin])
431                        OR (spip_version_compare($vmax[$id_plugin], $versions_a_supprimer[$_id_paquet], '<'))) 
432                                $vmax[$_id_plugin] = $versions_a_supprimer[$_id_paquet];
433                }
434        }
435
436        // On supprime les paquets inutiles
437        sql_delete('spip_paquets', sql_in('id_paquet', $paquets_a_supprimer));
438
439        // On verifie pour chaque plugin concerne par la disparition de paquets si c'est la version
440        // la plus elevee qui a ete supprimee.
441        // Si oui, on positionne le vmax a 0, ce qui permettra de remettre a jour le plugin systematiquement
442        // a la prochaine actualisation.
443        // Cette operation est necessaire car on n'impose pas que les informations du plugin soient identiques
444        // pour chaque paquet !!!
445        if ($resultats = sql_select('id_plugin, vmax', 'spip_plugins', sql_in('id_plugin', $ids_plugin))) {
446                while ($plugin = sql_fetch($resultats)) {
447                        if (spip_version_compare($plugin['vmax'], $vmax[$plugin['id_plugin']], '='))
448                                sql_updateq('spip_plugins',     array('vmax' => '0.0'), 'id_plugin=' . sql_quote($plugin['id_plugin']));
449                }
450        }
451
452        if ($ids_plugin) {
453                // On cherche pour chaque plugin de la liste si un paquet existe encore dans le meme depot
454                // Si aucun autre paquet n'existe on peut supprimer le plugin de la table spip_depots_plugins
455                if ($resultats = sql_select('id_plugin', 'spip_paquets', 
456                                                                        array('id_depot=' . sql_quote($id_depot), sql_in('id_plugin', $ids_plugin)))) {
457                        while ($paquet = sql_fetch($resultats)) {
458                                $cle = array_search($paquet['id_plugin'], $ids_plugin);
459                                if ($cle !== false)
460                                        unset($ids_plugin[$cle]);
461                        }
462                }
463                if (count($ids_plugin) > 0) {
464                        // On supprime les liens des plugins n'etant plus heberges par le depot
465                        sql_delete('spip_depots_plugins', array('id_depot=' . sql_quote($id_depot), sql_in('id_plugin', $ids_plugin)));
466                               
467                        // Maintenant on verifie si les plugins supprimes sont encore heberges par d'autre depot
468                        // Si non, on peut supprimer le plugin lui-meme de la table spip_plugins
469                        $plugins_a_supprimer = $ids_plugin;
470                        if ($liens = sql_allfetsel('id_plugin', 'spip_depots_plugins', sql_in('id_plugin', $ids_plugin))) {
471                                $plugins_a_conserver = array_map('reset', $liens);
472                                // L'intersection des deux tableaux renvoie les plugins a supprimer     
473                                $plugins_a_supprimer = array_diff($ids_plugin, $plugins_a_conserver);
474                        }
475                       
476                        // On supprime les plugins identifies
477                        if ($plugins_a_supprimer)
478                                sql_delete('spip_plugins', sql_in('id_plugin', $plugins_a_supprimer));
479                }
480        }
481       
482        return true;
483}
484
485
486// Les archives xml sont deja applaties, pas la peine de se compliquer.
487function svp_remplir_champs_sql($p) {
488
489        if (!$p)
490                return array();
491
492        // On passe le prefixe en lettres majuscules comme ce qui est fait dans SPIP
493        // Ainsi les valeurs dans la table spip_plugins coincideront avec celles de la meta plugin
494        $p['prefix'] = strtoupper($p['prefix']);
495
496        // calcul du tableau de dependances
497        $dependances = array();
498        $v_spip = '';
499        if (is_array($p['necessite'])) {
500                foreach ($p['necessite'] as $c=>$n) {
501                        $p['necessite'][$c]['id'] = strtoupper($n['id']);
502                        if ($n['id'] == 'SPIP') {
503                                $v_spip = $n['version'];
504                        }
505                }
506                $dependances['necessite'] = $p['necessite'];
507        }
508       
509        if (is_array($p['utilise'])) {
510                foreach ($p['utilise'] as $c=>$n) {
511                        $p['utilise'][$c]['id'] = strtoupper($n['id']);
512                }
513                $dependances['utilise'] = $p['utilise'];
514        }
515
516        // Etat numerique (pour simplifier la recherche de maj)
517        $num = array('stable'=>4, 'test'=>3, 'dev'=>2, 'experimental'=>1);
518        $etatnum = isset($num[$p['etat']]) ? $num[$p['etat']] : 0;
519       
520        // On passe en utf-8 avec le bon charset les champs pouvant contenir des entites html
521        $p['description'] = unicode2charset(html2unicode($p['description']));
522        $p['slogan'] = unicode2charset(html2unicode($p['slogan']));
523        $p['nom'] = unicode2charset(html2unicode($p['nom']));
524        $p['auteur'] = unicode2charset(html2unicode($p['auteur']));
525        $p['licence'] = unicode2charset(html2unicode($p['licence']));
526
527        // Nom, slogan et branche
528        if ($p['prefix'] == _SVP_PREFIXE_PLUGIN_THEME) {
529                // Traitement specifique des themes qui aujourd'hui sont consideres comme des paquets
530                // d'un plugin unique de prefixe "theme"
531                $nom = _SVP_NOM_PLUGIN_THEME;
532                $slogan = _SVP_SLOGAN_PLUGIN_THEME;
533        }
534        else {
535                // Calcul *temporaire* de la nouvelles balise slogan si celle-ci n'est
536                // pas renseignee et de la balise nom. Ceci devrait etre temporaire jusqu'a la nouvelle ere
537                // glaciaire des plugins
538                // - Slogan     :       si vide alors on prend la premiere phrase de la description limitee a 255
539                $slogan = (!$p['slogan']) ? svp_remplir_slogan($p['description']) : $p['slogan'];
540                // - Nom :      on repere dans le nom du plugin un chiffre en fin de nom
541                //                      et on l'ampute de ce numero pour le normaliser
542                //                      et on passe tout en unicode avec le charset du site
543                $nom = svp_normaliser_nom($p['nom']);
544        }
545       
546        return array(
547                'plugin' => array(
548                        'prefixe' => $p['prefix'],
549                        'nom' => $nom,
550                        'slogan' => $slogan,
551                        'categorie' => $p['categorie'],
552                        'tags' => $p['tags']),
553                'paquet' => array(
554                        'logo' => $p['icon'],
555                        'description' => $p['description'],
556                        'auteur' => $p['auteur'],
557                        'version' => $p['version'],
558                        'version_base' => $p['version_base'],
559                        'version_spip' => $v_spip,
560                        'etat' => $p['etat'],
561                        'etatnum' => $etatnum,
562                        'licence' => $p['licence'],
563                        'lien' => $p['lien'],
564                        'dependances' => serialize($dependances))
565        );
566}
567
568function svp_remplir_slogan($description) {
569        include_spip('inc/texte');
570
571        // On extrait les traductions de l'eventuel multi
572        // Si le nom n'est pas un multi alors le tableau renvoye est de la forme '' => 'nom'
573        $descriptions = extraire_trads(str_replace(array('<multi>', '</multi>'), array(), $description, $nbr_replace));
574        $multi = ($nbr_replace > 0) ? true : false;
575
576        // On boucle sur chaque multi ou sur la chaine elle-meme en extrayant le slogan
577        // dans les differentes langues
578        $slogan = '';
579        foreach ($descriptions as $_lang => $_descr) {
580                $_descr = trim($_descr);
581                if (!$_lang)
582                        $_lang = 'fr';
583                $nbr_matches = preg_match(',^(.+)[.!?\r\n\f],Um', $_descr, $matches);
584                $slogan .= (($multi) ? '[' . $_lang . ']' : '') . 
585                                        (($nbr_matches > 0) ? trim($matches[1]) : couper($_descr, 150, ''));
586        }
587
588        if ($slogan)
589                // On renvoie un nouveau slogan multi ou pas
590                $slogan = (($multi) ? '<multi>' : '') . $slogan . (($multi) ? '</multi>' : '');
591
592        return $slogan;
593}
594
595function svp_normaliser_nom($nom) {
596        include_spip('inc/texte');
597
598        // On extrait les traductions de l'eventuel multi
599        // Si le nom n'est pas un multi alors le tableau renvoye est de la forme '' => 'nom'
600        $noms = extraire_trads(str_replace(array('<multi>', '</multi>'), array(), $nom, $nbr_replace));
601        $multi = ($nbr_replace > 0) ? true : false;
602       
603        $nouveau_nom = '';
604        foreach ($noms as $_lang => $_nom) {
605                $_nom = trim($_nom);
606                if (!$_lang)
607                        $_lang = 'fr';
608                $nbr_matches = preg_match(',(.+)(\s+[\d._]*)$,Um', $_nom, $matches);
609                $nouveau_nom .= (($multi) ? '[' . $_lang . ']' : '') . 
610                                                (($nbr_matches > 0) ? trim($matches[1]) : $_nom);
611        }
612       
613        if ($nouveau_nom)
614                // On renvoie un nouveau nom multi ou pas sans la valeur de la branche
615                $nouveau_nom = (($multi) ? '<multi>' : '') . $nouveau_nom . (($multi) ? '</multi>' : '');
616               
617        return $nouveau_nom;
618}
619
620
621// ----------------------- Analyses XML ---------------------------------
622
623// parse un fichier de source dont l'url est donnee
624// ce fichier est un fichier XML contenant <depot>...</depot>
625// et <archives>...</archives>
626function svp_xml_parse_depot($url){
627        include_spip('inc/xml');
628        include_spip('inc/distant');
629
630        // On lit le fichier xml
631        if (!$xml = recuperer_page($url)) {
632                return false;
633        }
634
635        // On enleve la balise doctype qui provoque une erreur "balise non fermee" lors du parsage
636        $xml = preg_replace('#<!DOCTYPE[^>]*>#','',$xml);
637
638        // Deux cas d'erreur de fichier non conforme
639        // - la syntaxe xml est incorrecte
640        // - aucun plugin dans le depot
641        // Si le bloc <depot> n'est pas renseigne on ne considere pas cela comme une erreur
642        $arbre = array();
643        if (!is_array($arbre = spip_xml_parse($xml)) OR !is_array($archives = $arbre['archives'][0])){
644                return false;
645        }
646
647        // On extrait les informations du depot si elles existent (balise <depot>)
648        $infos = array('depot' => array(), 'paquets' => array());
649        if (is_array($depot = $arbre['depot'][0]))
650                $infos['depot'] = svp_xml_aplatit_multiple(array('titre', 'descriptif', 'type', 'url_serveur', 'url_archives'), $depot);
651        if (!$infos['depot']['titre'])
652                $infos['depot']['titre'] = _T('svp:titre_nouveau_depot');
653        if (!$infos['depot']['type'])
654                $infos['depot']['type'] = 'svn';
655
656        // On extrait les informations de chaque plugin du depot (balise <archives>)
657        foreach ($archives as $z=>$c){
658                $c = $c[0];
659                // si fichier zip, on ajoute le paquet dans la liste
660                // - cas 1 : c'est un plugin donc on integre les infos du plugin
661                // - cas 2 : c'est une archive non plugin, pas d'infos autres que celles de l'archive
662                if ($url = $c['file'][0]) {
663                        if (is_array($c['plugin']))
664                                $plugin = svp_xml_parse_plugin($c['plugin'][0]);
665                        else
666                                $plugin = array();
667                        // On remplit les infos dans les deux cas
668                        $infos['paquets'][$url] = array(
669                                'plugin' => $plugin, 
670                                'file' => $url,
671                                'size' => $c['size'][0],
672                                'date' => $c['date'][0],        // c'est la date de generation du zip
673                                'source' => $c['source'][0],
674                                'last_commit' => $c['last_commit'][0]
675                        );
676                }
677        }
678       
679        return $infos;
680}
681
682
683// aplatit plusieurs cles d'un arbre xml dans un tableau
684// effectue un trim() au passage
685function svp_xml_aplatit_multiple($array, $arbre){
686        $a = array();
687        // array('uri','archive'=>'zip',...)
688        foreach ($array as $i=>$n){
689                if (is_string($i)) $cle = $i;
690                else $cle = $n;
691                $a[$n] = trim(spip_xml_aplatit($arbre[$cle]));
692        }
693        return $a;     
694}
695
696
697// parse un plugin.xml genere par spip_xml_parse()
698// en un tableau plus facilement utilisable
699// cette fonction doit permettre de mapper des changements
700// de syntaxe entre plugin.xml et step
701function svp_xml_parse_plugin($arbre){
702
703        if (!is_array($arbre)) 
704                return false;
705       
706        // on commence par les simples !
707        $plug_arbre = svp_xml_aplatit_multiple(
708                                array('nom','icon','auteur','licence','version','version_base','etat','slogan','categorie','tags',
709                                'description','lien','options','fonctions','prefix','install'), 
710                                $arbre);
711        $plug_arbre['prefix'] = strtolower($plug_arbre['prefix']);
712       
713        // on continue avec les plus complexes...       
714        // 1) balises avec attributs
715        foreach (array(
716                        'necessite'=>array('necessite', null),
717                        'utilise'=>array('utilise', null),
718                        'chemin'=>array('path', array('dir'=>'')))
719                                as $balise=>$p){
720                $params = $res = array();
721                // recherche de la balise et extraction des attributs
722                if (spip_xml_match_nodes(",^$balise,",$arbre, $res)){
723                        foreach(array_keys($res) as $tag){
724                                list($tag,$att) = spip_xml_decompose_tag($tag);
725                                $params[] = $att;
726                        }
727                } 
728                // valeur par defaut
729                else {
730                        if ($p[1]!==null)
731                                $params[] = $p[1];
732                }
733                $plug_arbre[$p[0]] = $params;           
734        }
735
736        return $plug_arbre;
737}
738
739
740// ----------------------- Recherches de plugins ---------------------------------
741
742function svp_rechercher_plugins_spip($phrase, $categorie, $etat, $depot, $version_spip='',
743                                                                        $exclusions=array(), $afficher_exclusions=false, $doublon=false, $tri='nom') {
744
745        include_spip('inc/rechercher');
746       
747        $plugins = array();
748        $scores = array();
749        $ids_paquets = array();
750
751        // On prepare l'utilisation de la recherche en base SPIP en la limitant aux tables spip_plugins
752        // et spip_paquets  si elle n'est pas vide
753        if ($phrase) {
754                $liste = liste_des_champs();
755                $tables = array('plugin' => $liste['plugin'], 'paquet' => $liste['paquet']);
756                $options = array('jointures' => true, 'score' => true);
757       
758                // On cherche dans tous les enregistrements de ces tables des correspondances les plugins qui
759                // correspondent a la phrase recherchee
760                // -- On obtient une liste d'id de plugins et d'id de paquets
761                $resultats = array('plugin' => array(), 'paquet' => array());
762                $resultats = recherche_en_base($phrase, $tables, $options);
763                // -- On prepare le tableau des scores avec les paquets trouves par la recherche
764                if ($resultats) {
765                        // -- On convertit les id de plugins en id de paquets
766                        $ids = array();
767                        if ($resultats['plugin']) {
768                                $ids_plugin = array_keys($resultats['plugin']);
769                                $where[] = sql_in('id_plugin', $ids_plugin);
770                                $ids = sql_allfetsel('id_paquet, id_plugin', 'spip_paquets', $where);
771                        }
772                        // -- On prepare les listes des id de paquet et des scores de ces memes paquets
773                        if ($resultats['paquet']) {
774                                $ids_paquets = array_keys($resultats['paquet']);
775                                foreach ($resultats['paquet'] as $_id => $_score) {
776                                        $scores[$_id] = intval($resultats['paquet'][$_id]['score']);
777                                }
778                        }
779                        // -- On merge les deux tableaux de paquets sans doublon en mettant a jour un tableau des scores
780                        foreach ($ids as $_ids) {
781                                $id_paquet = intval($_ids['id_paquet']);
782                                $id_plugin = intval($_ids['id_plugin']);
783                                if (array_search($id_paquet, $ids_paquets) === false) {
784                                        $ids_paquets[] = $id_paquet;
785                                        $scores[$id_paquet] = intval($resultats['plugin'][$id_plugin]['score']);
786                                }
787                                else {
788                                        $scores[$id_paquet] = intval($resultats['paquet'][$id_paquet]['score']) 
789                                                                                + intval($resultats['plugin'][$id_plugin]['score']);
790                                }
791                        }
792                }
793        }
794
795        // Maintenant, on continue la recherche en appliquant, sur la liste des id de paquets,
796        // les filtres complementaires : categorie, etat, exclusions et compatibilite spip
797        // si on a bien trouve des resultats precedemment ou si aucune phrase n'a ete saisie
798        // -- Preparation de la requete
799        if (!$phrase OR $resultats) {
800                $from = array('spip_plugins AS t1', 'spip_paquets AS t2', 'spip_depots AS t3');
801                $select = array('t1.nom AS nom', 't1.slogan AS slogan', 't1.prefixe AS prefixe', 't1.id_plugin AS id_plugin', 
802                                                't2.id_paquet AS id_paquet', 't2.description AS description', 't2.version_spip AS version_spip',
803                                                't2.auteur AS auteur', 't2.licence AS licence', 't2.etat AS etat',
804                                                't2.logo AS logo', 't2.version AS version', 't2.nom_archive AS nom_archive',
805                                                't3.url_archives AS url_archives', );
806                $where = array('t1.id_plugin=t2.id_plugin', 't2.id_depot=t3.id_depot');
807                if ($ids_paquets)
808                        $where[] = sql_in('t2.id_paquet', $ids_paquets);
809                if (($categorie) AND ($categorie != 'toute_categorie'))
810                        $where[] = 't1.categorie=' . sql_quote($categorie);
811                if (($etat) AND ($etat != 'tout_etat'))
812                        $where[] = 't2.etat=' . sql_quote($etat);
813                if (($depot) AND ($depot != 'tout_depot'))
814                        $where[] = 't2.id_depot=' . sql_quote($depot);
815                if ($exclusions AND !$afficher_exclusions)
816                        $where[] = sql_in('t2.id_plugin', $exclusions, 'NOT');
817       
818                if ($resultats = sql_select($select, $from, $where)) {
819                        while ($paquets = sql_fetch($resultats)) {
820                                $prefixe = $paquets['prefixe'];
821                                $version = $paquets['version'];
822                                $nom = extraire_multi($paquets['nom']);
823                                $slogan = extraire_multi($paquets['slogan']);
824                                $description = extraire_multi($paquets['description']);
825                                if (svp_verifier_compatibilite_spip($paquets['version_spip'], $version_spip)) {
826                                        // Le paquet remplit tous les criteres, on peut le selectionner
827                                        // -- on utilise uniquement la langue du site
828                                        $paquets['nom'] = $nom;
829                                        $paquets['slogan'] = $slogan;
830                                        $paquets['description'] = $description;
831                                        // -- on ajoute le score si on a bien saisi une phrase
832                                        if ($phrase)
833                                                $paquets['score'] = $scores[intval($paquets['id_paquet'])];
834                                        else
835                                                $paquets['score'] = 0;
836                                        // -- on construit l'url de l'archive
837                                        $paquets['url_archive'] = $paquets['url_archives'] . '/' . $paquets['nom_archive'];
838                                        // -- on gere les exclusions si elle doivent etre affichees
839                                        if ($afficher_exclusions AND in_array($paquets['id_plugin'], $exclusions))
840                                                $paquets['installe'] = true;
841                                        else
842                                                $paquets['installe'] = false;
843                                        // -- On traite les doublons (meme plugin, versions differentes)
844                                        if ($doublon)
845                                                // ajout systematique du paquet
846                                                $plugins[] = $paquets;
847                                        else {
848                                                // ajout
849                                                // - si pas encore trouve
850                                                // - ou si sa version est inferieure (on garde que la derniere version)
851                                                if (!$plugins[$prefixe]
852                                                OR ($plugins[$prefixe] AND spip_version_compare($plugins[$prefixe]['version'], $version, '<'))) {
853                                                        $plugins[$prefixe] = $paquets;
854                                                }
855                                        }
856                                }
857                        }
858                }
859               
860                // On trie le tableau par score décroissant ou nom croissant
861                $fonction = 'svp_trier_par_' . $tri;
862                if ($doublon)
863                        usort($plugins, $fonction);
864                else
865                        uasort($plugins, $fonction);
866        }
867       
868        return $plugins;
869}
870
871
872/**
873 * Recuperation des id des plugins a exclure car deja installes
874 *
875 * @return array
876 */
877function svp_lister_plugins_installes(){
878
879        $ids = array();
880
881        // On recupere la liste des plugins installes physiquement sur le site
882        // Pour l'instant ce n'est pas possible avec les fonctions natives de SPIP
883        // donc on se contente des plugins actifs
884        // - liste des prefixes en lettres majuscules des plugins actifs
885        include_spip('inc/plugin');
886        $plugins = liste_plugin_actifs();
887
888        // - liste des id de plugin correspondants
889        //   Il se peut que certains plugins ne soient pas trouves dans la bdd car aucun zip n'est disponible
890        //   (donc pas inclus dans archives.xml). C'est le cas des extensions du core
891        $ids = sql_allfetsel('id_plugin', 'spip_plugins', sql_in('prefixe', array_keys($plugins)));
892        $ids = array_map('reset', $ids);
893        $ids = array_map('intval', $ids);
894
895        return $ids;
896}
897
898
899/**
900 * Test de la compatibilite du plugin avec une version donnee de SPIP
901 *
902 * @return boolean
903 */
904function svp_verifier_compatibilite_spip($version, $version_spip) {
905        include_spip('inc/plugin');
906        if (!$version_spip)
907                $version_spip = $GLOBALS['spip_version_branche'].".".$GLOBALS['spip_version_code'];
908        return plugin_version_compatible($version, $version_spip);
909}
910
911
912/**
913 * Tri decroissant des resultats par score.
914 * Cette fonction est appelee par un usort ou uasort
915 *
916 * @return int
917 */
918function svp_trier_par_score($p1, $p2){
919        if ($p1['score'] == $p2['score']) 
920                $retour = 0;
921        else 
922                $retour = ($p1['score'] < $p2['score']) ? 1 : -1;
923        return $retour;
924}
925
926
927/**
928 * Tri croissant des resultats par nom.
929 * Si le nom est identique on classe par version decroissante
930 * Cette fonction est appelee par un usort ou uasort
931 *
932 * @return int
933 */
934function svp_trier_par_nom($p1, $p2){
935        $c1 = strcasecmp($p1['nom'], $p2['nom']);
936        if ($c1 == 0) {
937                $c2 = spip_version_compare($p1['version'], $p1['version'], '<');
938                $retour = ($c2) ? 1 : -1;
939        }
940        else 
941                $retour = ($c1 < 0) ? -1 : 1;
942        return $retour;
943}
944
945?>
Note: See TracBrowser for help on using the repository browser.