kernel
[ class tree: kernel ] [ index: kernel ] [ all elements ]

Source for file BitBase.php

Documentation is available at BitBase.php

  1. <?php
  2. /**
  3.  * Virtual bitweaver base class
  4.  *
  5.  * @package kernel
  6.  * @version $Header$
  7.  *
  8.  *  Copyright (c) 2004 bitweaver.org
  9.  *  All Rights Reserved. See below for details and a complete list of authors.
  10.  *  Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See http://www.gnu.org/copyleft/lesser.html for details
  11.  *
  12.  *  Virtual base class (as much as one can have such things in PHP) for all
  13.  *  derived tikiwiki classes that require database access.
  14.  *
  15.  *  created 2004/8/15
  16.  *
  17.  * @author spider <spider@steelsun.com>
  18.  */
  19.  
  20. /**
  21.  * required setup
  22.  */
  23. require_once ( KERNEL_PKG_PATH.'BitDbBase.php' );
  24.  
  25. define( 'STORAGE_BINARY', 1 );
  26. define( 'STORAGE_IMAGE', 2 );
  27.  
  28. /**
  29.  * Virtual base for BitCacheable.
  30.  *
  31.  * @package kernel
  32.  */
  33. interface BitCacheable  {
  34.     public function getCacheKey(); 
  35. }
  36.  
  37. /**
  38.  * Virtual base class (as much as one can have such things in PHP) for all
  39.  * derived bitweaver classes that require database access.
  40.  *
  41.  * @package kernel
  42.  */
  43. abstract class BitBase {
  44.     /**
  45.      * Error hash that will contain an error codes we encounter along
  46.      * the way this hash can be used by presentation layer ti give feedback
  47.      * to the user.
  48.      * @todo not used yet
  49.      * @private
  50.      */
  51.     var $mErrors;
  52.  
  53.     /**
  54.      * Same idea as the error hash but this is for successful operations
  55.      * @private
  56.      */
  57.     var $mSuccess;
  58.  
  59.     /**
  60.      * String used to refer to preference caching and database table
  61.      * @private
  62.      */
  63.     var $mName;
  64.  
  65.     /**
  66.      * Used to store database mechanism
  67.      * @private
  68.      */
  69.     var $mDb;
  70.  
  71.     /**
  72.      * Used to store database type
  73.      * @private
  74.      */
  75.     var $dType;
  76.  
  77.     /**
  78.      * Standard Query Cache Time. Variable can be set to 0 to flush particular queries
  79.      * @private
  80.      */
  81.     var $mCacheTime;
  82.  
  83.     /**
  84.      * Data hash that represents this classes row(s) in the db
  85.      **/
  86.  
  87.     var $mInfo = array();
  88.  
  89.     /**
  90.      * Data hash that contains logging information relevant to database operations
  91.      **/
  92.  
  93.     var $mLogs = array();
  94.  
  95.     var $mPreventCache = FALSE;
  96.  
  97.  
  98.     const CACHE_STATE_NONE = 0;
  99.     const CACHE_STATE_DELETE = -1;
  100.     const CACHE_STATE_ADDED = 1;
  101.     const CACHE_STATE_STORED = 2;
  102.  
  103.     function __construct( $pName = '' ) {
  104.         global $gBitDb;
  105.         $this->mName = $pName;
  106.         $this->mCacheTime = BIT_QUERY_CACHE_TIME;
  107.         if( is_object( $gBitDb ) ) {
  108.             $this->setDatabase($gBitDb);
  109.         }
  110.         $this->mErrors = array();
  111.         $this->mInfo = array();
  112.     }
  113.  
  114.     function __destruct() {
  115.         unset( $this->mDb );
  116.         $this->storeInCache();
  117.     }
  118.  
  119.     protected function load() {
  120.         return TRUE;
  121.     }
  122.  
  123.     /**
  124.      * During initialisation, we assign a name which is used by the class.
  125.      * @param pName a unique identified used in caching and database
  126.      *  mechanisms
  127.      ***/
  128.     function BitBase( $pName = '' ) {
  129.         self::__construct( $pName );
  130.     }
  131.  
  132.     /**
  133.      * Delete content object and all related records
  134.      *
  135.      * @access public
  136.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  137.      */
  138.     protected function expunge() {
  139.         $this->clearFromCache();
  140.     }
  141.  
  142.     public function clearFromCache( &$pParamHash=NULL ) {
  143.         $this->mCacheTime = BIT_QUERY_CACHE_DISABLE;
  144.         if( $this->isCacheableObject() && static::isCacheActive() && ($cacheKey = $this->getCacheUuid()) ) {
  145.             $ret = apc_delete( $cacheKey );
  146.         }
  147.     }
  148.  
  149.     /**
  150. /**
  151.      * storeInCache
  152.      *
  153.      * @param string $pCacheKey unique identifier for object in cache store
  154.      * @access public
  155.      * @return TRUE on success, FALSE on failure
  156.      */
  157.     protected function storeInCache() {
  158.         $ret = FALSE;
  159.         if( $this->isCacheableObject() && static::isCacheActive() && ($cacheKey = $this->getCacheUuid()) ) {
  160.             $ret = apc_store( $cacheKey, $this, 3600 );
  161.         }
  162.         return $ret;
  163.     }
  164.  
  165.     public function __wakeup() {
  166.         global $gBitDb;
  167.         $this->setDatabase( $gBitDb );
  168.     }
  169.  
  170.     public static function loadFromCache( $pCacheKey ) {
  171.         $ret = NULL;
  172.         if( static::isCacheActive() && static::isCacheableClass() && !empty( $pCacheKey ) ) {
  173.             if( $ret = apc_fetch( static::getCacheUuidFromKey( $pCacheKey ) ) ) {
  174.             } else {
  175.             }
  176.         }
  177.         return $ret;
  178.     }
  179.  
  180.     static public function getObjectById( $pObjectId ) {
  181.         $className = get_called_class();
  182.         if( !($ret = $className::loadFromCache( $pObjectId ) ) ) {
  183.             $ret = new $className( $pObjectId );
  184.             $ret->load();
  185.         }
  186.         return $ret;
  187.     }
  188.  
  189.     public function getCacheUuid() {
  190.         return static::getCacheUuidFromKey( $this->getCacheKey() );
  191.     }
  192.  
  193.     public static function getCacheUuidFromKey( $pCacheUuid = '' ) {
  194.         global $gBitDbName, $gBitDbHost;
  195.         $ret = $_SERVER['HTTP_HOST'].':'.$gBitDbName.'@'.$gBitDbHost.':'.get_called_class().'#'.$pCacheUuid;
  196.         return $ret;
  197.     }
  198.  
  199.     public static function isCacheActive() {
  200.         // only apc is supported for now.
  201.         return (function_exists( 'apc_add' ) && defined( 'BIT_CACHE_OBJECTS' ) && BIT_CACHE_OBJECTS );
  202.     }
  203.  
  204.     public function isCacheableObject() {
  205.         return method_exists( $this, 'getCacheKey' ) && empty( $this->mPreventCache );
  206.     }
  207.  
  208.     public static function isCacheableClass() {
  209.         return false;
  210.     }
  211.  
  212.     public function isCached() {
  213.         return apc_exists( $this->getCacheUuid() );
  214.     }
  215.  
  216.     public function setCacheableObject( $pCacheState = TRUE ) {
  217.         $this->mPreventCache = !empty( $pCacheState );
  218.     }
  219.  
  220.     final public static function getClass() {
  221.         return get_called_class();
  222.     }
  223.  
  224.     public function getConfig( $pName, $pDefault = NULL ) {
  225.         global $gBitSystem;
  226.         return $gBitSystem->getConfig( $pName, $pDefault );
  227.     }
  228.  
  229.     public function isFeatureActive( $pFeatureName ) {
  230.         global $gBitSystem;
  231.         return $gBitSystem->isFeatureActive( $pFeatureName );
  232.     }
  233.  
  234.     /**
  235.      * Sets database mechanism for the instance
  236.      * @param pDB the instance of the database mechanism
  237.      ***/
  238.     public function setDatabase( &$pDB ) {
  239.         // set internal db and retrieve values
  240.         $this->mDb = &$pDB;
  241.         $this->dType = $this->mDb->mType;
  242.     }
  243.  
  244.     /**
  245.      * Determines if there is a valide database connection
  246.      **/
  247.  
  248.     public function isDatabaseValid() {
  249.         return( !empty( $this->mDb ) && $this->mDb->isValid() );
  250.     }
  251.  
  252.     /**
  253.      * Return pointer to current Database
  254.      **/
  255.  
  256.     public function getDb() {
  257.         return ( !empty( $this->mDb ) ? $this->mDb : NULL  );
  258.     }
  259.  
  260.     function debugMarkTime() {
  261.         $this->mDebugMicrotime = microtime(1);
  262.     }
  263.  
  264.     function debugOutput( $pString ) {
  265.         global $gDebug;
  266.         if( $gDebug || !defined( 'IS_LIVE' ) || !IS_LIVE ) {
  267.             if( empty(  $this->mLastOutputTime ) ) {
  268.                 $elapsed = (float)0.000;
  269.             } else {
  270.                 $elapsed = (microtime(1) - (float)$this->mLastOutputTime);
  271.             }
  272.             if( !empty( $this->mDebugMicrotime ) ) {
  273.                 $pString = "ELAPSED TIME: ".round( (float)((microtime(1) - $this->mDebugMicrotime)), 3).' sec, +'.round( $elapsed, 3 ).' '.$pString;
  274.             }
  275.             bit_error_log( $pString );
  276.             $this->mLastOutputTime = microtime(1);
  277.         }
  278.     }
  279.     // =-=-=-=-=-=-=-=-=-=-=- Non-DB related functions =-=-=-=-=-=-=-=-=-=-=-=-=
  280.  
  281.     /**
  282.      * verifyIdParamter Determines if any given variable exists and is a number
  283.      *
  284.      * @param mixed $pId this can be a string, number or array. if it's an array, all values in the array will be checked to see if they are numeric
  285.      * @access public
  286.      * @return TRUE if the input was numeric, FALSE if it wasn't
  287.      */
  288.     public static function verifyIdParameter( &$pParamHash, $pKey ) {
  289.         // check all possibilities as quickly as possible as this function is called frequently
  290.         return !empty( $pParamHash[$pKey] ) && (is_int( $pParamHash[$pKey] ) || ctype_digit( $pParamHash[$pKey] ) || (is_numeric($pParamHash[$pKey]) ? intval( $pParamHash[$pKey] ) == $pParamHash[$pKey] : false));
  291.     }
  292.  
  293.     /**
  294.      * verifyId Determines if any given variable exists and is a number
  295.      *
  296.      * @param mixed $pId this can be a string, number or array. if it's an array, all values in the array will be checked to see if they are numeric
  297.      * @access public
  298.      * @return TRUE if the input was numeric, FALSE if it wasn't
  299.      */
  300.     public static function verifyId( $pId ) {
  301.         if( empty( $pId )) {
  302.             return FALSE;
  303.         }
  304.         if( is_array( $pId )) {
  305.             foreach( $pId as $id ) {
  306.                 if( (is_int( $id ) || ctype_digit( $id ) || (is_numeric( $id ) ? intval( $id ) == $id : false)) ) {
  307.                     return FALSE;
  308.                 }
  309.             }
  310.             return TRUE;
  311.         }
  312.         return( !empty( $pId ) && (is_int( $pId ) || ctype_digit( $pId ) || (is_numeric( $pId ) ? intval( $pId ) == $pId : false)) );
  313. ;
  314.     }
  315.  
  316.     /**
  317.      * getParameter Gets a hash value it exists, or returns an optional default
  318.      *
  319.      * @param associativearray $pParamHash Hash of key=>value pairs
  320.      * @param string $pHashKey Key used to search for value
  321.      * @param string $pDefault Default value to return if not found. NULL if nothing is passed in.
  322.      * @access public
  323.      * @return TRUE if the input was numeric, FALSE if it wasn't
  324.      */
  325.     public static function getParameter( &$pParamHash, $pKey, $pDefaultValue=NULL ) {
  326.         if( isset( $pParamHash[$pKey] ) ) {
  327.             $ret = $pParamHash[$pKey];
  328.         } else {
  329.             $ret = $pDefaultValue;
  330.         }
  331.  
  332.         return $ret;
  333.     }
  334.  
  335.     /**
  336.      * This method should be THE method used to display a template. php files should not
  337.      * access $gBitSmarty directly.
  338.      *
  339.      * @param string pMsg error message to be displayed
  340.      * @return none this function will DIE DIE DIE!!!
  341.      * @access public
  342.      ***/
  343.     public function display( $pPackage, $pTemplate ) {
  344.         global $gBitSmarty, $gBitLanguage, $style, $style_base;
  345.         if( !empty( $style ) && !empty( $style_base )) {
  346.             if (file_exists(BIT_THEMES_PATH."styles/$style_base/$pTemplate")) {
  347.                 // Theme has overriden template
  348.                 $_smarty_tpl_file = 'file:'.BIT_STYLES_PATH."/$style_base/$pTemplate";
  349.             } else {
  350.                 // Use default
  351.                 $_smarty_tpl_file = 'file:'.BIT_ROOT_PATH."$pPackage/templates/$pTemplate";
  352.             }
  353.         }
  354. /*
  355.         global $gBitLanguage, $style, $style_base;
  356.         if (isset($style) && isset($style_base)) {
  357.             if (file_exists(BIT_STYLES_PATH."/$style_base/$_smarty_tpl_file")) {
  358.                 $_smarty_tpl_file = BIT_STYLES_PATH."/$style_base/$_smarty_tpl_file";
  359.             }
  360.         }
  361.  */
  362.         $gBitSmarty->display( $_smarty_tpl_file );
  363.         //        $gBitSmarty->display( 'bitpackage:'.$pPackage.$pTemplate );
  364.     }
  365.  
  366.     /**
  367.      * Assign an entry to the mInfo hash if the current object is valid
  368.      * @param pFieldName the hash key to retrieve the value
  369.      * @param pValue the value of the hash key
  370.      ***/
  371.     public function setField( $pFieldName, $pValue ) {
  372.         $ret = FALSE;
  373.         if( $this->isValid() ) {
  374.             $this->mInfo[$pFieldName] = $pValue;
  375.             $ret = TRUE;
  376.         }
  377.         return $ret;
  378.     }
  379.  
  380.     /**
  381.      * Returns entry from the mInfo hash if field exists
  382.      * @param pFieldName the hash key to retrieve the value
  383.      * @param pDefault the value to return of there is now hash value present
  384.      ***/
  385.     public function getField( $pFieldName, $pDefault = NULL ) {
  386.         return( !empty( $this->mInfo[$pFieldName] ) ? $this->mInfo[$pFieldName] : $pDefault );
  387.     }
  388.  
  389.     /**
  390.      * Prepares parameters with default values for any getList function
  391.      * @param pParamHash hash of parameters for any getList() function
  392.      * @return the link to display the page.
  393.      */
  394.     public static function prepGetList( &$pListHash ) {
  395.         global $gBitSmarty, $gBitSystem;
  396.  
  397.         // valid_sort_modes are set, we check them against our selected sort_mode
  398.         if( !empty( $pListHash['sort_mode'] ) && !empty( $pListHash['valid_sort_modes'] ) && is_array( $pListHash['valid_sort_modes'] )) {
  399.             if( is_string( $pListHash['sort_mode'] )) {
  400.                 if( !static::verifySortMode( $pListHash['sort_mode'], $pListHash['valid_sort_modes'] )) {
  401.                     $pListHash['sort_mode'] = '';
  402.                 }
  403.             } elseif( is_array( $pListHash['sort_mode'] )) {
  404.                 // make sure all values of the sort_mode array match something in the valid valid_sort_modes hash
  405.                 foreach( $pListHash['sort_mode'] as $key => $mode ) {
  406.                     if( !static::verifySortMode( $mode, $pListHash['valid_sort_modes'] )) {
  407.                         unset( $pListHash['sort_mode'][$key] );
  408.                     }
  409.                 }
  410.             }
  411.         }
  412.  
  413.         if( empty( $pListHash['max_records'] ) || !is_numeric( $pListHash['max_records'] ) ) {
  414.             global $gBitSystem;
  415.             $pListHash['max_records'] = $gBitSystem->getConfig( "max_records", 10 );
  416.         }
  417.         $pListHash['max_records'] = (int)$pListHash['max_records'];
  418.  
  419.         if( !isset( $pListHash['offset'] ) || !is_numeric( $pListHash['offset'] ) ) {
  420.             $pListHash['offset'] = 0;
  421.             if( isset($pListHash['page'] )) {
  422.                 $pListHash['offset'] = ($pListHash['page'] - 1) * $pListHash['max_records'];
  423.             } else {
  424.                 if( !empty( $_REQUEST["offset"] )) {
  425.                     $pListHash['offset'] = $_REQUEST['offset'];
  426.                 } elseif( isset( $_REQUEST['page'] ) && is_numeric( $_REQUEST['page'] ) && $_REQUEST['page'] > 0 ) {
  427.                     $pListHash['offset'] = ($_REQUEST['page'] - 1) * $pListHash['max_records'];
  428.                 } elseif( isset( $_REQUEST['list_page'] ) && is_numeric( $_REQUEST['list_page'] ) && $_REQUEST['list_page'] > 0 ) {
  429.                     $pListHash['offset'] = ( $_REQUEST['list_page'] - 1 ) * $pListHash['max_records'];
  430.                 }
  431.             }
  432.         }
  433.  
  434.         // migrate towards a safer hash key
  435.         if( empty( $pListHash['user_id'] ) && !empty( $pListHash['lookup_user_id'] ) ) {
  436.             $pListHash['user_id'] = $pListHash['lookup_user_id'];
  437.         }
  438.  
  439.         // Don't use  $_REQUEST["find"] as it can really screw with modules on search pages
  440.         if( !empty( $pListHash["find"] )) {
  441.             $pListHash['find']= $pListHash["find"];
  442.         } else {
  443.             $pListHash['find'] = NULL;
  444.         }
  445.         $gBitSmarty->assign( 'find', $pListHash['find'] );
  446.  
  447.         if( isset( $_REQUEST['date'] )) {
  448.             $pListHash['date']= $_REQUEST['date'];
  449.         } else {
  450.             $pListHash['date'] = $gBitSystem->getUTCTime();
  451.         }
  452.  
  453.         if( empty( $pListHash['load_comments'] )) {
  454.             $pListHash['load_comments'] = FALSE;
  455.         }
  456.         if( empty( $pListHash['load_num_comments'] )) {
  457.             $pListHash['load_num_comments'] = FALSE;
  458.         }
  459.         if( empty( $pListHash['parse_data'] )) {
  460.             $pListHash['parse_data'] = FALSE;
  461.         }
  462.     }
  463.  
  464.     /**
  465.      * verifySortMode is used to validate a given sort_mode agains an array of valid sort modes
  466.      *
  467.      * @param string $pSortMode sort mode to check
  468.      * @param array $pValidSortModes array of available sort modes
  469.      * @access public
  470.      * @return TRUE on success, FALSE on failure
  471.      */
  472.     public static function verifySortMode( $pSortMode, $pValidSortModes ) {
  473.         if( !empty( $pSortMode ) && is_string( $pSortMode ) && !empty( $pValidSortModes ) && is_array( $pValidSortModes )) {
  474.             foreach( $pValidSortModes as $mode ) {
  475.                 // we will not check the table - that would just be too complicated...
  476.                 if( preg_match( "/^(\w+\.)?{$mode}_(desc|asc)$/", $pSortMode )) {
  477.                     return TRUE;
  478.                 }
  479.             }
  480.         }
  481.  
  482.         return FALSE;
  483.     }
  484.  
  485.  
  486.     /**
  487.     * Updates results from any getList function to provide the control set
  488.     * displaying in the smarty template
  489.     * @param array hash of parameters returned by any getList() function
  490.     * @return - none the hash is updated via the reference
  491.     */
  492.     public static function postGetList( &$pListHash ) {
  493.         global $gBitSystem;
  494.         $pListHash['listInfo']['page_records'] = (!empty( $pListHash['page_records'] ) ? $pListHash['page_records'] : $pListHash['max_records'] );
  495.         if( !isset( $pListHash['cant'] ) ) {
  496.             $pListHash['cant'] = $pListHash['max_records'];
  497.         }
  498.  
  499.         if( !isset( $pListHash['offset'] ) || !is_numeric( $pListHash['offset'] ) ) {
  500.             $pListHash['offset'] = 0;
  501.         }
  502.  
  503.         $pListHash['listInfo']['total_records'] = $pListHash['cant'];
  504.         $pListHash['listInfo']['total_pages'] = ceil( $pListHash['cant'] / $pListHash['max_records'] );
  505.         $pListHash['listInfo']['current_page'] = 1 + ( $pListHash['offset'] / $pListHash['max_records'] );
  506.  
  507.         if( isset( $pListHash["cant"] ) && $pListHash["cant"] > ( $pListHash['offset'] + $pListHash['max_records'] ) ) {
  508.             $pListHash['listInfo']['next_offset'] = $pListHash['offset'] + $pListHash['max_records'];
  509.         } else {
  510.             $pListHash['listInfo']['next_offset'] = -1;
  511.         }
  512.  
  513.         // If offset is > 0 then prev_offset
  514.         if( $pListHash['offset'] > 0 ) {
  515.             $pListHash['listInfo']['prev_offset'] = $pListHash['offset'] - $pListHash['max_records'];
  516.         } else {
  517.             $pListHash['listInfo']['prev_offset'] = -1;
  518.         }
  519.  
  520.         $pListHash['listInfo']['offset'] = $pListHash['offset'];
  521.         $pListHash['listInfo']['find'] = $pListHash['find'];
  522.         if( !empty( $pListHash['sort_mode'] ) ) {
  523.             $pListHash['listInfo']['sort_mode'] = $pListHash['sort_mode'];
  524.         }
  525.         $pListHash['listInfo']['max_records'] = $pListHash['max_records'];
  526.  
  527.         $pListHash['listInfo']['block_pages'] = 3;
  528.         $pListHash['listInfo']['start_block'] = floor( $pListHash['offset'] / $pListHash['max_records'] ) * $pListHash['max_records'] + 1;
  529.  
  530.         // calculate what links to show
  531.         if( $gBitSystem->isFeatureActive( 'site_direct_pagination' ) ) {
  532.             // number of continuous links to display on either side
  533.             $continuous = 5;
  534.             // number of skipping links to display on either side
  535.             $skipping = 5;
  536.  
  537.             // size of steps to take when skipping
  538.             // if you have more than 1000 pages, you should consider not using the pagination form
  539.             if( $pListHash['listInfo']['total_pages'] < 50 ) {
  540.                 $step = 5;
  541.             } elseif( $pListHash['listInfo']['total_pages'] < 100 ) {
  542.                 $step = 10;
  543.             } elseif( $pListHash['listInfo']['total_pages'] < 250 ) {
  544.                 $step = 25;
  545.             } elseif( $pListHash['listInfo']['total_pages'] < 500 ) {
  546.                 $step = 50;
  547.             } else {
  548.                 $step = 100;
  549.             }
  550.  
  551.             $prev  = ( $pListHash['listInfo']['current_page'] - $continuous > 0 ) ? $pListHash['listInfo']['current_page'] - $continuous : 1;
  552.             $next  = ( $pListHash['listInfo']['current_page'] + $continuous < $pListHash['listInfo']['total_pages'] ) ? $pListHash['listInfo']['current_page'] + $continuous : $pListHash['listInfo']['total_pages'];
  553.             for( $i = $pListHash['listInfo']['current_page'] - 1; $i >= $prev; $i -= 1 ) {
  554.                 $pListHash['listInfo']['block']['prev'][$i] = $i;
  555.             }
  556.             if( $prev != 1 ) {
  557.                 // replace the last of the continuous links with a ...
  558.                 $pListHash['listInfo']['block']['prev'][$i + 1] = "&hellip;";
  559.                 // add $skipping links to pages separated by $step pages
  560.                 if( ( $min = $pListHash['listInfo']['current_page'] - $continuous - ( $step * $skipping ) ) < 0 ) {
  561.                     $min = 0;
  562.                 }
  563.                 for( $j = ( floor( $i / $step ) * $step ); $j > $min; $j -= $step ) {
  564.                     $pListHash['listInfo']['block']['prev'][$j] = $j;
  565.                 }
  566.                 $pListHash['listInfo']['block']['prev'][1] = 1;
  567.             }
  568.             // reverse array that links are in the correct order
  569.             if( !empty( $pListHash['listInfo']['block']['prev'] ) ) {
  570.                 $pListHash['listInfo']['block']['prev'] = array_reverse( $pListHash['listInfo']['block']['prev'], TRUE );
  571.             }
  572.  
  573.             // here we start adding next links
  574.             for( $i = $pListHash['listInfo']['current_page'] + 1; $i <= $next; $i += 1 ) {
  575.                 $pListHash['listInfo']['block']['next'][$i] = $i;
  576.             }
  577.             if( $next != $pListHash['listInfo']['total_pages'] ) {
  578.                 // replace the last of the continuous links with a ...
  579.                 $pListHash['listInfo']['block']['next'][$i - 1] = "&hellip;";
  580.                 // add $skipping links to pages separated by $step pages
  581.                 if( ( $max = $pListHash['listInfo']['current_page'] + $continuous + ( $step * $skipping ) ) > $pListHash['listInfo']['total_pages'] ) {
  582.                     $max = $pListHash['listInfo']['total_pages'];
  583.                 }
  584.                 for( $j = ( ceil( $i / $step ) * $step ); $j < $max; $j += $step ) {
  585.                     $pListHash['listInfo']['block']['next'][$j] = $j;
  586.                 }
  587.                 $pListHash['listInfo']['block']['next'][$pListHash['listInfo']['total_pages']] = $pListHash['listInfo']['total_pages'];
  588.             }
  589.         }
  590.     }
  591.  
  592. }

Documentation generated on Wed, 29 Jul 2015 13:55:39 +0000 by phpDocumentor 1.5.0-lsces