X-Git-Url: http://git.polytechnique.org/?a=blobdiff_plain;f=classes%2Fplfilter.php;h=c1139df10e4e13df59d7ba9018ede39455de4f65;hb=7c44b8bc211c768efdb3be75c5a7057bf0e5663e;hp=592d3d575ab483c0d4a8fc4d2a995cec07800b6b;hpb=bd9b36fe4faf29db8da42c144bf2c7db365b87ad;p=platal.git diff --git a/classes/plfilter.php b/classes/plfilter.php index 592d3d5..c1139df 100644 --- a/classes/plfilter.php +++ b/classes/plfilter.php @@ -19,6 +19,9 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ***************************************************************************/ +__autoload('xdb'); + +// {{{ class PlLimit class PlLimit { private $count = null; @@ -32,7 +35,7 @@ class PlLimit public function getSql() { - if (!is_null($this->count)) { + if (!is_null($this->count) && $this->count != 0) { if (!is_null($this->from) && $this->from != 0) { return XDB::format('LIMIT {?}, {?}', (int)$this->from, (int)$this->count); } else { @@ -42,7 +45,9 @@ class PlLimit return ''; } } +// }}} +// {{{ class PlSqlJoin class PlSqlJoin { private $mode; @@ -53,10 +58,12 @@ class PlSqlJoin const MODE_RIGHT = 'RIGHT'; const MODE_INNER = 'INNER'; - public function __construct($mode, $table, $condition) + private function __construct($mode, $params) { + $table = array_shift($params); + $condition = call_user_func_array(array('XDB', 'format'), $params); if ($mode != self::MODE_LEFT && $mode != self::MODE_RIGHT && $mode != self::MODE_INNER) { - Platal::page()->kill("Join mode error : unknown mode $mode"); + Platal::page()->kill("Join mode error: unknown mode $mode"); return; } $this->mode = $mode; @@ -98,7 +105,7 @@ class PlSqlJoin { $str = ''; foreach ($joins as $key => $join) { - if (! ($join instanceof PlSqlJoin)) { + if (!($join instanceof PlSqlJoin)) { Platal::page()->kill("Error: not a join: $join"); } $mode = $join->mode(); @@ -111,15 +118,289 @@ class PlSqlJoin } return $str; } + + /** Build a left join + * @param table The name of the table. + * @param condition The condition of the jointure + */ + public static function left() + { + $params = func_get_args(); + return new PlSqlJoin(self::MODE_LEFT, $params); + } + + /** Build a right join + * @param table The name of the table. + * @param condition The condition of the jointure + */ + public static function right() + { + $params = func_get_args(); + return new PlSqlJoin(self::MODE_RIGHT, $params); + } + + /** Build a inner join + * @param table The name of the table. + * @param condition The condition of the jointure + */ + public static function inner() + { + $params = func_get_args(); + return new PlSqlJoin(self::MODE_INNER, $params); + } +} +// }}} + +// {{{ class PlFilterOrder +/** Base class for ordering results of a query. + * Parameters for the ordering must be given to the constructor ($desc for a + * descending order). + * The getSortTokens function is used to get actual ordering part of the query. + */ +abstract class PlFilterOrder +{ + protected $desc = false; + public function __construct($desc = false) + { + $this->desc = $desc; + $this->_tokens = null; + } + + public function toggleDesc() + { + $this->desc = !$this->desc; + } + + public function setDescending($desc = true) + { + $this->desc = $desc; + } + + public function buildSort(PlFilter &$pf) + { + $sel = $this->getSortTokens($pf); + $this->_tokens = $sel; + if (!is_array($sel)) { + $sel = array($sel); + } + if ($this->desc) { + foreach ($sel as $k => $s) { + $sel[$k] = $s . ' DESC'; + } + } + return $sel; + } + + /** This function must return the tokens to use for ordering + * @param &$pf The PlFilter whose results must be ordered + * @return The name of the field to use for ordering results + */ + abstract protected function getSortTokens(PlFilter &$pf); } +// }}} + +// {{{ class PlFilterGroupableOrder +/** Extension of a PlFilterOrder, for orders where the value on which ordering + * is done could be used for grouping results (promo, country, ...) + */ +class PlFilterGroupableOrder extends PlFilterOrder +{ + /** This function will be called when trying to retrieve groups; + * the returned token will be used to group the values. + * It will always be called AFTER getSortTokens(). + */ + public function getGroupToken(PlFilter &$pf) + { + return $this->_tokens; + } +} +// }}} + +// {{{ class PFO_Random +class PFO_Random extends PlFilterOrder +{ + private $seed = null; + + public function __construct($seed = null, $desc = false) + { + parent::__construct($desc); + $this->seed = $seed; + } + + protected function getSortTokens(PlFilter &$pf) + { + if ($this->seed == null) { + return 'RAND()'; + } else { + return XDB::format('RAND({?})', $this->seed); + } + } +} +// }}} + +// {{{ interface PlFilterCondition +interface PlFilterCondition +{ + const COND_TRUE = 'TRUE'; + const COND_FALSE = 'FALSE'; + + public function buildCondition(PlFilter &$pf); +} +// }}} + +// {{{ class PFC_OneChild +abstract class PFC_OneChild implements PlFilterCondition +{ + protected $child; + + public function __construct(&$child = null) + { + if (!is_null($child) && ($child instanceof PlFilterCondition)) { + $this->setChild($child); + } + } + public function setChild(PlFilterCondition &$cond) + { + $this->child =& $cond; + } +} +// }}} + +// {{{ class PFC_NChildren +abstract class PFC_NChildren implements PlFilterCondition +{ + protected $children = array(); + + public function __construct() + { + $this->addChildren(pl_flatten(func_get_args())); + } + + public function addChildren(array $conds) + { + foreach ($conds as &$cond) { + if (!is_null($cond) && ($cond instanceof PlFilterCondition)) { + $this->addChild($cond); + } + } + } + + public function addChild(PlFilterCondition &$cond) + { + $this->children[] =& $cond; + } + + protected function catConds(array $cond, $op, $fallback) + { + if (count($cond) == 0) { + return $fallback; + } else if (count($cond) == 1) { + return $cond[0]; + } else { + return '(' . implode(') ' . $op . ' (', $cond) . ')'; + } + } +} +// }}} + +// {{{ class PFC_True +class PFC_True implements PlFilterCondition +{ + public function buildCondition(PlFilter &$uf) + { + return self::COND_TRUE; + } +} +// }}} + +// {{{ class PFC_False +class PFC_False implements PlFilterCondition +{ + public function buildCondition(PlFilter &$uf) + { + return self::COND_FALSE; + } +} +// }}} + +// {{{ class PFC_Not +class PFC_Not extends PFC_OneChild +{ + public function buildCondition(PlFilter &$uf) + { + $val = $this->child->buildCondition($uf); + if ($val == self::COND_TRUE) { + return self::COND_FALSE; + } else if ($val == self::COND_FALSE) { + return self::COND_TRUE; + } else { + return 'NOT (' . $val . ')'; + } + } +} +// }}} + +// {{{ class PFC_And +class PFC_And extends PFC_NChildren +{ + public function buildCondition(PlFilter &$uf) + { + if (empty($this->children)) { + return self::COND_FALSE; + } else { + $true = self::COND_FALSE; + $conds = array(); + foreach ($this->children as &$child) { + $val = $child->buildCondition($uf); + if ($val == self::COND_TRUE) { + $true = self::COND_TRUE; + } else if ($val == self::COND_FALSE) { + return self::COND_FALSE; + } else { + $conds[] = $val; + } + } + return $this->catConds($conds, 'AND', $true); + } + } +} +// }}} + +// {{{ class PFC_Or +class PFC_Or extends PFC_NChildren +{ + public function buildCondition(PlFilter &$uf) + { + if (empty($this->children)) { + return self::COND_TRUE; + } else { + $true = self::COND_TRUE; + $conds = array(); + foreach ($this->children as &$child) { + $val = $child->buildCondition($uf); + if ($val == self::COND_TRUE) { + return self::COND_TRUE; + } else if ($val == self::COND_FALSE) { + $true = self::COND_FALSE; + } else { + $conds[] = $val; + } + } + return $this->catConds($conds, 'OR', $true); + } + } +} +// }}} + +// {{{ class PlFilter 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 filter(array $objects, $limit = null); public abstract function setCondition(PlFilterCondition &$cond); @@ -127,10 +408,20 @@ abstract class PlFilter public abstract function getTotalCount(); + /** Whether this PlFilter can return grouped results through + * $this->getGroups(); + */ + public abstract function hasGroups(); + + /** Used to retrieve value/amount resulting from grouping by the first + * given order. + */ + public abstract function getGroups(); + /** Get objects, selecting only those within a limit * @param $limit The portion of the matching objects to select */ - public abstract function get(PlLimit &$limit); + public abstract function get($limit = null); /** PRIVATE FUNCTIONS */ @@ -140,21 +431,25 @@ abstract class PlFilter * * "$ME" => "joined table alias" is always added to these. */ - private $joinMetas = array(); + protected $joinMetas = array(); + + protected $joinMethods = 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() + protected function buildJoins() { $joins = array(); - foreach ($this->$joinMethods as $method) { + foreach ($this->joinMethods as $method) { $joins = array_merge($joins, $this->$method()); } - return PlSqlJoin::formatJoins($joins, $this->$joinMetas); + return PlSqlJoin::formatJoins($joins, $this->joinMetas); } } +// }}} +// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: ?>