/** * Optimiser les liens morts dans la base de donnees * * @param array $flux * @return array */ function organiseur_optimiser_base_disparus($flux) { // // Messages prives // # supprimer les messages lies a un auteur disparu $res = sql_select("M.id_message AS id", "spip_messages AS M\n\t\t LEFT JOIN spip_auteurs AS A\n\t\t ON A.id_auteur=M.id_auteur", "A.id_auteur IS NULL"); $flux['data'] += optimiser_sansref('spip_messages', 'id_message', $res); return $flux; }
function optimiser_base_disparus($attente = 86400) { # format = 20060610110141, si on veut forcer une optimisation tout de suite $mydate = date("YmdHis", time() - $attente); $n = 0; // // Rubriques // # les articles qui sont dans une id_rubrique inexistante # attention on controle id_rubrique>0 pour ne pas tuer les articles # specialement affectes a une rubrique non-existante (plugin, # cf. http://trac.rezo.net/trac/spip/ticket/1549 ) $res = sql_select("articles.id_article AS id", "spip_articles AS articles LEFT JOIN spip_rubriques AS rubriques ON articles.id_rubrique=rubriques.id_rubrique", "articles.id_rubrique > 0 AND rubriques.id_rubrique IS NULL AND articles.maj < $mydate"); $n+= optimiser_sansref('spip_articles', 'id_article', $res); # les breves qui sont dans une id_rubrique inexistante $res = sql_select("breves.id_breve AS id", "spip_breves AS breves LEFT JOIN spip_rubriques AS rubriques ON breves.id_rubrique=rubriques.id_rubrique", "rubriques.id_rubrique IS NULL AND breves.maj < $mydate"); $n+= optimiser_sansref('spip_breves', 'id_breve', $res); # les forums lies a une id_rubrique inexistante $res = sql_select("forum.id_forum AS id", "spip_forum AS forum LEFT JOIN spip_rubriques AS rubriques ON forum.id_rubrique=rubriques.id_rubrique", "rubriques.id_rubrique IS NULL AND forum.id_rubrique>0"); $n+= optimiser_sansref('spip_forum', 'id_forum', $res); # les droits d'auteurs sur une id_rubrique inexistante # (plusieurs entrees seront eventuellement detruites pour chaque rub) $res = sql_select("auteurs_rubriques.id_rubrique AS id", "spip_auteurs_rubriques AS auteurs_rubriques LEFT JOIN spip_rubriques AS rubriques ON auteurs_rubriques.id_rubrique=rubriques.id_rubrique", "rubriques.id_rubrique IS NULL"); $n+= optimiser_sansref('spip_auteurs_rubriques', 'id_rubrique', $res); # les liens des mots affectes a une id_rubrique inexistante $res = sql_select("mots_rubriques.id_rubrique AS id", "spip_mots_rubriques AS mots_rubriques LEFT JOIN spip_rubriques AS rubriques ON mots_rubriques.id_rubrique=rubriques.id_rubrique", "rubriques.id_rubrique IS NULL"); $n+= optimiser_sansref('spip_mots_rubriques', 'id_rubrique', $res); // // Articles // sql_delete("spip_articles", "statut='poubelle' AND maj < $mydate"); # les liens d'auteurs d'articles effaces $res = sql_select("auteurs_articles.id_article AS id", "spip_auteurs_articles AS auteurs_articles LEFT JOIN spip_articles AS articles ON auteurs_articles.id_article=articles.id_article", "articles.id_article IS NULL"); $n+= optimiser_sansref('spip_auteurs_articles', 'id_article', $res); # les liens de mots affectes a des articles effaces $res = sql_select("mots_articles.id_article AS id", "spip_mots_articles AS mots_articles LEFT JOIN spip_articles AS articles ON mots_articles.id_article=articles.id_article", "articles.id_article IS NULL"); $n+= optimiser_sansref('spip_mots_articles', 'id_article', $res); # les forums lies a des articles effaces $res = sql_select("forum.id_forum AS id", "spip_forum AS forum LEFT JOIN spip_articles AS articles ON forum.id_article=articles.id_article", "articles.id_article IS NULL AND forum.id_article>0"); $n+= optimiser_sansref('spip_forum', 'id_forum', $res); // // Breves // sql_delete("spip_breves", "statut='refuse' AND maj < $mydate"); # les liens de mots affectes a des breves effacees $res = sql_select("mots_breves.id_breve AS id", "spip_mots_breves AS mots_breves LEFT JOIN spip_breves AS breves ON mots_breves.id_breve=breves.id_breve", "breves.id_breve IS NULL"); $n+= optimiser_sansref('spip_mots_breves', 'id_breve', $res); # les forums lies a des breves effacees $res = sql_select("forum.id_forum AS id", "spip_forum AS forum LEFT JOIN spip_breves AS breves ON forum.id_breve=breves.id_breve", "breves.id_breve IS NULL AND forum.id_breve>0"); $n+= optimiser_sansref('spip_forum', 'id_forum', $res); // // Sites // sql_delete("spip_syndic", "maj < $mydate AND statut = 'refuse'"); # les articles syndiques appartenant a des sites effaces $res = sql_select("syndic_articles.id_syndic AS id", "spip_syndic_articles AS syndic_articles LEFT JOIN spip_syndic AS syndic ON syndic_articles.id_syndic=syndic.id_syndic", "syndic.id_syndic IS NULL"); $n+= optimiser_sansref('spip_syndic_articles', 'id_syndic', $res); # les liens de mots affectes a des sites effaces $res = sql_select("mots_syndic.id_syndic AS id", "spip_mots_syndic AS mots_syndic LEFT JOIN spip_syndic AS syndic ON mots_syndic.id_syndic=syndic.id_syndic", "syndic.id_syndic IS NULL"); $n+= optimiser_sansref('spip_mots_syndic', 'id_syndic', $res); # les forums lies a des sites effaces $res = sql_select("forum.id_forum AS id", "spip_forum AS forum LEFT JOIN spip_syndic AS syndic ON forum.id_syndic=syndic.id_syndic", "syndic.id_syndic IS NULL AND forum.id_syndic>0"); $n+= optimiser_sansref('spip_forum', 'id_forum', $res); // // Auteurs // # les liens d'articles sur des auteurs effaces $res = sql_select("auteurs_articles.id_auteur AS id", "spip_auteurs_articles AS auteurs_articles LEFT JOIN spip_auteurs AS auteurs ON auteurs_articles.id_auteur=auteurs.id_auteur", "auteurs.id_auteur IS NULL"); $n+= optimiser_sansref('spip_auteurs_articles', 'id_auteur', $res); # les liens de messages sur des auteurs effaces $res = sql_select("auteurs_messages.id_auteur AS id", "spip_auteurs_messages AS auteurs_messages LEFT JOIN spip_auteurs AS auteurs ON auteurs_messages.id_auteur=auteurs.id_auteur", "auteurs.id_auteur IS NULL"); $n+= optimiser_sansref('spip_auteurs_messages', 'id_auteur', $res); # les liens de rubriques sur des auteurs effaces $res = sql_select("auteurs_rubriques.id_rubrique AS id", "spip_auteurs_rubriques AS auteurs_rubriques LEFT JOIN spip_rubriques AS rubriques ON auteurs_rubriques.id_rubrique=rubriques.id_rubrique", "rubriques.id_rubrique IS NULL"); $n+= optimiser_sansref('spip_auteurs_rubriques', 'id_rubrique', $res); # effacer les auteurs poubelle qui ne sont lies a aucun article $res = sql_select("auteurs.id_auteur AS id", "spip_auteurs AS auteurs LEFT JOIN spip_auteurs_articles AS auteurs_articles ON auteurs_articles.id_auteur=auteurs.id_auteur", "auteurs_articles.id_auteur IS NULL AND auteurs.statut='5poubelle' AND auteurs.maj < $mydate"); $n+= optimiser_sansref('spip_auteurs', 'id_auteur', $res); # supprimer les auteurs 'nouveau' qui n'ont jamais donne suite # au mail de confirmation (45 jours pour repondre, ca devrait suffire) sql_delete("spip_auteurs", "statut='nouveau' AND maj < ". sql_quote(date('Y-m-d', time()-45*24*3600))); // // Documents // # les liens des documents qui sont lies a un objet inexistant $r = sql_select("DISTINCT objet","spip_documents_liens"); while ($t = sql_fetch($r)){ $type = $t['objet']; $spip_table_objet = table_objet_sql($type); $id_table_objet = id_table_objet($type); $res = sql_select("L.id_document AS id,id_objet", "spip_documents_liens AS L LEFT JOIN $spip_table_objet AS O ON O.$id_table_objet=L.id_objet AND L.objet=".sql_quote($type), "O.$id_table_objet IS NULL"); // sur une cle primaire composee, pas d'autres solutions que de virer un a un while ($row = sql_fetch($res)){ sql_delete("spip_documents_liens", array("id_document=".$row['id'],"id_objet=".$row['id_objet'],"objet=".sql_quote($type))); spip_log("Entree ".$row['id']."/".$row['id_objet']."/$type supprimee dans la table spip_documents_liens"); } } // on ne nettoie volontairement pas automatiquement les documents orphelins // // Messages prives // # supprimer les messages lies a un auteur disparu $res = sql_select("messages.id_message AS id", "spip_messages AS messages LEFT JOIN spip_auteurs AS auteurs ON auteurs.id_auteur=messages.id_auteur", "auteurs.id_auteur IS NULL"); $n+= optimiser_sansref('spip_messages', 'id_message', $res); // // Mots-cles // $result = sql_delete("spip_mots", "titre='' AND maj < $mydate"); # les liens mots-articles sur des mots effaces $res = sql_select("mots_articles.id_mot AS id", "spip_mots_articles AS mots_articles LEFT JOIN spip_mots AS mots ON mots_articles.id_mot=mots.id_mot", "mots.id_mot IS NULL"); $n+= optimiser_sansref('spip_mots_articles', 'id_mot', $res); # les liens mots-breves sur des mots effaces $res = sql_select("mots_breves.id_mot AS id", "spip_mots_breves AS mots_breves LEFT JOIN spip_mots AS mots ON mots_breves.id_mot=mots.id_mot", "mots.id_mot IS NULL"); $n+= optimiser_sansref('spip_mots_breves', 'id_mot', $res); # les liens mots-forum sur des mots effaces $res = sql_select("mots_forum.id_mot AS id", "spip_mots_forum AS mots_forum LEFT JOIN spip_mots AS mots ON mots_forum.id_mot=mots.id_mot", "mots.id_mot IS NULL"); $n+= optimiser_sansref('spip_mots_forum', 'id_mot', $res); # les liens mots-rubriques sur des mots effaces $res = sql_select("mots_rubriques.id_mot AS id", "spip_mots_rubriques AS mots_rubriques LEFT JOIN spip_mots AS mots ON mots_rubriques.id_mot=mots.id_mot", "mots.id_mot IS NULL"); $n+= optimiser_sansref('spip_mots_rubriques', 'id_mot', $res); # les liens mots-syndic sur des mots effaces $res = sql_select("mots_syndic.id_mot AS id", "spip_mots_syndic AS mots_syndic LEFT JOIN spip_mots AS mots ON mots_syndic.id_mot=mots.id_mot", "mots.id_mot IS NULL"); $n+= optimiser_sansref('spip_mots_syndic', 'id_mot', $res); // // Forums // sql_delete("spip_forum", "statut='redac' AND maj < $mydate"); # les liens mots-forum sur des forums effaces $res = sql_select("mots_forum.id_forum AS id", "spip_mots_forum AS mots_forum LEFT JOIN spip_forum AS forum ON mots_forum.id_forum=forum.id_forum", "forum.id_forum IS NULL"); $n+= optimiser_sansref('spip_mots_forum', 'id_forum', $res); $n = pipeline('optimiser_base_disparus', array( 'args'=>array( 'attente' => $attente, 'date' => $mydate), 'data'=>$n )); // // CNIL -- Informatique et libertes // // masquer le numero IP des vieux forums // ## date de reference = 4 mois ## definir a 0 pour desactiver define('_CNIL_PERIODE', 3600*24*31*4); if (_CNIL_PERIODE) { $critere_cnil = 'date_heure<"'.date('Y-m-d', time()-_CNIL_PERIODE).'"' . ' AND statut != "spam"' . ' AND (ip LIKE "%.%" OR ip LIKE "%:%")'; # ipv4 ou ipv6 $c = sql_countsel('spip_forum', $critere_cnil); if ($c>0) { spip_log("CNIL: masquer IP de $c forums anciens"); sql_update('spip_forum', array('ip' => 'MD5(ip)'), $critere_cnil); } } if (!$n) spip_log("Optimisation des tables: aucun lien mort"); }
/** * Optimiser la base de donnee en supprimant les forums orphelins * * @param int $n * @return int */ function forum_optimiser_base_disparus($flux) { $n =& $flux['data']; $mydate = $flux['args']['date']; # les forums lies a une id_objet inexistant $r = sql_select("DISTINCT objet", 'spip_forum'); while ($t = sql_fetch($r)) { if ($type = $t['objet']) { $spip_table_objet = table_objet_sql($type); $id_table_objet = id_table_objet($type); # les forums lies a un objet inexistant $res = sql_select("forum.id_forum AS id", "spip_forum AS forum\n\t\t\t\t\t\t\t\tLEFT JOIN {$spip_table_objet} AS O\n\t\t\t\t\t\t\t\t\tON O.{$id_table_objet}=forum.id_objet", "forum.objet=" . sql_quote($type) . " AND O.{$id_table_objet} IS NULL AND forum.id_objet>0"); $n += optimiser_sansref('spip_forum', 'id_forum', $res); } } // // Forums // sql_delete("spip_forum", "statut='redac' AND maj < {$mydate}"); // nettoyer les documents des forums en spam&poubelle pour eviter de sortir des quota disques // bizarrement on ne nettoie jamais les messages eux meme ? include_spip('action/editer_liens'); if (objet_associable('document')) { $res = sql_select('L.id_document,F.id_forum', "spip_documents_liens AS L JOIN spip_forum AS F ON (F.id_forum=L.id_objet AND L.objet='forum')", "F.statut IN ('off','spam')"); while ($row = sql_fetch($res)) { include_spip('inc/autoriser'); // si un seul lien (ce forum donc), on supprime le document // si un document est attache a plus d'un forum, c'est un cas bizarre ou gere a la main // on ne touche a rien ! if (count(objet_trouver_liens(array('document' => $row['id_document']), '*')) == 1) { autoriser_exception('supprimer', 'document', $row['id_document']); if ($supprimer_document = charger_fonction('supprimer_document', 'action', true)) { $supprimer_document($row['id_document']); } } } } // // CNIL -- Informatique et libertes // // masquer le numero IP des vieux forums // ## date de reference = 4 mois ## definir a 0 pour desactiver if (!defined('_CNIL_PERIODE')) { define('_CNIL_PERIODE', 3600 * 24 * 31 * 4); } if (_CNIL_PERIODE) { $critere_cnil = 'date_heure<"' . date('Y-m-d', time() - _CNIL_PERIODE) . '"' . ' AND statut != "spam"' . ' AND (ip LIKE "%.%" OR ip LIKE "%:%")'; # ipv4 ou ipv6 $c = sql_countsel('spip_forum', $critere_cnil); if ($c > 0) { spip_log("CNIL: masquer IP de {$c} forums anciens"); sql_update('spip_forum', array('ip' => 'MD5(ip)'), $critere_cnil); } } return $flux; }
/** * Optimiser la base de donnee en supprimant les liens orphelins * * @param array $flux * @return array */ function sites_optimiser_base_disparus($flux) { $n =& $flux['data']; $mydate = $flux['args']['date']; sql_delete("spip_syndic", "maj < {$mydate} AND statut = 'refuse'"); # les articles syndiques appartenant a des sites effaces $res = sql_select("S.id_syndic AS id", "spip_syndic_articles AS S\n\t\t LEFT JOIN spip_syndic AS syndic\n\t\t ON S.id_syndic=syndic.id_syndic", "syndic.id_syndic IS NULL"); $n += optimiser_sansref('spip_syndic_articles', 'id_syndic', $res); return $flux; }
/** * Suppression des liens morts entre tables * * Supprime des liens morts entre tables suite à la suppression d'articles, * d'auteurs, etc... * * @note * Maintenant que MySQL 5 a des Cascades on pourrait faire autrement * mais on garde la compatibilité avec les versions précédentes. * * @pipeline_appel optimiser_base_disparus * * @param int $attente * Attente entre 2 exécutions de la tache en secondes * @return void **/ function optimiser_base_disparus($attente = 86400) { # format = 20060610110141, si on veut forcer une optimisation tout de suite $mydate = sql_quote(date("Y-m-d H:i:s", time() - $attente)); $n = 0; // // Rubriques // # les articles qui sont dans une id_rubrique inexistante # attention on controle id_rubrique>0 pour ne pas tuer les articles # specialement affectes a une rubrique non-existante (plugin, # cf. http://trac.rezo.net/trac/spip/ticket/1549 ) $res = sql_select("A.id_article AS id", "spip_articles AS A\n\t\t LEFT JOIN spip_rubriques AS R\n\t\t ON A.id_rubrique=R.id_rubrique", "A.id_rubrique > 0\n\t\t\t AND R.id_rubrique IS NULL\n\t\t AND A.maj < {$mydate}"); $n += optimiser_sansref('spip_articles', 'id_article', $res); // les articles a la poubelle sql_delete("spip_articles", "statut='poubelle' AND maj < {$mydate}"); // // Auteurs // include_spip('action/editer_liens'); // optimiser les liens de tous les auteurs vers des objets effaces // et depuis des auteurs effaces $n += objet_optimiser_liens(array('auteur' => '*'), '*'); # effacer les auteurs poubelle qui ne sont lies a rien $res = sql_select("A.id_auteur AS id", "spip_auteurs AS A\n\t\t \tLEFT JOIN spip_auteurs_liens AS L\n\t\t ON L.id_auteur=A.id_auteur", "L.id_auteur IS NULL\n\t\t \tAND A.statut='5poubelle' AND A.maj < {$mydate}"); $n += optimiser_sansref('spip_auteurs', 'id_auteur', $res); # supprimer les auteurs 'nouveau' qui n'ont jamais donne suite # au mail de confirmation (45 jours pour repondre, ca devrait suffire) sql_delete("spip_auteurs", "statut='nouveau' AND maj < " . sql_quote(date('Y-m-d', time() - 45 * 24 * 3600))); /** * Permet aux plugins de compléter l'optimisation suite aux éléments disparus * * L'index 'data' est un entier indiquant le nombre d'optimisations * qui ont été réalisées (par exemple le nombre de suppressions faites) * et qui doit être incrémenté par les fonctions * utilisant ce pipeline si elles suppriment des éléments. * * @pipeline_appel optimiser_base_disparus */ $n = pipeline('optimiser_base_disparus', array('args' => array('attente' => $attente, 'date' => $mydate), 'data' => $n)); if (!$n) { spip_log("Optimisation des tables: aucun lien mort"); } }
/** * Sous fonction optimisation * qui nettoie les liens morts (vers un objet inexistant) * pour un objet source dont la clé primaire * et la table de lien sont fournies * * $objets et de la forme * array($objet=>$id_objets,...) * un * pour $id,$objet,$id_objets permet de traiter par lot * * @internal * @param string $objet_source * @param string $primary * @param string $table_lien * @param int $id * @param array $objets * @return bool|int */ function lien_optimise($objet_source, $primary, $table_lien, $id, $objets) { include_spip('genie/optimiser'); $echec = false; $dels = 0; foreach ($objets as $objet => $id_objets) { $objet = $objet == '*' ? $objet : objet_type($objet); # securite if (!is_array($id_objets) or reset($id_objets) == "NOT") { $id_objets = array($id_objets); } foreach ($id_objets as $id_objet) { $where = lien_where($primary, $id, $objet, $id_objet); # les liens vers un objet inexistant $r = sql_select("DISTINCT objet", $table_lien, $where); while ($t = sql_fetch($r)) { $type = $t['objet']; $spip_table_objet = table_objet_sql($type); $id_table_objet = id_table_objet($type); $res = sql_select("L.{$primary} AS id,L.id_objet", "{$table_lien} AS L\n\t\t\t\t\t\t\t\t\tLEFT JOIN {$spip_table_objet} AS O\n\t\t\t\t\t\t\t\t\t\tON (O.{$id_table_objet}=L.id_objet AND L.objet=" . sql_quote($type) . ")", "L.objet=" . sql_quote($type) . " AND O.{$id_table_objet} IS NULL"); // sur une cle primaire composee, pas d'autres solutions que de virer un a un while ($row = sql_fetch($res)) { $e = sql_delete($table_lien, array("{$primary}=" . $row['id'], "id_objet=" . $row['id_objet'], "objet=" . sql_quote($type))); if ($e != false) { $dels += $e; spip_log("Entree " . $row['id'] . "/" . $row['id_objet'] . "/{$type} supprimee dans la table {$table_lien}", _LOG_INFO_IMPORTANTE); } } } # les liens depuis un objet inexistant $table_source = table_objet_sql($objet_source); // filtrer selon $id, $objet, $id_objet eventuellement fournis // (en general '*' pour chaque) $where = lien_where("L.{$primary}", $id, $objet, $id_objet); $where[] = "O.{$primary} IS NULL"; $res = sql_select("L.{$primary} AS id", "{$table_lien} AS L LEFT JOIN {$table_source} AS O ON L.{$primary}=O.{$primary}", $where); $dels += optimiser_sansref($table_lien, $primary, $res); } } return $echec ? false : $dels; }
/** * Optimiser la base de données en supprimant les liens de brèves orphelins * * @pipeline optimiser_base_disparus * * @param array $flux Données du pipeline * @return array Données du pipeline */ function breves_optimiser_base_disparus($flux) { $n =& $flux['data']; $mydate = $flux['args']['date']; # les breves qui sont dans une id_rubrique inexistante $res = sql_select("B.id_breve AS id", "spip_breves AS B\n\t\t LEFT JOIN spip_rubriques AS R\n\t\t ON B.id_rubrique=R.id_rubrique", "R.id_rubrique IS NULL\n\t\t AND B.maj < " . sql_quote($mydate)); $n += optimiser_sansref('spip_breves', 'id_breve', $res); // // Breves // sql_delete("spip_breves", "statut='refuse' AND maj < {$mydate}"); return $flux; }