Dotclear

source: inc/admin/class.dc.filter.php @ 757:eb965b99e594

Revision 757:eb965b99e594, 17.7 KB checked in by Dsls <dsls@…>, 14 years ago (diff)

fixed notice in class.dc.filter.php
added jqueryui css

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

Sites map