svp_depoter_local.php 23 KB

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