Dotclear

source: inc/admin/class.dc.filter.php @ 1148:d179f4623e4b

Revision 1148:d179f4623e4b, 16.2 KB checked in by Dsls <dsls@…>, 12 years ago (diff)

fixed textfilter

Line 
1<?php
2# -- BEGIN LICENSE BLOCK ---------------------------------------
3#
4# This file is part of Dotclear 2.
5#
6# Copyright (c) 2003-2013 Olivier Meunier & Association Dotclear
7# Licensed under the GPL version 2.0 license.
8# See LICENSE file or
9# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10#
11# -- END LICENSE BLOCK -----------------------------------------
12
13if (!defined('DC_RC_PATH')) { return; }
14
15
16class dcFilterSetExtension extends Twig_Extension {
17     private $filtersets;
18
19     public function __construct($core)
20     {
21          $this->core = $core;
22          $this->tpl = 'formfilter_layout.html.twig';
23     }
24     
25     public function initRuntime(Twig_Environment $environment)
26     {
27          $this->core->tpl->getExtension('dc_form')->addTemplate($this->tpl);
28     }
29     
30     
31     public function getFunctions()
32     {
33          return array(
34               'filterset' => new Twig_Function_Method(
35                    $this,
36                    'renderFilterSet',
37                    array(
38                         'is_safe' => array('html'),
39                         'needs_context' => true
40          )));
41     }
42
43     
44
45     public function renderFilterSet($context,$name,$attributes=array())
46     {
47          $context['filtersetname']=$name;
48          echo $this->core->tpl->getExtension('dc_form')->renderBlock(
49               'filterset',
50               $context
51          );
52     }
53     
54
55     public function getName()
56     {
57          return 'dc_filterset';
58     }
59
60}
61
62
63class dcFilterSet extends dcForm {
64     protected $filters;      /// <b>array</b> lists of currently applied filters
65     protected $form_prefix;       /// <b>string</b> displayed form prefix
66     protected $action;            /// <b>string</b> form action page
67     protected $hideform;          /// <b>boolean</b> start form display hidden by default or not
68     protected $name;              /// <b>string</b> filterset name
69     protected $core;
70
71     /**
72     Inits dcFilterSet object
73     
74     @param    core      <b>dcCore</b>       Dotclear core reference
75     @param    form_prefix    <b>string</b>       form prefix to use for parameters
76     */
77     public function __construct($core,$name,$action,$form_prefix="f_") {
78          $this->form_prefix=$form_prefix;
79          $this->filters = new ArrayObject();
80          $this->action = $action;
81          $this->filtered = false;
82          parent::__construct($core,$name,$action,'POST');
83          $this->id = "filters";
84     }
85
86     public function setup() {
87          $form_combo = array();
88          $form_combo['-'] = '';
89          foreach ($this->filters as $filter) {
90               $filter->init();
91               $form_combo[$filter->id]=$filter->name;
92          }
93          $p = $this->form_prefix;
94          $this
95               ->addField (
96                    new dcFieldCombo ($p.'add_filter','',$form_combo,array(
97                    )))
98               ->addField (
99                    new  dcFieldSubmit($p.'add',__('Add this filter'),array(
100                    )))
101               ->addField (
102                    new dcFieldSubmit($p.'clear_filters',__('Delete all filters'),array(
103                    )))
104               ->addField (
105                    new dcFieldSubmit($p.'apply',__('Apply filters and display options'),array(
106                    )))
107               ->addField (
108                    new dcFieldSubmit($p.'reset',__('Reset'),array(
109                    )))
110          ;
111          $this->setupFields();
112          $submitted = $this->getSubmittedFields();
113          /* Use cases :
114               (1) $_POST not empty for formfilter fields :
115                    * efilters are set from $_POST
116                    * lfilters are set from $_GET
117                    * keep filters div shown
118               (2) $_POST empty :
119                    * both efilters and lfilters are set from $_GET
120                    * hide filter div
121          */
122          $action = false;
123          //$allowed_actions = array('clear_filters','add','del_.*','apply','reset');
124          $allowed_actions = '#^(clear_filters|add|del_.*|apply|reset)$#';
125          // Fetch each $_POST parameter to see whether filters are concerned.
126          // Only 1 action at a time is allowed.
127
128          foreach ($_POST as $k => $v) {
129               if (strpos($k,$this->form_prefix)===0) {
130                    $tmp = substr($k,strlen($this->form_prefix));
131                    $count = preg_match($allowed_actions,$tmp,$match);
132                    echo $action;
133                    if ($count==1) {
134                         $action = $match[1];
135                         break;
136                    }
137               }
138          }
139          if ($action !== false) {
140               // Use case (1)
141               if ($action != 'clear_filters' && $action != 'reset')  {
142                    $this->setupEditFilters($_POST);
143                    if ($action == 'add'){
144                         if (isset($_POST[$p.'add_filter'])
145                              && isset($this->filters[$_POST[$p.'add_filter']])) {
146                         $this->filters[$_POST[$p.'add_filter']]->add();
147                         }
148                    } elseif (strpos($action,'del_') === 0) {
149                         $count = preg_match('#del_(.+)_([0-9]+)#',$action,$match);
150                         echo "action=".$action;
151                         if (($count == 1) && isset($this->filters[$match[1]])) {
152                              $this->filters[$match[1]]->remove($match[2]);
153                              echo "remove";
154                         }
155                    } elseif ($action=="apply") {
156                         $data = $this->saveFilters();
157                         $query = http_build_query($data,'','&');
158                         if ($query != '') {
159                              $query = (strpos($this->action,'?') === false ? '?' : '&').$query;
160                         }
161                         http::redirect($this->action.$query);
162                         exit;
163                    }
164               }
165               if (isset($_POST[$p."query"])) {
166                    parse_str($_POST[$p."query"],$out);
167                    $this->setupAppliedFilters($out);
168                    if ($action == 'reset') {
169                         $this->setupEditFilters($out);
170                    }
171               }
172               $this->hideform=false;
173          } else {
174               // Use case (2)
175               $load_from_settings = true;
176               foreach($_GET as $k=>$v) {
177                    if (strpos($k,$this->form_prefix)===0) {
178                         $load_from_settings=false;
179                         break;
180                    }
181               }
182               $get = $_GET;
183               if ($load_from_settings) {
184                    $get = new ArrayObject(array_merge($this->loadFilters(),$get));
185               }
186               $this->setupEditFilters($get);
187               $this->setupAppliedFilters($get);
188          }
189          $queryParams = $this->getListedFilters();
190          $this->addField(
191               new dcFieldHidden($this->form_prefix.'query',
192                    http_build_query($queryParams)));
193          $this->core->tpl->addGlobal('filterset_'.$this->name,$this->getContext());
194     }
195
196     /**
197     Saves user filters to preferences
198     */
199     protected function saveFilters() {
200          $ser = array();
201          $ws = $GLOBALS['core']->auth->user_prefs->addWorkspace('filters');
202          $data = new ArrayObject();
203          $data= $this->serialize();
204          $ws->put($this->name,serialize($data->getArrayCopy()),'string');
205          return $data;
206     }
207
208     /**
209     Loads user filters from preferences
210     */
211     protected function loadFilters() {
212          $ws = $GLOBALS['core']->auth->user_prefs->addWorkspace('filters');
213          $data = (!is_null($ws->{$this->name})) ? unserialize($ws->{$this->name}) : array();
214          if (is_array($data))
215               return $data;
216          else
217               return array();
218     }
219
220     /**
221     Updates filters values according to form_data
222     To be called before any call to display() or getForm()
223     
224     @param    form_data <b>array</b>   form values (usually $_GET or $_POST)
225     */
226     protected function setupEditFilters ($form_data) {
227          $this->hideform = true;
228          foreach ($this->filters as $filter) {
229               $filter->setupFields ($form_data);
230          }
231     }
232     protected function setupAppliedFilters ($form_data) {
233          foreach ($this->filters as $filter) {
234               $filter->setupAppliedFilter ($form_data);
235          }
236     }
237     /**
238     Retrieves the filters values as parameters
239     
240     @param    filters   <b>array</b>   list of concerned filters
241     
242     @return   <b>array</b>   the array of parameters
243
244     */
245
246     protected function serialize() {
247          $arr = new ArrayObject();
248          foreach ($this->filters as $f) {
249               if ($f->isEnabled()) {
250                    $f->serialize($arr);
251               }
252          }
253          return $arr;
254     }
255     /**
256     Adds a new filter to list
257     
258     @param    filter         <b>dcFilter</b>          the filter to add
259     */
260     public function addFilter (dcFilter $filter) {
261          $filter->setFormPrefix($this->form_prefix);
262          $filter->setFilterSet($this);
263          $this->filters[$filter->id] = $filter;
264          return $this;
265     }
266     public function getContext() {
267          $fcontext = new ArrayObject();
268          foreach ($this->filters as $f) {
269               if($f->isEnabled()) {
270                    $f->appendEditLines($fcontext);
271               }
272          }
273          return array(
274               'active_filters' => $fcontext, 
275               'prefix'=>$this->form_prefix);
276     }
277
278     protected function getListedFilters() {
279          $arr = new ArrayObject();
280          foreach ($this->filters as $f) {
281               if ($f->isEnabled())
282                    $f->updateAppliedValues($arr);
283          }
284          return $arr;
285     }
286     /**
287     Applies fieldset and return resulting parameters for request
288     
289     @param    method    <b>string</b>       form method to use (default: "get")
290     @param    method    <b>string</b>       form method to use (default: "get")
291     
292     */
293     public function applyFilters($params) {
294          foreach ($this->filters as $filter) {
295               if ($filter->isApplied()) {
296                    $filter->applyFilter($params);
297                    $this->filtered = true;
298               }
299          }
300          return $this->filtered;
301     }
302
303     public function getDelName($field_id,$pos) {
304          return $this->form_prefix.'del_'.$field_id.'_'.$pos;
305     }
306
307}
308
309
310
311/**
312* dcFilter - describes an abstract filter
313*
314*/
315abstract class dcFilter  {
316     public $filterset;            ///<b>string</b> filterset parent
317     public $id;                        ///<b>string</b> field id (local to fieldset)
318     public $name;                 ///<b>string</b> filter name
319     public $desc;                 ///<b>string</b> field description
320     protected $request_param;     ///<b>string</b> resulting parameter array key
321     protected $enabled;           ///<b>string</b> true if filter is enabled
322     protected $fields;            ///<b>array</b> currently edited values
323     protected $avalues;           ///<b>array</b> currently applied values
324     public $filter_id;            ///<b>string</b> field id (global to the page)
325
326     public function __construct ($id,$name,$desc,$request_param) {
327          $this->id = $id;
328          $this->name=$name;
329          $this->desc = $desc;
330          $this->request_param = $request_param;
331          $this->enabled=false;
332          $this->avalues = array();
333          $this->filter_id = $this->id;
334          $this->fields = array();
335     }
336
337     public function setupFields($data) {
338          $val = $this->parseData($data);
339          $pos=0;
340          foreach($val['values'] as $v) {
341               $this->addField($pos,$v);
342               $pos++;
343          }
344          $this->enabled = ($pos> 0);
345     }//  abstract public function setupFields($data);
346
347
348     public function init() {
349     }
350
351     /**
352     Extract values from data (data being an array, such as $_GET or $_POST)
353     
354     @param    $data     <b>array</b>   data to parse
355     @return   <b>array</b>   field values
356     
357     */
358     protected function parseData($data) {
359          $count=0;
360          $arr = array();
361          while (isset($data[$this->getFieldId($count)])) {
362               $arr[] = $data[$this->getFieldId($count)];
363               $count++;
364          }
365          return array('values' => $arr);
366     }
367     
368     public function setupAppliedFilter($data) {
369          $this->avalues = $this->parseData($data);
370     }
371
372     public function updateAppliedValues($arr) {
373          foreach ($this->avalues['values'] as $k=>$v) {
374               $arr[$this->getFieldID($k)]=$v;
375          }
376     }
377
378     /**
379     Defines the filterset containing this filter
380     
381     @param    prefix         <b>dcFilterset</b>  the filterset
382     */
383     public function setFilterSet($fs) {
384          $this->filterset = $fs;
385     }
386     
387     /**
388     
389     Defines form prefix for filter
390     
391     @param    prefix         <b>string</b>  the form prefix
392     */
393     public function setFormPrefix($prefix) {
394          $this->filter_id = $prefix.$this->id;
395     }
396
397     /**
398     Get a field id
399     
400     @param    pos       <b>integer</b> position of field, in case of multiple field (0 if only 1 field set, default value)
401     @return   <b>string</b> The field ID
402     */
403     protected function getFieldId($pos=0) {
404          if ($pos == 0) {
405               return $this->filter_id;
406          } else {
407               return $this->filter_id.'_'.$pos;
408          }
409     }
410     
411     
412     /**
413     Tells whether the filter is enabled or not
414     
415     @return   <b>boolean</b> true if enabled, false otherwise
416     */
417     public function isEnabled() {
418          return $this->enabled;
419     }
420     
421     protected abstract function addField($pos,$value=NULL);
422
423     /**
424     Adds the current filter to the list
425     */
426     public function add() {
427          $this->addField(count($this->fields));
428          $this->enabled = true;
429     }
430     
431     /**
432     Removes a value from filter
433     */
434     public function remove($pos) {
435          if (isset($this->fields[$pos])) {
436               $this->filterset->removeField($this->fields[$pos]);
437               array_splice($this->fields,$pos,1);
438               for ($cur=$pos; $cur<count($this->fields);$cur++) {
439                    $this->filterset->renameField($this->fields[$cur],$this->getFieldID($cur));
440               }
441               $this->enabled = (count($this->fields)!=0);
442          }
443
444     }
445
446     abstract protected function appendSingleLine($ctx,$pos);
447
448     public function appendEditLines($ctx) {
449          foreach ($this->fields as $cur => $f) {
450               $line = new ArrayObject();
451               $line['lineclass'] = $this->id;
452               $line['del_id'] = $this->filterset->getDelName($this->id,$cur);
453               $del = new dcFieldSubmit(
454                    $this->filterset->getDelName($this->id,$cur),
455                    '-',
456                    array(
457                         'attr' => array(
458                              'title' => __('Delete the following filter')))
459               );
460               $this->filterset->addField($del);
461               $this->appendSingleLine($line,$cur);
462               $ctx[]=$line;
463          }
464     }
465
466     public function serialize($arr) {
467          for ($cur=0; $cur < count($this->fields); $cur++) {
468               $arr[$this->getFieldId($cur)]=$this->fields[$cur]->getValue();
469          }
470     }
471     
472     public function isApplied(){
473          return (count($this->avalues['values']) != 0);
474     }
475
476     /**
477     Convert filter values into a $param filter, used for the upcoming SQL request
478     
479     @param <b>ArrayObject</b> the parameters array to enrich
480
481    @return boolean true if a filter has been applied, false otherwise
482    */
483     public function applyFilter($params) {
484          return false;
485     }
486
487     public function header() {
488          return '';
489     }
490
491}
492
493
494/**
495@ingroup DC_CORE
496@nosubgrouping
497@brief abstract filter class.
498
499Handle combo filter on admin side. Can be single or multi-valued
500*/
501class comboFilter extends dcFilter {
502     protected $options;
503     protected $verb;
504     protected $extra;
505     
506     public function __construct($id,$name,$desc,$request_param,$options,$extra=array()) {
507          parent::__construct($id,$name,$desc,$request_param);
508          $this->options = $options;
509          $this->extra = $extra;
510     }
511
512     public function init() {
513          parent::init();
514          $this->verb = new dcFieldCombo(
515               $this->filter_id.'_v', 
516               'is',
517               array(
518                    'is'=>__('is'),
519                    'isnot'=>__('is not'))
520          );
521     }
522
523     protected function parseData($data) {
524          $val = parent::parseData($data);
525          $val['verb'] = $this->verb->parseValue($data);
526          return $val;
527     }
528
529     protected function addField($pos,$value=NULL) {
530          if ($value === NULL) {
531               $value = current($this->options);
532          }
533          $f = new dcFieldCombo(
534               $this->getFieldID($pos),
535               $value,
536               $this->options);
537          $this->filterset->addField($f);
538          $this->fields[]=$f;
539     }
540
541     public function setupFields($data) {
542          /*$val = $this->parseData($data);
543          $this->verb->setup($data);
544          $pos=0;
545          foreach($val['values'] as $v) {
546               $this->addField($pos,$v);
547          }
548          $this->enabled = (count($this->fields) != 0);*/
549          parent::setupFields($data);
550          $this->verb->setup($data);
551          $this->filterset->addField($this->verb);
552     }
553     public function updateAppliedValues($arr) {
554          parent::updateAppliedValues($arr);
555          if ($this->enabled) {
556               $arr[$this->verb->getName()] = $this->verb->getValue();
557          }
558     }
559     public function add() {
560          if (isset($this->extra['singleval']) && (count($this->fields) > 0))
561               return;
562          parent::add();
563     }
564
565     public function appendSingleLine($line,$pos) {
566          $f = $this->fields[$pos];
567          $line['ffield'] = $f->getName();
568
569          if ($pos == 0) {
570               $line['fwidget']='filter_combo';
571               $line['fverb'] = $this->verb->getName();
572               $line['desc']=$this->desc;
573          } else {
574               $line['fwidget']='filter_combo_cont';
575          };
576     }
577     
578     public function serialize($arr) {
579          parent::serialize($arr);
580          $arr[$this->filter_id.'_v']=$this->verb->getValue();
581     }
582     
583     public function applyFilter($params) {
584          $attr = $this->request_param;
585          if ($this->avalues['verb'] != "is") {
586               $params[$attr."_not"] = true;
587          }
588          if (isset($this->extra['singleval']))
589               $params[$attr]=$this->avalues['values'][0];
590          else
591               $params[$attr]=$this->avalues['values'];
592     }
593
594}
595
596class booleanFilter extends dcFilter {
597     protected $options;
598     protected $verb;
599     
600     public function __construct($id,$name,$desc,$request_param,$options) {
601          parent::__construct($id,$name,$desc,$request_param);
602          $this->options = $options;
603     }
604
605
606
607     public function appendSingleLine($line,$pos) {
608          $f = $this->fields[$pos];
609          $line['ffield'] = $f->getName();
610
611          if ($pos == 0) {
612               $line['fwidget']='filter_boolean';
613               $line['desc']=$this->desc;
614          };
615     }
616
617     protected function addField($pos,$value=NULL) {
618          if (count($this->fields)>0)
619               return;
620          if ($value === NULL) {
621               $value = 1;
622          }
623          $f = new dcFieldCombo(
624               $this->getFieldID($pos),
625               $value,
626               $this->options);
627          $this->filterset->addField($f);
628          $this->fields[]=$f;
629     }
630
631     public function applyFilter($params) {
632          $params[$this->request_param]=$this->avalues['values'][0];
633     }
634     
635}
636
637class textFilter extends dcFilter {
638     protected $options;
639     protected $verb;
640     
641     public function __construct($id,$name,$desc,$request_param,$options) {
642          parent::__construct($id,$name,$desc,$request_param);
643          $this->options = $options;
644     }
645
646     public function setupFields($data) {
647          $val = $this->parseData($data);
648          foreach($val['values'] as $k=>$v) {
649               $this->addField($k,$v);
650          }
651          $this->enabled = (count($this->fields) != 0);
652     }
653
654     public function appendSingleLine($line,$pos) {
655          $f = $this->fields[$pos];
656          $line['ffield'] = $f->getName();
657
658          if ($pos == 0) {
659               $line['fwidget']='filter_boolean';
660               $line['desc']=$this->desc;
661          };
662     }
663
664     protected function addField($pos,$value=NULL) {
665          if (count($this->fields)>0)
666               return;
667          if ($value === NULL) {
668               $value = '';
669          }
670          $f = new dcFieldText(
671               $this->getFieldID($pos),
672               $value);
673          $this->filterset->addField($f);
674          $this->fields[]=$f;
675     }
676
677     public function applyFilter($params) {
678          $params[$this->request_param]=$this->avalues['values'][0];
679     }
680     
681}
682
683?>
Note: See TracBrowser for help on using the repository browser.

Sites map