From: Raphaël Barrois Date: Wed, 20 Jan 2010 16:15:23 +0000 (+0100) Subject: Imrpove API for PlSet, create abstract PlFilter X-Git-Tag: core/1.1.0~94 X-Git-Url: http://git.polytechnique.org/?a=commitdiff_plain;h=bd9b36fe4faf29db8da42c144bf2c7db365b87ad;p=platal.git Imrpove API for PlSet, create abstract PlFilter Signed-off-by: Raphaël Barrois --- diff --git a/classes/plfilter.php b/classes/plfilter.php index 6cdeb70..592d3d5 100644 --- a/classes/plfilter.php +++ b/classes/plfilter.php @@ -19,6 +19,30 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ***************************************************************************/ +class PlLimit +{ + private $count = null; + private $from = null; + + public function __construct($count = null, $from = null) + { + $this->count = $count; + $this->from = $from; + } + + public function getSql() + { + if (!is_null($this->count)) { + if (!is_null($this->from) && $this->from != 0) { + return XDB::format('LIMIT {?}, {?}', (int)$this->from, (int)$this->count); + } else { + return XDB::format('LIMIT {?}', (int)$this->count); + } + } + return ''; + } +} + class PlSqlJoin { private $mode; @@ -50,50 +74,85 @@ class PlSqlJoin return $this->table; } - public function condiftion() + public function condition() { return $this->condition; } -} -abstract class PlFilter -{ - public abstract function filter(array $objects, $count = null, $offset = null); - - public abstract function setCondition(PlFilterCondition &$cond); - - public abstract function addSort(PlFilterOrder &$sort); - - private function replaceJoinMetas($cond, $key) + /** Replace all "metas" in the condition with their translation. + * $ME always becomes the alias of the table + * @param $key The name the joined table will have in the final query + * @param $joinMetas An array of meta => conversion to apply to the condition + */ + public function replaceJoinMetas($key, $joinMetas = array()) { - return str_replace(array('$ME'), array($key), $cond); + $joinMetas['$ME'] = $key; + return str_replace(array_keys($joinMetas), $joinMetas, $this->condition); } - private function formatJoin(array $joins) + /** Create a join command from an array of PlSqlJoin + * @param $joins The list of 'join' to convert into an SQL query + * @param $joinMetas An array of ('$META' => 'conversion') to apply to the joins. + */ + public static function formatJoins(array $joins, array $joinMetas) { $str = ''; foreach ($joins as $key => $join) { - if (! $join instanceof PlSqlJoin) { - Platal::page()->kill("Error : not a join : $join"); + if (! ($join instanceof PlSqlJoin)) { + Platal::page()->kill("Error: not a join: $join"); } $mode = $join->mode(); $table = $join->table(); $str .= ' ' . $mode . ' JOIN ' . $table . ' AS ' . $key; if ($join->condition() != null) { - $str .= ' ON (' . $this->replaceJoinMetas($join->condition(), $key) . ')'; + $str .= ' ON (' . $join->replaceJoinMetas($key, $joinMetas) . ')'; } $str .= "\n"; } return $str; } +} + +abstract class PlFilter +{ + /** Filters objects matching the PlFilter + * @param $objects The objects to filter + * @param $limit The portion of the matching objects to show + */ + public abstract function filter(array $objects, PlLimit &$limit); + + public abstract function setCondition(PlFilterCondition &$cond); + + public abstract function addSort(PlFilterOrder &$sort); + + public abstract function getTotalCount(); + + /** Get objects, selecting only those within a limit + * @param $limit The portion of the matching objects to select + */ + public abstract function get(PlLimit &$limit); + + /** PRIVATE FUNCTIONS + */ + + /** List of metas to replace in joins: + * '$COIN' => 'pan.x' means 'replace $COIN with pan.x in the condition of the joins' + * + * "$ME" => "joined table alias" is always added to these. + */ + private $joinMetas = array(); + /** Build the 'join' part of the query + * This function will call all methods declared in self::$joinMethods + * to get an array of PlSqlJoin objects to merge + */ private function buildJoins() { $joins = array(); - foreach (self::$joinMethods as $method) { + foreach ($this->$joinMethods as $method) { $joins = array_merge($joins, $this->$method()); } - return $this->formatJoin($joins); + return PlSqlJoin::formatJoins($joins, $this->$joinMetas); } } diff --git a/classes/plfiltercondition.php b/classes/plfiltercondition.php index 91545e9..450aad9 100644 --- a/classes/plfiltercondition.php +++ b/classes/plfiltercondition.php @@ -34,7 +34,7 @@ abstract class PFC_OneChild implements PlFilterCondition { protected $child; - public function __construct($child = null) + public function __construct(&$child = null) { if (!is_null($child) && ($child instanceof PlFilterCondition)) { $this->setChild($child); diff --git a/classes/plfilterorder.php b/classes/plfilterorder.php index 09e5911..a9b61d9 100644 --- a/classes/plfilterorder.php +++ b/classes/plfilterorder.php @@ -27,6 +27,16 @@ abstract class PlFilterOrder $this->desc = $desc; } + public function toggleDesc() + { + $this->desc = !$desc; + } + + public function setDescending($desc = true) + { + $this->desc = $desc; + } + public function buildSort(PlFilter &$pf) { $sel = $this->getSortTokens($pf); diff --git a/classes/plset.php b/classes/plset.php index 4b08d99..1fd155e 100644 --- a/classes/plset.php +++ b/classes/plset.php @@ -23,10 +23,9 @@ */ class PlSet { - private $from = null; - private $groupby = null; - private $joins = null; - private $where = null; + private $conds = null; + private $orders = null; + private $limit = null; protected $count = null; @@ -35,12 +34,21 @@ class PlSet 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,31 +67,23 @@ 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"; - } - $query = "SELECT SQL_CALC_FOUND_ROWS - $fields - FROM $from - $joins - $where - $groupby - $order - $limit"; -// echo $query; -// print_r($this); - $it = XDB::query($query); - $it = $it->fetchAllAssoc(); - $count = XDB::query('SELECT FOUND_ROWS()'); - $this->count = intval($count->fetchOneCell()); + $this->orders[] = $order; + } + + /** 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 private static function buildFilter(PlFilterCondition $cond, $orders); + + public function &get(PlFilterLimit $limit = null) + { + $pf = self::buildFilter($this->conds, $this->orders); + + $it = $pf->get($limit); + $this->count = $pf->getTotalCount(); return $it; } @@ -108,27 +108,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; @@ -186,6 +165,34 @@ interface PlView 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; @@ -202,6 +209,11 @@ abstract class MultipageView implements PlView 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; @@ -210,34 +222,18 @@ abstract class MultipageView implements PlView $this->params = $params; } - public function joins() - { - return null; - } - - public function where() - { - return null; - } - - public function groupBy() - { - return null; - } - - public function bounds() + /** Add an order to the view + */ + protected function addSort(PlViewOrder &$pvo, $default = false) { - return null; - } - - protected function addSortKey($name, array $keys, $desc, $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); @@ -245,40 +241,60 @@ abstract class MultipageView implements PlView if ($invert) { $order = substr($order, 1); } - $list = array(); - foreach ($this->sortkeys[$order]['keys'] as $item) { - $desc = ($item{0} == '-'); - if ($desc) { - $item = substr($item, 1); + $list = array(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; } + /** Name of the template to use for displaying items of the view + */ abstract public function templateName(); + /** 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 private function getBoundValue($obj); + + /** Applies the view to a page + * @param $page Page to which the view will be applied + */ public function apply(PlPage &$page) { - $res = $this->set->get($this->fields(), - $this->joins(), - $this->where(), - $this->groupBy(), - $this->order(), - $this->entriesPerPage, - $this->offset); + 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 = $res[0][$this->bound_field]; - $last = $end[$this->bound_field]; + $first = $this->getBoundValue($res[0]); + $last = $this->getBoundValue($end); } elseif ($show_bounds == -1) { - $first = $end[$this->bound_field]; - $last = $res[0][$this->bound_field]; + $first = $this->getBoundValue($end); + $last = $this->getBoundValue($res[0]); } $page->assign('first', $first); $page->assign('last', $last); diff --git a/templates/plview.multipage.tpl b/templates/plview.multipage.tpl index d2e1428..e22bacc 100644 --- a/templates/plview.multipage.tpl +++ b/templates/plview.multipage.tpl @@ -55,12 +55,12 @@ [ {if $name eq $order} tri ascendant - {$sort.desc} + {$sort->displaytext} {elseif $order eq "-$name"} tri ascendant - {$sort.desc} + {$sort->displaytext} {else} - {$sort.desc} + {$sort->displaytext} {/if} ]  {/foreach}