]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Filters/AdvancedMembersList.php
2fc1b0740700f72e43d144672503f59a11fabf2b
[galette.git] / galette / lib / Galette / Filters / AdvancedMembersList.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Members list advanced filters
7 *
8 * PHP version 5
9 *
10 * Copyright © 2012-2014 The Galette Team
11 *
12 * This file is part of Galette (http://galette.tuxfamily.org).
13 *
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
26 *
27 * @category Filters
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2012-2014 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @version SVN: $Id$
34 * @link http://galette.tuxfamily.org
35 * @since 0.73dev 2012-10-16
36 */
37
38 namespace Galette\Filters;
39
40 use Analog\Analog;
41 use Galette\Entity\Status;
42 use Galette\Entity\ContributionsTypes;
43 use Galette\Entity\Contribution;
44 use Galette\Repository\Members;
45 use Galette\DynamicFields\DynamicField;
46 use Galette\Repository\PaymentTypes;
47
48 /**
49 * Members list filters and paginator
50 *
51 * @name AdvancedMembersList
52 * @category Filters
53 * @package Galette
54 *
55 * @author Johan Cwiklinski <johan@x-tnd.be>
56 * @copyright 2012-2014 The Galette Team
57 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
58 * @link http://galette.tuxfamily.org
59 */
60
61 class AdvancedMembersList extends MembersList
62 {
63
64 const OP_AND = 0;
65 const OP_OR = 1;
66
67 const OP_EQUALS = 0;
68 const OP_CONTAINS = 1;
69 const OP_NOT_EQUALS = 2;
70 const OP_NOT_CONTAINS = 3;
71 const OP_STARTS_WITH = 4;
72 const OP_ENDS_WITH = 5;
73 const OP_BEFORE = 6;
74 const OP_AFTER = 7;
75
76 private $_creation_date_begin;
77 private $_creation_date_end;
78 private $_modif_date_begin;
79 private $_modif_date_end;
80 private $_due_date_begin;
81 private $_due_date_end;
82 private $_birth_date_begin;
83 private $_birth_date_end;
84 private $_show_public_infos = Members::FILTER_DC_PUBINFOS;
85 private $_status = array();
86 private $_contrib_creation_date_begin;
87 private $_contrib_creation_date_end;
88 private $_contrib_begin_date_begin;
89 private $_contrib_begin_date_end;
90 private $_contrib_end_date_begin;
91 private $_contrib_end_date_end;
92 private $_contributions_types;
93 private $_payments_types;
94 private $_contrib_min_amount;
95 private $_contrib_max_amount;
96
97 protected $advancedmemberslist_fields = array(
98 'creation_date_begin',
99 'creation_date_end',
100 'modif_date_begin',
101 'modif_date_end',
102 'due_date_begin',
103 'due_date_end',
104 'birth_date_begin',
105 'birth_date_end',
106 'show_public_infos',
107 'status',
108 'contrib_creation_date_begin',
109 'contrib_creation_date_end',
110 'contrib_begin_date_begin',
111 'contrib_begin_date_end',
112 'contrib_end_date_begin',
113 'contrib_end_date_end',
114 'contributions_types',
115 'payments_types',
116 'contrib_min_amount',
117 'contrib_max_amount',
118 'contrib_dynamic',
119 'free_search'
120 );
121
122 protected $virtuals_advancedmemberslist_fields = array(
123 'rcreation_date_begin',
124 'rcreation_date_end',
125 'rmodif_date_begin',
126 'rmodif_date_end',
127 'rdue_date_begin',
128 'rdue_date_end',
129 'rbirth_date_begin',
130 'rbirth_date_end',
131 'rcontrib_creation_date_begin',
132 'rcontrib_creation_date_end',
133 'rcontrib_begin_date_begin',
134 'rcontrib_begin_date_end',
135 'rcontrib_end_date_begin',
136 'rcontrib_end_date_end',
137 'search_fields'
138 );
139
140 //an empty free search criteria to begin
141 private $_free_search = array(
142 'empty' => array(
143 'field' => '',
144 'search' => '',
145 'log_op' => self::OP_AND,
146 'qry_op' => self::OP_EQUALS
147 )
148 );
149
150 //an empty contributions dynamic field criteria to begin
151 private $_contrib_dynamic = array(
152 'empty' => array(
153 'field' => '',
154 'search' => '',
155 'log_op' => self::OP_AND,
156 'qry_op' => self::OP_EQUALS
157 )
158 );
159
160 /**
161 * Default constructor
162 *
163 * @param MembersList $simple A simple filter search to keep
164 */
165 public function __construct($simple = null)
166 {
167 parent::__construct();
168 if ($simple instanceof MembersList) {
169 foreach ($this->pagination_fields as $pf) {
170 $this->$pf = $simple->$pf;
171 }
172 foreach ($this->memberslist_fields as $mlf) {
173 $this->$mlf = $simple->$mlf;
174 }
175 }
176 }
177
178 /**
179 * Do we want to filter within contributions?
180 *
181 * @return boolean
182 */
183 public function withinContributions()
184 {
185 if ($this->_contrib_creation_date_begin != null
186 || $this->_contrib_creation_date_end != null
187 || $this->_contrib_begin_date_begin != null
188 || $this->_contrib_begin_date_end != null
189 || $this->_contrib_end_date_begin != null
190 || $this->_contrib_begin_date_end != null
191 || $this->_contrib_min_amount != null
192 || $this->_contrib_max_amount != null
193 || count($this->_contrib_dynamic) > 0
194 || count($this->_contributions_types) > 0
195 || count($this->_payments_types) > 0
196 ) {
197 return true;
198 } else {
199 return false;
200 }
201 }
202
203 /**
204 * Reinit default parameters
205 *
206 * @return void
207 */
208 public function reinit()
209 {
210 parent::reinit();
211
212 $this->_creation_date_begin = null;
213 $this->_creation_date_end = null;
214 $this->_modif_date_begin = null;
215 $this->_modif_date_end = null;
216 $this->_due_date_begin = null;
217 $this->_due_date_end = null;
218 $this->_birth_date_begin = null;
219 $this->_birth_date_end = null;
220 $this->_show_public_infos = Members::FILTER_DC_PUBINFOS;
221 $this->_status = array();
222
223 $this->_contrib_creation_date_begin = null;
224 $this->_contrib_creation_date_end = null;
225 $this->_contrib_begin_date_begin = null;
226 $this->_contrib_begin_date_end = null;
227 $this->_contrib_end_date_begin = null;
228 $this->_contrib_begin_date_end = null;
229 $this->_contributions_types = array();
230 $this->_payments_types = array();
231
232 $this->_free_search = array(
233 'empty' => array(
234 'field' => '',
235 'search' => '',
236 'log_op' => self::OP_AND,
237 'qry_op' => self::OP_EQUALS
238 )
239 );
240
241 $this->_contrib_dynamic = array(
242 'empty' => array(
243 'field' => '',
244 'search' => '',
245 'log_op' => self::OP_AND,
246 'qry_op' => self::OP_EQUALS
247 )
248 );
249 }
250
251 /**
252 * Global getter method
253 *
254 * @param string $name name of the property we want to retrive
255 *
256 * @return object the called property
257 */
258 public function __get($name)
259 {
260
261 Analog::log(
262 '[AdvancedMembersList] Getting property `' . $name . '`',
263 Analog::DEBUG
264 );
265
266 if (in_array($name, $this->pagination_fields)
267 || in_array($name, $this->memberslist_fields)
268 ) {
269 return parent::__get($name);
270 } else {
271 if (in_array($name, $this->advancedmemberslist_fields)
272 || in_array($name, $this->virtuals_advancedmemberslist_fields)
273 ) {
274 $rname = '_' . $name;
275 switch ($name) {
276 case 'creation_date_begin':
277 case 'creation_date_end':
278 case 'modif_date_begin':
279 case 'modif_date_end':
280 case 'due_date_begin':
281 case 'due_date_end':
282 case 'birth_date_begin':
283 case 'birth_date_end':
284 case 'contrib_creation_date_begin':
285 case 'contrib_creation_date_end':
286 case 'contrib_begin_date_begin':
287 case 'contrib_begin_date_end':
288 case 'contrib_end_date_begin':
289 case 'contrib_end_date_end':
290 try {
291 if ($this->$rname !== null) {
292 $d = new \DateTime($this->$rname);
293 return $d->format(__("Y-m-d"));
294 }
295 } catch (\Exception $e) {
296 //oops, we've got a bad date :/
297 Analog::log(
298 'Bad date (' . $this->$rname . ') | ' .
299 $e->getMessage(),
300 Analog::INFO
301 );
302 return $this->$rname;
303 }
304 break;
305 case 'rcreation_date_begin':
306 case 'rcreation_date_end':
307 case 'rmodif_date_begin':
308 case 'rmodif_date_end':
309 case 'rdue_date_begin':
310 case 'rdue_date_end':
311 case 'rbirth_date_begin':
312 case 'rbirth_date_end':
313 case 'rcontrib_creation_date_begin':
314 case 'rcontrib_creation_date_end':
315 case 'rcontrib_begin_date_begin':
316 case 'rcontrib_begin_date_end':
317 case 'rcontrib_end_date_begin':
318 case 'rcontrib_end_date_end':
319 //same as above, but raw format
320 $rname = '_' . substr($name, 1);
321 return $this->$rname;
322 case 'search_fields':
323 $search_fields = array_merge($this->memberslist_fields, $this->advancedmemberslist_fields);
324 $key = array_search('selected', $search_fields);
325 unset($search_fields[$key]);
326 $key = array_search('unreachable', $search_fields);
327 unset($search_fields[$key]);
328 $key = array_search('query', $search_fields);
329 unset($search_fields[$key]);
330 return $search_fields;
331 }
332 return $this->$rname;
333 } else {
334 Analog::log(
335 '[AdvancedMembersList] Unable to get proprety `' .$name . '`',
336 Analog::WARNING
337 );
338 }
339 }
340 }
341
342 /**
343 * Global setter method
344 *
345 * @param string $name name of the property we want to assign a value to
346 * @param object $value a relevant value for the property
347 *
348 * @return void
349 */
350 public function __set($name, $value)
351 {
352 global $zdb, $preferences, $login;
353
354 if (in_array($name, $this->pagination_fields)
355 || in_array($name, $this->memberslist_fields)
356 ) {
357 parent::__set($name, $value);
358 } else {
359 Analog::log(
360 '[AdvancedMembersList] Setting property `' . $name . '`',
361 Analog::DEBUG
362 );
363
364 $prop = '_' . $name;
365
366 switch ($name) {
367 case 'creation_date_begin':
368 case 'creation_date_end':
369 case 'modif_date_begin':
370 case 'modif_date_end':
371 case 'due_date_begin':
372 case 'due_date_end':
373 case 'birth_date_begin':
374 case 'birth_date_end':
375 case 'contrib_creation_date_begin':
376 case 'contrib_creation_date_end':
377 case 'contrib_begin_date_begin':
378 case 'contrib_begin_date_end':
379 case 'contrib_end_date_begin':
380 case 'contrib_end_date_end':
381 if ($value !== null && trim($value) !== '') {
382 try {
383 $d = \DateTime::createFromFormat(__("Y-m-d"), $value);
384 if ($d === false) {
385 throw new \Exception('Incorrect format');
386 }
387 $this->$prop = $d->format('Y-m-d');
388 } catch (\Exception $e) {
389 Analog::log(
390 'Incorrect date format for ' . $name .
391 '! was: ' . $value,
392 Analog::WARNING
393 );
394 }
395 }
396 break;
397 case 'contrib_min_amount':
398 case 'contrib_max_amount':
399 if (is_float($value)) {
400 $this->$prop = $value;
401 } else {
402 if ($value !== null) {
403 Analog::log(
404 'Incorrect amount for ' . $name . '! ' .
405 'Should be a float (' . gettype($value) . ' given)',
406 Analog::WARNING
407 );
408 }
409 }
410 break;
411 case 'show_public_infos':
412 if (is_numeric($value)) {
413 $this->$prop = $value;
414 } else {
415 Analog::log(
416 '[AdvancedMembersList] Value for property `' . $name .
417 '` should be an integer (' . gettype($value) . ' given)',
418 Analog::WARNING
419 );
420 }
421 break;
422 case 'status':
423 if (!is_array($value)) {
424 $value = array($value);
425 }
426 $this->_status = array();
427 foreach ($value as $v) {
428 if (is_numeric($v)) {
429 //check status existence
430 $s = new Status($zdb);
431 $res = $s->get($v);
432 if ($res !== false) {
433 $this->_status[] = $v;
434 } else {
435 Analog::log(
436 'Status #' . $v . ' does not exists!',
437 Analog::WARNING
438 );
439 }
440 } else {
441 Analog::log(
442 '[AdvancedMembersList] Value for status filter should be an '
443 .'integer (' . gettype($v) . ' given',
444 Analog::WARNING
445 );
446 }
447 }
448 break;
449 case 'contributions_types':
450 if (!is_array($value)) {
451 $value = array($value);
452 }
453 $this->_contributions_types = array();
454 foreach ($value as $v) {
455 if (is_numeric($v)) {
456 //check type existence
457 $s = new ContributionsTypes($zdb);
458 $res = $s->get($v);
459 if ($res !== false) {
460 $this->_contributions_types[] = $v;
461 } else {
462 Analog::log(
463 'Contribution type #' . $v . ' does not exists!',
464 Analog::WARNING
465 );
466 }
467 } else {
468 Analog::log(
469 '[AdvancedMembersList] Value for contribution type '
470 . 'filter should be an integer (' . gettype($v) .
471 ' given',
472 Analog::WARNING
473 );
474 }
475 }
476 break;
477 case 'payments_types':
478 if (!is_array($value)) {
479 $value = array($value);
480 }
481 $this->_payments_types = array();
482 $ptypes = new PaymentTypes(
483 $zdb,
484 $preferences,
485 $login
486 );
487 $ptlist = $ptypes->getList();
488
489 foreach ($value as $v) {
490 if (is_numeric($v)) {
491 if (isset($ptlist[$v])) {
492 $this->_payments_types[] = $v;
493 } else {
494 Analog::log(
495 'Payment type #' . $v . ' does not exists!',
496 Analog::WARNING
497 );
498 }
499 } else {
500 Analog::log(
501 '[AdvancedMembersList] Value for payment type filter should be an '
502 .'integer (' . gettype($v) . ' given',
503 Analog::WARNING
504 );
505 }
506 }
507 break;
508 case 'free_search':
509 if (isset($this->_free_search['empty'])) {
510 unset($this->_free_search['empty']);
511 }
512 if (is_array($value)) {
513 if (isset($value['field'])
514 && isset($value['search'])
515 && isset($value['log_op'])
516 && isset($value['qry_op'])
517 && isset($value['idx'])
518 && isset($value['type'])
519 ) {
520 $id = $value['idx'];
521 unset($value['idx']);
522
523 //handle value according to type
524 switch ($value['type']) {
525 case DynamicField::DATE:
526 if ($value['search'] !== null && trim($value['search']) !== '') {
527 try {
528 $d = \DateTime::createFromFormat(__("Y-m-d"), $value['search']);
529 if ($d === false) {
530 throw new \Exception('Incorrect format');
531 }
532 $value['search'] = $d->format('Y-m-d');
533 } catch (\Exception $e) {
534 Analog::log(
535 'Incorrect date format for ' . $value['field'] .
536 '! was: ' . $value['search'],
537 Analog::WARNING
538 );
539 }
540 }
541 break;
542 }
543
544 $this->_free_search[$id] = $value;
545 } else {
546 Analog::log(
547 '[AdvancedMembersList] bad construct for free filter',
548 Analog::WARNING
549 );
550 }
551 } else {
552 Analog::log(
553 '[AdvancedMembersList] Value for free filter should be an '
554 .'array (' . gettype($value) . ' given',
555 Analog::WARNING
556 );
557 }
558 break;
559 default:
560 if (substr($name, 0, 4) === 'cds_'
561 || substr($name, 0, 5) === 'cdsc_'
562 ) {
563 if (is_array($value) || trim($value) !== '') {
564 if (isset($this->_contrib_dynamic['empty'])) {
565 unset($this->_contrib_dynamic['empty']);
566 }
567
568 $id = null;
569 if (substr($name, 0, 5) === 'cdsc_') {
570 $id = substr($name, 5, strlen($name));
571 } else {
572 $id = substr($name, 4, strlen($name));
573 }
574 $this->_contrib_dynamic[$id] = $value;
575 }
576 } else {
577 Analog::log(
578 '[AdvancedMembersList] Unable to set proprety `' .
579 $name . '`',
580 Analog::WARNING
581 );
582 }
583 break;
584 }
585 }
586 }
587 }