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

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

Commentaire : verbe manquant.

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 exister
388 *     si la balise `<spip>` est présente dedans
389 *
390 * @see svp_phraser_plugin() côté SVP
391 * @see plugins_fusion_paquet() côté SVP
392 *
393 * @see plugins_get_infos_dist() côté SPIP (extractions de tous les paquets d'un dossier)
394 *
395 * @param array $paquet Description d'un paquet
396 * @return array Description d'un paquet adaptée
397**/
398function svp_adapter_structure_dependances($paquet) {
399        // mettre les necessite, utilise, librairie dans la cle 0
400        foreach (array('necessite', 'utilise', 'lib', 'procure') as $dep) {
401                if (!empty($paquet[$dep])) {
402                        $paquet[$dep] = array($paquet[$dep]);
403                }
404        }
405        return $paquet;
406}
407
408/**
409 * Fait correspondre l'état des métas des plugins actifs & installés
410 * avec ceux en base de données dans spip_paquets pour le dépot local
411 **/
412function svp_base_actualiser_paquets_actifs() {
413        $installes = lire_config('plugin_installes');
414        $actifs = lire_config('plugin');
415        $attentes = lire_config('plugin_attente');
416
417        $locaux = sql_allfetsel(
418                array('id_paquet', 'prefixe', 'actif', 'installe', 'attente', 'constante', 'src_archive'),
419                'spip_paquets',
420                'id_depot=' . sql_quote(0));
421        $changements = array();
422
423        foreach ($locaux as $l) {
424                $copie = $l;
425                $prefixe = strtoupper($l['prefixe']);
426                // actif ?
427                if (isset($actifs[$prefixe])
428                        and ($actifs[$prefixe]['dir_type'] == $l['constante'])
429                        and ($actifs[$prefixe]['dir'] == $l['src_archive'])
430                ) {
431                        $copie['actif'] = "oui";
432                } else {
433                        $copie['actif'] = "non";
434                }
435
436                // attente ?
437                if (isset($attentes[$prefixe])
438                        and ($attentes[$prefixe]['dir_type'] == $l['constante'])
439                        and ($attentes[$prefixe]['dir'] == $l['src_archive'])
440                ) {
441                        $copie['attente'] = "oui";
442                        $copie['actif'] = "oui"; // il est presente dans la liste des actifs (en erreur).
443                } else {
444                        $copie['attente'] = "non";
445                }
446
447                // installe ?
448                if (in_array($l['src_archive'], $installes)) {
449                        $copie['installe'] = "oui";
450                } else {
451                        $copie['installe'] = "non";
452                }
453
454                if ($copie != $l) {
455                        $changements[$l['id_paquet']] = array(
456                                'actif' => $copie['actif'],
457                                'installe' => $copie['installe'],
458                                'attente' => $copie['attente']
459                        );
460                }
461        }
462
463        if (count($changements)) {
464                // On insere, en encapsulant pour sqlite...
465                if (sql_preferer_transaction()) {
466                        sql_demarrer_transaction();
467                }
468
469                foreach ($changements as $id_paquet => $data) {
470                        sql_updateq('spip_paquets', $data, 'id_paquet=' . intval($id_paquet));
471                }
472
473                if (sql_preferer_transaction()) {
474                        sql_terminer_transaction();
475                }
476        }
477
478}
479
480/**
481 * Construit le contenu multilangue (tag <multi>) des balises nom, slogan
482 * et description à partir des items de langue contenus dans le fichier
483 * paquet-prefixe_langue.php
484 *
485 * @param string $prefixe Préfixe du plugin
486 * @param string $dir_source Chemin d'accès du plugin
487 * @return array
488 *     Tableau clé => texte multilangue entre <multi> et </multi>
489 *     Les clés peuvent être 'nom', 'slogan' et 'description', mais
490 *     seules les clés ayant une explication dans la chaine de langue
491 *     sont retournées.
492 */
493function svp_compiler_multis($prefixe, $dir_source) {
494
495        $multis = array();
496        // ici on cherche le fichier et les cles avec un prefixe en minuscule systematiquement...
497        $prefixe = strtolower($prefixe);
498        $module = "paquet-$prefixe";
499        $item_nom = $prefixe . "_nom";
500        $item_slogan = $prefixe . "_slogan";
501        $item_description = $prefixe . "_description";
502
503        // On cherche tous les fichiers de langue destines a la traduction du paquet.xml
504        if ($fichiers_langue = glob($dir_source . "/lang/{$module}_*.php")) {
505                include_spip('inc/lang_liste');
506                $nom = $slogan = $description = '';
507                foreach ($fichiers_langue as $_fichier_langue) {
508                        $nom_fichier = basename($_fichier_langue, '.php');
509                        $langue = substr($nom_fichier, strlen($module) + 1 - strlen($nom_fichier));
510                        // Si la langue est reconnue, on traite la liste des items de langue
511                        if (isset($GLOBALS['codes_langues'][$langue])) {
512                                $GLOBALS['idx_lang'] = $langue;
513                                include($_fichier_langue);
514                                foreach ($GLOBALS[$langue] as $_item => $_traduction) {
515                                        if ($_traduction = trim($_traduction)) {
516                                                if ($_item == $item_nom) {
517                                                        $nom .= "[$langue]$_traduction";
518                                                }
519                                                if ($_item == $item_slogan) {
520                                                        $slogan .= "[$langue]$_traduction";
521                                                }
522                                                if ($_item == $item_description) {
523                                                        $description .= "[$langue]$_traduction";
524                                                }
525                                        }
526                                }
527                        }
528                }
529
530                // Finaliser la construction des balises multi
531                if ($nom) {
532                        $multis['nom'] = "<multi>$nom</multi>";
533                }
534                if ($slogan) {
535                        $multis['slogan'] = "<multi>$slogan</multi>";
536                }
537                if ($description) {
538                        $multis['description'] = "<multi>$description</multi>";
539                }
540        }
541
542        return $multis;
543}
544
545
546/**
547 * Met à jour les informations d'obsolescence des paquets locaux.
548 *
549 * L'obsolescence indique qu'un paquet est plus ancien (de version ou état
550 * moins avancé) qu'un autre également présent localement.
551 *
552 * @param array $ids_plugin
553 *     Liste d'identifiants de plugins
554 *     En cas d'absence, passera sur tous les paquets locaux
555 **/
556function svp_corriger_obsolete_paquets($ids_plugin = array()) {
557        // on minimise au maximum le nombre de requetes.
558        // 1 pour lister les paquets
559        // 1 pour mettre à jour les obsoletes à oui
560        // 1 pour mettre à jour les obsoletes à non
561
562        $where = array('pa.id_plugin = pl.id_plugin', 'id_depot=' . sql_quote(0));
563        if ($ids_plugin) {
564                $where[] = sql_in('pl.id_plugin', $ids_plugin);
565        }
566
567        // comme l'on a de nouveaux paquets locaux...
568        // certains sont peut etre devenus obsoletes
569        // parmis tous les plugins locaux presents
570        // concernes par les memes prefixes que les plugins ajoutes.
571        $obsoletes = array();
572        $changements = array();
573
574        $paquets = sql_allfetsel(
575                array('pa.id_paquet', 'pl.prefixe', 'pa.version', 'pa.etatnum', 'pa.obsolete', 'pa.compatibilite_spip'),
576                array('spip_paquets AS pa', 'spip_plugins AS pl'),
577                $where);
578
579        // L'obsolescence doit tenir compte de la compatibilité avec notre version de SPIP en cours
580        foreach ($paquets as $c => $p) {
581                $paquets[$c]['compatible'] = plugin_version_compatible($p['compatibilite_spip'], $GLOBALS['spip_version_branche'],
582                        'spip');
583        }
584
585        foreach ($paquets as $c => $p) {
586
587                $obsoletes[$p['prefixe']][] = $c;
588
589                // si 2 paquet locaux ont le meme prefixe,
590                // mais pas la meme version,
591                // sont compatibles avec notre SPIP,
592                // l'un est obsolete : la version la plus ancienne
593                // Si version et etat sont egaux, on ne decide pas d'obsolescence.
594                if (count($obsoletes[$p['prefixe']]) > 1) {
595                        foreach ($obsoletes[$p['prefixe']] as $cle) {
596                                if ($cle == $c) {
597                                        continue;
598                                }
599                                if (!$paquets[$c]['compatible']) {
600                                        continue;
601                                }
602
603                                // je suis plus petit qu'un autre
604                                if (spip_version_compare($paquets[$c]['version'], $paquets[$cle]['version'], '<')) {
605                                        if ($paquets[$c]['etatnum'] <= $paquets[$cle]['etatnum']) {
606                                                if ($paquets[$c]['obsolete'] != 'oui') {
607                                                        $paquets[$c]['obsolete'] = 'oui';
608                                                        $changements[$c] = true;
609                                                }
610                                        }
611                                } // je suis plus grand ou egal a un autre...
612                                else {
613                                        // je suis strictement plus grand qu'un autre...
614                                        if (spip_version_compare($paquets[$c]['version'], $paquets[$cle]['version'], '>')) {
615                                                // si mon etat est meilleur, rendre obsolete les autres
616                                                if ($paquets[$c]['etatnum'] >= $paquets[$cle]['etatnum']) {
617                                                        if ($paquets[$cle]['obsolete'] != 'oui') {
618                                                                $paquets[$cle]['obsolete'] = 'oui';
619                                                                $changements[$cle] = true;
620                                                        }
621                                                }
622                                        }
623
624                                        // je suis egal a un autre
625                                        // si mon etat est strictement meilleur, rendre obsolete les autres
626                                        elseif ($paquets[$c]['etatnum'] > $paquets[$cle]['etatnum']) {
627                                                if ($paquets[$cle]['obsolete'] != 'oui') {
628                                                        $paquets[$cle]['obsolete'] = 'oui';
629                                                        $changements[$cle] = true;
630                                                }
631                                        }
632                                }
633
634                        }
635                } else {
636                        if ($paquets[$c]['obsolete'] != 'non') {
637                                $paquets[$c]['obsolete'] = 'non';
638                                $changements[$c] = true;
639                        }
640                }
641        }
642
643        if (count($changements)) {
644                $oui = $non = array();
645                foreach ($changements as $c => $null) {
646                        if ($paquets[$c]['obsolete'] == 'oui') {
647                                $oui[] = $paquets[$c]['id_paquet'];
648                        } else {
649                                $non[] = $paquets[$c]['id_paquet'];
650                        }
651                }
652
653                if ($oui) {
654                        sql_updateq('spip_paquets', array('obsolete' => 'oui'), sql_in('id_paquet', $oui));
655                }
656                if ($non) {
657                        sql_updateq('spip_paquets', array('obsolete' => 'non'), sql_in('id_paquet', $non));
658                }
659        }
660}
661
662
663/**
664 * Supprime les plugins devenus orphelins dans cette liste.
665 *
666 * @param array $ids_plugin
667 *     Liste d'identifiants de plugins
668 * @return array
669 *     Liste de plugins non orphelins
670 **/
671function svp_supprimer_plugins_orphelins($ids_plugin) {
672        // tous les plugins encore lies a des depots...
673        if ($ids_plugin) {
674                $p = sql_allfetsel('DISTINCT(p.id_plugin)', array('spip_plugins AS p', 'spip_paquets AS pa'),
675                        array(sql_in('p.id_plugin', $ids_plugin), 'p.id_plugin=pa.id_plugin'));
676                $p = array_map('array_shift', $p);
677                $diff = array_diff($ids_plugin, $p);
678                // pour chaque plugin non encore utilise, on les vire !
679                sql_delete('spip_plugins', sql_in('id_plugin', $diff));
680
681                return $p; // les plugins encore en vie !
682        }
683
684        return array();
685}
686
687
688/**
689 * Cherche dans les dépots distants un plugin qui serait plus à jour
690 * que le prefixe, version et état que l'on transmet
691 *
692 * @param string $prefixe
693 *    Préfixe du plugin
694 * @param string $version
695 *    Version du paquet à comparer
696 * @param int $etatnum
697 *    État du paquet numérique
698 * @return string
699 *    Version plus à jour, sinon rien
700 **/
701function svp_rechercher_maj_version($prefixe, $version, $etatnum) {
702
703        $maj_version = "";
704
705        if ($res = sql_allfetsel(
706                array('pl.id_plugin', 'pa.version'),
707                array('spip_plugins AS pl', 'spip_paquets AS pa'),
708                array(
709                        'pl.id_plugin = pa.id_plugin',
710                        'pa.id_depot>' . sql_quote(0),
711                        'pl.prefixe=' . sql_quote($prefixe),
712                        'pa.etatnum>=' . sql_quote($etatnum)
713                ))
714        ) {
715
716                foreach ($res as $paquet_distant) {
717                        // si version superieure et etat identique ou meilleur,
718                        // c'est que c'est une mise a jour possible !
719                        if (spip_version_compare($paquet_distant['version'], $version, '>')) {
720                                if (!strlen($maj_version) or spip_version_compare($paquet_distant['version'], $maj_version, '>')) {
721                                        $maj_version = $paquet_distant['version'];
722                                }
723                                # a voir si on utilisera...
724                                # "superieur"           => "varchar(3) DEFAULT 'non' NOT NULL",
725                                # // superieur : version plus recente disponible (distant) d'un plugin (actif?) existant
726                        }
727                }
728        }
729
730        return $maj_version;
731}
732
733
734/**
735 * Actualise l'information 'maj_version' pour tous les paquets locaux
736 *
737 * @uses  svp_rechercher_maj_version()
738 **/
739function svp_actualiser_maj_version() {
740        $update = array();
741        // tous les paquets locaux
742        if ($locaux = sql_allfetsel(
743                array('id_paquet', 'prefixe', 'version', 'maj_version', 'etatnum'),
744                array('spip_paquets'),
745                array('id_depot=' . sql_quote(0)))
746        ) {
747                foreach ($locaux as $paquet) {
748                        $new_maj_version = svp_rechercher_maj_version($paquet['prefixe'], $paquet['version'], $paquet['etatnum']);
749                        if ($new_maj_version != $paquet['maj_version']) {
750                                $update[$paquet['id_paquet']] = array('maj_version' => $new_maj_version);
751                        }
752                }
753        }
754        if ($update) {
755                // On insere, en encapsulant pour sqlite...
756                if (sql_preferer_transaction()) {
757                        sql_demarrer_transaction();
758                }
759
760                foreach ($update as $id_paquet => $data) {
761                        sql_updateq('spip_paquets', $data, 'id_paquet=' . intval($id_paquet));
762                }
763
764                if (sql_preferer_transaction()) {
765                        sql_terminer_transaction();
766                }
767        }
768}
Note: See TracBrowser for help on using the repository browser.