function trouver_champ_exterieur($cle, $joints, &$boucle, $checkarrivee = false) { static $trouver_table; if (!$trouver_table) $trouver_table = charger_fonction('trouver_table', 'base'); // support de la recherche multi champ if (!is_array($cle)) $cle = array($cle); foreach($joints as $k => $join) { if ($join && $table = $trouver_table($join, $boucle->sql_serveur)) { if (isset($table['field']) // verifier que toutes les cles cherchees sont la AND (count(array_intersect($cle, array_keys($table['field'])))==count($cle)) // si on sait ou on veut arriver, il faut que ca colle AND ($checkarrivee==false || $checkarrivee==$table['table'])) return array($table['table'], $table); } } // une cle id_xx peut etre implementee par un couple (id_objet,objet) foreach($cle as $k=>$c) { if (is_array($decompose = decompose_champ_id_objet($c))){ unset($cle[$k]); $cle[] = array_shift($decompose); // id_objet $cle[] = array_shift($decompose); // objet return trouver_champ_exterieur($cle,$joints,$boucle,$checkarrivee); } } return ""; }
function calculer_critere_infixe_externe(&$boucle, $crit, $op, $desc, $col, $col_alias, $table) { global $exceptions_des_jointures; $where = ''; $calculer_critere_externe = 'calculer_critere_externe_init'; // gestion par les plugins des jointures tordues // pas automatiques mais necessaires if (is_array($exceptions_des_jointures[$table])) { $t = $exceptions_des_jointures[$table]; $index = isset($t[$col]) ? $t[$col] : (isset($t['']) ? $t[''] : array()); if (count($index)==3) list($t, $col, $calculer_critere_externe) = $index; elseif (count($index)==2) list($t, $col) = $t[$col]; elseif (count($index)==1){ list($calculer_critere_externe) = $index; $t = $table; } else $t=''; // jointure non declaree. La trouver. } elseif (isset($exceptions_des_jointures[$col])) list($t, $col) = $exceptions_des_jointures[$col]; else $t =''; // jointure non declaree. La trouver. $table = $calculer_critere_externe($boucle, $boucle->jointures, $col, $desc, ($crit->cond OR $op !='='), $t); if (!$table) return ''; list($nom, $desc) = trouver_champ_exterieur($col, $boucle->jointures, $boucle); if (count(trouver_champs_decomposes($col,$desc))>1){ $col_alias = $col; // id_article devient juste le nom d'origine $e = decompose_champ_id_objet($col); $col = array_shift($e); $where = primary_doublee($e, $table); } return array($col, $col_alias, $table, $where); }
/** * Décrit un critère non déclaré explicitement, sur un champ externe à la table * * Décrit un critère non déclaré comme {id_article} {id_article>3} qui correspond * à un champ non présent dans la table, et donc à retrouver par jointure si possible. * * @param Boucle $boucle Description de la boucle * @param Critere $crit Paramètres du critère dans cette boucle * @param string $op L'opérateur utilisé, tel que '=' * @param array $desc Description de la table * @param string $col Nom de la colonne à trouver (la véritable) * @param string $col_alias Alias de la colonne éventuel utilisé dans le critère ex: id_enfant * @param string $table Nom de la table SQL de la boucle * @return array|string * Liste si jointure possible : * - string $col * - string $col_alias * - string $table * - array $where * - array $desc * * Chaîne vide si on ne trouve pas le champ par jointure... **/ function calculer_critere_infixe_externe($boucle, $crit, $op, $desc, $col, $col_alias, $table) { global $exceptions_des_jointures; $where = ''; $calculer_critere_externe = 'calculer_critere_externe_init'; // gestion par les plugins des jointures tordues // pas automatiques mais necessaires $table_sql = table_objet_sql($table); if (isset($exceptions_des_jointures[$table_sql]) and is_array($exceptions_des_jointures[$table_sql]) and (isset($exceptions_des_jointures[$table_sql][$col]) or isset($exceptions_des_jointures[$table_sql]['']))) { $t = $exceptions_des_jointures[$table_sql]; $index = isset($t[$col]) ? $t[$col] : (isset($t['']) ? $t[''] : array()); if (count($index) == 3) { list($t, $col, $calculer_critere_externe) = $index; } elseif (count($index) == 2) { list($t, $col) = $t[$col]; } elseif (count($index) == 1) { list($calculer_critere_externe) = $index; $t = $table; } else { $t = ''; } // jointure non declaree. La trouver. } elseif (isset($exceptions_des_jointures[$col])) { list($t, $col) = $exceptions_des_jointures[$col]; } else { $t = ''; } // jointure non declaree. La trouver. // ici on construit le from pour fournir $col en piochant dans les jointures // si des jointures explicites sont fournies, on cherche d'abord dans celles ci // permet de forcer une table de lien quand il y a ambiguite // <BOUCLE_(DOCUMENTS documents_liens){id_mot}> // alors que <BOUCLE_(DOCUMENTS){id_mot}> produit la meme chose que <BOUCLE_(DOCUMENTS mots_liens){id_mot}> $table = ""; if ($boucle->jointures_explicites) { $jointures_explicites = explode(' ', $boucle->jointures_explicites); $table = $calculer_critere_externe($boucle, $jointures_explicites, $col, $desc, $crit->cond or $op != '=', $t); } // et sinon on cherche parmi toutes les jointures declarees if (!$table) { $table = $calculer_critere_externe($boucle, $boucle->jointures, $col, $desc, $crit->cond or $op != '=', $t); } if (!$table) { return ''; } // il ne reste plus qu'a trouver le champ dans les from list($nom, $desc, $cle) = trouver_champ_exterieur($col, $boucle->from, $boucle); if (count($cle) > 1 or reset($cle) !== $col) { $col_alias = $col; // id_article devient juste le nom d'origine if (count($cle) > 1 and reset($cle) == 'id_objet') { $e = decompose_champ_id_objet($col); $col = array_shift($e); $where = primary_doublee($e, $table); } else { $col = reset($cle); } } return array($col, $col_alias, $table, $where, $desc); }
/** * Cherche une colonne (ou plusieurs colonnes) dans les tables de jointures * possibles indiquées. * * @param string|array $cle * Nom de la ou des colonnes à trouver dans les tables de jointures * @param array $joints * Liste des jointures possibles (ex: $boucle->jointures ou $boucle->jointures_explicites) * @param Boucle $boucle * Description de la boucle * @param bool|string $checkarrivee * false : peu importe la table, si on trouve le/les champs, c'est bon. * string : nom de la table jointe où on veut trouver le champ. * @return array|string * chaîne vide : on n'a pas trouvé * liste si trouvé : nom de la table, description de la table */ function trouver_champ_exterieur($cle, $joints, &$boucle, $checkarrivee = false) { static $trouver_table = ''; if (!$trouver_table) { $trouver_table = charger_fonction('trouver_table', 'base'); } // support de la recherche multi champ : // si en seconde etape on a decompose le champ id_xx en id_objet,objet // on reentre ici soit en cherchant une table les 2 champs id_objet,objet // soit une table avec les 3 champs id_xx, id_objet, objet if (!is_array($cle)) { $cle = array($cle); } foreach ($joints as $k => $join) { if ($join && ($table = $trouver_table($join, $boucle->sql_serveur))) { if (isset($table['field']) and count(array_intersect($cle, array_keys($table['field']))) == count($cle) and $checkarrivee == false || $checkarrivee == $table['table']) { return array($table['table'], $table); } } } // au premier coup, on essaye de decomposer, si possible if (count($cle) == 1 and $c = reset($cle) and is_array($decompose = decompose_champ_id_objet($c))) { $desc = $boucle->show; // cas 1 : la cle id_xx est dans la table de depart // -> on cherche uniquement id_objet,objet a l'arrivee if (isset($desc['field'][$c])) { $cle = array(); $cle[] = array_shift($decompose); // id_objet $cle[] = array_shift($decompose); // objet return trouver_champ_exterieur($cle, $joints, $boucle, $checkarrivee); } else { $depart = liste_champs_jointures($desc['table'], $desc); foreach ($depart as $d) { $cle = array(); $cle[] = array_shift($decompose); // id_objet $cle[] = array_shift($decompose); // objet $cle[] = $d; if ($ext = trouver_champ_exterieur($cle, $joints, $boucle, $checkarrivee)) { return $ext; } } } } return ""; }