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