source: spip-zone/_plugins_/critere_mots/trunk/critere_mots_fonctions.php @ 114363

Last change on this file since 114363 was 114363, checked in by real3t@…, 19 months ago

[Critère {mots}] Compatibilité avec le plugin Mots arborescents (https://contrib.spip.net/4726) : on considère que les objets recherchés pour un mot clef ont le mot clef en question ou au moins un des mots clefs de la branche du mot.

PS : je me suis demandé si faire un pipeline n'aurait pas été aussi une méthode pour résoudre la question (pour rajouter au mots en cours les autres mots de la branche, mais ça m'a semblé plus simple dans la mesure où le besoin ne doit pas concerner d'autres usages).

File size: 6.3 KB
Line 
1<?php
2
3if (!defined('_ECRIRE_INC_VERSION')) {
4        return;
5}
6
7define ('_CRITERE_MOTS_OPTIMISE',1);// pour pouvoir revenir aux anciennes requetes si besoin
8
9// Critere {mots} : "l'article est lie a tous les mots demandes"
10// {mots?} ne s'applique que si au moins un mot est demande
11// on passe dans l'url &mots[]=titre1&mots[]=titre2
12// et/ou &mots[]=11 etc
13// parametre optionnel : {mots score} ou score est un nombre entre 0 et 1
14// qui indique le pourcentage de mots a valider
15// ex: {mots? 0.66} selectionne tous les articles qui ont au moins 2/3
16// ou encore {mots score} qui indique le nombre de mots communs (par exemple 2) si score >= 1
17// ex: {mots 2} indique qu'il doit y avoir 2 mots communs
18// ou encore {mots 66%} indique qu'on doit avoir 66% de mot en commun (identique à {mots 0.66}
19// de mots en commun avec ceux demandes par le contexte (ou l'URL)
20// par defaut score=100% (tous les mots demandes doivent figurer)
21function critere_mots_dist($idb, &$boucles, $crit,$id_ou_titre=false) {
22
23        $boucle = &$boucles[$idb];
24        $_table = table_objet($boucle->id_table);
25        $objet_delatable=objet_type($_table);
26        $id_objet = id_table_objet($boucle->id_table);
27        $tri = false;
28
29        // pouvoir utiliser plusieurs fois le critère dans une même boucle.
30        $hash = substr(uniqid(), -4);
31
32        if (isset($crit->param[0][2]) and ($crit->param[0][2]->texte == "tri" or $crit->param[0][2]->texte=="!tri")){
33                        $tri = true;
34        }
35       
36        if (isset($crit->param[0][0])) {
37                $score = calculer_liste(array($crit->param[0][0]), array(), $boucles, $boucles[$idb]->id_parent);
38        } else {
39                $score = "'100%'";
40        }
41
42        if (isset($crit->param[0][1])) {
43                $quoi = calculer_liste(array($crit->param[0][1]), array(), $boucles, $boucles[$idb]->id_parent);
44        } else {
45                $quoi = '@$Pile[0]["mots"]';
46        }
47        $boucle->hash .= '
48        // {MOTS}
49        $prepare_mots = charger_fonction(\'prepare_mots\', \'inc\');
50        $mots_where_' . $hash . ' = $prepare_mots('.$quoi.', "'.$boucle->id_table.'", "'.$crit->cond.'", '.$score.', "' . $boucle->sql_serveur . '","'.$id_ou_titre.'");
51        ';
52
53        $t = $boucle->id_table . '.' . $boucle->primary;
54        if (!in_array($t, $boucles[$idb]->select)) {
55                $boucle->select[]= $t; # pour postgres, neuneu ici
56        }
57
58        $boucle->where[] = "\n\t\t".'$mots_where_' . $hash;
59        if ($tri == true) {
60
61                $boucle->jointures[]="mots_liens" ;
62                $boucle->from['mots_liens'] = "spip_mots_liens";
63                $boucle->join["mots_liens"] = array(
64                    "'$boucle->id_table'",
65                    "'id_objet'",
66                    "'$id_objet'",
67                    "'mots_liens.objet='.sql_quote('$objet_delatable')");
68                $boucle->where[] = "\n\t\t".'sql_in(\'mots_liens.id_mot\',sql_quote('.$quoi.'))';
69                $boucle->group[] = "mots_liens.id_objet";
70                if ($crit->param[0][2]->texte == "tri") // si dans le sens ascendant
71                    $boucle->order[] = "'COUNT(mots_liens.id_objet) ASC'";
72                else
73                    $boucle->order[] = "'COUNT(mots_liens.id_objet) DESC'";
74               
75                // Pseudo critère "Si"
76                $boucle->hash .= "\n\tif (!isset(\$si_init)) { \$command['si'] = array(); \$si_init = true; }\n";
77                $boucle->hash .= "\t\$command['si'][] = (count($quoi) > '0');";
78        }
79
80
81}
82
83
84
85function critere_mots_selon_id_dist($idb, &$boucles, $crit){
86    critere_mots_dist($idb, $boucles, $crit,'id');
87}
88function critere_mots_selon_titre_dist($idb, &$boucles, $crit){
89    critere_mots_dist($idb, $boucles, $crit,'titre');
90}
91
92
93function inc_prepare_mots_dist($mots, $table='articles', $cond=false, $score, $serveur='',$id_ou_titre=false) {
94  $score = trim($score);
95        if (!is_array($mots)
96        OR !$mots = array_filter($mots)) {
97                // traiter le cas {mots?}
98                if ($cond)
99                        return '';
100                else
101                // {mots} mais pas de mot dans l'url
102                        return '0=1';
103        }
104
105
106  $_table = table_objet($table);
107  $objet_delatable=objet_type($_table);
108
109        $_id_table = id_table_objet($table);
110        $where = array();
111   
112  //selon le cas, on sélectionne sur les titres ou sur les id
113  if (!$id_ou_titre){
114      foreach($mots as $mot) {
115          if (preg_match(',^[1-9][0-9]*$,', $mot))
116              $id_mot = $mot;
117          else
118              $id_mot = sql_getfetsel('id_mot', 'spip_mots', 'titre='.sql_quote($mot));
119          if (function_exists('calcul_branche_mot_in')) {
120                          $where[] = sql_in('id_mot',calcul_branche_mot_in($id_mot)).' and objet='.sql_quote($objet_delatable);
121                  } else {
122                        $where[] = 'id_mot='.sql_quote($id_mot).' and objet='.sql_quote($objet_delatable);
123                  }               
124      }
125  }
126        elseif($id_ou_titre == 'id'){
127           foreach($mots as $id_mot) {
128          if (function_exists('calcul_branche_mot_in')) {
129                        $where[] = sql_in('id_mot',calcul_branche_mot_in($id_mot)).' and objet='.sql_quote($objet_delatable);
130                  } else {
131                        $where[] = 'id_mot='.sql_quote($id_mot).' and objet='.sql_quote($objet_delatable);
132                  }
133           }
134        }
135        elseif($id_ou_titre == 'titre'){
136           foreach($mots as $mot) {
137                $id_mot = sql_getfetsel('id_mot', 'spip_mots', 'titre='.sql_quote($mot));
138                    if (function_exists('calcul_branche_mot_in')) {
139                          $where[] = sql_in('id_mot',calcul_branche_mot_in($id_mot)).' and objet='.sql_quote($objet_delatable);
140                    } else {
141                          $where[] = 'id_mot='.sql_quote($id_mot).' and objet='.sql_quote($objet_delatable);
142                    }
143           }
144        }
145       
146        // on analyse la jointure spip_mots_$_table
147        // sans regarder spip_mots ni les groupes
148        // (=> faire attention si on utilise les mots techniques)
149   
150        // si on a un % dans le score, c'est que c'est un %age
151        if (substr($score,-1)=='%'){
152       
153           $score = str_replace('%','',$score);
154           $having = ' HAVING SUM(1) >= '.ceil($score/100 * count($where)) ;
155        }
156        elseif ((0 < $score) and ($score < 1)){
157           $having = ' HAVING SUM(1) >= '.ceil($score * count($where)) ;
158        }
159        else{
160           $having = ' HAVING SUM(1) >= '. $score;
161           }
162       
163        $in = array();
164        // Normalement on devrait faire un sous-select, mais mysql 5* a un bug (ttp://bugs.mysql.com/bug.php?id=32665)
165        // du coup on calcule d'abord le résultat de la sous-select, et on intègre cela inc_prepare_mots_dist
166  $s = sql_query("SELECT id_objet as i FROM spip_mots_liens WHERE "
167    . join(' OR ', $where)
168    . ' GROUP BY id_objet,objet'
169    . $having);
170  while($t = sql_fetch($s)){
171                        $in[] = $t['i'];
172        }
173        if ($in){
174          $wh = sql_in("$_table.$_id_table", $in);
175  }
176        else{
177                $wh = '22=0';//1=0 est automatiquement filtré par le compilateur
178        }
179        return $wh;
180}
181
182function critere_mots_enleve_mot_de_liste($listemots, $id_mot) {
183        if (!is_array($listemots) OR !$listemots)
184                return $listemots;
185        $listemots = array_unique($listemots);
186        $listemots = array_diff($listemots,array($id_mot));
187        return $listemots;
188}
Note: See TracBrowser for help on using the repository browser.