source: spip-zone/_core_/plugins/svp/inc/svp_depoter_local.php @ 99161

Last change on this file since 99161 was 99161, checked in by marcimat@…, 3 years ago

Homogénéisation du tableau de description des dépendances (nécessite, librairie, utilise et procure)
qui dans certains cas étaient décrites dans un tableau intermédiaire d'index 0, et parfois non.

En fait SVP lorsqu'il analyse les paquet/plugin.xml présents dans une archivelist.xml met
ces informations de dépendances dans un index 0, et parfois en plus semble t'il dans un index
de compatibilité de version de spip SI la balise <spip> est présente dans le paquet/plugin.xml en question.

Cependant que lorsqu'on récupère les informations de paquet.xml présents dans plugins/ ou plugins-dist/
par la fonction prévue par SPIP, les informations de dépendances ne sont pas indéxées elles dans cette clé 0,
inutile d'ailleurs car on ne récupère que les infos correspondante à notre version de SPIP utilisée.

Pour harmoniser, un morceau de code était utilisé dans SVP, mais un peu tard. Cela faisait que
la fonction plugins_preparer_sql_paquet() recevait à l'ajout d'un dépot des paquets avec des dépendances utilisant la clé [0],
mais actualisait ensuite les paquets locaux sans cet index ensuite lors de l'appel à svp_actualiser_paquets_locaux().

Et l'ajout récent du code relatif à la balise <procure> montrait des notices PHP dans la fonction preparer_sql (avant ce
problème n'était pas visible).

En déplaçant un peu plus tôt le code qui harmonise tout dans l'index 0 et en ajoutant 'procure' au passage dedans, ce problème rentre dans l'ordre.

Je pense que cela pouvait entrainer des erreurs dans le calcul de l'ordre d'installation / désinstallation des plugins locaux.
En relation donc avec https://core.spip.net/issues/3689

