/** * Chargement du formulaire d'édition de liens * * #FORMULAIRE_EDITER_LIENS{auteurs,article,23} * pour associer des auteurs à l'article 23, sur la table pivot spip_auteurs_liens * #FORMULAIRE_EDITER_LIENS{article,23,auteurs} * pour associer des auteurs à l'article 23, sur la table pivot spip_articles_liens * #FORMULAIRE_EDITER_LIENS{articles,auteur,12} * pour associer des articles à l'auteur 12, sur la table pivot spip_articles_liens * #FORMULAIRE_EDITER_LIENS{auteur,12,articles} * pour associer des articles à l'auteur 12, sur la table pivot spip_auteurs_liens * * @param string $a * @param string|int $b * @param int|string $c * @param bool $editable * @return array */ function formulaires_editer_liens_charger_dist($a, $b, $c, $editable = true) { list($table_source, $objet, $id_objet, $objet_lien) = determine_source_lien_objet($a, $b, $c); if (!$table_source or !$objet or !$objet_lien or !$id_objet) { return false; } $objet_source = objet_type($table_source); $table_sql_source = table_objet_sql($objet_source); // verifier existence de la table xxx_liens include_spip('action/editer_liens'); if (!objet_associable($objet_lien)) { return false; } // L'éditabilité :) est définie par un test permanent (par exemple "associermots") ET le 4ème argument $editable = ($editable and autoriser('associer' . $table_source, $objet, $id_objet)); if (!$editable and !count(objet_trouver_liens(array($objet_lien => '*'), array($objet_lien == $objet_source ? $objet : $objet_source => '*')))) { return false; } $valeurs = array('id' => "{$table_source}-{$objet}-{$id_objet}-{$objet_lien}", '_vue_liee' => $table_source . "_lies", '_vue_ajout' => $table_source . "_associer", '_objet_lien' => $objet_lien, 'id_lien_ajoute' => _request('id_lien_ajoute'), 'objet' => $objet, 'id_objet' => $id_objet, 'objet_source' => $objet_source, 'table_source' => $table_source, 'recherche' => '', 'visible' => 0, 'ajouter_lien' => '', 'supprimer_lien' => '', '_oups' => _request('_oups'), 'editable' => $editable); return $valeurs; }
function inc_recherche_to_array_dist($recherche, $options = array()) { // options par defaut $options = array_merge(array('score' => true, 'champs' => false, 'toutvoir' => false, 'matches' => false, 'jointures' => false), $options); include_spip('inc/rechercher'); include_spip('inc/autoriser'); $requete = array("SELECT" => array(), "FROM" => array(), "WHERE" => array(), "GROUPBY" => array(), "ORDERBY" => array(), "LIMIT" => "", "HAVING" => array()); $table = sinon($options['table'], 'article'); if ($options['champs']) { $champs = $options['champs']; } else { $l = liste_des_champs(); $champs = $l['article']; } $serveur = $options['serveur']; list($methode, $q, $preg) = expression_recherche($recherche, $options); $jointures = $options['jointures'] ? liste_des_jointures() : array(); $_id_table = id_table_objet($table); // c'est un pis-aller : ca a peu de chance de marcher, mais mieux quand meme que en conservant la ',' // (aka ca marche au moins dans certains cas comme avec spip_formulaires_reponses_champs) if (strpos($_id_table, ",") !== false) { $_id_table = explode(',', $_id_table); $_id_table = reset($_id_table); } $requete['SELECT'][] = "t." . $_id_table; $a = array(); // Recherche fulltext foreach ($champs as $champ => $poids) { if (is_array($champ)) { spip_log("requetes imbriquees interdites"); } else { if (strpos($champ, ".") === FALSE) { $champ = "t.{$champ}"; } $requete['SELECT'][] = $champ; $a[] = $champ . ' ' . $methode . ' ' . $q; } } if ($a) { $requete['WHERE'][] = join(" OR ", $a); } $requete['FROM'][] = table_objet_sql($table) . ' AS t'; $results = array(); $s = sql_select($requete['SELECT'], $requete['FROM'], $requete['WHERE'], implode(" ", $requete['GROUPBY']), $requete['ORDERBY'], $requete['LIMIT'], $requete['HAVING'], $serveur); while ($t = sql_fetch($s, $serveur) and (!isset($t['score']) or $t['score'] > 0)) { $id = intval($t[$_id_table]); if ($options['toutvoir'] or autoriser('voir', $table, $id)) { // indiquer les champs concernes $champs_vus = array(); $score = 0; $matches = array(); $vu = false; foreach ($champs as $champ => $poids) { $champ = explode('.', $champ); $champ = end($champ); // translitteration_rapide uniquement si on est deja en utf-8 $value = $GLOBALS['meta']['charset'] == 'utf-8' ? translitteration_rapide($t[$champ]) : translitteration($t[$champ]); if ($n = $options['score'] || $options['matches'] ? preg_match_all($preg, $value, $regs, PREG_SET_ORDER) : preg_match($preg, $value)) { $vu = true; if ($options['champs']) { $champs_vus[$champ] = $t[$champ]; } if ($options['score']) { $score += $n * $poids; } if ($options['matches']) { $matches[$champ] = $regs; } if (!$options['champs'] and !$options['score'] and !$options['matches']) { break; } } } if ($vu) { if (!isset($results)) { $results = array(); } $results[$id] = array(); if ($champs_vus) { $results[$id]['champs'] = $champs_vus; } if ($score) { $results[$id]['score'] = $score; } if ($matches) { $results[$id]['matches'] = $matches; } } } } // Gerer les donnees associees // ici on est un peu naze : pas capables de reconstruire une jointure complexe // on ne sait passer que par table de laison en 1 coup if (isset($jointures[$table]) and $joints = recherche_en_base($recherche, $jointures[$table], array_merge($options, array('jointures' => false)))) { include_spip('action/editer_liens'); $trouver_table = charger_fonction('trouver_table', 'base'); $cle_depart = id_table_objet($table); $table_depart = table_objet($table, $serveur); $desc_depart = $trouver_table($table_depart, $serveur); $depart_associable = objet_associable($table); foreach ($joints as $table_liee => $ids_trouves) { // on peut definir une fonction de recherche jointe pour regler les cas particuliers if (!($rechercher_joints = charger_fonction("rechercher_joints_{$table}_{$table_liee}", "inc", true) or $rechercher_joints = charger_fonction("rechercher_joints_objet_{$table_liee}", "inc", true) or $rechercher_joints = charger_fonction("rechercher_joints_{$table}_objet_lie", "inc", true))) { $cle_arrivee = id_table_objet($table_liee); $table_arrivee = table_objet($table_liee, $serveur); $desc_arrivee = $trouver_table($table_arrivee, $serveur); // cas simple : $cle_depart dans la table_liee if (isset($desc_arrivee['field'][$cle_depart])) { $s = sql_select("{$cle_depart}, {$cle_arrivee}", $desc_arrivee['table_sql'], sql_in($cle_arrivee, array_keys($ids_trouves)), '', '', '', '', $serveur); } elseif (isset($desc_depart['field'][$cle_arrivee])) { $s = sql_select("{$cle_depart}, {$cle_arrivee}", $desc_depart['table_sql'], sql_in($cle_arrivee, array_keys($ids_trouves)), '', '', '', '', $serveur); } elseif ($l = objet_associable($table_liee)) { list($primary, $table_liens) = $l; $s = sql_select("id_objet as {$cle_depart}, {$primary} as {$cle_arrivee}", $table_liens, array("objet='{$table}'", sql_in($primary, array_keys($ids_trouves))), '', '', '', '', $serveur); } elseif ($l = $depart_associable) { list($primary, $table_liens) = $l; $s = sql_select("{$primary} as {$cle_depart}, id_objet as {$cle_arrivee}", $table_liens, array("objet='{$table_liee}'", sql_in('id_objet', array_keys($ids_trouves))), '', '', '', '', $serveur); } elseif ($t = $trouver_table($table_arrivee . "_" . $table_depart, $serveur) or $t = $trouver_table($table_depart . "_" . $table_arrivee, $serveur)) { $s = sql_select("{$cle_depart},{$cle_arrivee}", $t["table_sql"], sql_in($cle_arrivee, array_keys($ids_trouves)), '', '', '', '', $serveur); } } else { list($cle_depart, $cle_arrivee, $s) = $rechercher_joints($table, $table_liee, array_keys($ids_trouves), $serveur); } while ($t = is_array($s) ? array_shift($s) : sql_fetch($s)) { $id = $t[$cle_depart]; $joint = $ids_trouves[$t[$cle_arrivee]]; if (!isset($results)) { $results = array(); } if (!isset($results[$id])) { $results[$id] = array(); } if (isset($joint['score']) and $joint['score']) { if (!isset($results[$id]['score'])) { $results[$id]['score'] = 0; } $results[$id]['score'] += $joint['score']; } if (isset($joint['champs']) and $joint['champs']) { foreach ($joint['champs'] as $c => $val) { $results[$id]['champs'][$table_liee . '.' . $c] = $val; } } if (isset($joint['matches']) and $joint['matches']) { foreach ($joint['matches'] as $c => $val) { $results[$id]['matches'][$table_liee . '.' . $c] = $val; } } } } } return $results; }
/** * Lorsqu'un champ versionée est une jointure, récuperer tous les liens * et les mettre sous forme de liste énumérée * * @param string $objet * @param string $id_objet * @param string $jointure * @return string */ function recuperer_valeur_champ_jointure($objet, $id_objet, $jointure) { $objet_joint = objet_type($jointure); include_spip('action/editer_liens'); $v = array(); if (objet_associable($objet_joint)) { $liens = objet_trouver_liens(array($objet_joint => '*'), array($objet => $id_objet)); foreach ($liens as $l) { $v[] = $l[$objet_joint]; } } elseif (objet_associable($objet)) { $liens = objet_trouver_liens(array($objet => $id_objet), array($objet_joint => '*')); foreach ($liens as $l) { $v[] = $l[$objet]; } } sort($v); return implode(",", $v); }
/** * 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; }
/** * Lister des rôles connus en base pour une liaion, pour un objet source * * On retourne cette liste dans le datalist de saisie libre role. * * @param string $objet_source Objet dont on veut récupérer la liste des identifiants * @param string $objet Objet sur lequel est liée la source * @param string $objet_lien Objet dont on utilise la table de liaison (c'est forcément soit $objet_source, soit $objet) * @return array|bool * - Tableau de roles : tableau de description des roles, * - false si pas de role déclarés */ function roles_connus_en_base($objet_source, $objet, $objet_lien) { static $done = array(); // stocker le résultat $hash = "{$objet_source}-{$objet}-{$objet_lien}"; if (isset($done[$hash])) { return $done[$hash]; } if (!($lien = objet_associable($objet_lien))) { return $done[$hash] = false; } // pas de roles sur ces objets, on sort $roles = roles_presents($objet_lien, $objet_lien == $objet ? $objet_source : $objet); if (!$roles) { return $done[$hash] = false; } list($primary, $l) = $lien; $colone_role = $roles['colonne']; $all = sql_allfetsel("DISTINCT {$colone_role}", $l, "objet=" . sql_quote($objet_source == $objet_lien ? $objet : $objet_source)); $done[$hash] = array_map("reset", $all); return $done[$hash]; }
/** * Chargement du formulaire d'édition de liens * * #FORMULAIRE_EDITER_LIENS{auteurs,article,23} * pour associer des auteurs à l'article 23, sur la table pivot spip_auteurs_liens * #FORMULAIRE_EDITER_LIENS{article,23,auteurs} * pour associer des auteurs à l'article 23, sur la table pivot spip_articles_liens * #FORMULAIRE_EDITER_LIENS{articles,auteur,12} * pour associer des articles à l'auteur 12, sur la table pivot spip_articles_liens * #FORMULAIRE_EDITER_LIENS{auteur,12,articles} * pour associer des articles à l'auteur 12, sur la table pivot spip_auteurs_liens * * @param string $a * @param string|int $b * @param int|string $c * @param array|bool $options * - Si array, tableau d'options * - Si bool : valeur de l'option 'editable' uniquement * * @return array */ function formulaires_editer_liens_charger_dist($a, $b, $c, $options = array()) { // compat avec ancienne signature ou le 4eme argument est $editable if (!is_array($options)) { $options = array('editable' => $options); } elseif (!isset($options['editable'])) { $options['editable'] = true; } $editable = $options['editable']; list($table_source, $objet, $id_objet, $objet_lien) = determine_source_lien_objet($a, $b, $c); if (!$table_source or !$objet or !$objet_lien or !$id_objet) { return false; } $objet_source = objet_type($table_source); $table_sql_source = table_objet_sql($objet_source); // verifier existence de la table xxx_liens include_spip('action/editer_liens'); if (!objet_associable($objet_lien)) { return false; } // L'éditabilité :) est définie par un test permanent (par exemple "associermots") ET le 4ème argument include_spip('inc/autoriser'); $editable = ($editable and autoriser('associer' . $table_source, $objet, $id_objet) and autoriser('modifier', $objet, $id_objet)); if (!$editable and !count(objet_trouver_liens(array($objet_lien => '*'), array($objet_lien == $objet_source ? $objet : $objet_source => '*')))) { return false; } // squelettes de vue et de d'association // ils sont différents si des rôles sont définis. $skel_vue = $table_source . "_lies"; $skel_ajout = $table_source . "_associer"; // description des roles include_spip('inc/roles'); if ($roles = roles_presents($objet_source, $objet)) { // on demande de nouveaux squelettes en conséquence $skel_vue = $table_source . "_roles_lies"; $skel_ajout = $table_source . "_roles_associer"; } $valeurs = array('id' => "{$table_source}-{$objet}-{$id_objet}-{$objet_lien}", '_vue_liee' => $skel_vue, '_vue_ajout' => $skel_ajout, '_objet_lien' => $objet_lien, 'id_lien_ajoute' => _request('id_lien_ajoute'), 'objet' => $objet, 'id_objet' => $id_objet, 'objet_source' => $objet_source, 'table_source' => $table_source, 'recherche' => '', 'visible' => 0, 'ajouter_lien' => '', 'supprimer_lien' => '', 'qualifier_lien' => '', '_roles' => $roles, '_oups' => _request('_oups'), 'editable' => $editable); // les options non definies dans $valeurs sont passees telles quelles au formulaire html $valeurs = array_merge($options, $valeurs); return $valeurs; }
/** * Fonction générique qui * applique une operation de liaison entre un ou des objets et des objets listés * * $objets_source et $objets_lies sont de la forme * array($objet=>$id_objets,...) * $id_objets peut lui meme etre un scalaire ou un tableau pour une liste d'objets du meme type * * Les objets sources sont les pivots qui portent les liens * et pour lesquels une table spip_xxx_liens existe * (auteurs, documents, mots) * * on peut passer optionnellement une qualification du (des) lien(s) qui sera * alors appliquee dans la foulee. * En cas de lot de liens, c'est la meme qualification qui est appliquee a tous * * @internal * @param string $operation * Nom de la fonction PHP qui traitera l'opération * @param array $objets_source * Liste de ou des objets source * De la forme array($objet=>$id_objets,...), où $id_objets peut lui * même être un scalaire ou un tableau pour une liste d'objets du même type * @param array $objets_lies * Liste de ou des objets liés * De la forme array($objet=>$id_objets,...), où $id_objets peut lui * même être un scalaire ou un tableau pour une liste d'objets du même type * @param null|array $set * Liste de coupels champs valeur, soit array(champs => valeur) * En fonction des opérations il peut servir à différentes utilisations * @return bool|int|array */ function objet_traiter_liaisons($operation, $objets_source, $objets_lies, $set = null) { // accepter une syntaxe minimale pour supprimer tous les liens if ($objets_lies == '*') { $objets_lies = array('*' => '*'); } $modifs = 0; // compter le nombre de modifications $echec = null; foreach ($objets_source as $objet => $ids) { if ($a = objet_associable($objet)) { list($primary, $l) = $a; if (!is_array($ids)) { $ids = array($ids); } elseif (reset($ids) == "NOT") { // si on demande un array('NOT',...) => recuperer la liste d'ids correspondants $where = lien_where($primary, $ids, '*', '*'); $ids = sql_allfetsel($primary, $l, $where); $ids = array_map('reset', $ids); } foreach ($ids as $id) { $res = $operation($objet, $primary, $l, $id, $objets_lies, $set); if ($res === false) { spip_log("objet_traiter_liaisons [Echec] : {$operation} sur {$objet}/{$primary}/{$l}/{$id}", _LOG_ERREUR); $echec = true; } else { $modifs = $modifs ? is_array($res) ? array_merge($modifs, $res) : $modifs + $res : $res; } } } else { $echec = true; } } return $echec ? false : $modifs; // pas d'erreur }