Dotclear

source: inc/admin/class.dc.filter.php @ 755:38c4f75f3dd5

Revision 755:38c4f75f3dd5, 17.1 KB checked in by Dsls <dsls@…>, 14 years ago (diff)

Intermediate commit for form filters, breaks columns for the moment.

More to come soon...

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

Sites map