File size: 24.9 KB
Line 
1<?php
2
3/**
4 * Traitement du dépot local
5 *
6 * Le dépot local est la liste de paquets qui sont présents sur l'hébergement
7 * dans un des répertoires de plugins, actifs ou non actifs.
8 *
9 * Dans la base, un dépot local est représenté avec un id_dépot nul.
10 * Il n'y a cependant pas de ligne spécifique décrivant le dépot local
11 * dans la table SQL spip_depots, mais juste des valeurs id_depot=0 dans
12 * la table spip_paquets.
13 *
14 * @plugin SVP pour SPIP
15 * @license GPL
16 * @package SPIP\SVP\Depots
17 */
18
19/**
20 * Met à jour les tables SQL paquets et plugins pour qui concerne
21 * les paquets locaux (ceux présents sur le site).
22 *
23 * On ne met à jour que ce qui a changé, sauf si on force le recalcule
24 * de toutes les informations locales avec var_mode=vider_paquets_locaux
25 * dans l'URL ou en mettant le paramètre $force à true.
26 *
27 * @uses  svp_descriptions_paquets_locaux()
28 * @uses  svp_base_supprimer_paquets_locaux()
29 * @uses  svp_base_inserer_paquets_locaux()
30 * @uses  svp_base_modifier_paquets_locaux()
31 * @uses  svp_base_actualiser_paquets_actifs()
32 *
33 * @param bool $force
34 *     - false : n'actualise que les paquets modifiés
35 *     - true : efface et recrée la liste de tous les paquets locaux
36 * @param array $erreurs_xml
37 *     Si des erreurs XML sont présentes, elles se retrouvent dans ce tableau
38 * @return string
39 *     Temps d'exécution
40 **/
41function svp_actualiser_paquets_locaux($force = false, &$erreurs_xml = array()) {
42
43        spip_timer('paquets_locaux');
44        $paquets = svp_descriptions_paquets_locaux($erreurs_xml);
45
46        // un mode pour tout recalculer sans désinstaller le plugin... !
47        if ($force
48                or _request('var_mode') == 'vider_paquets_locaux'
49                or _request('var_mode') == 'recalcul'
50        ) {
51                svp_base_supprimer_paquets_locaux();
52                svp_base_inserer_paquets_locaux($paquets);
53        } else {
54                svp_base_modifier_paquets_locaux($paquets);
55        }
56        svp_base_actualiser_paquets_actifs();
57
58        $temps = spip_timer('paquets_locaux');
59#spip_log('svp_actualiser_paquets_locaux', 'SVP');
60#spip_log($temps, 'SVP');
61        return "Éxécuté en : " . $temps;
62
63}
64
65
66/**
67 * Calcule la description de chaque paquet local
68 *
69 * Les paquets peuvent être stockés à 3 endroits :
70 * plugins, plugins-dist, plugins-supp définis par les constantes respectives
71 * _DIR_PLUGINS, _DIR_PLUGINS_DIST, _DIR_PLUGINS_SUPP
72 *
73 * @param array $erreurs_xml
74 *     Les erreurs XML éventuelles des paquet.xml se retrouvent dedans s'il y en a
75 * @return array
76 *     Descriptions des paquets (intégrant un hash), stockés par
77 *     constante, puis par chemin.
78 *     array[_DIR_PLUGIN*][$chemin] = description
79 **/
80function svp_descriptions_paquets_locaux(&$erreurs_xml = array()) {
81        include_spip('inc/plugin');
82        liste_plugin_files(_DIR_PLUGINS);
83        liste_plugin_files(_DIR_PLUGINS_DIST);
84        $get_infos = charger_fonction('get_infos', 'plugins');
85        $paquets_locaux = array(
86                '_DIR_PLUGINS' => $get_infos(array(), false, _DIR_PLUGINS),
87                '_DIR_PLUGINS_DIST' => $get_infos(array(), false, _DIR_PLUGINS_DIST),
88        );
89        if (defined('_DIR_PLUGINS_SUPPL') and _DIR_PLUGINS_SUPPL) {
90                liste_plugin_files(_DIR_PLUGINS_SUPPL);
91                $paquets_locaux['_DIR_PLUGINS_SUPPL'] = $get_infos(array(), false, _DIR_PLUGINS_SUPPL);
92        }
93
94        // creer la liste des signatures
95        foreach ($paquets_locaux as $const_dir => $paquets) {
96                foreach ($paquets as $chemin => $paquet) {
97                        // on propose le paquet uniquement s'il n'y a pas eu d'erreur de lecture XML bloquante
98                        if (!isset($paquet['erreur'])) {
99                                $paquets_locaux[$const_dir][$chemin]['signature'] = md5($const_dir . $chemin . serialize($paquet));
100                        } else {
101                                // Erreur XML !
102                                unset($paquets_locaux[$const_dir][$chemin]);
103                                spip_log("Impossible de lire la description XML de $chemin . Erreurs :", 'svp.' . _LOG_ERREUR);
104                                spip_log($paquet['erreur'], 'svp.' . _LOG_ERREUR);
105                                $erreurs_xml[] = $paquet['erreur'][0];
106                        }
107                }
108        }
109
110        return $paquets_locaux;
111}
112
113
114/**
115 * Supprime tous les paquets et plugins locaux.
116 **/
117function svp_base_supprimer_paquets_locaux() {
118        sql_delete('spip_paquets', 'id_depot = ' . 0); //_paquets locaux en 0
119        sql_delete('spip_plugins', sql_in('id_plugin', sql_get_select('DISTINCT(id_plugin)', 'spip_paquets'), 'NOT'));
120}
121
122
123/**
124 * Actualise les informations en base sur les paquets locaux
125 * en ne modifiant que ce qui a changé.
126 *
127 * @uses  svp_supprimer_plugins_orphelins()
128 * @uses  svp_base_inserer_paquets_locaux()
129 *
130 * @param array $paquets_locaux
131 *     Descriptions des paquets (intégrant un hash), stockés par
132 *     constante, puis par chemin.
133 *     array[_DIR_PLUGIN*][$chemin] = description
134 **/
135function svp_base_modifier_paquets_locaux($paquets_locaux) {
136        include_spip('inc/svp_depoter_distant');
137
138        // On ne va modifier QUE les paquets locaux qui ont change
139        // Et cela en comparant les md5 des informations fournies.
140        $signatures = array();
141
142        // recuperer toutes les signatures
143        foreach ($paquets_locaux as $const_dir => $paquets) {
144                foreach ($paquets as $chemin => $paquet) {
145                        $signatures[$paquet['signature']] = array(
146                                'constante' => $const_dir,
147                                'chemin' => $chemin,
148                                'paquet' => $paquet,
149                        );
150                }
151        }
152
153        // tous les paquets du depot qui ne font pas parti des signatures
154        $anciens_paquets = sql_allfetsel('id_paquet', 'spip_paquets',
155                array('id_depot=' . sql_quote(0), sql_in('signature', array_keys($signatures), 'NOT')));
156        $anciens_paquets = array_map('array_shift', $anciens_paquets);
157
158        // tous les plugins correspondants aux anciens paquets
159        $anciens_plugins = sql_allfetsel('p.id_plugin', array('spip_plugins AS p', 'spip_paquets AS pa'),
160                array('p.id_plugin=pa.id_plugin', sql_in('pa.id_paquet', $anciens_paquets)));
161        $anciens_plugins = array_map('array_shift', $anciens_plugins);
162
163        // suppression des anciens paquets
164        sql_delete('spip_paquets', sql_in('id_paquet', $anciens_paquets));
165
166        // supprimer les plugins orphelins
167        svp_supprimer_plugins_orphelins($anciens_plugins);
168
169        // on ne garde que les paquets qui ne sont pas presents dans la base
170        $signatures_base = sql_allfetsel('signature', 'spip_paquets', 'id_depot=' . sql_quote(0));
171        $signatures_base = array_map('array_shift', $signatures_base);
172        $signatures = array_diff_key($signatures, array_flip($signatures_base));
173
174        // on recree la liste des paquets locaux a inserer
175        $paquets_locaux = array();
176        foreach ($signatures as $s => $infos) {
177                if (!isset($paquets_locaux[$infos['constante']])) {
178                        $paquets_locaux[$infos['constante']] = array();
179                }
180                $paquets_locaux[$infos['constante']][$infos['chemin']] = $infos['paquet'];
181        }
182
183        svp_base_inserer_paquets_locaux($paquets_locaux);
184}
185
186
187/**
188 * Insère en base tous les paquets locaux transmis
189 *
190 * De chaque description est extrait la partie plugin (1 seul plugin
191 * par préfixe de plugin connu) et la partie paquet (il peut y avoir plusieurs
192 * paquets pour un même préfixe de plugin).
193 *
194 * @note
195 *     On essaie au mieux de faire des requêtes d'insertions multiples,
196 *     mieux gérées par les moteurs SQL (particulièrement pour SQLite)
197 *
198 * @uses  plugins_preparer_sql_paquet()
199 * @uses  svp_compiler_multis()
200 * @uses  eclater_plugin_paquet()
201 * @uses  svp_rechercher_maj_version()
202 * @uses  svp_corriger_obsolete_paquets()
203 *
204 * @param array $paquets_locaux
205 *     Descriptions des paquets (intégrant un hash), stockés par
206 *     constante, puis par chemin.
207 *     array[_DIR_PLUGIN*][$chemin] = description
208 **/
209function svp_base_inserer_paquets_locaux($paquets_locaux) {
210        include_spip('inc/svp_depoter_distant');
211
212        // On initialise les informations specifiques au paquet :
213        // l'id du depot et les infos de l'archive
214        $paquet_base = array(
215                'id_depot' => 0,
216                'nom_archive' => '',
217                'nbo_archive' => '',
218                'maj_archive' => '',
219                'src_archive' => '',
220                'date_modif' => '',
221                'maj_version' => '',
222                'signature' => '',
223        );
224
225        $preparer_sql_paquet = charger_fonction('preparer_sql_paquet', 'plugins');
226
227        // pour chaque decouverte, on insere les paquets en base.
228        // on evite des requetes individuelles, tres couteuses en sqlite...
229        $cle_plugins = array(); // prefixe => id
230        $insert_plugins = array(); // insertion prefixe...
231        $insert_plugins_vmax = array(); // vmax des nouveaux plugins...
232        $insert_paquets = array(); // insertion de paquet...
233
234        include_spip('inc/config');
235        $recents = lire_config('plugins_interessants');
236        $installes = lire_config('plugin_installes');
237        $actifs = lire_config('plugin');
238        $attentes = lire_config('plugin_attente');
239
240        foreach ($paquets_locaux as $const_dir => $paquets) {
241                foreach ($paquets as $chemin => $paquet) {
242                        // Si on est en presence d'un plugin dont la dtd est "paquet" on compile en multi
243                        // les nom, slogan et description a partir des fichiers de langue.
244                        // De cette façon, les informations des plugins locaux et distants seront identiques
245                        // => On evite l'utilisation de _T() dans les squelettes
246                        if ($paquet['dtd'] == 'paquet') {
247                                $multis = svp_compiler_multis($paquet['prefix'], constant($const_dir) . '/' . $chemin);
248                                if (isset($multis['nom'])) {
249                                        $paquet['nom'] = $multis['nom'];
250                                }
251                                $paquet['slogan'] = (isset($multis['slogan'])) ? $multis['slogan'] : '';
252                                $paquet['description'] = (isset($multis['description'])) ? $multis['description'] : '';
253                        }
254
255                        // On met les neccesite, utilise, procure, dans la clé 0
256                        // pour être homogène avec le résultat d'une extraction de paquet xml
257                        // dans une source d'archives. cf svp_phraser_plugin()
258                        $paquet = svp_adapter_structure_dependances($paquet);
259
260
261                        $le_paquet = $paquet_base;
262                        #$le_paquet['traductions'] = serialize($paquet['traductions']);
263
264                        if ($champs = $preparer_sql_paquet($paquet)) {
265
266                                // Eclater les champs recuperes en deux sous tableaux, un par table (plugin, paquet)
267                                $champs = eclater_plugin_paquet($champs);
268                                $paquet_plugin = true;
269
270                                // On complete les informations du paquet et du plugin
271                                $le_paquet = array_merge($le_paquet, $champs['paquet']);
272                                $le_plugin = $champs['plugin'];
273
274                                // On loge l'absence de categorie ou une categorie erronee et on positionne la categorie par defaut "aucune"
275                                if (!$le_plugin['categorie']) {
276                                        $le_plugin['categorie'] = 'aucune';
277                                } else {
278                                        if (!in_array($le_plugin['categorie'], $GLOBALS['categories_plugin'])) {
279                                                $le_plugin['categorie'] = 'aucune';
280                                        }
281                                }
282
283                                // creation du plugin...
284                                $prefixe = strtoupper($le_plugin['prefixe']);
285                                // on fait attention lorqu'on cherche ou ajoute un plugin
286                                // le nom et slogan est TOUJOURS celui de la plus haute version
287                                // et il faut donc possiblement mettre a jour la base...
288                                //
289                                // + on est tolerant avec les versions identiques de plugin deja presentes
290                                //   on permet le recalculer le titre...
291                                if (!isset($cle_plugins[$prefixe])) {
292                                        if (!$res = sql_fetsel('id_plugin, vmax', 'spip_plugins', 'prefixe = ' . sql_quote($prefixe))) {
293                                                // on ne stocke pas de vmax pour les plugins locaux dans la bdd... (parait il)
294                                                if (!isset($insert_plugins[$prefixe])) {
295                                                        $insert_plugins[$prefixe] = $le_plugin;
296                                                        $insert_plugins_vmax[$prefixe] = $le_paquet['version'];
297                                                } elseif (spip_version_compare($le_paquet['version'], $insert_plugins_vmax[$prefixe], '>')) {
298                                                        $insert_plugins[$prefixe] = $le_plugin;
299                                                        $insert_plugins_vmax[$prefixe] = $le_paquet['version'];
300                                                }
301                                        } else {
302                                                $id_plugin = $res['id_plugin'];
303                                                $cle_plugins[$prefixe] = $id_plugin;
304                                                // comme justement on ne stocke pas de vmax pour les plugins locaux...
305                                                // il est possible que ce test soit faux. pff.
306                                                if (spip_version_compare($le_paquet['version'], $res['vmax'], '>=')) {
307                                                        sql_updateq('spip_plugins', $le_plugin, 'id_plugin=' . sql_quote($id_plugin));
308                                                }
309                                        }
310                                }
311
312                                // ajout du prefixe dans le paquet
313                                $le_paquet['prefixe'] = $prefixe;
314                                $le_paquet['constante'] = $const_dir;
315                                $le_paquet['src_archive'] = $chemin;
316                                $le_paquet['recent'] = isset($recents[$chemin]) ? $recents[$chemin] : 0;
317                                $le_paquet['installe'] = is_array($chemin) && in_array($chemin,
318                                        $installes) ? 'oui' : 'non'; // est desinstallable ?
319                                $le_paquet['obsolete'] = 'non';
320                                $le_paquet['signature'] = $paquet['signature'];
321
322                                // le plugin est il actuellement actif ?
323                                $actif = "non";
324                                if (isset($actifs[$prefixe])
325                                        and ($actifs[$prefixe]['dir_type'] == $const_dir)
326                                        and ($actifs[$prefixe]['dir'] == $chemin)
327                                ) {
328                                        $actif = "oui";
329                                }
330                                $le_paquet['actif'] = $actif;
331
332                                // le plugin etait il actif mais temporairement desactive
333                                // parce qu'une dependence a disparue ?
334                                $attente = "non";
335                                if (isset($attentes[$prefixe])
336                                        and ($attentes[$prefixe]['dir_type'] == $const_dir)
337                                        and ($attentes[$prefixe]['dir'] == $chemin)
338                                ) {
339                                        $attente = "oui";
340                                        $le_paquet['actif'] = "oui"; // il est presenté dans la liste des actifs (en erreur).
341                                }
342                                $le_paquet['attente'] = $attente;
343
344                                // on recherche d'eventuelle mises a jour existantes
345                                if ($maj_version = svp_rechercher_maj_version($prefixe, $le_paquet['version'], $le_paquet['etatnum'])) {
346                                        $le_paquet['maj_version'] = $maj_version;
347                                }
348
349                                $insert_paquets[] = $le_paquet;
350                        }
351                }
352        }
353
354        if ($insert_plugins) {
355                sql_insertq_multi('spip_plugins', $insert_plugins);
356                $pls = sql_allfetsel(array('id_plugin', 'prefixe'), 'spip_plugins', sql_in('prefixe', array_keys($insert_plugins)));
357                foreach ($pls as $p) {
358                        $cle_plugins[$p['prefixe']] = $p['id_plugin'];
359                }
360        }
361
362        if ($insert_paquets) {
363
364                // sert pour le calcul d'obsolescence
365                $id_plugin_concernes = array();
366
367                foreach ($insert_paquets as $c => $p) {
368                        $insert_paquets[$c]['id_plugin'] = $cle_plugins[$p['prefixe']];
369                        $id_plugin_concernes[$insert_paquets[$c]['id_plugin']] = true;
370                }
371
372                sql_insertq_multi('spip_paquets', $insert_paquets);
373
374                svp_corriger_obsolete_paquets(array_keys($id_plugin_concernes));
375        }
376}
377
378
379/**
380 * Adapte la structure des dépendances d'un paquet xml lu par SPIP
381 * à une structure attendue par SVP.
382 *
383 * C'est à dire, met les necessite, utilises, lib, procure dans une sous clé 0
384 *
385 * @note
386 *     Cette clé 0 indique la description principale du paquet.xml
387 *     mais d'autres clés semblent pouvoir si la balise `<spip>` est présente dedans
388 *
389 * @see svp_phraser_plugin() côté SVP
390 * @see plugins_fusion_paquet() côté SVP
391 *
392 * @see plugins_get_infos_dist() côté SPIP (extractions de tous les paquets d'un dossier)
393 *
394 * @param array $paquet Description d'un paquet
395 * @return array Description d'un paquet adaptée
396**/
397function svp_adapter_structure_dependances($paquet) {
398        // mettre les necessite, utilise, librairie dans la cle 0
399        foreach (array('necessite', 'utilise', 'lib', 'procure') as $dep) {
400                if (!empty($paquet[$dep])) {
401                        $paquet[$dep] = array($paquet[$dep]);
402                }
403        }
404        return $paquet;
405}
406
407/**
408 * Fait correspondre l'état des métas des plugins actifs & installés
409 * avec ceux en base de données dans spip_paquets pour le dépot local
410 **/
411function svp_base_actualiser_paquets_actifs() {
412        $installes = lire_config('plugin_installes');
413        $actifs = lire_config('plugin');
414        $attentes = lire_config('plugin_attente');
415
416        $locaux = sql_allfetsel(
417                array('id_paquet', 'prefixe', 'actif', 'installe', 'attente', 'constante', 'src_archive'),
418                'spip_paquets',
419                'id_depot=' . sql_quote(0));
420        $changements = array();
421
422        foreach ($locaux as $l) {
423                $copie = $l;
424                $prefixe = strtoupper($l['prefixe']);
425                // actif ?
426                if (isset($actifs[$prefixe])
427                        and ($actifs[$prefixe]['dir_type'] == $l['constante'])
428                        and ($actifs[$prefixe]['dir'] == $l['src_archive'])
429                ) {
430                        $copie['actif'] = "oui";
431                } else {
432                        $copie['actif'] = "non";
433                }
434
435                // attente ?
436                if (isset($attentes[$prefixe])
437                        and ($attentes[$prefixe]['dir_type'] == $l['constante'])
438                        and ($attentes[$prefixe]['dir'] == $l['src_archive'])
439                ) {
440                        $copie['attente'] = "oui";
441                        $copie['actif'] = "oui"; // il est presente dans la liste des actifs (en erreur).
442                } else {
443                        $copie['attente'] = "non";
444                }
445
446                // installe ?
447                if (in_array($l['src_archive'], $installes)) {
448                        $copie['installe'] = "oui";
449                } else {
450                        $copie['installe'] = "non";
451                }
452
453                if ($copie != $l) {
454                        $changements[$l['id_paquet']] = array(
455                                'actif' => $copie['actif'],
456                                'installe' => $copie['installe'],
457                                'attente' => $copie['attente']
458                        );
459                }
460        }
461
462        if (count($changements)) {
463                // On insere, en encapsulant pour sqlite...
464                if (sql_preferer_transaction()) {
465                        sql_demarrer_transaction();
466                }
467
468                foreach ($changements as $id_paquet => $data) {
469                        sql_updateq('spip_paquets', $data, 'id_paquet=' . intval($id_paquet));
470                }
471
472                if (sql_preferer_transaction()) {
473                        sql_terminer_transaction();
474                }
475        }
476
477}
478
479/**
480 * Construit le contenu multilangue (tag <multi>) des balises nom, slogan
481 * et description à partir des items de langue contenus dans le fichier
482 * paquet-prefixe_langue.php
483 *
484 * @param string $prefixe Préfixe du plugin
485 * @param string $dir_source Chemin d'accès du plugin
486 * @return array
487 *     Tableau clé => texte multilangue entre <multi> et </multi>
488 *     Les clés peuvent être 'nom', 'slogan' et 'description', mais
489 *     seules les clés ayant une explication dans la chaine de langue
490 *     sont retournées.
491 */
492function svp_compiler_multis($prefixe, $dir_source) {
493
494        $multis = array();
495        // ici on cherche le fichier et les cles avec un prefixe en minuscule systematiquement...
496        $prefixe = strtolower($prefixe);
497        $module = "paquet-$prefixe";
498        $item_nom = $prefixe . "_nom";
499        $item_slogan = $prefixe . "_slogan";
500        $item_description = $prefixe . "_description";
501
502        // On cherche tous les fichiers de langue destines a la traduction du paquet.xml
503        if ($fichiers_langue = glob($dir_source . "/lang/{$module}_*.php")) {
504                include_spip('inc/lang_liste');
505                $nom = $slogan = $description = '';
506                foreach ($fichiers_langue as $_fichier_langue) {
507                        $nom_fichier = basename($_fichier_langue, '.php');
508                        $langue = substr($nom_fichier, strlen($module) + 1 - strlen($nom_fichier));
509                        // Si la langue est reconnue, on traite la liste des items de langue
510                        if (isset($GLOBALS['codes_langues'][$langue])) {
511                                $GLOBALS['idx_lang'] = $langue;
512                                include($_fichier_langue);
513                                foreach ($GLOBALS[$langue] as $_item => $_traduction) {
514                                        if ($_traduction = trim($_traduction)) {
515                                                if ($_item == $item_nom) {
516                                                        $nom .= "[$langue]$_traduction";
517                                                }
518                                                if ($_item == $item_slogan) {
519                                                        $slogan .= "[$langue]$_traduction";
520                                                }
521                                                if ($_item == $item_description) {
522                                                        $description .= "[$langue]$_traduction";
523                                                }
524                                        }
525                                }
526                        }
527                }
528
529                // Finaliser la construction des balises multi
530                if ($nom) {
531                        $multis['nom'] = "<multi>$nom</multi>";
532                }
533                if ($slogan) {
534                        $multis['slogan'] = "<multi>$slogan</multi>";
535                }
536                if ($description) {
537                        $multis['description'] = "<multi>$description</multi>";
538                }
539        }
540
541        return $multis;
542}
543
544
545/**
546 * Met à jour les informations d'obsolescence des paquets locaux.
547 *
548 * L'obsolescence indique qu'un paquet est plus ancien (de version ou état
549 * moins avancé) qu'un autre également présent localement.
550 *
551 * @param array $ids_plugin
552 *     Liste d'identifiants de plugins
553 *     En cas d'absence, passera sur tous les paquets locaux
554 **/
555function svp_corriger_obsolete_paquets($ids_plugin = array()) {
556        // on minimise au maximum le nombre de requetes.
557        // 1 pour lister les paquets
558        // 1 pour mettre à jour les obsoletes à oui
559        // 1 pour mettre à jour les obsoletes à non
560
561        $where = array('pa.id_plugin = pl.id_plugin', 'id_depot=' . sql_quote(0));
562        if ($ids_plugin) {
563                $where[] = sql_in('pl.id_plugin', $ids_plugin);
564        }
565
566        // comme l'on a de nouveaux paquets locaux...
567        // certains sont peut etre devenus obsoletes
568        // parmis tous les plugins locaux presents
569        // concernes par les memes prefixes que les plugins ajoutes.
570        $obsoletes = array();
571        $changements = array();
572
573        $paquets = sql_allfetsel(
574                array('pa.id_paquet', 'pl.prefixe', 'pa.version', 'pa.etatnum', 'pa.obsolete', 'pa.compatibilite_spip'),
575                array('spip_paquets AS pa', 'spip_plugins AS pl'),
576                $where);
577
578        // L'obsolescence doit tenir compte de la compatibilité avec notre version de SPIP en cours
579        foreach ($paquets as $c => $p) {
580                $paquets[$c]['compatible'] = plugin_version_compatible($p['compatibilite_spip'], $GLOBALS['spip_version_branche'],
581                        'spip');
582        }
583
584        foreach ($paquets as $c => $p) {
585
586                $obsoletes[$p['prefixe']][] = $c;
587
588                // si 2 paquet locaux ont le meme prefixe,
589                // mais pas la meme version,
590                // sont compatibles avec notre SPIP,
591                // l'un est obsolete : la version la plus ancienne
592                // Si version et etat sont egaux, on ne decide pas d'obsolescence.
593                if (count($obsoletes[$p['prefixe']]) > 1) {
594                        foreach ($obsoletes[$p['prefixe']] as $cle) {
595                                if ($cle == $c) {
596                                        continue;
597                                }
598                                if (!$paquets[$c]['compatible']) {
599                                        continue;
600                                }
601
602                                // je suis plus petit qu'un autre
603                                if (spip_version_compare($paquets[$c]['version'], $paquets[$cle]['version'], '<')) {
604                                        if ($paquets[$c]['etatnum'] <= $paquets[$cle]['etatnum']) {
605                                                if ($paquets[$c]['obsolete'] != 'oui') {
606                                                        $paquets[$c]['obsolete'] = 'oui';
607                                                        $changements[$c] = true;
608                                                }
609                                        }
610                                } // je suis plus grand ou egal a un autre...
611                                else {
612                                        // je suis strictement plus grand qu'un autre...
613                                        if (spip_version_compare($paquets[$c]['version'], $paquets[$cle]['version'], '>')) {
614                                                // si mon etat est meilleur, rendre obsolete les autres
615                                                if ($paquets[$c]['etatnum'] >= $paquets[$cle]['etatnum']) {
616                                                        if ($paquets[$cle]['obsolete'] != 'oui') {
617                                                                $paquets[$cle]['obsolete'] = 'oui';
618                                                                $changements[$cle] = true;
619                                                        }
620                                                }
621                                        }
622
623                                        // je suis egal a un autre
624                                        // si mon etat est strictement meilleur, rendre obsolete les autres
625                                        elseif ($paquets[$c]['etatnum'] > $paquets[$cle]['etatnum']) {
626                                                if ($paquets[$cle]['obsolete'] != 'oui') {
627                                                        $paquets[$cle]['obsolete'] = 'oui';
628                                                        $changements[$cle] = true;
629                                                }
630                                        }
631                                }
632
633                        }
634                } else {
635                        if ($paquets[$c]['obsolete'] != 'non') {
636                                $paquets[$c]['obsolete'] = 'non';
637                                $changements[$c] = true;
638                        }
639                }
640        }
641
642        if (count($changements)) {
643                $oui = $non = array();
644                foreach ($changements as $c => $null) {
645                        if ($paquets[$c]['obsolete'] == 'oui') {
646                                $oui[] = $paquets[$c]['id_paquet'];
647                        } else {
648                                $non[] = $paquets[$c]['id_paquet'];
649                        }
650                }
651
652                if ($oui) {
653                        sql_updateq('spip_paquets', array('obsolete' => 'oui'), sql_in('id_paquet', $oui));
654                }
655                if ($non) {
656                        sql_updateq('spip_paquets', array('obsolete' => 'non'), sql_in('id_paquet', $non));
657                }
658        }
659}
660
661
662/**
663 * Supprime les plugins devenus orphelins dans cette liste.
664 *
665 * @param array $ids_plugin
666 *     Liste d'identifiants de plugins
667 * @return array
668 *     Liste de plugins non orphelins
669 **/
670function svp_supprimer_plugins_orphelins($ids_plugin) {
671        // tous les plugins encore lies a des depots...
672        if ($ids_plugin) {
673                $p = sql_allfetsel('DISTINCT(p.id_plugin)', array('spip_plugins AS p', 'spip_paquets AS pa'),
674                        array(sql_in('p.id_plugin', $ids_plugin), 'p.id_plugin=pa.id_plugin'));
675                $p = array_map('array_shift', $p);
676                $diff = array_diff($ids_plugin, $p);
677                // pour chaque plugin non encore utilise, on les vire !
678                sql_delete('spip_plugins', sql_in('id_plugin', $diff));
679
680                return $p; // les plugins encore en vie !
681        }
682
683        return array();
684}
685
686
687/**
688 * Cherche dans les dépots distants un plugin qui serait plus à jour
689 * que le prefixe, version et état que l'on transmet
690 *
691 * @param string $prefixe
692 *    Préfixe du plugin
693 * @param string $version
694 *    Version du paquet à comparer
695 * @param int $etatnum
696 *    État du paquet numérique
697 * @return string
698 *    Version plus à jour, sinon rien
699 **/
700function svp_rechercher_maj_version($prefixe, $version, $etatnum) {
701
702        $maj_version = "";
703
704        if ($res = sql_allfetsel(
705                array('pl.id_plugin', 'pa.version'),
706                array('spip_plugins AS pl', 'spip_paquets AS pa'),
707                array(
708                        'pl.id_plugin = pa.id_plugin',
709                        'pa.id_depot>' . sql_quote(0),
710                        'pl.prefixe=' . sql_quote($prefixe),
711                        'pa.etatnum>=' . sql_quote($etatnum)
712                ))
713        ) {
714
715                foreach ($res as $paquet_distant) {
716                        // si version superieure et etat identique ou meilleur,
717                        // c'est que c'est une mise a jour possible !
718                        if (spip_version_compare($paquet_distant['version'], $version, '>')) {
719                                if (!strlen($maj_version) or spip_version_compare($paquet_distant['version'], $maj_version, '>')) {
720                                        $maj_version = $paquet_distant['version'];
721                                }
722                                # a voir si on utilisera...
723                                # "superieur"           => "varchar(3) DEFAULT 'non' NOT NULL",
724                                # // superieur : version plus recente disponible (distant) d'un plugin (actif?) existant
725                        }
726                }
727        }
728
729        return $maj_version;
730}
731
732
733/**
734 * Actualise l'information 'maj_version' pour tous les paquets locaux
735 *
736 * @uses  svp_rechercher_maj_version()
737 **/
738function svp_actualiser_maj_version() {
739        $update = array();
740        // tous les paquets locaux
741        if ($locaux = sql_allfetsel(
742                array('id_paquet', 'prefixe', 'version', 'maj_version', 'etatnum'),
743                array('spip_paquets'),
744                array('id_depot=' . sql_quote(0)))
745        ) {
746                foreach ($locaux as $paquet) {
747                        $new_maj_version = svp_rechercher_maj_version($paquet['prefixe'], $paquet['version'], $paquet['etatnum']);
748                        if ($new_maj_version != $paquet['maj_version']) {
749                                $update[$paquet['id_paquet']] = array('maj_version' => $new_maj_version);
750                        }
751                }
752        }
753        if ($update) {
754                // On insere, en encapsulant pour sqlite...
755                if (sql_preferer_transaction()) {
756                        sql_demarrer_transaction();
757                }
758
759                foreach ($update as $id_paquet => $data) {
760                        sql_updateq('spip_paquets', $data, 'id_paquet=' . intval($id_paquet));
761                }
762
763                if (sql_preferer_transaction()) {
764                        sql_terminer_transaction();
765                }
766        }
767}
Note: See TracBrowser for help on using the repository browser.