BugFixes in PlSet and PlFilter
[platal.git] / classes / plset.php
index 648d814..93afc3f 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /***************************************************************************
- *  Copyright (C) 2003-2008 Polytechnique.org                              *
+ *  Copyright (C) 2003-2009 Polytechnique.org                              *
  *  http://opensource.polytechnique.org/                                   *
  *                                                                         *
  *  This program is free software; you can redistribute it and/or modify   *
  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
  ***************************************************************************/
 
+
 /** UserSet is a light-weight Model/View tool for displaying a set of items
  */
-class PlSet
+abstract class PlSet
 {
-    private $from    = null;
-    private $groupby = null;
-    private $joins   = null;
-    private $where   = null;
+    private $conds   = null;
+    private $orders  = null;
+    private $limit   = null;
 
-    private $count   = null;
+    protected $count   = null;
 
     private $mods      = array();
     private $modParams = array();
     private $mod       = null;
     private $default   = null;
 
-    public function __construct($from, $joins = '', $where = '', $groupby = '')
+    public function __construct(PlFilterCondition &$cond, $orders)
     {
-        $this->from    = $from;
-        $this->joins   = $joins;
-        $this->where   = $where;
-        $this->groupby = $groupby;
+        if ($cond instanceof PFC_And) {
+            $this->conds = $cond;
+        } else {
+            $this->conds = new PFC_And($cond);
+        }
+
+        if ($orders instanceof PlFilterOrder) {
+            $this->orders = array($order);
+        } else {
+            foreach ($orders as $order) {
+                $this->orders[] = $order;
+            }
+        }
     }
 
     public function addMod($name, $description, $default = false, array $params = array())
@@ -59,30 +68,31 @@ class PlSet
         unset($this->mods[$name]);
     }
 
-    private function &query($fields, $from, $joins, $where, $groupby, $order, $limit)
+    public function addSort(PlFilterOrder &$order)
     {
-        if (trim($order)) {
-            $order = "ORDER BY $order";
-        }
-        if (trim($where)) {
-            $where = "WHERE $where";
-        }
-        if (trim($groupby)) {
-            $groupby = "GROUP BY $groupby";
+        $this->orders[] = $order;
+    }
+
+    public function addCond(PlFilterCondition &$cond)
+    {
+        $this->conds->addChild($cond);
+    }
+
+    /** This function builds the right kind of PlFilter from given data
+     * @param $cond The PlFilterCondition for the filter
+     * @param $orders An array of PlFilterOrder for the filter
+     */
+    abstract protected function buildFilter(PlFilterCondition &$cond, $orders);
+
+    public function &get(PlLimit $limit = null)
+    {
+        $pf = $this->buildFilter($this->conds, $this->orders);
+
+        if (is_null($limit)) {
+            $limit = new PlLimit(20, 0);
         }
-        $query = "SELECT  SQL_CALC_FOUND_ROWS
-                          $fields
-                    FROM  $from
-                          $joins
-                          $where
-                          $groupby
-                          $order
-                          $limit";
-//        echo $query;
-//        print_r($this);
-        $it    = XDB::iterator($query);
-        $count = XDB::query('SELECT FOUND_ROWS()');
-        $this->count = intval($count->fetchOneCell());
+        $it          = $pf->get($limit);
+        $this->count = $pf->getTotalCount();
         return $it;
     }
 
@@ -107,27 +117,6 @@ class PlSet
         return $encode ? urlencode($qs) : $qs;
     }
 
-    public function &get($fields, $joins, $where, $groupby, $order, $limitcount = null, $limitfrom = null)
-    {
-        if (!is_null($limitcount)) {
-            if (!is_null($limitfrom)) {
-                $limitcount = "$limitfrom,$limitcount";
-            }
-            $limitcount = "LIMIT $limitcount";
-        }
-        $joins  = $this->joins . ' ' . $joins;
-        if (trim($this->where)) {
-            if (trim($where)) {
-                $where .= ' AND ';
-            }
-            $where .= $this->where;
-        }
-        if (!$groupby) {
-            $groupby = $this->groupby;
-        }
-        return $this->query($fields, $this->from, $joins, $where, $groupby, $order, $limitcount);
-    }
-
     public function count()
     {
         return $this->count;
@@ -153,7 +142,7 @@ class PlSet
         return $view;
     }
 
