source: extensions/GrumPluginClasses/classes/GPCCategorySelector.class.inc.php @ 7310

Last change on this file since 7310 was 7310, checked in by grum, 14 years ago

fix bug on the rbuilder and migrate ajax call on the gpc ajax manager
fix bug:1945
add some functionnalities

  • Property svn:executable set to *
File size: 11.3 KB
Line 
1<?php
2/**
3 * -----------------------------------------------------------------------------
4 * class name     : GPCCategorySelector
5 * class version  : 1.0.1
6 * plugin version : 3.3.3
7 * date           : 2010-10-20
8 * -----------------------------------------------------------------------------
9 * author: grum at piwigo.org
10 * << May the Little SpaceFrog be with you >>
11 * -----------------------------------------------------------------------------
12 *
13 * :: HISTORY
14 *
15| release | date       |
16| 1.0.0   | 2010/10/09 | * create class
17|         |            |
18| 1.0.1   | 2010/10/20 | * fix bug on the private select methods
19|         |            |
20|         |            |
21|         |            |
22|         |            |
23|         |            |
24|         |            |
25 *
26 *
27 * -----------------------------------------------------------------------------
28 *
29 *  this class provides methods to easily insert a hierarchical categories
30 *  selector in the HTML pages
31 *
32 * -----------------------------------------------------------------------------
33 *
34 * Const
35 *  - GPCCategorySelector::FILTER_ALL
36 *  - GPCCategorySelector::FILTER_ACCESSIBLE
37 *  - GPCCategorySelector::FILTER_PUBLIC
38 *  there is no filter 'private only' or 'not accessible only' because these
39 *  kind of categories are probably sub categories of 'public' categories
40 *
41 *
42 * Methods
43 *  - public __construct($options)
44 *  - public __destruct()
45 *  - public setFilter($filter)
46 *  - public getFilter()
47 *  - public setGalleryRoot($galleryRoot)
48 *  - public getGalleryRoot()
49 *  - public getCategoryList()
50 *
51 *
52 * -----------------------------------------------------------------------------
53 *
54 */
55
56
57class GPCCategorySelector
58{
59  const FILTER_ALL            = 'all';         // no filter, all categories are listed
60  const FILTER_ACCESSIBLE     = 'accessible'; // only accessible categories are listed (public + private with some access right)
61  const FILTER_PUBLIC         = 'public';     // only public categories are listed
62
63  const USER_MODE_ADMIN       = 'admin';      // returns result without user acces right applied (admin can see everything...)
64  const USER_MODE_PUBLIC      = 'public';     // returns result with user acces right applied
65
66
67  private $options=array(
68    'filter'      => self::FILTER_ACCESSIBLE,
69    'galleryRoot' => true,
70    'tree'        => false,
71    'userMode'    => self::USER_MODE_PUBLIC,
72  );
73
74
75  /**
76   * constructor for the object
77   *
78   * all options are facultative
79   *
80   * @param Array $options : an array with the options
81   *               String 'filter'      : can take one the defined FILTER values
82   *               Bool   'galleryRoot' : if set to true, the category list
83   *                                      contain at root, an item with id = 0
84   *                                      and named 'all the gallery'
85   *               Bool   'tree'        : if set to true, the category list
86   *                                      is returned as a tree, otherwise result
87   *                                      is returned as a flat array
88   *               String 'userMode'    : 'admin' returns result without user
89   *                                      right access applied ; 'public' returns
90   *                                      result with user right acces applied
91   */
92  public function __construct($options=array())
93  {
94    if(isset($options['filter'])) $this->setFilter($options['filter']);
95    if(isset($options['galleryRoot'])) $this->setGalleryRoot($options['galleryRoot']);
96    if(isset($options['tree'])) $this->setTree($options['tree']);
97    if(isset($options['userMode'])) $this->setUserMode($options['userMode']);
98  }
99
100  /**
101   * destructor dor the object
102   */
103  public function __destruct()
104  {
105    unset($this->options);
106  }
107
108  /**
109   * set the filter value to apply on the categories
110   *
111   * @param String $filer : the filter value
112   * @return String : the filter value
113   */
114  public function setFilter($filter)
115  {
116    if($filter==self::FILTER_ALL or
117       $filter==self::FILTER_ACCESSIBLE or
118       $filter==self::FILTER_PUBLIC) $this->options['filter']=$filter;
119
120    if($this->options['userMode']==self::USER_MODE_PUBLIC and
121       !($this->options['filter']==self::FILTER_ACCESSIBLE or $this->options['filter']==self::FILTER_PUBLIC)) $this->options['filter']==self::FILTER_ACCESSIBLE;
122
123    return($this->options['filter']);
124  }
125
126  /**
127   * get the filter value affected on the categories
128   *
129   * @return String : the filter
130   */
131  public function getFilter()
132  {
133    return($this->options['filter']);
134  }
135
136
137  /**
138   * set to true to add a root item named 'all the gallery'
139   * id for this item will be equal to 0
140   *
141   * @param Bool $galleryRoot :
142   * @return Bool :
143   */
144  public function setGalleryRoot($galleryRoot)
145  {
146    if(is_bool($galleryRoot)) $this->options['galleryRoot']=$galleryRoot;
147    return($this->options['galleryRoot']);
148  }
149
150
151  /**
152   * get if a root item named 'all the gallery' is present or not
153   *
154   * @return Bool :
155   */
156  public function getGalleryRoot()
157  {
158    return($this->options['galleryRoot']);
159  }
160
161
162  /**
163   * get if the result have to be returned as a tree or as a flat array
164   *
165   * @return Bool :
166   */
167  public function getTree()
168  {
169    return($this->options['tree']);
170  }
171
172
173  /**
174   * set if the result have to be returned as a tree or as a flat array
175   *
176   * @param Bool $tree :
177   * @return Bool :
178   */
179  public function setTree($tree)
180  {
181    if(is_bool($tree)) $this->options['tree']=$tree;
182    return($this->options['tree']);
183  }
184
185
186
187
188  /**
189   * returns the user mode currently applied
190   *
191   * @return String :
192   */
193  public function getUserMode()
194  {
195    return($this->options['userMode']);
196  }
197
198
199  /**
200   * set the user mode to apply
201   *
202   * @param String $userMode :
203   * @return String :
204   */
205  public function setUserMode($userMode)
206  {
207    if($userMode==self::USER_MODE_ADMIN || $userMode==self::USER_MODE_PUBLIC) $this->options['userMode']=$userMode;
208
209    if($this->options['userMode']==self::USER_MODE_PUBLIC and
210       !($this->options['filter']==self::FILTER_ACCESSIBLE or $this->options['filter']==self::FILTER_PUBLIC)) $this->options['filter']==self::FILTER_ACCESSIBLE;
211    return($this->options['userMode']);
212  }
213
214
215
216  /**
217   * build an ordered category list
218   * returns an array, each item is an array like :
219   *  'id'     => the category Id
220   *  'name'   => the category name
221   *  'level'  => the category level
222   *  'status' => the category status (0='private', 1='public')
223   *  'childs' => the category have childs ? (true or false in flat mode, childs
224   *                in tree mode)
225   *
226   * @return Array : the list
227   */
228  public function getCategoryList()
229  {
230    global $user;
231
232    $returned=array();
233
234    if($this->options['galleryRoot'])
235    {
236      $startLevel=1;
237    }
238    else
239    {
240      $startLevel=0;
241    }
242
243    $sql="SELECT DISTINCT pct.id, pct.name, pct.global_rank AS rank, pct.status
244          FROM ".CATEGORIES_TABLE." pct ";
245
246    switch($this->options['filter'])
247    {
248      case self::FILTER_PUBLIC :
249        $sql.=" WHERE pct.status = 'public' ";
250        break;
251      case self::FILTER_ACCESSIBLE :
252        if(!is_admin())
253        {
254          $sql.=" JOIN ".USER_CACHE_CATEGORIES_TABLE." pucc
255                  ON (pucc.cat_id = pct.id) AND pucc.user_id='".$user['id']."' ";
256        }
257        else
258        {
259          $sql.=" JOIN (
260                    SELECT DISTINCT pgat.cat_id AS catId FROM ".GROUP_ACCESS_TABLE." pgat
261                    UNION DISTINCT
262                    SELECT DISTINCT puat.cat_id AS catId FROM ".USER_ACCESS_TABLE." puat
263                    UNION DISTINCT
264                    SELECT DISTINCT pct2.id AS catId FROM ".CATEGORIES_TABLE." pct2 WHERE pct2.status='public'
265                       ) pat
266                  ON pat.catId = pct.id ";
267        }
268
269        break;
270    }
271    $sql.="ORDER BY global_rank;";
272
273    $result=pwg_query($sql);
274    if($result)
275    {
276      while($row=pwg_db_fetch_assoc($result))
277      {
278        $row['level']=$startLevel+substr_count($row['rank'], '.');
279
280        /* rank is in formated without leading zero, giving bad order
281         *  1
282         *  1.10
283         *  1.11
284         *  1.2
285         *  1.3
286         *  ....
287         *
288         *  this loop cp,vert all sub rank in four 0 format, allowing to order
289         *  categories easily
290         *  0001
291         *  0001.0010
292         *  0001.0011
293         *  0001.0002
294         *  0001.0003
295         */
296        $row['rank']=explode('.', $row['rank']);
297        foreach($row['rank'] as $key=>$rank)
298        {
299          $row['rank'][$key]=str_pad($rank, 4, '0', STR_PAD_LEFT);
300        }
301        $row['rank']=implode('.', $row['rank']);
302
303        $returned[]=$row;
304      }
305    }
306
307    if($this->options['galleryRoot'])
308    {
309      $returned[]=array(
310        'id'     => 0,
311        'name'   => l10n('All the gallery'),
312        'rank'   => '0000',
313        'level'  => 0,
314        'status' => 'public',
315        'childs'  => null
316      );
317    }
318
319    usort($returned, array(&$this, 'compareCat'));
320
321    if($this->options['tree'])
322    {
323      $index=0;
324      $returned=$this->buildSubLevel($returned, $index);
325    }
326    else
327    {
328      //check if cats have childs & remove rank (enlight the response)
329      $prevLevel=-1;
330      for($i=count($returned)-1;$i>=0;$i--)
331      {
332        unset($returned[$i]['rank']);
333        if($returned[$i]['status']=='private')
334        {
335          $returned[$i]['status']='0';
336        }
337        else
338        {
339          $returned[$i]['status']='1';
340        }
341
342        if($returned[$i]['level']>=$prevLevel)
343        {
344          $returned[$i]['childs']=false;
345        }
346        else
347        {
348          $returned[$i]['childs']=true;
349        }
350        $prevLevel=$returned[$i]['level'];
351      }
352    }
353
354    return($returned);
355  }
356
357  /**
358   * used for sort comparison
359   * defined as public, but don't use it directly
360   *
361   * this function compare two categorie with their rank value
362   */
363  public function compareCat($catA, $catB)
364  {
365    if($catA['rank'] == $catB['rank'])
366    {
367      return(0);
368    }
369    return( ($catA['rank'] < $catB['rank'])?-1:1 );
370  }
371
372
373  /**
374   * used to convert a flat array in a leveled array
375   */
376  private function buildSubLevel(&$list, &$currentIndex)
377  {
378    $returned=array();
379
380    $localIndex=$currentIndex;
381    $list[$localIndex]['childs']=array();
382    // reduce size of returned data
383    unset($list[$currentIndex]['rank']);
384    if($list[$currentIndex]['status']=='private')
385    {
386      $list[$currentIndex]['status']='0';
387    }
388    else
389    {
390      $list[$currentIndex]['status']='1';
391    }
392    $currentIndex++;
393
394
395    while($currentIndex<count($list))
396    {
397      if($list[$currentIndex]['level']>$list[$localIndex]['level'])
398      {
399        $list[$localIndex]['childs']=$this->buildSubLevel($list, $currentIndex);
400      }
401      else if($list[$currentIndex]['level']==$list[$localIndex]['level'])
402      {
403        $returned[]=$list[$localIndex];
404
405        $localIndex=$currentIndex;
406        $list[$currentIndex]['childs']=array();
407
408        // reduce size of returned data
409        unset($list[$currentIndex]['rank']);
410        if($list[$currentIndex]['status']=='private')
411        {
412          $list[$currentIndex]['status']='0';
413        }
414        else
415        {
416          $list[$currentIndex]['status']='1';
417        }
418
419        $currentIndex++;
420      }
421      else
422      {
423        $returned[]=$list[$localIndex];
424        return($returned);
425      }
426    }
427    $returned[]=$list[$localIndex];
428
429    return($returned);
430  }
431
432}
433/*
434
435*/
Note: See TracBrowser for help on using the repository browser.