public function __call($m, $a)
{
if ( ! ($a[0] instanceof IPF_ORM_Event)) {
- throw new IPF_ORM_Exception_Profiler("Couldn't listen event. Event should be an instance of Doctrine_Event.");
+ throw new IPF_ORM_Exception_Profiler("Couldn't listen event. Event should be an instance of IPF_Event.");
}
--- /dev/null
+<?php
+
+class IPF_ORM_Pager
+{
+ protected $_query;
+ protected $_countQuery;
+ protected $_countQueryParams;
+ protected $_numResults;
+ protected $_maxPerPage;
+ protected $_page;
+ protected $_lastPage;
+ protected $_executed;
+
+ public function __construct($query, $page, $maxPerPage = 0)
+ {
+ $this->_setExecuted(false);
+
+ $this->_setQuery($query);
+ $this->_setPage($page);
+
+ $this->setMaxPerPage($maxPerPage);
+ }
+
+ protected function _initialize($params = array())
+ {
+ // retrieve the number of items found
+ $count = $this->getCountQuery()->count($this->getCountQueryParams($params));
+
+ $this->_setNumResults($count);
+ $this->_setExecuted(true); // _adjustOffset relies of _executed equals true = getNumResults()
+
+ $this->_adjustOffset();
+ }
+
+ protected function _adjustOffset()
+ {
+ // Define new total of pages
+ $this->_setLastPage(
+ max(1, ceil($this->getNumResults() / $this->getMaxPerPage()))
+ );
+ $offset = ($this->getPage() - 1) * $this->getMaxPerPage();
+
+ // Assign new offset and limit to IPF_ORM_Query object
+ $p = $this->getQuery();
+ $p->offset($offset);
+ $p->limit($this->getMaxPerPage());
+ }
+
+ public function getExecuted()
+ {
+ return $this->_executed;
+ }
+
+ protected function _setExecuted($executed)
+ {
+ $this->_executed = $executed;
+ }
+
+ public function getRange($rangeStyle, $options = array())
+ {
+ $class = 'IPF_ORM_Pager_Range_' . ucfirst($rangeStyle);
+ return new $class($options, $this);
+ }
+
+ public function getNumResults()
+ {
+ if ($this->getExecuted()) {
+ return $this->_numResults;
+ }
+ throw new IPF_ORM_Exception(
+ 'Cannot retrieve the number of results of a not yet executed Pager query'
+ );
+ }
+
+ protected function _setNumResults($nb)
+ {
+ $this->_numResults = $nb;
+ }
+
+ public function getFirstPage()
+ {
+ return 1;
+ }
+
+ public function getLastPage()
+ {
+ if ($this->getExecuted()) {
+ return $this->_lastPage;
+ }
+
+ throw new IPF_ORM_Exception(
+ 'Cannot retrieve the last page number of a not yet executed Pager query'
+ );
+ }
+
+ protected function _setLastPage($page)
+ {
+ $this->_lastPage = $page;
+
+ if ($this->getPage() > $page) {
+ $this->_setPage($page);
+ }
+ }
+
+ public function getPage()
+ {
+ return $this->_page;
+ }
+
+ public function getNextPage()
+ {
+ if ($this->getExecuted()) {
+ return min($this->getPage() + 1, $this->getLastPage());
+ }
+
+ throw new IPF_ORM_Exception(
+ 'Cannot retrieve the last page number of a not yet executed Pager query'
+ );
+ }
+
+ public function getPreviousPage()
+ {
+ if ($this->getExecuted()) {
+ return max($this->getPage() - 1, $this->getFirstPage());
+ }
+
+ throw new IPF_ORM_Exception(
+ 'Cannot retrieve the previous page number of a not yet executed Pager query'
+ );
+ }
+
+ public function getFirstIndice()
+ {
+ return ($this->getPage() - 1) * $this->getMaxPerPage() + 1;
+ }
+
+ public function getLastIndice()
+ {
+ return min($this->getNumResults(), ($this->getPage() * $this->getMaxPerPage()));
+ }
+
+ public function haveToPaginate()
+ {
+ if ($this->getExecuted()) {
+ return $this->getNumResults() > $this->getMaxPerPage();
+ }
+
+ throw new IPF_ORM_Exception(
+ 'Cannot know if it is necessary to paginate a not yet executed Pager query'
+ );
+ }
+
+ public function setPage($page)
+ {
+ $this->_setPage($page);
+ $this->_setExecuted(false);
+ }
+
+ private function _setPage($page)
+ {
+ $page = intval($page);
+ $this->_page = ($page <= 0) ? 1 : $page;
+ }
+
+ public function getMaxPerPage()
+ {
+ return $this->_maxPerPage;
+ }
+
+ public function setMaxPerPage($max)
+ {
+ if ($max > 0) {
+ $this->_maxPerPage = $max;
+ } else if ($max == 0) {
+ $this->_maxPerPage = 25;
+ } else {
+ $this->_maxPerPage = abs($max);
+ }
+
+ $this->_setExecuted(false);
+ }
+
+ public function getResultsInPage()
+ {
+ $page = $this->getPage();
+
+ if ($page != $this->getLastPage()) {
+ return $this->getMaxPerPage();
+ }
+
+ $offset = ($this->getPage() - 1) * $this->getMaxPerPage();
+
+ return abs($this->getNumResults() - $offset);
+ }
+
+ public function getQuery()
+ {
+ return $this->_query;
+ }
+
+ protected function _setQuery($query)
+ {
+ if (is_string($query)) {
+ $query = IPF_ORM_Query::create()->parseQuery($query);
+ }
+
+ $this->_query = $query;
+ }
+
+ public function getCountQuery()
+ {
+ return ($this->_countQuery !== null) ? $this->_countQuery : $this->_query;
+ }
+
+ public function setCountQuery($query, $params = null)
+ {
+ if (is_string($query)) {
+ $query = IPF_ORM_Query::create()->parseQuery($query);
+ }
+
+ $this->_countQuery = $query;
+
+ $this->setCountQueryParams($params);
+
+ $this->_setExecuted(false);
+ }
+
+ public function getCountQueryParams($defaultParams = array())
+ {
+ return ($this->_countQueryParams !== null) ? $this->_countQueryParams : $defaultParams;
+ }
+
+ public function setCountQueryParams($params = array(), $append = false)
+ {
+ if ($append && is_array($this->_countQueryParams)) {
+ $this->_countQueryParams = array_merge($this->_countQueryParams, $params);
+ } else {
+ if ($params !== null && !is_array($params)) {
+ $params = array($params);
+ }
+
+ $this->_countQueryParams = $params;
+ }
+
+ $this->_setExecuted(false);
+ }
+
+ public function execute($params = array(), $hydrationMode = IPF_ORM::FETCH_RECORD)
+ {
+ if (!$this->getExecuted()) {
+ $this->_initialize($params);
+ }
+ return $this->getQuery()->execute($params, $hydrationMode);
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+class IPF_ORM_Pager_Layout
+{
+ private $_pager;
+ private $_pagerRange;
+ private $_template;
+ private $_selectedTemplate;
+ private $_separatorTemplate;
+ private $_urlMask;
+ private $_maskReplacements = array();
+
+ public function __construct($pager, $pagerRange, $urlMask)
+ {
+ $this->_setPager($pager);
+ $this->_setPagerRange($pagerRange);
+ $this->_setUrlMask($urlMask);
+
+ $this->setTemplate('[<a href="{%url}">{%page}</a>]');
+ $this->setSelectedTemplate('');
+ $this->setSeparatorTemplate('');
+ }
+
+ public function getPager()
+ {
+ return $this->_pager;
+ }
+
+ protected function _setPager($pager)
+ {
+ $this->_pager = $pager;
+ }
+
+ public function execute($params = array(), $hydrationMode = IPF_ORM::FETCH_RECORD)
+ {
+ return $this->getPager()->execute($params, $hydrationMode);
+ }
+
+ public function getPagerRange()
+ {
+ return $this->_pagerRange;
+ }
+
+ protected function _setPagerRange($pagerRange)
+ {
+ $this->_pagerRange = $pagerRange;
+ $this->getPagerRange()->setPager($this->getPager());
+ }
+
+ public function getUrlMask()
+ {
+ return $this->_urlMask;
+ }
+
+ protected function _setUrlMask($urlMask)
+ {
+ $this->_urlMask = $urlMask;
+ }
+
+ public function getTemplate()
+ {
+ return $this->_template;
+ }
+
+ public function setTemplate($template)
+ {
+ $this->_template = $template;
+ }
+
+ public function getSelectedTemplate()
+ {
+ return $this->_selectedTemplate;
+ }
+
+ public function setSelectedTemplate($selectedTemplate)
+ {
+ $this->_selectedTemplate = $selectedTemplate;
+ }
+
+ public function getSeparatorTemplate()
+ {
+ return $this->_separatorTemplate;
+ }
+
+ public function setSeparatorTemplate($separatorTemplate)
+ {
+ $this->_separatorTemplate = $separatorTemplate;
+ }
+
+ public function addMaskReplacement($oldMask, $newMask, $asValue = false)
+ {
+ if (($oldMask = trim($oldMask)) != 'page_number') {
+ $this->_maskReplacements[$oldMask] = array(
+ 'newMask' => $newMask,
+ 'asValue' => ($asValue === false) ? false : true
+ );
+ }
+ }
+
+ public function removeMaskReplacement($oldMask)
+ {
+ if (isset($this->_maskReplacements[$oldMask])) {
+ $this->_maskReplacements[$oldMask] = null;
+ unset($this->_maskReplacements[$oldMask]);
+ }
+ }
+
+ public function cleanMaskReplacements()
+ {
+ $this->_maskReplacements = null;
+ $this->_maskReplacements = array();
+ }
+
+ public function display($options = array(), $return = true)
+ {
+ $range = $this->getPagerRange()->rangeAroundPage();
+ $str = '';
+
+ // For each page in range
+ for ($i = 0, $l = count($range); $i < $l; $i++) {
+ // Define some optional mask values
+ $options['page_number'] = $range[$i];
+
+ $str .= $this->processPage($options);
+
+ // Apply separator between pages
+ if ($i < $l - 1) {
+ $str .= $this->getSeparatorTemplate();
+ }
+ }
+
+ // Possible wish to return value instead of print it on screen
+ if ($return) {
+ return $str;
+ }
+
+ echo $str;
+ }
+
+ public function processPage($options = array())
+ {
+ // Check if at least basic options are defined
+ if (!isset($options['page_number'])) {
+ throw new IPF_ORM_Exception(
+ 'Cannot process template of the given page. ' .
+ 'Missing at least one of needed parameters: \'page\' or \'page_number\''
+ );
+
+ // Should never reach here
+ return '';
+ }
+
+ // Assign "page" options index if not defined yet
+ if (!isset($this->_maskReplacements['page']) && !isset($options['page'])) {
+ $options['page'] = $options['page_number'];
+ }
+
+ return $this->_parseTemplate($options);
+ }
+
+ public function __toString()
+ {
+ return $this->display(array(), true);
+ }
+
+ protected function _parseTemplate($options = array())
+ {
+ $str = $this->_parseUrlTemplate($options);
+ $replacements = $this->_parseReplacementsTemplate($options);
+
+ return strtr($str, $replacements);
+ }
+
+ protected function _parseUrlTemplate($options = array())
+ {
+ $str = '';
+
+ // If given page is the current active one
+ if ($options['page_number'] == $this->getPager()->getPage()) {
+ $str = $this->_parseMaskReplacements($this->getSelectedTemplate());
+ }
+
+ // Possible attempt where Selected == Template
+ if ($str == '') {
+ $str = $this->_parseMaskReplacements($this->getTemplate());
+ }
+
+ return $str;
+ }
+
+ protected function _parseReplacementsTemplate($options = array())
+ {
+ // Defining "url" options index to allow {%url} mask
+ $options['url'] = $this->_parseUrl($options);
+
+ $replacements = array();
+
+ foreach ($options as $k => $v) {
+ $replacements['{%'.$k.'}'] = $v;
+ }
+
+ return $replacements;
+ }
+
+ protected function _parseUrl($options = array())
+ {
+ $str = $this->_parseMaskReplacements($this->getUrlMask());
+
+ $replacements = array();
+
+ foreach ($options as $k => $v) {
+ $replacements['{%'.$k.'}'] = $v;
+ }
+
+ return strtr($str, $replacements);
+ }
+
+ protected function _parseMaskReplacements($str)
+ {
+ $replacements = array();
+
+ foreach ($this->_maskReplacements as $k => $v) {
+ $replacements['{%'.$k.'}'] = ($v['asValue'] === true) ? $v['newMask'] : '{%'.$v['newMask'].'}';
+ }
+
+ return strtr($str, $replacements);
+ }
+}
--- /dev/null
+<?php
+
+abstract class IPF_ORM_Pager_Range
+{
+ protected $_options;
+ private $pager;
+
+ final public function __construct($options = array(), $pager = null)
+ {
+ $this->_setOptions($options);
+
+ if ($pager !== null) {
+ $this->setPager($pager);
+ }
+ }
+
+ public function getPager()
+ {
+ return $this->pager;
+ }
+
+ public function setPager($pager)
+ {
+ $this->pager = $pager;
+
+ // Lazy-load initialization. It only should be called when all
+ // needed information data is ready (this can only happens when we have
+ // options stored and a IPF_ORM_Pager assocated)
+ $this->_initialize();
+ }
+
+ public function getOptions()
+ {
+ return $this->_options;
+ }
+
+ public function getOption($option)
+ {
+ if (isset($this->_options[$option])) {
+ return $this->_options[$option];
+ }
+
+ throw new IPF_ORM_Exception(
+ 'Cannot access unexistent option \'' . $option . '\' in IPF_ORM_Pager_Range class'
+ );
+ }
+
+ protected function _setOptions($options)
+ {
+ $this->_options = $options;
+ }
+
+ public function isInRange($page)
+ {
+ return (array_search($page, $this->rangeAroundPage()) !== false);
+ }
+
+ abstract protected function _initialize();
+
+ abstract public function rangeAroundPage();
+}
--- /dev/null
+<?php
+
+class IPF_ORM_Pager_Range_Jumping extends IPF_ORM_Pager_Range
+{
+ private $_chunkLength;
+
+ protected function _initialize()
+ {
+ if (isset($this->_options['chunk'])) {
+ $this->_setChunkLength($this->_options['chunk']);
+ } else {
+ throw new IPF_ORM_Exception('Missing parameter \'chunk\' that must be define in options.');
+ }
+ }
+
+ public function getChunkLength()
+ {
+ return $this->_chunkLength;
+ }
+
+ protected function _setChunkLength($chunkLength)
+ {
+ $this->_chunkLength = $chunkLength;
+ }
+
+ public function rangeAroundPage()
+ {
+ $pager = $this->getPager();
+
+ if ($pager->getExecuted()) {
+ $page = $pager->getPage();
+
+ // Define initial assignments for StartPage and EndPage
+ $startPage = $page - ($page - 1) % $this->getChunkLength();
+ $endPage = ($startPage + $this->getChunkLength()) - 1;
+
+ // Check for EndPage out-range
+ if ($endPage > $pager->getLastPage()) {
+ $endPage = $pager->getLastPage();
+ }
+
+ // No need to check for out-range in start, it will never happens
+
+ return range($startPage, $endPage);
+ }
+
+ throw new IPF_ORM_Exception(
+ 'Cannot retrieve the range around the page of a not yet executed Pager query'
+ );
+ }
+}
--- /dev/null
+<?php
+
+class IPF_ORM_Pager_Range_Sliding extends IPF_ORM_Pager_Range
+{
+ private $_chunkLength;
+
+ protected function _initialize()
+ {
+ if (isset($this->_options['chunk'])) {
+ $this->_setChunkLength($this->_options['chunk']);
+ } else {
+ throw new IPF_ORM_Exception('Missing parameter \'chunk\' that must be defined in options.');
+ }
+ }
+
+ public function getChunkLength()
+ {
+ return $this->_chunkLength;
+ }
+
+ protected function _setChunkLength($chunkLength)
+ {
+ $chunkLength = (int) $chunkLength;
+ if (!$chunkLength) {
+ $chunkLength = 1;
+ } else {
+ $this->_chunkLength = $chunkLength;
+ }
+ }
+
+ public function rangeAroundPage()
+ {
+ $pager = $this->getPager();
+
+ if ($pager->getExecuted()) {
+ $page = $pager->getPage();
+ $pages = $pager->getLastPage();
+
+ $chunk = $this->getChunkLength();
+
+ if ($chunk > $pages) {
+ $chunk = $pages;
+ }
+
+ $chunkStart = $page - (floor($chunk / 2));
+ $chunkEnd = $page + (ceil($chunk / 2)-1);
+
+ if ($chunkStart < 1) {
+ $adjust = 1 - $chunkStart;
+ $chunkStart = 1;
+ $chunkEnd = $chunkEnd + $adjust;
+ }
+
+ if ($chunkEnd > $pages) {
+ $adjust = $chunkEnd - $pages;
+ $chunkStart = $chunkStart - $adjust;
+ $chunkEnd = $pages;
+ }
+
+ return range($chunkStart, $chunkEnd);
+ }
+
+ throw new IPF_ORM_Exception(
+ 'Cannot retrieve the range around the page of a not yet executed Pager query'
+ );
+ }
+}