Project

General

Profile

Souhaits #907 » Members.php.diff

Alain Castera, 03/12/2019 05:12 PM

View differences:

Members.php 2019-03-12 16:39:00.000000000 +0100
41 41
use Galette\Entity\DynamicFieldsHandle;
42 42

  
43 43
use Analog\Analog;
44
use Zend\Db\Adapter\Adapter; //modification for multiple groups search
44 45
use Zend\Db\Sql\Expression;
45 46
use Zend\Db\Sql\Predicate\PredicateSet;
46 47
use Zend\Db\Sql\Predicate\Operator;
......
1131 1132
            }
1132 1133

  
1133 1134
            if ($this->filters instanceof AdvancedMembersList) {
1135
/** modification for multiple groups search
1136
Recherche d'un membre appartenant à un groupe parmi une liste (OR) ou à tous les groupes d'une liste (AND)
1137

  
1138
L'idée de base est de faire la liste des adhérents des groupes de la liste, que l'on pourra ensuite injecter dans la requête pour la pris en compte des autres paramètres. 
1139
À cette fin, on crée une table (temporaire pour ne pas impacter la base pour d'autres instances de 
1140
galette) que l'on remplit avec les id_adh de galettes.groups.members pour chaque groupe inclus dans la liste, 
1141
l'un après l'autre.
1142
Si on fait un "OR", ça suffit, on a récupéré les adhérent; Si on fait un "AND", on va imposer que l'adhérent soit présent dans la liste autant de fois qu'il y a de groupes recherchés (count de sql); 
1143
Jusque là, c'est simple. Mais quand un adhérent est dans un groupe recherché ET un de ses sous-groupes, ou dans
1144
 2 sous-groupes du groupe recherché, il apparait 2 fois pour le même groupe recherché et ça fausse le compte.
1145
Pour contourner l'obstacle, on sépare la recherche pour chaqe groupe en limitant les résultats à 1.
1146
On pourrait sans doute faire ça en une seule requête, mais c'est plus lisible en séparant les étapes.
1147
Surtout que mysql ne supporte pas "WITH" !!!
1148
Et comme je ne connais pas bien l'interface Zend, je fais sûrement trop de choses à la main
1149
Je n'ai pas compris le cas "gs.parent_group=NULL" utilisé danns la recherche simple, donc je l'ai enlevé.
1150
NOTA : on a la même limitation à un seul niveau d'imbrication que dans la recherche simple. Il faudrait dans les deux cas introduire une forme de récursivité pour descendre la chaîne des gs.parent_group, mais ce sera pour une autre fois ... ou pas :-)
1151
*/
1152
              if ( count($this->filters->groups_search) > 0
1153
                    && !isset($this->filters->groups_search['empty'])
1154
                ) {
1155
           $tmpres= $zdb->db->query ('CREATE TEMPORARY TABLE '.PREFIX_DB.'groupsearch (id_adh INT);',Adapter::QUERY_MODE_EXECUTE); // first, build a temporary table which count how many selected groups an adh is member
1156
           unset($tmpres);
1157
           $grpAnded=0;
1158
           foreach ( $this->filters->groups_search as $gs ) { // then add a row for each ig/searched group pair
1159
           $tmpres = $zdb->db->query ('INSERT INTO '.PREFIX_DB.'groupsearch SELECT ggm.id_adh'
1160
                     . ' FROM '. PREFIX_DB . Group::GROUPSUSERS_TABLE . ' AS ggm '
1161
                     . ' LEFT JOIN '. PREFIX_DB . Group::TABLE .' AS gg ON ggm.id_group=gg.id_group'
1162
                     . ' WHERE gg.id_group = '. $gs['group'] .' OR gg.parent_group = '.$gs['group'] . ' group by ggm.id_adh;'
1163
                   ,Adapter::QUERY_MODE_EXECUTE);
1164
           unset($tmpres);
1165
           $grpAnded++;
1166
           }
1167
           // now extract adherent Ids from this temporary table
1168
           $tmpselect = $zdb->select('groupsearch');
1169
           $tmpselect->columns(array('id_adh'));
1170
           $tmpselect->group('id_adh');
1171
           // if "ORing" groups, we are done. If "ANDing", we have to select only those with max count.*/
1172
           if ($this->filters->groups_search_log_op == AdvancedMembersList::OP_AND) {
1173
             $tmpselect->having('COUNT(id_adh)='.$grpAnded);
1174
           }
1175
           $grpcount=$zdb->execute($tmpselect)->toArray(); // get list of adherent ids
1176
// error -> exception changes in Zenddb ?
1177
           // now we got appropriate id_adhs, inject these in select
1178
           $in = 'a.'.Adherent::PK. ' IN ('; $firstAdh=True;
1179
           foreach($grpcount as $ad_id) {
1180
             if (!$firstAdh) {$in.=',';}
1181
             $in.= $ad_id['id_adh'];$firstAdh=False;
1182
           }
1183
           $in.=')';
1184
           $select->where($in);
1185
        }
1186
/** end modification for multiple groups search */
1187

  
1134 1188
                if ($this->filters->rbirth_date_begin
1135 1189
                    || $this->filters->rbirth_date_end
1136 1190
                ) {
(7-7/11)