/** * Actualisation de la table des paquets pour le dépot choisi * * Enlève de la base les paquets du dépots qui ne sont plus présents * dans la description du XML. Ajoute ou met à jour les autres. * * @param int $id_depot * Identifiant du dépot * @param array $paquets * Tableau des paquets extraits du fichier XML * L'index est le nom de l'archive (xxxx.zip) et le contenu est * un tableau à deux entrées : * - Index 'plugin' : le tableau des infos du plugin * - Index 'file' : le nom de l'archive .zip * @param int $nb_paquets * Nombre de paquets réellement inserés dans la base * @param int $nb_plugins * Nombre de plugins parmi les paquets inserés * @param int &$nb_autres * Nombre de contributions non issues de plugin parmi les paquets inserés * @return bool * false si aucun dépot ou paquets, true sinon */ function svp_actualiser_paquets($id_depot, $paquets, &$nb_paquets, &$nb_plugins, &$nb_autres) { // Initialisation des compteurs $nb_paquets = 0; $nb_plugins = 0; $nb_autres = 0; // Si aucun depot ou aucun paquet on renvoie une erreur if (!$id_depot or !is_array($paquets)) { return false; } // On initialise l'url de base des logos du depot et son type afin de // calculer l'url complete de chaque logo $select = array('url_archives', 'type'); $depot = sql_fetsel($select, 'spip_depots', 'id_depot=' . sql_quote($id_depot)); // On supprime tous les paquets du depot // qui ont ete evacues, c'est a dire ceux dont les signatures // ne correspondent pas aux nouveaux... // et on retablit les vmax des plugins restants... $signatures = array(); foreach ($paquets as $_paquet) { $signatures[] = $_paquet['md5']; } // tous les paquets du depot qui ne font pas parti des signatures $anciens_paquets = sql_allfetsel('id_paquet', 'spip_paquets', array('id_depot=' . sql_quote($id_depot), sql_in('signature', $signatures, 'NOT'))); $anciens_paquets = array_map('array_shift', $anciens_paquets); // pour ces vieux paquets, on les nettoie de la base if ($anciens_paquets) { // tous les plugins correspondants aux anciens paquets $anciens_plugins = sql_allfetsel('pl.id_plugin', array('spip_plugins AS pl', 'spip_paquets AS pa'), array('pl.id_plugin=pa.id_plugin', sql_in('pa.id_paquet', $anciens_paquets))); $anciens_plugins = array_map('array_shift', $anciens_plugins); // suppression des anciens paquets sql_delete('spip_paquets', sql_in('id_paquet', $anciens_paquets)); // suppressions des liaisons depots / anciens plugins // on enlève la liaison lorsqu'il n'y a plus aucun paquet lie a un des plugins qui ont vu un paquet enlevé // liste des plugins qui ont encore des paquets dans ce depot $plugins_restants = sql_allfetsel('pl.id_plugin', array('spip_plugins AS pl', 'spip_paquets AS pa'), array(sql_in('pl.id_plugin', $anciens_plugins), 'pl.id_plugin=pa.id_plugin', 'pa.id_depot=' . sql_quote($id_depot))); $plugins_restants = array_map('array_shift', $plugins_restants); // par opposition, on retrouve ceux qui n'en ont plus... $plugins_supprimes = array_diff($anciens_plugins, $plugins_restants); sql_delete('spip_depots_plugins', array('id_depot=' . sql_quote($id_depot), sql_in('id_plugin', $plugins_supprimes))); unset($plugins_restants, $plugins_supprimes); // supprimer les plugins orphelins include_spip('inc/svp_depoter_local'); svp_supprimer_plugins_orphelins($anciens_plugins); // corriger les vmax des plugins svp_corriger_vmax_plugins($anciens_plugins); // corriger les compats, branches aussi svp_completer_plugins($anciens_plugins); } // on ne garde que les paquets qui ne sont pas presents dans la base $signatures = sql_allfetsel('signature', 'spip_paquets', 'id_depot=' . sql_quote($id_depot)); $signatures = array_map('array_shift', $signatures); foreach ($paquets as $cle => $_infos) { if (in_array($_infos['md5'], $signatures)) { unset($paquets[$cle]); } } // tableaux d'actions $insert_paquets = array(); $insert_plugins = array(); $insert_contribs = array(); $prefixes = array(); // prefixe => id_plugin // On met a jour ou on cree chaque paquet a partir du contenu du fichier xml // On ne fait pas cas de la compatibilite avec la version de SPIP installee // car l'operation doit permettre de collecter tous les paquets foreach ($paquets as $_archive => $_infos) { $insert_paquet = array(); // On initialise les informations specifiques au paquet : // l'id du depot et les infos de l'archive $insert_paquet['id_depot'] = $id_depot; $insert_paquet['nom_archive'] = $_archive; $insert_paquet['nbo_archive'] = $_infos['size']; $insert_paquet['maj_archive'] = date('Y-m-d H:i:s', $_infos['date']); $insert_paquet['src_archive'] = $_infos['source']; $insert_paquet['date_modif'] = $_infos['last_commit']; // On serialise le tableau des traductions par module $insert_paquet['traductions'] = serialize($_infos['traductions']); // On ajoute la signature $insert_paquet['signature'] = $_infos['md5']; // On verifie si le paquet est celui d'un plugin ou pas // -- Les traitements du XML dependent de la DTD utilisee // Formatage des informations extraites du plugin pour insertion dans la base SVP $formater = charger_fonction('preparer_sql_' . $_infos['dtd'], 'plugins'); if ($champs_aplat = $formater($_infos['plugin'])) { // Eclater les champs recuperes en deux sous tableaux, un par table (plugin, paquet) $champs = eclater_plugin_paquet($champs_aplat); $paquet_plugin = true; // On complete les informations du paquet et du plugin $insert_paquet = array_merge($insert_paquet, $champs['paquet']); $insert_plugin = $champs['plugin']; // On construit l'url complete du logo // Le logo est maintenant disponible a la meme adresse que le zip et porte le nom du zip. // Son extension originale est conservee if ($insert_paquet['logo']) { $insert_paquet['logo'] = $depot['url_archives'] . '/' . basename($insert_paquet['nom_archive'], '.zip') . '.' . pathinfo($insert_paquet['logo'], PATHINFO_EXTENSION); } // On loge l'absence de categorie ou une categorie erronee et on positionne la categorie // par defaut "aucune" // Provisoire tant que la DTD n'est pas en fonction if (!$insert_plugin['categorie']) { spip_log("Categorie absente dans le paquet issu de <" . $insert_paquet['src_archive'] . "> du depot <" . $insert_paquet['id_depot'] . ">\n", 'svp_paquets.' . _LOG_INFO_IMPORTANTE); $insert_plugin['categorie'] = 'aucune'; } else { $svp_categories = $GLOBALS['categories_plugin']; if (!in_array($insert_plugin['categorie'], $svp_categories)) { spip_log("Categorie k" . $insert_plugin['categorie'] . "l incorrecte dans le paquet issu de <" . $insert_paquet['src_archive'] . "> du depot <" . $insert_paquet['id_depot'] . ">\n", 'svp_paquets.' . _LOG_INFO_IMPORTANTE); $insert_plugin['categorie'] = 'aucune'; } } } else { $paquet_plugin = false; } // On teste l'existence du paquet dans la base avec les champs // id_depot, nom_archive et src_archive pour être sur de l'unicité. // - si le paquet n'existe pas, on le crée, // - sinon (et ça ne devrait pas arriver), on ne fait qu'un update if (!($paquet = sql_fetsel('*', 'spip_paquets', array('id_depot=' . sql_quote($insert_paquet['id_depot']), 'nom_archive=' . sql_quote($insert_paquet['nom_archive']), 'src_archive=' . sql_quote($insert_paquet['src_archive']))))) { // Le paquet n'existe pas encore en base de donnees // ------------------------------------------------ // On positionne la date de creation a celle du dernier commit ce qui est bien le cas $insert_paquet['date_crea'] = $insert_paquet['date_modif']; // Les collisions ne sont possibles que si on ajoute un nouveau paquet $collision = false; if ($paquet_plugin) { // On est en presence d'un PLUGIN // ------------------------------ // On evite les doublons de paquet // Pour determiner un doublon on verifie actuellement : // - le prefixe // - la version du paquet et de la base // - l'etat $where = array('t1.id_plugin=t2.id_plugin', 't1.version=' . sql_quote($insert_paquet['version']), 't1.version_base=' . sql_quote($insert_paquet['version_base']), 't1.etatnum=' . sql_quote($insert_paquet['etatnum']), 't1.id_depot>' . intval(0), 't2.prefixe=' . sql_quote($insert_plugin['prefixe'])); if (!($id_paquet = sql_getfetsel('t1.id_paquet', 'spip_paquets AS t1, spip_plugins AS t2', $where))) { // On traite d'abord le plugin du paquet pour recuperer l'id_plugin // On rajoute le plugin dans la table spip_plugins si celui-ci n'y est pas encore ou on recupere // l'id si il existe deja et on le met a jour si la version du paquet est plus elevee $plugin = sql_fetsel('id_plugin, vmax', 'spip_plugins', array('prefixe=' . sql_quote($insert_plugin['prefixe']))); if (!$plugin and !array_key_exists($insert_plugin['prefixe'], $insert_plugins)) { $insert_plugins[$insert_plugin['prefixe']] = array_merge($insert_plugin, array('vmax' => $insert_paquet['version'])); } else { if ($plugin) { $id_plugin = $plugin['id_plugin']; $prefixes[$insert_plugin['prefixe']] = $id_plugin; } if (array_key_exists($insert_plugin['prefixe'], $insert_plugins) and spip_version_compare($insert_plugins[$insert_plugin['prefixe']]['vmax'], $insert_paquet['version'], '<=')) { // attribuer au plugin le nom et le slogan du paquet le plus à jour $insert_plugins[$insert_plugin['prefixe']]['nom'] = $insert_plugin['nom']; $insert_plugins[$insert_plugin['prefixe']]['slogan'] = $insert_plugin['slogan']; $insert_plugins[$insert_plugin['prefixe']]['vmax'] = $insert_paquet['version']; } } // On traite maintenant le paquet connaissant l'id du plugin // temporaire qui sera supprime lors de la connaissance de l'id_paquet $insert_paquet['prefixe'] = $insert_plugin['prefixe']; $insert_paquets[] = $insert_paquet; } else { $collision = true; } } else { // On est en presence d'une CONTRIBUTION NON PLUGIN // ------------------------------------------------ $where = array('id_depot=' . sql_quote($insert_paquet['id_depot']), 'nom_archive=' . sql_quote($insert_paquet['nom_archive'])); if (!($id_paquet = sql_getfetsel('id_paquet', 'spip_paquets', $where))) { // Ce n'est pas un plugin, donc id_plugin=0 et toutes les infos plugin sont nulles $insert_paquet['id_plugin'] = 0; $insert_contribs[] = $insert_paquet; } else { $collision = true; } } // On loge le paquet ayant ete refuse dans un fichier a part afin de les verifier // apres coup if ($collision) { spip_log("Collision avec le paquet <" . $insert_paquet['nom_archive'] . " / " . $insert_paquet['src_archive'] . "> du depot <" . $insert_paquet['id_depot'] . ">\n", 'svp_paquets.' . _LOG_INFO_IMPORTANTE); } } else { // Le paquet existe deja en base de donnees // ---------------------------------------- // On ne devrait plus arriver ICI... // Code obsolete ? spip_log('!!!!!! Passage dans code obsolete (svp/svp_depoter_distant)', 'depoter'); // on effectue les traitements en attente // pour que les updates soient corrects svp_inserer_multi($insert_plugins, $insert_paquets, $insert_contribs, $prefixes); // On met a jour le paquet en premier lieu qu'il soit un plugin ou une contribution sql_updateq('spip_paquets', $insert_paquet, 'id_paquet=' . sql_quote($paquet['id_paquet'])); } } // on effectue les traitements en attente // pour que les updates soient corrects svp_inserer_multi($insert_plugins, $insert_paquets, $insert_contribs, $prefixes); // On rajoute le plugin comme heberge par le depot si celui-ci n'est pas encore enregistre comme tel $ids = sql_allfetsel('p.id_plugin', array('spip_plugins AS p', 'spip_depots_plugins AS dp'), array('p.id_plugin=dp.id_plugin', 'dp.id_depot=' . sql_quote($id_depot))); $ids = array_map('array_shift', $ids); // inserer les liens avec le depots $insert_dp = array(); $news_id = array_diff(array_values($prefixes), $ids); foreach ($news_id as $id) { $insert_dp[] = array('id_depot' => $id_depot, 'id_plugin' => $id); } if ($insert_dp) { sql_insertq_multi('spip_depots_plugins', $insert_dp); } // on recalcul les vmax des plugins de ce depot. svp_corriger_vmax_plugins(array_values($prefixes)); // On compile maintenant certaines informations des paquets mis a jour dans les plugins // (date de creation, date de modif, version spip...) svp_completer_plugins_depot($id_depot); // Si on est pas en mode runtime, on utilise surement l'espace public pour afficher les plugins. // Il faut donc s'assurer que les urls suivent bien la mise à jour // - on supprime toutes les urls plugin // - on les regenere pour la liste des plugins mise a jour if (!_SVP_MODE_RUNTIME) { svp_actualiser_url_plugins($id_depot); } // Calcul des compteurs de paquets, plugins et contributions $nb_paquets = sql_countsel('spip_paquets', 'id_depot=' . sql_quote($id_depot)); $nb_plugins = sql_countsel('spip_depots_plugins', 'id_depot=' . sql_quote($id_depot)); $nb_autres = sql_countsel('spip_paquets', array('id_depot=' . sql_quote($id_depot), 'id_plugin=0')); return true; }
/** * Insère en base tous les paquets locaux transmis * * De chaque description est extrait la partie plugin (1 seul plugin * par préfixe de plugin connu) et la partie paquet (il peut y avoir plusieurs * paquets pour un même préfixe de plugin). * * @note * On essaie au mieux de faire des requêtes d'insertions multiples, * mieux gérées par les moteurs SQL (particulièrement pour SQLite) * * @param array $paquets_locaux * Descriptions des paquets (intégrant un hash), stockés par * constante, puis par chemin. * array[_DIR_PLUGIN*][$chemin] = description **/ function svp_base_inserer_paquets_locaux($paquets_locaux) { include_spip('inc/svp_depoter_distant'); // On initialise les informations specifiques au paquet : // l'id du depot et les infos de l'archive $paquet_base = array('id_depot' => 0, 'nom_archive' => '', 'nbo_archive' => '', 'maj_archive' => '', 'src_archive' => '', 'date_modif' => '', 'maj_version' => '', 'signature' => ''); $preparer_sql_paquet = charger_fonction('preparer_sql_paquet', 'plugins'); // pour chaque decouverte, on insere les paquets en base. // on evite des requetes individuelles, tres couteuses en sqlite... $cle_plugins = array(); // prefixe => id $insert_plugins = array(); // insertion prefixe... $insert_plugins_vmax = array(); // vmax des nouveaux plugins... $insert_paquets = array(); // insertion de paquet... include_spip('inc/config'); $recents = lire_config('plugins_interessants'); $installes = lire_config('plugin_installes'); $actifs = lire_config('plugin'); $attentes = lire_config('plugin_attente'); foreach ($paquets_locaux as $const_dir => $paquets) { foreach ($paquets as $chemin => $paquet) { // Si on est en presence d'un plugin dont la dtd est "paquet" on compile en multi // les nom, slogan et description a partir des fichiers de langue. // De cette façon, les informations des plugins locaux et distants seront identiques // => On evite l'utilisation de _T() dans les squelettes if ($paquet['dtd'] == 'paquet') { $multis = svp_compiler_multis($paquet['prefix'], constant($const_dir) . '/' . $chemin); if (isset($multis['nom'])) { $paquet['nom'] = $multis['nom']; } $paquet['slogan'] = isset($multis['slogan']) ? $multis['slogan'] : ''; $paquet['description'] = isset($multis['description']) ? $multis['description'] : ''; } $le_paquet = $paquet_base; #$le_paquet['traductions'] = serialize($paquet['traductions']); if ($champs = $preparer_sql_paquet($paquet)) { // Eclater les champs recuperes en deux sous tableaux, un par table (plugin, paquet) $champs = eclater_plugin_paquet($champs); $paquet_plugin = true; // On complete les informations du paquet et du plugin $le_paquet = array_merge($le_paquet, $champs['paquet']); $le_plugin = $champs['plugin']; // On loge l'absence de categorie ou une categorie erronee et on positionne la categorie par defaut "aucune" if (!$le_plugin['categorie']) { $le_plugin['categorie'] = 'aucune'; } else { if (!in_array($le_plugin['categorie'], $GLOBALS['categories_plugin'])) { $le_plugin['categorie'] = 'aucune'; } } // creation du plugin... $prefixe = strtoupper($le_plugin['prefixe']); // on fait attention lorqu'on cherche ou ajoute un plugin // le nom et slogan est TOUJOURS celui de la plus haute version // et il faut donc possiblement mettre a jour la base... // // + on est tolerant avec les versions identiques de plugin deja presentes // on permet le recalculer le titre... if (!isset($cle_plugins[$prefixe])) { if (!($res = sql_fetsel('id_plugin, vmax', 'spip_plugins', 'prefixe = ' . sql_quote($prefixe)))) { // on ne stocke pas de vmax pour les plugins locaux dans la bdd... (parait il) if (!isset($insert_plugins[$prefixe])) { $insert_plugins[$prefixe] = $le_plugin; $insert_plugins_vmax[$prefixe] = $le_paquet['version']; } elseif (spip_version_compare($le_paquet['version'], $insert_plugins_vmax[$prefixe], '>')) { $insert_plugins[$prefixe] = $le_plugin; $insert_plugins_vmax[$prefixe] = $le_paquet['version']; } } else { $id_plugin = $res['id_plugin']; $cle_plugins[$prefixe] = $id_plugin; // comme justement on ne stocke pas de vmax pour les plugins locaux... // il est possible que ce test soit faux. pff. if (spip_version_compare($le_paquet['version'], $res['vmax'], '>=')) { sql_updateq('spip_plugins', $le_plugin, 'id_plugin=' . sql_quote($id_plugin)); } } } // ajout du prefixe dans le paquet $le_paquet['prefixe'] = $prefixe; $le_paquet['constante'] = $const_dir; $le_paquet['src_archive'] = $chemin; $le_paquet['recent'] = isset($recents[$chemin]) ? $recents[$chemin] : 0; $le_paquet['installe'] = in_array($chemin, $installes) ? 'oui' : 'non'; // est desinstallable ? $le_paquet['obsolete'] = 'non'; $le_paquet['signature'] = $paquet['signature']; // le plugin est il actuellement actif ? $actif = "non"; if (isset($actifs[$prefixe]) and $actifs[$prefixe]['dir_type'] == $const_dir and $actifs[$prefixe]['dir'] == $chemin) { $actif = "oui"; } $le_paquet['actif'] = $actif; // le plugin etait il actif mais temporairement desactive // parce qu'une dependence a disparue ? $attente = "non"; if (isset($attentes[$prefixe]) and $attentes[$prefixe]['dir_type'] == $const_dir and $attentes[$prefixe]['dir'] == $chemin) { $attente = "oui"; $le_paquet['actif'] = "oui"; // il est presenté dans la liste des actifs (en erreur). } $le_paquet['attente'] = $attente; // on recherche d'eventuelle mises a jour existantes if ($maj_version = svp_rechercher_maj_version($prefixe, $le_paquet['version'], $le_paquet['etatnum'])) { $le_paquet['maj_version'] = $maj_version; } $insert_paquets[] = $le_paquet; } } } if ($insert_plugins) { sql_insertq_multi('spip_plugins', $insert_plugins); $pls = sql_allfetsel(array('id_plugin', 'prefixe'), 'spip_plugins', sql_in('prefixe', array_keys($insert_plugins))); foreach ($pls as $p) { $cle_plugins[$p['prefixe']] = $p['id_plugin']; } } if ($insert_paquets) { // sert pour le calcul d'obsolescence $id_plugin_concernes = array(); foreach ($insert_paquets as $c => $p) { $insert_paquets[$c]['id_plugin'] = $cle_plugins[$p['prefixe']]; $id_plugin_concernes[$insert_paquets[$c]['id_plugin']] = true; // remettre les necessite, utilise, librairie dans la cle 0 // comme SVP if ($dep = unserialize($insert_paquets[$c]['dependances']) and is_array($dep)) { foreach ($dep as $d => $contenu) { if ($contenu) { $new = array(); foreach ($contenu as $n) { unset($n['id']); $new[strtolower($n['nom'])] = $n; } $dep[$d] = array($new); } } $insert_paquets[$c]['dependances'] = serialize($dep); } } sql_insertq_multi('spip_paquets', $insert_paquets); svp_corriger_obsolete_paquets(array_keys($id_plugin_concernes)); } }