-    public function apply($baseurl, PlatalPage &$page, $view = null, $data = null)
+    public function apply($baseurl, PlPage &$page, $view = null, $data = null)
     {
         $view =& $this->buildView($view, $data);
         if (is_null($view)) {
@@ -163,7 +152,7 @@ class PlSet
         if (!isset($args['rechercher'])) {
             $args['rechercher'] = 'Chercher';
         }
-        $page->changeTpl('core/plset.tpl');
+        $page->coreTpl('plset.tpl');
         $page->assign('plset_base', $baseurl);
         $page->assign('plset_mods', $this->mods);
         $page->assign('plset_mod', $this->mod);
@@ -181,10 +170,38 @@ class PlSet
 interface PlView
 {
     public function __construct(PlSet &$set, $data, array $params);
-    public function apply(PlatalPage &$page);
+    public function apply(PlPage &$page);
     public function args();
 }
 
+/** This class describes an Order as used in a PlView :
+ * - It is based on a PlFilterOrder
+ * - It has a short identifier
+ * - It has a full name, to display on the page
+ */
+class PlViewOrder
+{
+    public $pfo         = null;
+    public $name        = null;
+    public $displaytext = null;
+
+    /** Build a PlViewOrder
+     * @param $name Name of the order (key)
+     * @param $displaytext Text to display
+     * @param $pfo PlFilterOrder for the order
+     */
+    public function __construct($name, PlFilterOrder &$pfo, $displaytext = null)
+    {
+        $this->name         = $name;
+        if (is_null($displaytext)) {
+            $this->displaytext = ucfirst($name);
+        } else {
+            $this->displaytext  = $displaytext;
+        }
+        $this->pfo        = $pfo;
+    }
+}
+
 abstract class MultipageView implements PlView
 {
     protected $set;
@@ -199,6 +216,13 @@ abstract class MultipageView implements PlView
     protected $sortkeys = array();
     protected $defaultkey = null;
 
+    protected $bound_field = null;
+
+    /** Builds a MultipageView
+     * @param $set The associated PlSet
+     * @param $data Data for the PlSet
+     * @param $params Parameters of the view
+     */
     public function __construct(PlSet &$set, $data, array $params)
     {
         $this->set   =& $set;
@@ -207,29 +231,18 @@ abstract class MultipageView implements PlView
         $this->params = $params;
     }
 
-    public function joins()
-    {
-        return null;
-    }
-
-    public function where()
-    {
-        return null;
-    }
-
-    public function groupBy()
-    {
-        return null;
-    }
-
-    protected function addSortKey($name, array $keys, $desc, $default = false)
+    /** Add an order to the view
+     */
+    protected function addSort(PlViewOrder &$pvo, $default = false)
     {
-        $this->sortkeys[$name] = array('keys' => $keys, 'desc' => $desc);
+        $this->sortkeys[$pvo->name] = $pvo;
         if (!$this->defaultkey || $default) {
-            $this->defaultkey = $name;
+            $this->defaultkey = $pvo->name;
         }
     }
 
+    /** Returns a list of PFO objects, the "default" one first
+     */
     public function order()
     {
         $order = Env::v('order', $this->defaultkey);
@@ -238,37 +251,80 @@ abstract class MultipageView implements PlView
             $order = substr($order, 1);
         }
         $list = array();
-        foreach ($this->sortkeys[$order]['keys'] as $item) {
-            $desc = ($item{0} == '-');
-            if ($desc) {
-                $item = substr($item, 1);
+        if (count($this->sortkeys)) {
+            $list[0] = null;
+        }
+        foreach ($this->sortkeys as $name => $sort) {
+            $desc = $sort->pfo->isDescending();;
+            if ($invert) {
+                $sort->pfo->toggleDesc();
             }
-            if ($desc xor $invert) {
-                $item .= ' DESC';
+            if ($name == $order) {
+                $list[0] = $sort->pfo;
+            } else {
+                $list[] = $sort->pfo;
             }
-            $list[] = $item;
         }
-        return implode(', ', $list);
+        return $list;
+    }
+
+    /** Returns information on the order of bounds
+     * @return * 1  if normal bounds
+     *         * -1 if inversed bounds
+     *         * 0  if bounds shouldn't be displayed
+     */
+    public function bounds()
+    {
+        return null;
     }
 
+    public function limit()
+    {
+        return null;
+    }
+
+    /** Name of the template to use for displaying items of the view
+     */
     abstract public function templateName();
 
-    public function apply(PlatalPage &$page)
+    /** Returns the value of a boundary of the current view (in order
+     * to show "from C to F")
+     * @param $obj The boundary result whose value must be shown to the user
+     */
+    abstract protected function getBoundValue($obj);
+
+    /** Applies the view to a page
+     * @param $page Page to which the view will be applied
+     */
+    public function apply(PlPage &$page)
     {
+        foreach ($this->order() as $order) {
+            $this->set->addSort($order->pfo);
+        }
+        $res = $this->set->get($this->limit());
+
+        $show_bounds = $this->bounds();
+        $end         = end($res);
+        if ($show_bounds) {
+            if ($show_bounds == 1) {
+                $first = $this->getBoundValue($res[0]);
+                $last  = $this->getBoundValue($end);
+            } elseif ($show_bounds == -1) {
+                $first = $this->getBoundValue($end);
+                $last  = $this->getBoundValue($res[0]);
+            }
+            $page->assign('first', $first);
+            $page->assign('last', $last);
+        }
+
+        $page->assign('show_bounds', $show_bounds);
         $page->assign('order', Env::v('order', $this->defaultkey));
         $page->assign('orders', $this->sortkeys);
         $page->assign_by_ref('plview', $this);
-        $page->assign_by_ref('set',
-                             $this->set->get($this->fields(),
-                                             $this->joins(),
-                                             $this->where(),
-                                             $this->groupBy(),
-                                             $this->order(),
-                                             $this->entriesPerPage,
-                                             $this->offset));
+        $page->assign_by_ref('set', $res);
         $count = $this->set->count();
         $this->pages = intval(ceil($count / $this->entriesPerPage));
-        return 'include/plview.multipage.tpl';
+        return PlPage::getCoreTpl('plview.multipage.tpl');
     }
 
     public function args()