home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / Pager / Common.php next >
Encoding:
PHP Script  |  2005-10-16  |  39.3 KB  |  1,411 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3.  
  4. /**
  5.  * Contains the Pager_Common class
  6.  *
  7.  * PHP versions 4 and 5
  8.  *
  9.  * LICENSE: Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. The name of the author may not be used to endorse or promote products
  17.  *    derived from this software without specific prior written permission.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
  20.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22.  * IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY
  23.  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29.  *
  30.  * @category   HTML
  31.  * @package    Pager
  32.  * @author     Lorenzo Alberton <l dot alberton at quipo dot it>
  33.  * @author     Richard Heyes <richard@phpguru.org>
  34.  * @copyright  2003-2005 Lorenzo Alberton, Richard Heyes
  35.  * @license    http://www.debian.org/misc/bsd.license  BSD License (3 Clause)
  36.  * @version    CVS: $Id: Common.php,v 1.40 2005/09/27 07:49:14 quipo Exp $
  37.  * @link       http://pear.php.net/package/Pager
  38.  */
  39.  
  40. /**
  41.  * Two constants used to guess the path- and file-name of the page
  42.  * when the user doesn't set any other value
  43.  */
  44. if (substr($_SERVER['PHP_SELF'], -1) == '/') {
  45.     define('CURRENT_FILENAME', '');
  46.     define('CURRENT_PATHNAME', str_replace('\\', '/', $_SERVER['PHP_SELF']));
  47. } else {
  48.     define('CURRENT_FILENAME', preg_replace('/(.*)\?.*/', '\\1', basename($_SERVER['PHP_SELF'])));
  49.     define('CURRENT_PATHNAME', str_replace('\\', '/', dirname($_SERVER['PHP_SELF'])));
  50. }
  51. /**
  52.  * Error codes
  53.  */
  54. define('PAGER_OK',                         0);
  55. define('ERROR_PAGER',                     -1);
  56. define('ERROR_PAGER_INVALID',             -2);
  57. define('ERROR_PAGER_INVALID_PLACEHOLDER', -3);
  58. define('ERROR_PAGER_INVALID_USAGE',       -4);
  59. define('ERROR_PAGER_NOT_IMPLEMENTED',     -5);
  60.  
  61. /**
  62.  * Pager_Common - Common base class for [Sliding|Jumping] Window Pager
  63.  * Extend this class to write a custom paging class
  64.  *
  65.  * @category   HTML
  66.  * @package    Pager
  67.  * @author     Lorenzo Alberton <l dot alberton at quipo dot it>
  68.  * @author     Richard Heyes <richard@phpguru.org>
  69.  * @copyright  2003-2005 Lorenzo Alberton, Richard Heyes
  70.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  71.  * @link       http://pear.php.net/package/Pager
  72.  */
  73. class Pager_Common
  74. {
  75.     // {{{ class vars
  76.  
  77.     /**
  78.      * @var integer number of items
  79.      * @access private
  80.      */
  81.     var $_totalItems;
  82.  
  83.     /**
  84.      * @var integer number of items per page
  85.      * @access private
  86.      */
  87.     var $_perPage     = 10;
  88.  
  89.     /**
  90.      * @var integer number of page links for each window
  91.      * @access private
  92.      */
  93.     var $_delta       = 10;
  94.  
  95.     /**
  96.      * @var integer current page number
  97.      * @access private
  98.      */
  99.     var $_currentPage = 1;
  100.  
  101.     /**
  102.      * @var integer total pages number
  103.      * @access private
  104.      */
  105.     var $_totalPages  = 1;
  106.  
  107.     /**
  108.      * @var string CSS class for links
  109.      * @access private
  110.      */
  111.     var $_linkClass   = '';
  112.  
  113.     /**
  114.      * @var string wrapper for CSS class name
  115.      * @access private
  116.      */
  117.     var $_classString = '';
  118.  
  119.     /**
  120.      * @var string path name
  121.      * @access private
  122.      */
  123.     var $_path        = CURRENT_PATHNAME;
  124.  
  125.     /**
  126.      * @var string file name
  127.      * @access private
  128.      */
  129.     var $_fileName    = CURRENT_FILENAME;
  130.  
  131.     /**
  132.      * @var boolean you have to use FALSE with mod_rewrite
  133.      * @access private
  134.      */
  135.     var $_append      = true;
  136.  
  137.     /**
  138.      * @var string specifies which HTTP method to use
  139.      * @access private
  140.      */
  141.     var $_httpMethod  = 'GET';
  142.  
  143.     /**
  144.      * @var boolean whether or not to import submitted data
  145.      * @access private
  146.      */
  147.     var $_importQuery = true;
  148.  
  149.     /**
  150.      * @var string name of the querystring var for pageID
  151.      * @access private
  152.      */
  153.     var $_urlVar      = 'pageID';
  154.  
  155.     /**
  156.      * @var array data to pass through the link
  157.      * @access private
  158.      */
  159.     var $_linkData    = array();
  160.  
  161.     /**
  162.      * @var array additional URL vars
  163.      * @access private
  164.      */
  165.     var $_extraVars   = array();
  166.     
  167.     /**
  168.      * @var array URL vars to ignore
  169.      * @access private
  170.      */
  171.     var $_excludeVars = array();
  172.  
  173.     /**
  174.      * @var boolean TRUE => expanded mode (for Pager_Sliding)
  175.      * @access private
  176.      */
  177.     var $_expanded    = true;
  178.  
  179.     /**
  180.      * @var string alt text for "first page" (use "%d" placeholder for page number)
  181.      * @access private
  182.      */
  183.     var $_altFirst     = 'first page';
  184.  
  185.     /**
  186.      * @var string alt text for "previous page"
  187.      * @access private
  188.      */
  189.     var $_altPrev     = 'previous page';
  190.  
  191.     /**
  192.      * @var string alt text for "next page"
  193.      * @access private
  194.      */
  195.     var $_altNext     = 'next page';
  196.  
  197.     /**
  198.      * @var string alt text for "last page" (use "%d" placeholder for page number)
  199.      * @access private
  200.      */
  201.     var $_altLast     = 'last page';
  202.  
  203.     /**
  204.      * @var string alt text for "page"
  205.      * @access private
  206.      */
  207.     var $_altPage     = 'page';
  208.  
  209.     /**
  210.      * @var string image/text to use as "prev" link
  211.      * @access private
  212.      */
  213.     var $_prevImg     = '<< Back';
  214.  
  215.     /**
  216.      * @var string image/text to use as "next" link
  217.      * @access private
  218.      */
  219.     var $_nextImg     = 'Next >>';
  220.  
  221.     /**
  222.      * @var string link separator
  223.      * @access private
  224.      */
  225.     var $_separator   = '';
  226.  
  227.     /**
  228.      * @var integer number of spaces before separator
  229.      * @access private
  230.      */
  231.     var $_spacesBeforeSeparator = 0;
  232.  
  233.     /**
  234.      * @var integer number of spaces after separator
  235.      * @access private
  236.      */
  237.     var $_spacesAfterSeparator  = 1;
  238.  
  239.     /**
  240.      * @var string CSS class name for current page link
  241.      * @access private
  242.      */
  243.     var $_curPageLinkClassName  = '';
  244.  
  245.     /**
  246.      * @var string Text before current page link
  247.      * @access private
  248.      */
  249.     var $_curPageSpanPre        = '';
  250.  
  251.     /**
  252.      * @var string Text after current page link
  253.      * @access private
  254.      */
  255.     var $_curPageSpanPost       = '';
  256.  
  257.     /**
  258.      * @var string Text before first page link
  259.      * @access private
  260.      */
  261.     var $_firstPagePre  = '[';
  262.  
  263.     /**
  264.      * @var string Text to be used for first page link
  265.      * @access private
  266.      */
  267.     var $_firstPageText = '';
  268.  
  269.     /**
  270.      * @var string Text after first page link
  271.      * @access private
  272.      */
  273.     var $_firstPagePost = ']';
  274.  
  275.     /**
  276.      * @var string Text before last page link
  277.      * @access private
  278.      */
  279.     var $_lastPagePre   = '[';
  280.  
  281.     /**
  282.      * @var string Text to be used for last page link
  283.      * @access private
  284.      */
  285.     var $_lastPageText  = '';
  286.  
  287.     /**
  288.      * @var string Text after last page link
  289.      * @access private
  290.      */
  291.     var $_lastPagePost  = ']';
  292.  
  293.     /**
  294.      * @var string Will contain the HTML code for the spaces
  295.      * @access private
  296.      */
  297.     var $_spacesBefore  = '';
  298.  
  299.     /**
  300.      * @var string Will contain the HTML code for the spaces
  301.      * @access private
  302.      */
  303.     var $_spacesAfter   = '';
  304.  
  305.     /**
  306.      * @var string $_firstLinkTitle
  307.      * @access private
  308.      */
  309.     var $_firstLinkTitle = 'first page';
  310.  
  311.     /**
  312.      * @var string $_nextLinkTitle
  313.      * @access private
  314.      */
  315.     var $_nextLinkTitle = 'next page';
  316.  
  317.     /**
  318.      * @var string $_prevLinkTitle
  319.      * @access private
  320.      */
  321.     var $_prevLinkTitle = 'previous page';
  322.  
  323.     /**
  324.      * @var string $_lastLinkTitle
  325.      * @access private
  326.      */
  327.     var $_lastLinkTitle = 'last page';
  328.  
  329.     /**
  330.      * @var string Text to be used for the 'show all' option in the select box
  331.      * @access private
  332.      */
  333.     var $_showAllText   = '';
  334.  
  335.     /**
  336.      * @var array data to be paged
  337.      * @access private
  338.      */
  339.     var $_itemData      = null;
  340.  
  341.     /**
  342.      * @var boolean If TRUE and there's only one page, links aren't shown
  343.      * @access private
  344.      */
  345.     var $_clearIfVoid   = true;
  346.  
  347.     /**
  348.      * @var boolean Use session for storing the number of items per page
  349.      * @access private
  350.      */
  351.     var $_useSessions   = false;
  352.  
  353.     /**
  354.      * @var boolean Close the session when finished reading/writing data
  355.      * @access private
  356.      */
  357.     var $_closeSession  = false;
  358.  
  359.     /**
  360.      * @var string name of the session var for number of items per page
  361.      * @access private
  362.      */
  363.     var $_sessionVar    = 'setPerPage';
  364.  
  365.     /**
  366.      * Pear error mode (when raiseError is called)
  367.      * (see PEAR doc)
  368.      *
  369.      * @var int $_pearErrorMode
  370.      * @access private
  371.      */
  372.     var $_pearErrorMode = null;
  373.  
  374.     // }}}
  375.     // {{{ public vars
  376.  
  377.     /**
  378.      * @var string Complete set of links
  379.      * @access public
  380.      */
  381.     var $links = '';
  382.  
  383.     /**
  384.      * @var string Complete set of link tags
  385.      * @access public
  386.      */
  387.     var $linkTags = '';
  388.  
  389.     /**
  390.      * @var array Array with a key => value pair representing
  391.      *            page# => bool value (true if key==currentPageNumber).
  392.      *            can be used for extreme customization.
  393.      * @access public
  394.      */
  395.     var $range = array();
  396.  
  397.     // }}}
  398.     // {{{ getPageData()
  399.  
  400.     /**
  401.      * Returns an array of current pages data
  402.      *
  403.      * @param $pageID Desired page ID (optional)
  404.      * @return array Page data
  405.      * @access public
  406.      */
  407.     function getPageData($pageID = null)
  408.     {
  409.         $pageID = empty($pageID) ? $this->_currentPage : $pageID;
  410.  
  411.         if (!isset($this->_pageData)) {
  412.             $this->_generatePageData();
  413.         }
  414.         if (!empty($this->_pageData[$pageID])) {
  415.             return $this->_pageData[$pageID];
  416.         }
  417.         return false;
  418.     }
  419.  
  420.     // }}}
  421.     // {{{ getPageIdByOffset()
  422.  
  423.     /**
  424.      * Returns pageID for given offset
  425.      *
  426.      * @param $index Offset to get pageID for
  427.      * @return int PageID for given offset
  428.      */
  429.     function getPageIdByOffset($index)
  430.     {
  431.         $msg = '<b>PEAR::Pager Error:</b>'
  432.               .' function "getPageIdByOffset()" not implemented.';
  433.         return $this->raiseError($msg, ERROR_PAGER_NOT_IMPLEMENTED);
  434.     }
  435.  
  436.     // }}}
  437.     // {{{ getOffsetByPageId()
  438.  
  439.     /**
  440.      * Returns offsets for given pageID. Eg, if you
  441.      * pass it pageID one and your perPage limit is 10
  442.      * it will return (1, 10). PageID of 2 would
  443.      * give you (11, 20).
  444.      *
  445.      * @param integer PageID to get offsets for
  446.      * @return array  First and last offsets
  447.      * @access public
  448.      */
  449.     function getOffsetByPageId($pageid = null)
  450.     {
  451.         $pageid = isset($pageid) ? $pageid : $this->_currentPage;
  452.         if (!isset($this->_pageData)) {
  453.             $this->_generatePageData();
  454.         }
  455.  
  456.         if (isset($this->_pageData[$pageid]) || is_null($this->_itemData)) {
  457.             return array(
  458.                         max(($this->_perPage * ($pageid - 1)) + 1, 1),
  459.                         min($this->_totalItems, $this->_perPage * $pageid)
  460.                    );
  461.         } else {
  462.             return array(0, 0);
  463.         }
  464.     }
  465.  
  466.     // }}}
  467.     // {{{ getPageRangeByPageId()
  468.  
  469.     /**
  470.      * @param integer PageID to get offsets for
  471.      * @return array  First and last offsets
  472.      */
  473.     function getPageRangeByPageId($pageID)
  474.     {
  475.         $msg = '<b>PEAR::Pager Error:</b>'
  476.               .' function "getPageRangeByPageId()" not implemented.';
  477.         return $this->raiseError($msg, ERROR_PAGER_NOT_IMPLEMENTED);
  478.     }
  479.  
  480.     // }}}
  481.     // {{{ getLinks()
  482.  
  483.     /**
  484.      * Returns back/next/first/last and page links,
  485.      * both as ordered and associative array.
  486.      *
  487.      * NB: in original PEAR::Pager this method accepted two parameters,
  488.      * $back_html and $next_html. Now the only parameter accepted is
  489.      * an integer ($pageID), since the html text for prev/next links can
  490.      * be set in the factory. If a second parameter is provided, then
  491.      * the method act as it previously did. This hack was done to mantain
  492.      * backward compatibility only.
  493.      *
  494.      * @param integer $pageID Optional pageID. If specified, links
  495.      *                for that page are provided instead of current one.  [ADDED IN NEW PAGER VERSION]
  496.      * @param  string $next_html HTML to put inside the next link [deprecated: use the factory instead]
  497.      * @return array back/next/first/last and page links
  498.      */
  499.     function getLinks($pageID=null, $next_html='')
  500.     {
  501.         $msg = '<b>PEAR::Pager Error:</b>'
  502.               .' function "getLinks()" not implemented.';
  503.         return $this->raiseError($msg, ERROR_PAGER_NOT_IMPLEMENTED);
  504.     }
  505.  
  506.     // }}}
  507.     // {{{ getCurrentPageID()
  508.  
  509.     /**
  510.      * Returns ID of current page
  511.      *
  512.      * @return integer ID of current page
  513.      */
  514.     function getCurrentPageID()
  515.     {
  516.         return $this->_currentPage;
  517.     }
  518.  
  519.     // }}}
  520.     // {{{ getNextPageID()
  521.  
  522.     /**
  523.      * Returns next page ID. If current page is last page
  524.      * this function returns FALSE
  525.      *
  526.      * @return mixed Next page ID
  527.      */
  528.     function getNextPageID()
  529.     {
  530.         return ($this->getCurrentPageID() == $this->numPages() ? false : $this->getCurrentPageID() + 1);
  531.     }
  532.  
  533.     // }}}
  534.     // {{{ getPreviousPageID()
  535.  
  536.     /**
  537.      * Returns previous page ID. If current page is first page
  538.      * this function returns FALSE
  539.      *
  540.      * @return mixed Previous pages' ID
  541.      */
  542.     function getPreviousPageID()
  543.     {
  544.         return $this->isFirstPage() ? false : $this->getCurrentPageID() - 1;
  545.     }
  546.  
  547.     // }}}
  548.     // {{{ numItems()
  549.  
  550.     /**
  551.      * Returns number of items
  552.      *
  553.      * @return int Number of items
  554.      */
  555.     function numItems()
  556.     {
  557.         return $this->_totalItems;
  558.     }
  559.  
  560.     // }}}
  561.     // {{{ numPages()
  562.  
  563.     /**
  564.      * Returns number of pages
  565.      *
  566.      * @return int Number of pages
  567.      */
  568.     function numPages()
  569.     {
  570.         return (int)$this->_totalPages;
  571.     }
  572.  
  573.     // }}}
  574.     // {{{ isFirstPage()
  575.  
  576.     /**
  577.      * Returns whether current page is first page
  578.      *
  579.      * @return bool First page or not
  580.      */
  581.     function isFirstPage()
  582.     {
  583.         return ($this->_currentPage < 2);
  584.     }
  585.  
  586.     // }}}
  587.     // {{{ isLastPage()
  588.  
  589.     /**
  590.      * Returns whether current page is last page
  591.      *
  592.      * @return bool Last page or not
  593.      */
  594.     function isLastPage()
  595.     {
  596.         return ($this->_currentPage == $this->_totalPages);
  597.     }
  598.  
  599.     // }}}
  600.     // {{{ isLastPageComplete()
  601.  
  602.     /**
  603.      * Returns whether last page is complete
  604.      *
  605.      * @return bool Last age complete or not
  606.      */
  607.     function isLastPageComplete()
  608.     {
  609.         return !($this->_totalItems % $this->_perPage);
  610.     }
  611.  
  612.     // }}}
  613.     // {{{ _generatePageData()
  614.  
  615.     /**
  616.      * Calculates all page data
  617.      * @access private
  618.      */
  619.     function _generatePageData()
  620.     {
  621.         // Been supplied an array of data?
  622.         if (!is_null($this->_itemData)) {
  623.             $this->_totalItems = count($this->_itemData);
  624.         }
  625.         $this->_totalPages = ceil((float)$this->_totalItems / (float)$this->_perPage);
  626.         $i = 1;
  627.         if (!empty($this->_itemData)) {
  628.             foreach ($this->_itemData as $key => $value) {
  629.                 $this->_pageData[$i][$key] = $value;
  630.                 if (count($this->_pageData[$i]) >= $this->_perPage) {
  631.                     $i++;
  632.                 }
  633.             }
  634.         } else {
  635.             $this->_pageData = array();
  636.         }
  637.  
  638.         //prevent URL modification
  639.         $this->_currentPage = min($this->_currentPage, $this->_totalPages);
  640.     }
  641.  
  642.     // }}}
  643.     // {{{ _renderLink()
  644.  
  645.     /**
  646.      * Renders a link using the appropriate method
  647.      *
  648.      * @param altText Alternative text for this link (title property)
  649.      * @param linkText Text contained by this link
  650.      * @return string The link in string form
  651.      * @access private
  652.      */
  653.     function _renderLink($altText, $linkText)
  654.     {
  655.         if ($this->_httpMethod == 'GET') {
  656.             if ($this->_append) {
  657.                 $href = '?' . $this->_http_build_query_wrapper($this->_linkData);
  658.             } else {
  659.                 $href = sprintf($this->_fileName, $this->_linkData[$this->_urlVar]);
  660.             }
  661.             return sprintf('<a href="%s"%s title="%s">%s</a>',
  662.                            htmlentities($this->_url . $href),
  663.                            empty($this->_classString) ? '' : ' '.$this->_classString,
  664.                            $altText,
  665.                            $linkText
  666.             );
  667.         }
  668.         if ($this->_httpMethod == 'POST') {
  669.             return sprintf('<a onclick=\'%s\' href="#"%s title="%s">%s</a>',
  670.                            $this->_generateFormOnClick($this->_url, $this->_linkData),
  671.                            empty($this->_classString) ? '' : ' '.$this->_classString,
  672.                            $altText,
  673.                            $linkText
  674.             );
  675.         }
  676.         return '';
  677.     }
  678.  
  679.     // }}}
  680.     // {{{ _generateFormOnClick()
  681.  
  682.     /**
  683.      * Mimics http_build_query() behavior in the way the data
  684.      * in $data will appear when it makes it back to the server.
  685.      *  For example:
  686.      * $arr =  array('array' => array(array('hello', 'world'),
  687.      *                                'things' => array('stuff', 'junk'));
  688.      * http_build_query($arr)
  689.      * and _generateFormOnClick('foo.php', $arr)
  690.      * will yield
  691.      * $_REQUEST['array'][0][0] === 'hello'
  692.      * $_REQUEST['array'][0][0] === 'world'
  693.      * $_REQUEST['array']['things'][0] === 'stuff'
  694.      * $_REQUEST['array']['things'][0] === 'junk'
  695.      *
  696.      * However, instead of  generating a query string, it generates
  697.      * Javascript to create and submit a form.
  698.      *
  699.      * @param string $formAction where the form should be submitted
  700.      * @param array  $data the associative array of names and values
  701.      * @return string A string of javascript that generates a form and submits it
  702.      * @access private
  703.      */
  704.     function _generateFormOnClick($formAction, $data)
  705.     {
  706.         // Check we have an array to work with
  707.         if (!is_array($data)) {
  708.             trigger_error(
  709.                 '_generateForm() Parameter 1 expected to be Array or Object. Incorrect value given.',
  710.                 E_USER_WARNING
  711.             );
  712.             return false;
  713.         }
  714.         $str = 'var form = document.createElement("form"); var input = ""; ';
  715.         // We /shouldn't/ need to escape the URL ...
  716.         $str .= sprintf('form.action = "%s"; ', htmlentities($formAction));
  717.         $str .= sprintf('form.method = "%s"; ', $this->_httpMethod);
  718.         foreach ($data as $key => $val) {
  719.             $str .= $this->_generateFormOnClickHelper($val, $key);
  720.         }
  721.         $str .= 'document.getElementsByTagName("body")[0].appendChild(form);';
  722.         $str .= 'form.submit();';
  723.         return $str;
  724.     }
  725.  
  726.     // }}}
  727.     // {{{ _generateFormOnClickHelper
  728.  
  729.     /**
  730.      * This is used by _generateFormOnClick(). 
  731.      * Recursively processes the arrays, objects, and literal values.
  732.      *
  733.      * @param data Data that should be rendered
  734.      * @param prev The name so far
  735.      * @return string A string of Javascript that creates form inputs
  736.      *                representing the data
  737.      * @access private
  738.      */
  739.     function _generateFormOnClickHelper($data, $prev = '')
  740.     {
  741.         $str = '';
  742.         if (is_array($data) || is_object($data)) {
  743.             // foreach key/visible member
  744.             foreach ((array)$data as $key => $val) {
  745.                 // append [$key] to prev
  746.                 $tempKey = sprintf('%s[%s]', $prev, $key);
  747.                 $str .= $this->_generateFormOnClickHelper($val, $tempKey);
  748.             }
  749.         } else {  // must be a literal value
  750.             // escape newlines and carriage returns
  751.             $search  = array("\n", "\r");
  752.             $replace = array('\n', '\n');
  753.             $escapedData = str_replace($search, $replace, $data);
  754.             // am I forgetting any dangerous whitespace?
  755.             // would a regex be faster?
  756.             $escapedData = htmlentities($escapedData);
  757.  
  758.             $str .= 'input = document.createElement("input"); ';
  759.             $str .= 'input.type = "hidden"; ';
  760.             $str .= sprintf('input.name = "%s"; ', $prev);
  761.             $str .= sprintf('input.value = "%s"; ', $escapedData);
  762.             $str .= 'form.appendChild(input); ';
  763.         }
  764.         return $str;
  765.     }
  766.  
  767.     // }}}
  768.     // {{{ _getLinksData()
  769.  
  770.     /**
  771.      * Returns the correct link for the back/pages/next links
  772.      *
  773.      * @return array Data
  774.      * @access private
  775.      */
  776.     function _getLinksData()
  777.     {
  778.         $qs = array();
  779.         if ($this->_importQuery) {
  780.             if ($this->_httpMethod == 'POST') {
  781.                 $qs = $_POST;
  782.             } elseif ($this->_httpMethod == 'GET') {
  783.                 $qs = $_GET;
  784.             }
  785.         }
  786.         if (count($this->_extraVars)){
  787.             $this->_recursive_urldecode($this->_extraVars);
  788.         }
  789.         $qs = array_merge($qs, $this->_extraVars);
  790.         foreach ($this->_excludeVars as $exclude) {
  791.             if (array_key_exists($exclude, $qs)) {
  792.                 unset($qs[$exclude]);
  793.             }
  794.         }
  795.         if (count($qs) && get_magic_quotes_gpc()){
  796.             $this->_recursive_stripslashes($qs);
  797.         }
  798.         return $qs;
  799.     }
  800.  
  801.     // }}}
  802.     // {{{ _recursive_stripslashes()
  803.     
  804.     /**
  805.      * Helper method
  806.      * @param mixed $var
  807.      * @access private
  808.      */
  809.     function _recursive_stripslashes(&$var)
  810.     {
  811.         if (is_array($var)) {
  812.             foreach (array_keys($var) as $k) {
  813.                 $this->_recursive_stripslashes($var[$k]);
  814.             }
  815.         } else {
  816.             $var = stripslashes($var);
  817.         }
  818.     }
  819.  
  820.     // }}}
  821.     // {{{ _recursive_urldecode()
  822.  
  823.     /**
  824.      * Helper method
  825.      * @param mixed $var
  826.      * @access private
  827.      */
  828.     function _recursive_urldecode(&$var)
  829.     {
  830.         if (is_array($var)) {
  831.             foreach (array_keys($var) as $k) {
  832.                 $this->_recursive_urldecode($var[$k]);
  833.             }
  834.         } else {
  835.             $trans_tbl = array_flip(get_html_translation_table(HTML_ENTITIES));
  836.             $var = strtr($var, $trans_tbl);
  837.         }
  838.     }
  839.  
  840.     // }}}
  841.     // {{{ _getBackLink()
  842.  
  843.     /**
  844.      * Returns back link
  845.      *
  846.      * @param $url  URL to use in the link  [deprecated: use the factory instead]
  847.      * @param $link HTML to use as the link [deprecated: use the factory instead]
  848.      * @return string The link
  849.      * @access private
  850.      */
  851.     function _getBackLink($url='', $link='')
  852.     {
  853.         //legacy settings... the preferred way to set an option
  854.         //now is passing it to the factory
  855.         if (!empty($url)) {
  856.             $this->_path = $url;
  857.         }
  858.         if (!empty($link)) {
  859.             $this->_prevImg = $link;
  860.         }
  861.         $back = '';
  862.         if ($this->_currentPage > 1) {
  863.             $this->_linkData[$this->_urlVar] = $this->getPreviousPageID();
  864.             $back = $this->_renderLink($this->_altPrev, $this->_prevImg)
  865.                   . $this->_spacesBefore . $this->_spacesAfter;
  866.         }
  867.         return $back;
  868.     }
  869.  
  870.     // }}}
  871.     // {{{ _getPageLinks()
  872.  
  873.     /**
  874.      * Returns pages link
  875.      *
  876.      * @param $url  URL to use in the link [deprecated: use the factory instead]
  877.      * @return string Links
  878.      * @access private
  879.      */
  880.     function _getPageLinks($url='')
  881.     {
  882.         $msg = '<b>PEAR::Pager Error:</b>'
  883.               .' function "getOffsetByPageId()" not implemented.';
  884.         return $this->raiseError($msg, ERROR_PAGER_NOT_IMPLEMENTED);
  885.  
  886.     }
  887.  
  888.     // }}}
  889.     // {{{ _getNextLink()
  890.  
  891.     /**
  892.      * Returns next link
  893.      *
  894.      * @param $url  URL to use in the link  [deprecated: use the factory instead]
  895.      * @param $link HTML to use as the link [deprecated: use the factory instead]
  896.      * @return string The link
  897.      * @access private
  898.      */
  899.     function _getNextLink($url='', $link='')
  900.     {
  901.         //legacy settings... the preferred way to set an option
  902.         //now is passing it to the factory
  903.         if (!empty($url)) {
  904.             $this->_path = $url;
  905.         }
  906.         if (!empty($link)) {
  907.             $this->_nextImg = $link;
  908.         }
  909.         $next = '';
  910.         if ($this->_currentPage < $this->_totalPages) {
  911.             $this->_linkData[$this->_urlVar] = $this->getNextPageID();
  912.             $next = $this->_spacesAfter
  913.                   . $this->_renderLink($this->_altNext, $this->_nextImg)
  914.                   . $this->_spacesBefore . $this->_spacesAfter;
  915.         }
  916.         return $next;
  917.     }
  918.  
  919.     // }}}
  920.     // {{{ _getFirstLinkTag()
  921.  
  922.     /**
  923.      * @return string
  924.      * @access private
  925.      */
  926.     function _getFirstLinkTag()
  927.     {
  928.         if ($this->isFirstPage() || ($this->_httpMethod != 'GET')) {
  929.             return '';
  930.         }
  931.         return sprintf('<link rel="first" href="%s" title="%s" />'."\n",
  932.             $this->_getLinkTagUrl(1),
  933.             $this->_firstLinkTitle
  934.         );
  935.     }
  936.  
  937.     // }}}
  938.     // {{{ _getPrevLinkTag()
  939.  
  940.     /**
  941.      * Returns previous link tag
  942.      *
  943.      * @return string the link tag
  944.      * @access private
  945.      */
  946.     function _getPrevLinkTag()
  947.     {
  948.         if ($this->isFirstPage() || ($this->_httpMethod != 'GET')) {
  949.             return '';
  950.         }
  951.         return sprintf('<link rel="previous" href="%s" title="%s" />'."\n",
  952.             $this->_getLinkTagUrl($this->getPreviousPageID()),
  953.             $this->_prevLinkTitle
  954.         );
  955.     }
  956.  
  957.     // }}}
  958.     // {{{ _getNextLinkTag()
  959.  
  960.     /**
  961.      * Returns next link tag
  962.      *
  963.      * @return string the link tag
  964.      * @access private
  965.      */
  966.     function _getNextLinkTag()
  967.     {
  968.         if ($this->isLastPage() || ($this->_httpMethod != 'GET')) {
  969.             return '';
  970.         }
  971.         return sprintf('<link rel="next" href="%s" title="%s" />'."\n",
  972.             $this->_getLinkTagUrl($this->getNextPageID()),
  973.             $this->_nextLinkTitle
  974.         );
  975.     }
  976.  
  977.     // }}}
  978.     // {{{ _getLastLinkTag()
  979.  
  980.     /**
  981.      * @return string the link tag
  982.      * @access private
  983.      */
  984.     function _getLastLinkTag()
  985.     {
  986.         if ($this->isLastPage() || ($this->_httpMethod != 'GET')) {
  987.             return '';
  988.         }
  989.         return sprintf('<link rel="last" href="%s" title="%s" />'."\n",
  990.             $this->_getLinkTagUrl($this->_totalPages),
  991.             $this->_lastLinkTitle
  992.         );
  993.     }
  994.  
  995.     // }}}
  996.     // {{{ _getLinkTagUrl()
  997.  
  998.     /**
  999.      * Helper method
  1000.      * @return string the link tag url
  1001.      * @access private
  1002.      */
  1003.     function _getLinkTagUrl($pageID)
  1004.     {
  1005.         $this->_linkData[$this->_urlVar] = $pageID;
  1006.         if ($this->_append) {
  1007.             $href = '?' . $this->_http_build_query_wrapper($this->_linkData);
  1008.         } else {
  1009.             $href = sprintf($this->_fileName, $this->_linkData[$this->_urlVar]);
  1010.         }
  1011.         return htmlentities($this->_url . $href);
  1012.     }
  1013.     
  1014.     // }}}
  1015.     // {{{ getPerPageSelectBox()
  1016.  
  1017.     /**
  1018.      * Returns a string with a XHTML SELECT menu,
  1019.      * useful for letting the user choose how many items per page should be
  1020.      * displayed. If parameter useSessions is TRUE, this value is stored in
  1021.      * a session var. The string isn't echoed right now so you can use it
  1022.      * with template engines.
  1023.      *
  1024.      * @param integer $start
  1025.      * @param integer $end
  1026.      * @param integer $step
  1027.      * @param boolean $showAllData If true, perPage is set equal to totalItems.
  1028.      * @param array   (or string $optionText for BC reasons)
  1029.      *                - 'optionText': text to show in each option.
  1030.      *                  Use '%d' where you want to see the number of pages selected.
  1031.      *                - 'attributes': (html attributes) Tag attributes or
  1032.      *                  HTML attributes id="foo" pairs, will be inserted in the
  1033.      *                  <select> tag
  1034.      * @return string xhtml select box
  1035.      * @access public
  1036.      */
  1037.     function getPerPageSelectBox($start=5, $end=30, $step=5, $showAllData=false, $extraParams=array())
  1038.     {
  1039.         // FIXME: needs POST support
  1040.         $optionText = '%d';
  1041.         $attributes = '';
  1042.         if (is_string($extraParams)) {
  1043.             //old behavior, BC maintained
  1044.             $optionText = $extraParams;
  1045.         } else {
  1046.             if (array_key_exists('optionText', $extraParams)) {
  1047.                 $optionText = $extraParams['optionText'];
  1048.             }
  1049.             if (array_key_exists('attributes', $extraParams)) {
  1050.                 $attributes = $extraParams['attributes'];
  1051.             }
  1052.         }
  1053.  
  1054.         if (!strstr($optionText, '%d')) {
  1055.             return $this->raiseError(
  1056.                 $this->errorMessage(ERROR_PAGER_INVALID_PLACEHOLDER),
  1057.                 ERROR_PAGER_INVALID_PLACEHOLDER
  1058.             );
  1059.         }
  1060.         $start = (int)$start;
  1061.         $end   = (int)$end;
  1062.         $step  = (int)$step;
  1063.         if (!empty($_SESSION[$this->_sessionVar])) {
  1064.             $selected = (int)$_SESSION[$this->_sessionVar];
  1065.         } else {
  1066.             $selected = $this->_perPage;
  1067.         }
  1068.  
  1069.         $tmp = '<select name="'.$this->_sessionVar.'"';
  1070.         if (!empty($attributes)) {
  1071.             $tmp .= ' '.$attributes;
  1072.         }
  1073.         $tmp .= '>';
  1074.         for ($i=$start; $i<=$end; $i+=$step) {
  1075.             $tmp .= '<option value="'.$i.'"';
  1076.             if ($i == $selected) {
  1077.                 $tmp .= ' selected="selected"';
  1078.             }
  1079.             $tmp .= '>'.sprintf($optionText, $i).'</option>';
  1080.         }
  1081.         if ($showAllData && $end < $this->_totalItems) {
  1082.             $tmp .= '<option value="'.$this->_totalItems.'"';
  1083.             if ($this->_totalItems == $selected) {
  1084.                 $tmp .= ' selected="selected"';
  1085.             }
  1086.             $tmp .= '>';
  1087.             if (empty($this->_showAllText)) {
  1088.                 $tmp .= str_replace('%d', $this->_totalItems, $optionText);
  1089.             } else {
  1090.                 $tmp .= $this->_showAllText;
  1091.             }
  1092.             $tmp .= '</option>';
  1093.         }
  1094.         $tmp .= '</select>';
  1095.         return $tmp;
  1096.     }
  1097.  
  1098.     // }}}
  1099.     // {{{ _printFirstPage()
  1100.  
  1101.     /**
  1102.      * Print [1]
  1103.      *
  1104.      * @return string String with link to 1st page,
  1105.      *                or empty string if this is the 1st page.
  1106.      * @access private
  1107.      */
  1108.     function _printFirstPage()
  1109.     {
  1110.         if ($this->isFirstPage()) {
  1111.             return '';
  1112.         }
  1113.         $this->_linkData[$this->_urlVar] = 1;
  1114.         return $this->_renderLink(
  1115.                 str_replace('%d', 1, $this->_altFirst),
  1116.                 $this->_firstPagePre . $this->_firstPageText . $this->_firstPagePost
  1117.         ) . $this->_spacesBefore . $this->_spacesAfter;
  1118.     }
  1119.  
  1120.     // }}}
  1121.     // {{{ _printLastPage()
  1122.  
  1123.     /**
  1124.      * Print [numPages()]
  1125.      *
  1126.      * @return string String with link to last page,
  1127.      *                or empty string if this is the 1st page.
  1128.      * @access private
  1129.      */
  1130.     function _printLastPage()
  1131.     {
  1132.         if ($this->isLastPage()) {
  1133.             return '';
  1134.         }
  1135.         $this->_linkData[$this->_urlVar] = $this->_totalPages;
  1136.         return $this->_renderLink(
  1137.                 str_replace('%d', $this->_totalPages, $this->_altLast),
  1138.                 $this->_lastPagePre . $this->_lastPageText . $this->_lastPagePost
  1139.         );
  1140.     }
  1141.  
  1142.     // }}}
  1143.     // {{{ _setFirstLastText()
  1144.  
  1145.     /**
  1146.      * sets the private _firstPageText, _lastPageText variables
  1147.      * based on whether they were set in the options
  1148.      *
  1149.      * @access private
  1150.      */
  1151.     function _setFirstLastText()
  1152.     {
  1153.         if ($this->_firstPageText == '') {
  1154.             $this->_firstPageText = '1';
  1155.         }
  1156.         if ($this->_lastPageText == '') {
  1157.             $this->_lastPageText = $this->_totalPages;
  1158.         }
  1159.     }
  1160.  
  1161.     // }}}
  1162.     // {{{ _http_build_query_wrapper()
  1163.     
  1164.     /**
  1165.      * This is a slightly modified version of the http_build_query() function;
  1166.      * it heavily borrows code from PHP_Compat's http_build_query().
  1167.      * The main change is the usage of htmlentities instead of urlencode,
  1168.      * since it's too aggressive
  1169.      *
  1170.      * @author Stephan Schmidt <schst@php.net>
  1171.      * @author Aidan Lister <aidan@php.net>
  1172.      * @author Lorenzo Alberton <l dot alberton at quipo dot it>
  1173.      * @param array $data
  1174.      * @return string
  1175.      * @access private
  1176.      */
  1177.     function _http_build_query_wrapper($data)
  1178.     {
  1179.         $data = (array)$data;
  1180.         if (empty($data)) {
  1181.             return '';
  1182.         }
  1183.         $separator = ini_get('arg_separator.output');
  1184.         if ($separator == '&') {
  1185.             $separator = '&'; //the string is escaped by htmlentities anyway...
  1186.         }
  1187.         $tmp = array ();
  1188.         foreach ($data as $key => $val) {
  1189.             if (is_scalar($val)) {
  1190.                 //array_push($tmp, $key.'='.$val);
  1191.                 $val = urlencode($val);
  1192.                 array_push($tmp, $key .'='. str_replace('%2F', '/', $val));
  1193.                 continue;
  1194.             }
  1195.             // If the value is an array, recursively parse it
  1196.             if (is_array($val)) {
  1197.                 array_push($tmp, $this->__http_build_query($val, htmlentities($key)));
  1198.                 continue;
  1199.             }
  1200.         }
  1201.         return implode($separator, $tmp);
  1202.     }
  1203.  
  1204.     // }}}
  1205.     // {{{ __http_build_query()
  1206.  
  1207.     /**
  1208.      * Helper function
  1209.      * @author Stephan Schmidt <schst@php.net>
  1210.      * @author Aidan Lister <aidan@php.net>
  1211.      * @access private
  1212.      */
  1213.     function __http_build_query($array, $name)
  1214.     {
  1215.         $tmp = array ();
  1216.         foreach ($array as $key => $value) {
  1217.             if (is_array($value)) {
  1218.                 array_push($tmp, $this->__http_build_query($value, $name.'%5B'.$key.'%5D'));
  1219.             } elseif (is_scalar($value)) {
  1220.                 array_push($tmp, $name.'%5B'.htmlentities($key).'%5D='.htmlentities($value));
  1221.             } elseif (is_object($value)) {
  1222.                 array_push($tmp, $this->__http_build_query(get_object_vars($value), $name.'%5B'.$key.'%5D'));
  1223.             }
  1224.         }
  1225.         return implode(ini_get('arg_separator.output'), $tmp);
  1226.     }
  1227.  
  1228.     // }}}
  1229.     // {{{ raiseError()
  1230.  
  1231.     /**
  1232.      * conditionally includes PEAR base class and raise an error
  1233.      *
  1234.      * @param string $msg  Error message
  1235.      * @param int    $code Error code
  1236.      * @access private
  1237.      */
  1238.     function raiseError($msg, $code)
  1239.     {
  1240.         include_once 'PEAR.php';
  1241.         if (empty($this->_pearErrorMode)) {
  1242.             $this->_pearErrorMode = PEAR_ERROR_RETURN;
  1243.         }
  1244.         return PEAR::raiseError($msg, $code, $this->_pearErrorMode);
  1245.     }
  1246.  
  1247.     // }}}
  1248.     // {{{ _setOptions()
  1249.  
  1250.     /**
  1251.      * Set and sanitize options
  1252.      *
  1253.      * @param mixed $options    An associative array of option names and
  1254.      *                          their values.
  1255.      * @return integer error code (PAGER_OK on success)
  1256.      * @access private
  1257.      */
  1258.     function _setOptions($options)
  1259.     {
  1260.         $allowed_options = array(
  1261.             'totalItems',
  1262.             'perPage',
  1263.             'delta',
  1264.             'linkClass',
  1265.             'path',
  1266.             'fileName',
  1267.             'append',
  1268.             'httpMethod',
  1269.             'importQuery',
  1270.             'urlVar',
  1271.             'altFirst',
  1272.             'altPrev',
  1273.             'altNext',
  1274.             'altLast',
  1275.             'altPage',
  1276.             'prevImg',
  1277.             'nextImg',
  1278.             'expanded',
  1279.             'separator',
  1280.             'spacesBeforeSeparator',
  1281.             'spacesAfterSeparator',
  1282.             'curPageLinkClassName',
  1283.             'curPageSpanPre',
  1284.             'curPageSpanPost',
  1285.             'firstPagePre',
  1286.             'firstPageText',
  1287.             'firstPagePost',
  1288.             'lastPagePre',
  1289.             'lastPageText',
  1290.             'lastPagePost',
  1291.             'firstLinkTitle',
  1292.             'nextLinkTitle',
  1293.             'prevLinkTitle',
  1294.             'lastLinkTitle',
  1295.             'showAllText',
  1296.             'itemData',
  1297.             'clearIfVoid',
  1298.             'useSessions',
  1299.             'closeSession',
  1300.             'sessionVar',
  1301.             'pearErrorMode',
  1302.             'extraVars',
  1303.             'excludeVars',
  1304.             'currentPage',
  1305.         );
  1306.         
  1307.         foreach ($options as $key => $value) {
  1308.             if (in_array($key, $allowed_options) && (!is_null($value))) {
  1309.                 $this->{'_' . $key} = $value;
  1310.             }
  1311.         }
  1312.  
  1313.         //autodetect http method
  1314.         if (!isset($options['httpMethod'])
  1315.             && !isset($_GET[$this->_urlVar])
  1316.             && isset($_POST[$this->_urlVar])
  1317.         ) {
  1318.             $this->_httpMethod = 'POST';
  1319.         } else {
  1320.             $this->_httpMethod = strtoupper($this->_httpMethod);
  1321.         }
  1322.  
  1323.         $this->_fileName = ltrim($this->_fileName, '/');  //strip leading slash
  1324.         $this->_path     = rtrim($this->_path, '/');      //strip trailing slash
  1325.  
  1326.         if ($this->_append) {
  1327.             $this->_fileName = CURRENT_FILENAME; //avoid possible user error;
  1328.             $this->_url = $this->_path.'/'.$this->_fileName;
  1329.         } else {
  1330.             $this->_url = $this->_path;
  1331.             if (strncasecmp($this->_fileName, 'javascript', 10) != 0) {
  1332.                 $this->_url .= '/';
  1333.             }
  1334.             if (!strstr($this->_fileName, '%d')) {
  1335.                 trigger_error($this->errorMessage(ERROR_PAGER_INVALID_USAGE), E_USER_WARNING);
  1336.             }
  1337.         }
  1338.  
  1339.         $this->_classString = '';
  1340.         if (strlen($this->_linkClass)) {
  1341.             $this->_classString = 'class="'.$this->_linkClass.'"';
  1342.         }
  1343.  
  1344.         if (strlen($this->_curPageLinkClassName)) {
  1345.             $this->_curPageSpanPre  = '<span class="'.$this->_curPageLinkClassName.'">';
  1346.             $this->_curPageSpanPost = '</span>';
  1347.         }
  1348.  
  1349.         $this->_perPage = max($this->_perPage, 1); //avoid possible user errors
  1350.  
  1351.         if ($this->_useSessions && !isset($_SESSION)) {
  1352.             session_start();
  1353.         }
  1354.         if (!empty($_REQUEST[$this->_sessionVar])) {
  1355.             $this->_perPage = max(1, (int)$_REQUEST[$this->_sessionVar]);
  1356.             if ($this->_useSessions) {
  1357.                 $_SESSION[$this->_sessionVar] = $this->_perPage;
  1358.             }
  1359.         }
  1360.  
  1361.         if (!empty($_SESSION[$this->_sessionVar])) {
  1362.              $this->_perPage = $_SESSION[$this->_sessionVar];
  1363.         }
  1364.  
  1365.         if ($this->_closeSession) {
  1366.             session_write_close();
  1367.         }
  1368.  
  1369.         $this->_spacesBefore = str_repeat(' ', $this->_spacesBeforeSeparator);
  1370.         $this->_spacesAfter  = str_repeat(' ', $this->_spacesAfterSeparator);
  1371.  
  1372.         if (isset($_REQUEST[$this->_urlVar]) && empty($options['currentPage'])) {
  1373.             $this->_currentPage = (int)$_REQUEST[$this->_urlVar];
  1374.         }
  1375.         $this->_currentPage = max($this->_currentPage, 1);
  1376.         $this->_linkData = $this->_getLinksData();
  1377.  
  1378.         return PAGER_OK;
  1379.     }
  1380.  
  1381.     // }}}
  1382.     // {{{ errorMessage()
  1383.  
  1384.     /**
  1385.      * Return a textual error message for a PAGER error code
  1386.      *
  1387.      * @param   int     $code error code
  1388.      * @return  string  error message
  1389.      * @access public
  1390.      */
  1391.     function errorMessage($code)
  1392.     {
  1393.         static $errorMessages;
  1394.         if (!isset($errorMessages)) {
  1395.             $errorMessages = array(
  1396.                 ERROR_PAGER                     => 'unknown error',
  1397.                 ERROR_PAGER_INVALID             => 'invalid',
  1398.                 ERROR_PAGER_INVALID_PLACEHOLDER => 'invalid format - use "%d" as placeholder.',
  1399.                 ERROR_PAGER_INVALID_USAGE       => 'if $options[\'append\'] is set to false, '
  1400.                                                   .' $options[\'fileName\'] MUST contain the "%d" placeholder.',
  1401.                 ERROR_PAGER_NOT_IMPLEMENTED     => 'not implemented'
  1402.             );
  1403.         }
  1404.  
  1405.         return '<b>PEAR::Pager error:</b> '. (isset($errorMessages[$code]) ?
  1406.             $errorMessages[$code] : $errorMessages[ERROR_PAGER]);
  1407.     }
  1408.  
  1409.     // }}}
  1410. }
  1411. ?>