Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 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.alberton@quipo.it>
33
 * @author    Richard Heyes <richard@phpguru.org>
34
 * @copyright 2003-2007 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.82 2008/05/31 12:44:55 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
    $http = (isset($_SERVER['HTTPS']) && ('on' == strtolower($_SERVER['HTTPS']))) ? 'https://' : 'http://';
46
    define('PAGER_CURRENT_FILENAME', '');
47
    define('PAGER_CURRENT_PATHNAME', $http.$_SERVER['HTTP_HOST'].str_replace('\\', '/', $_SERVER['PHP_SELF']));
48
} else {
49
    define('PAGER_CURRENT_FILENAME', preg_replace('/(.*)\?.*/', '\\1', basename($_SERVER['PHP_SELF'])));
50
    define('PAGER_CURRENT_PATHNAME', str_replace('\\', '/', dirname($_SERVER['PHP_SELF'])));
51
}
52
/**
53
 * Error codes
54
 */
55
define('PAGER_OK',                         0);
56
define('ERROR_PAGER',                     -1);
57
define('ERROR_PAGER_INVALID',             -2);
58
define('ERROR_PAGER_INVALID_PLACEHOLDER', -3);
59
define('ERROR_PAGER_INVALID_USAGE',       -4);
60
define('ERROR_PAGER_NOT_IMPLEMENTED',     -5);
61
 
62
/**
63
 * Pager_Common - Common base class for [Sliding|Jumping] Window Pager
64
 * Extend this class to write a custom paging class
65
 *
66
 * @category  HTML
67
 * @package   Pager
68
 * @author    Lorenzo Alberton <l.alberton@quipo.it>
69
 * @author    Richard Heyes <richard@phpguru.org>
70
 * @copyright 2003-2007 Lorenzo Alberton, Richard Heyes
71
 * @license   http://www.debian.org/misc/bsd.license  BSD License (3 Clause)
72
 * @link      http://pear.php.net/package/Pager
73
 */
74
class Pager_Common
75
{
76
    // {{{ class vars
77
 
78
    /**
79
     * @var integer number of items
80
     * @access private
81
     */
82
    var $_totalItems;
83
 
84
    /**
85
     * @var integer number of items per page
86
     * @access private
87
     */
88
    var $_perPage     = 10;
89
 
90
    /**
91
     * @var integer number of page links for each window
92
     * @access private
93
     */
94
    var $_delta       = 10;
95
 
96
    /**
97
     * @var integer current page number
98
     * @access private
99
     */
100
    var $_currentPage = 1;
101
 
102
    /**
103
     * @var integer total pages number
104
     * @access private
105
     */
106
    var $_totalPages  = 1;
107
 
108
    /**
109
     * @var string CSS class for links
110
     * @access private
111
     */
112
    var $_linkClass   = '';
113
 
114
    /**
115
     * @var string wrapper for CSS class name
116
     * @access private
117
     */
118
    var $_classString = '';
119
 
120
    /**
121
     * @var string path name
122
     * @access private
123
     */
124
    var $_path        = PAGER_CURRENT_PATHNAME;
125
 
126
    /**
127
     * @var string file name
128
     * @access private
129
     */
130
    var $_fileName    = PAGER_CURRENT_FILENAME;
131
 
132
    /**
133
     * @var boolean If false, don't override the fileName option. Use at your own risk.
134
     * @access private
135
     */
136
    var $_fixFileName = true;
137
 
138
    /**
139
     * @var boolean you have to use FALSE with mod_rewrite
140
     * @access private
141
     */
142
    var $_append      = true;
143
 
144
    /**
145
     * @var string specifies which HTTP method to use
146
     * @access private
147
     */
148
    var $_httpMethod  = 'GET';
149
 
150
    /**
151
     * @var string specifies which HTML form to use
152
     * @access private
153
     */
154
    var $_formID      = '';
155
 
156
    /**
157
     * @var boolean whether or not to import submitted data
158
     * @access private
159
     */
160
    var $_importQuery = true;
161
 
162
    /**
163
     * @var string name of the querystring var for pageID
164
     * @access private
165
     */
166
    var $_urlVar      = 'pageID';
167
 
168
    /**
169
     * @var array data to pass through the link
170
     * @access private
171
     */
172
    var $_linkData    = array();
173
 
174
    /**
175
     * @var array additional URL vars
176
     * @access private
177
     */
178
    var $_extraVars   = array();
179
 
180
    /**
181
     * @var array URL vars to ignore
182
     * @access private
183
     */
184
    var $_excludeVars = array();
185
 
186
    /**
187
     * @var boolean TRUE => expanded mode (for Pager_Sliding)
188
     * @access private
189
     */
190
    var $_expanded    = true;
191
 
192
    /**
193
     * @var boolean TRUE => show accesskey attribute on <a> tags
194
     * @access private
195
     */
196
    var $_accesskey   = false;
197
 
198
    /**
199
     * @var string extra attributes for the <a> tag
200
     * @access private
201
     */
202
    var $_attributes  = '';
203
 
204
    /**
205
     * @var string onclick
206
     * @access private
207
     */
208
    var $_onclick = '';
209
 
210
    /**
211
     * @var string alt text for "first page" (use "%d" placeholder for page number)
212
     * @access private
213
     */
214
    var $_altFirst     = 'first page';
215
 
216
    /**
217
     * @var string alt text for "previous page"
218
     * @access private
219
     */
220
    var $_altPrev     = 'previous page';
221
 
222
    /**
223
     * @var string alt text for "next page"
224
     * @access private
225
     */
226
    var $_altNext     = 'next page';
227
 
228
    /**
229
     * @var string alt text for "last page" (use "%d" placeholder for page number)
230
     * @access private
231
     */
232
    var $_altLast     = 'last page';
233
 
234
    /**
235
     * @var string alt text for "page" (use optional "%d" placeholder for page number)
236
     * @access private
237
     */
238
    var $_altPage     = 'page';
239
 
240
    /**
241
     * @var string image/text to use as "prev" link
242
     * @access private
243
     */
244
    var $_prevImg     = '&lt;&lt; Back';
245
 
246
    /**
247
     * image/text to use as "prev" link when no prev link is needed  (e.g. on the first page)
248
     * NULL deactivates it
249
     *
250
     * @var string
251
     * @access private
252
     */
253
    var $_prevImgEmpty = null;
254
 
255
    /**
256
     * @var string image/text to use as "next" link
257
     * @access private
258
     */
259
    var $_nextImg     = 'Next &gt;&gt;';
260
 
261
    /**
262
     * image/text to use as "next" link when
263
     * no next link is needed (e.g. on the last page)
264
     * NULL deactivates it
265
     *
266
     * @var string
267
     * @access private
268
     */
269
    var $_nextImgEmpty = null;
270
 
271
    /**
272
     * @var string link separator
273
     * @access private
274
     */
275
    var $_separator   = '';
276
 
277
    /**
278
     * @var integer number of spaces before separator
279
     * @access private
280
     */
281
    var $_spacesBeforeSeparator = 0;
282
 
283
    /**
284
     * @var integer number of spaces after separator
285
     * @access private
286
     */
287
    var $_spacesAfterSeparator  = 1;
288
 
289
    /**
290
     * @var string CSS class name for current page link
291
     * @access private
292
     */
293
    var $_curPageLinkClassName  = '';
294
 
295
    /**
296
     * @var string Text before current page link
297
     * @access private
298
     */
299
    var $_curPageSpanPre        = '';
300
 
301
    /**
302
     * @var string Text after current page link
303
     * @access private
304
     */
305
    var $_curPageSpanPost       = '';
306
 
307
    /**
308
     * @var string Text before first page link
309
     * @access private
310
     */
311
    var $_firstPagePre  = '[';
312
 
313
    /**
314
     * @var string Text to be used for first page link
315
     * @access private
316
     */
317
    var $_firstPageText = '';
318
 
319
    /**
320
     * @var string Text after first page link
321
     * @access private
322
     */
323
    var $_firstPagePost = ']';
324
 
325
    /**
326
     * @var string Text before last page link
327
     * @access private
328
     */
329
    var $_lastPagePre   = '[';
330
 
331
    /**
332
     * @var string Text to be used for last page link
333
     * @access private
334
     */
335
    var $_lastPageText  = '';
336
 
337
    /**
338
     * @var string Text after last page link
339
     * @access private
340
     */
341
    var $_lastPagePost  = ']';
342
 
343
    /**
344
     * @var string Will contain the HTML code for the spaces
345
     * @access private
346
     */
347
    var $_spacesBefore  = '';
348
 
349
    /**
350
     * @var string Will contain the HTML code for the spaces
351
     * @access private
352
     */
353
    var $_spacesAfter   = '';
354
 
355
    /**
356
     * @var string String used as title in <link rel="first"> tag
357
     * @access private
358
     */
359
    var $_firstLinkTitle = 'first page';
360
 
361
    /**
362
     * @var string String used as title in <link rel="next"> tag
363
     * @access private
364
     */
365
    var $_nextLinkTitle = 'next page';
366
 
367
    /**
368
     * @var string String used as title in <link rel="previous"> tag
369
     * @access private
370
     */
371
    var $_prevLinkTitle = 'previous page';
372
 
373
    /**
374
     * @var string String used as title in <link rel="last"> tag
375
     * @access private
376
     */
377
    var $_lastLinkTitle = 'last page';
378
 
379
    /**
380
     * @var string Text to be used for the 'show all' option in the select box
381
     * @access private
382
     */
383
    var $_showAllText   = '';
384
 
385
    /**
386
     * @var array data to be paged
387
     * @access private
388
     */
389
    var $_itemData      = null;
390
 
391
    /**
392
     * @var boolean If TRUE and there's only one page, links aren't shown
393
     * @access private
394
     */
395
    var $_clearIfVoid   = true;
396
 
397
    /**
398
     * @var boolean Use session for storing the number of items per page
399
     * @access private
400
     */
401
    var $_useSessions   = false;
402
 
403
    /**
404
     * @var boolean Close the session when finished reading/writing data
405
     * @access private
406
     */
407
    var $_closeSession  = false;
408
 
409
    /**
410
     * @var string name of the session var for number of items per page
411
     * @access private
412
     */
413
    var $_sessionVar    = 'setPerPage';
414
 
415
    /**
416
     * Pear error mode (when raiseError is called)
417
     * (see PEAR doc)
418
     *
419
     * @var integer $_pearErrorMode
420
     * @access private
421
     */
422
    var $_pearErrorMode = null;
423
 
424
    // }}}
425
    // {{{ public vars
426
 
427
    /**
428
     * @var string Complete set of links
429
     * @access public
430
     */
431
    var $links = '';
432
 
433
    /**
434
     * @var string Complete set of link tags
435
     * @access public
436
     */
437
    var $linkTags = '';
438
 
439
    /**
440
     * @var array Complete set of raw link tags
441
     * @access public
442
     */
443
    var $linkTagsRaw = array();
444
 
445
    /**
446
     * @var array Array with a key => value pair representing
447
     *            page# => bool value (true if key==currentPageNumber).
448
     *            can be used for extreme customization.
449
     * @access public
450
     */
451
    var $range = array();
452
 
453
    /**
454
     * @var array list of available options (safety check)
455
     * @access private
456
     */
457
    var $_allowed_options = array(
458
        'totalItems',
459
        'perPage',
460
        'delta',
461
        'linkClass',
462
        'path',
463
        'fileName',
464
        'fixFileName',
465
        'append',
466
        'httpMethod',
467
        'formID',
468
        'importQuery',
469
        'urlVar',
470
        'altFirst',
471
        'altPrev',
472
        'altNext',
473
        'altLast',
474
        'altPage',
475
        'prevImg',
476
        'prevImgEmpty',
477
        'nextImg',
478
        'nextImgEmpty',
479
        'expanded',
480
        'accesskey',
481
        'attributes',
482
        'onclick',
483
        'separator',
484
        'spacesBeforeSeparator',
485
        'spacesAfterSeparator',
486
        'curPageLinkClassName',
487
        'curPageSpanPre',
488
        'curPageSpanPost',
489
        'firstPagePre',
490
        'firstPageText',
491
        'firstPagePost',
492
        'lastPagePre',
493
        'lastPageText',
494
        'lastPagePost',
495
        'firstLinkTitle',
496
        'nextLinkTitle',
497
        'prevLinkTitle',
498
        'lastLinkTitle',
499
        'showAllText',
500
        'itemData',
501
        'clearIfVoid',
502
        'useSessions',
503
        'closeSession',
504
        'sessionVar',
505
        'pearErrorMode',
506
        'extraVars',
507
        'excludeVars',
508
        'currentPage',
509
    );
510
 
511
    // }}}
512
    // {{{ build()
513
 
514
    /**
515
     * Generate or refresh the links and paged data after a call to setOptions()
516
     *
517
     * @return void
518
     * @access public
519
     */
520
    function build()
521
    {
522
        //reset
523
        $this->_pageData   = array();
524
        $this->links       = '';
525
        $this->linkTags    = '';
526
        $this->linkTagsRaw = array();
527
 
528
        $this->_generatePageData();
529
        $this->_setFirstLastText();
530
 
531
        if ($this->_totalPages > (2 * $this->_delta + 1)) {
532
            $this->links .= $this->_printFirstPage();
533
        }
534
 
535
        $this->links .= $this->_getBackLink();
536
        $this->links .= $this->_getPageLinks();
537
        $this->links .= $this->_getNextLink();
538
 
539
        $this->linkTags .= $this->_getFirstLinkTag();
540
        $this->linkTags .= $this->_getPrevLinkTag();
541
        $this->linkTags .= $this->_getNextLinkTag();
542
        $this->linkTags .= $this->_getLastLinkTag();
543
 
544
        $this->linkTagsRaw['first'] = $this->_getFirstLinkTag(true);
545
        $this->linkTagsRaw['prev']  = $this->_getPrevLinkTag(true);
546
        $this->linkTagsRaw['next']  = $this->_getNextLinkTag(true);
547
        $this->linkTagsRaw['last']  = $this->_getLastLinkTag(true);
548
 
549
        if ($this->_totalPages > (2 * $this->_delta + 1)) {
550
            $this->links .= $this->_printLastPage();
551
        }
552
    }
553
 
554
    // }}}
555
    // {{{ getPageData()
556
 
557
    /**
558
     * Returns an array of current pages data
559
     *
560
     * @param integer $pageID Desired page ID (optional)
561
     *
562
     * @return array Page data
563
     * @access public
564
     */
565
    function getPageData($pageID = null)
566
    {
567
        $pageID = empty($pageID) ? $this->_currentPage : $pageID;
568
 
569
        if (!isset($this->_pageData)) {
570
            $this->_generatePageData();
571
        }
572
        if (!empty($this->_pageData[$pageID])) {
573
            return $this->_pageData[$pageID];
574
        }
575
        return array();
576
    }
577
 
578
    // }}}
579
    // {{{ getPageIdByOffset()
580
 
581
    /**
582
     * Returns pageID for given offset
583
     *
584
     * @param integer $index Offset to get pageID for
585
     *
586
     * @return integer PageID for given offset
587
     * @access public
588
     */
589
    function getPageIdByOffset($index)
590
    {
591
        $msg = 'function "getPageIdByOffset()" not implemented.';
592
        return $this->raiseError($msg, ERROR_PAGER_NOT_IMPLEMENTED);
593
    }
594
 
595
    // }}}
596
    // {{{ getOffsetByPageId()
597
 
598
    /**
599
     * Returns offsets for given pageID. Eg, if you
600
     * pass it pageID one and your perPage limit is 10
601
     * it will return (1, 10). PageID of 2 would
602
     * give you (11, 20).
603
     *
604
     * @param integer $pageID PageID to get offsets for
605
     *
606
     * @return array  First and last offsets
607
     * @access public
608
     */
609
    function getOffsetByPageId($pageID = null)
610
    {
611
        $pageID = isset($pageID) ? $pageID : $this->_currentPage;
612
        if (!isset($this->_pageData)) {
613
            $this->_generatePageData();
614
        }
615
 
616
        if (isset($this->_pageData[$pageID]) || is_null($this->_itemData)) {
617
            return array(
618
                        max(($this->_perPage * ($pageID - 1)) + 1, 1),
619
                        min($this->_totalItems, $this->_perPage * $pageID)
620
                   );
621
        }
622
        return array(0, 0);
623
    }
624
 
625
    // }}}
626
    // {{{ getPageRangeByPageId()
627
 
628
    /**
629
     * Given a PageId, it returns the limits of the range of pages displayed.
630
     *
631
     * @param integer $pageID PageID to get offsets for
632
     *
633
     * @return array First and last offsets
634
     * @access public
635
     */
636
    function getPageRangeByPageId($pageID = null)
637
    {
638
        $msg = 'function "getPageRangeByPageId()" not implemented.';
639
        return $this->raiseError($msg, ERROR_PAGER_NOT_IMPLEMENTED);
640
    }
641
 
642
    // }}}
643
    // {{{ getLinks()
644
 
645
    /**
646
     * Returns back/next/first/last and page links,
647
     * both as ordered and associative array.
648
     *
649
     * NB: in original PEAR::Pager this method accepted two parameters,
650
     * $back_html and $next_html. Now the only parameter accepted is
651
     * an integer ($pageID), since the html text for prev/next links can
652
     * be set in the factory. If a second parameter is provided, then
653
     * the method act as it previously did. This hack was done to mantain
654
     * backward compatibility only.
655
     *
656
     * @param integer $pageID    Optional pageID. If specified, links for that
657
     *                           page are provided instead of current one.
658
     *                           [ADDED IN NEW PAGER VERSION]
659
     * @param string  $next_html HTML to put inside the next link
660
     *                           [deprecated: use the factory instead]
661
     *
662
     * @return array back/next/first/last and page links
663
     * @access public
664
     */
665
    function getLinks($pageID=null, $next_html='')
666
    {
667
        $msg = 'function "getLinks()" not implemented.';
668
        return $this->raiseError($msg, ERROR_PAGER_NOT_IMPLEMENTED);
669
    }
670
 
671
    // }}}
672
    // {{{ getCurrentPageID()
673
 
674
    /**
675
     * Returns ID of current page
676
     *
677
     * @return integer ID of current page
678
     * @access public
679
     */
680
    function getCurrentPageID()
681
    {
682
        return $this->_currentPage;
683
    }
684
 
685
    // }}}
686
    // {{{ getNextPageID()
687
 
688
    /**
689
     * Returns next page ID. If current page is last page
690
     * this function returns FALSE
691
     *
692
     * @return mixed Next page ID or false
693
     * @access public
694
     */
695
    function getNextPageID()
696
    {
697
        return ($this->getCurrentPageID() == $this->numPages() ? false : $this->getCurrentPageID() + 1);
698
    }
699
 
700
    // }}}
701
    // {{{ getPreviousPageID()
702
 
703
    /**
704
     * Returns previous page ID. If current page is first page
705
     * this function returns FALSE
706
     *
707
     * @return mixed Previous page ID or false
708
     * @access public
709
     */
710
    function getPreviousPageID()
711
    {
712
        return $this->isFirstPage() ? false : $this->getCurrentPageID() - 1;
713
    }
714
 
715
    // }}}
716
    // {{{ numItems()
717
 
718
    /**
719
     * Returns number of items
720
     *
721
     * @return integer Number of items
722
     * @access public
723
     */
724
    function numItems()
725
    {
726
        return $this->_totalItems;
727
    }
728
 
729
    // }}}
730
    // {{{ numPages()
731
 
732
    /**
733
     * Returns number of pages
734
     *
735
     * @return integer Number of pages
736
     * @access public
737
     */
738
    function numPages()
739
    {
740
        return (int)$this->_totalPages;
741
    }
742
 
743
    // }}}
744
    // {{{ isFirstPage()
745
 
746
    /**
747
     * Returns whether current page is first page
748
     *
749
     * @return bool First page or not
750
     * @access public
751
     */
752
    function isFirstPage()
753
    {
754
        return ($this->_currentPage < 2);
755
    }
756
 
757
    // }}}
758
    // {{{ isLastPage()
759
 
760
    /**
761
     * Returns whether current page is last page
762
     *
763
     * @return bool Last page or not
764
     * @access public
765
     */
766
    function isLastPage()
767
    {
768
        return ($this->_currentPage == $this->_totalPages);
769
    }
770
 
771
    // }}}
772
    // {{{ isLastPageComplete()
773
 
774
    /**
775
     * Returns whether last page is complete
776
     *
777
     * @return bool Last age complete or not
778
     * @access public
779
     */
780
    function isLastPageComplete()
781
    {
782
        return !($this->_totalItems % $this->_perPage);
783
    }
784
 
785
    // }}}
786
    // {{{ _generatePageData()
787
 
788
    /**
789
     * Calculates all page data
790
     *
791
     * @return void
792
     * @access private
793
     */
794
    function _generatePageData()
795
    {
796
        // Been supplied an array of data?
797
        if (!is_null($this->_itemData)) {
798
            $this->_totalItems = count($this->_itemData);
799
        }
800
        $this->_totalPages = ceil((float)$this->_totalItems / (float)$this->_perPage);
801
        $i = 1;
802
        if (!empty($this->_itemData)) {
803
            foreach ($this->_itemData as $key => $value) {
804
                $this->_pageData[$i][$key] = $value;
805
                if (count($this->_pageData[$i]) >= $this->_perPage) {
806
                    $i++;
807
                }
808
            }
809
        } else {
810
            $this->_pageData = array();
811
        }
812
 
813
        //prevent URL modification
814
        $this->_currentPage = min($this->_currentPage, $this->_totalPages);
815
    }
816
 
817
    // }}}
818
    // {{{ _renderLink()
819
 
820
    /**
821
     * Renders a link using the appropriate method
822
     *
823
     * @param string $altText  Alternative text for this link (title property)
824
     * @param string $linkText Text contained by this link
825
     *
826
     * @return string The link in string form
827
     * @access private
828
     */
829
    function _renderLink($altText, $linkText)
830
    {
831
        if ($this->_httpMethod == 'GET') {
832
            if ($this->_append) {
833
                $href = '?' . $this->_http_build_query_wrapper($this->_linkData);
834
            } else {
835
                $href = str_replace('%d', $this->_linkData[$this->_urlVar], $this->_fileName);
836
            }
837
            $onclick = '';
838
            if (array_key_exists($this->_urlVar, $this->_linkData)) {
839
                $onclick = str_replace('%d', $this->_linkData[$this->_urlVar], $this->_onclick);
840
            }
841
            return sprintf('<a href="%s"%s%s%s%s title="%s">%s</a>',
842
                           htmlentities($this->_url . $href, ENT_COMPAT, 'UTF-8'),
843
                           empty($this->_classString) ? '' : ' '.$this->_classString,
844
                           empty($this->_attributes)  ? '' : ' '.$this->_attributes,
845
                           empty($this->_accesskey)   ? '' : ' accesskey="'.$this->_linkData[$this->_urlVar].'"',
846
                           empty($onclick)            ? '' : ' onclick="'.$onclick.'"',
847
                           $altText,
848
                           $linkText
849
            );
850
        } elseif ($this->_httpMethod == 'POST') {
851
            $href = $this->_url;
852
            if (!empty($_GET)) {
853
                $href .= '?' . $this->_http_build_query_wrapper($_GET);
854
            }
855
            return sprintf("<a href='javascript:void(0)' onclick='%s'%s%s%s title='%s'>%s</a>",
856
                           $this->_generateFormOnClick($href, $this->_linkData),
857
                           empty($this->_classString) ? '' : ' '.$this->_classString,
858
                           empty($this->_attributes)  ? '' : ' '.$this->_attributes,
859
                           empty($this->_accesskey)   ? '' : ' accesskey=\''.$this->_linkData[$this->_urlVar].'\'',
860
                           $altText,
861
                           $linkText
862
            );
863
        }
864
        return '';
865
    }
866
 
867
    // }}}
868
    // {{{ _generateFormOnClick()
869
 
870
    /**
871
     * Mimics http_build_query() behavior in the way the data
872
     * in $data will appear when it makes it back to the server.
873
     *  For example:
874
     * $arr =  array('array' => array(array('hello', 'world'),
875
     *                                'things' => array('stuff', 'junk'));
876
     * http_build_query($arr)
877
     * and _generateFormOnClick('foo.php', $arr)
878
     * will yield
879
     * $_REQUEST['array'][0][0] === 'hello'
880
     * $_REQUEST['array'][0][1] === 'world'
881
     * $_REQUEST['array']['things'][0] === 'stuff'
882
     * $_REQUEST['array']['things'][1] === 'junk'
883
     *
884
     * However, instead of  generating a query string, it generates
885
     * Javascript to create and submit a form.
886
     *
887
     * @param string $formAction where the form should be submitted
888
     * @param array  $data       the associative array of names and values
889
     *
890
     * @return string A string of javascript that generates a form and submits it
891
     * @access private
892
     */
893
    function _generateFormOnClick($formAction, $data)
894
    {
895
        // Check we have an array to work with
896
        if (!is_array($data)) {
897
            trigger_error(
898
                '_generateForm() Parameter 1 expected to be Array or Object. Incorrect value given.',
899
                E_USER_WARNING
900
            );
901
            return false;
902
        }
903
 
904
        if (!empty($this->_formID)) {
905
            $str = 'var form = document.getElementById("'.$this->_formID.'"); var input = ""; ';
906
        } else {
907
            $str = 'var form = document.createElement("form"); var input = ""; ';
908
        }
909
 
910
        // We /shouldn't/ need to escape the URL ...
911
        $str .= sprintf('form.action = "%s"; ', htmlentities($formAction, ENT_COMPAT, 'UTF-8'));
912
        $str .= sprintf('form.method = "%s"; ', $this->_httpMethod);
913
        foreach ($data as $key => $val) {
914
            $str .= $this->_generateFormOnClickHelper($val, $key);
915
        }
916
 
917
        if (empty($this->_formID)) {
918
            $str .= 'document.getElementsByTagName("body")[0].appendChild(form);';
919
        }
920
 
921
        $str .= 'form.submit(); return false;';
922
        return $str;
923
    }
924
 
925
    // }}}
926
    // {{{ _generateFormOnClickHelper
927
 
928
    /**
929
     * This is used by _generateFormOnClick().
930
     * Recursively processes the arrays, objects, and literal values.
931
     *
932
     * @param mixed  $data Data that should be rendered
933
     * @param string $prev The name so far
934
     *
935
     * @return string A string of Javascript that creates form inputs
936
     *                representing the data
937
     * @access private
938
     */
939
    function _generateFormOnClickHelper($data, $prev = '')
940
    {
941
        $str = '';
942
        if (is_array($data) || is_object($data)) {
943
            // foreach key/visible member
944
            foreach ((array)$data as $key => $val) {
945
                // append [$key] to prev
946
                $tempKey = sprintf('%s[%s]', $prev, $key);
947
                $str .= $this->_generateFormOnClickHelper($val, $tempKey);
948
            }
949
        } else {  // must be a literal value
950
            // escape newlines and carriage returns
951
            $search  = array("\n", "\r");
952
            $replace = array('\n', '\n');
953
            $escapedData = str_replace($search, $replace, $data);
954
            // am I forgetting any dangerous whitespace?
955
            // would a regex be faster?
956
            // if it's already encoded, don't encode it again
957
            if (!$this->_isEncoded($escapedData)) {
958
                $escapedData = urlencode($escapedData);
959
            }
960
            $escapedData = htmlentities($escapedData, ENT_QUOTES, 'UTF-8');
961
 
962
            $str .= 'input = document.createElement("input"); ';
963
            $str .= 'input.type = "hidden"; ';
964
            $str .= sprintf('input.name = "%s"; ', $prev);
965
            $str .= sprintf('input.value = "%s"; ', $escapedData);
966
            $str .= 'form.appendChild(input); ';
967
        }
968
        return $str;
969
    }
970
 
971
    // }}}
972
    // {{{ _isRegexp()
973
 
974
    /**
975
     * Returns true if the string is a regexp pattern
976
     *
977
     * @param string $string the pattern to check
978
     *
979
     * @return boolean
980
     * @access private
981
     */
982
    function _isRegexp($string) {
983
        return preg_match('/^\/.*\/([Uims]+)?$/', $string);
984
    }
985
 
986
    // }}}
987
    // {{{ _getLinksData()
988
 
989
    /**
990
     * Returns the correct link for the back/pages/next links
991
     *
992
     * @return array Data
993
     * @access private
994
     */
995
    function _getLinksData()
996
    {
997
        $qs = array();
998
        if ($this->_importQuery) {
999
            if ($this->_httpMethod == 'POST') {
1000
                $qs = $_POST;
1001
            } elseif ($this->_httpMethod == 'GET') {
1002
                $qs = $_GET;
1003
            }
1004
        }
1005
        foreach ($this->_excludeVars as $exclude) {
1006
            $use_preg = $this->_isRegexp($exclude);
1007
            foreach (array_keys($qs) as $qs_item) {
1008
                if ($use_preg) {
1009
                    if (preg_match($exclude, $qs_item, $matches)) {
1010
                        foreach ($matches as $m) {
1011
                            unset($qs[$m]);
1012
                        }
1013
                    }
1014
                } elseif ($qs_item == $exclude) {
1015
                    unset($qs[$qs_item]);
1016
                    break;
1017
                }
1018
            }
1019
        }
1020
        if (count($this->_extraVars)) {
1021
            $this->_recursive_urldecode($this->_extraVars);
1022
            $qs = array_merge($qs, $this->_extraVars);
1023
        }
1024
        if (count($qs)
1025
            && function_exists('get_magic_quotes_gpc')
1026
            && -1 == version_compare(PHP_VERSION, '5.2.99')
1027
            && get_magic_quotes_gpc()
1028
        ) {
1029
            $this->_recursive_stripslashes($qs);
1030
        }
1031
        return $qs;
1032
    }
1033
 
1034
    // }}}
1035
    // {{{ _recursive_stripslashes()
1036
 
1037
    /**
1038
     * Helper method
1039
     *
1040
     * @param string|array &$var variable to clean
1041
     *
1042
     * @return void
1043
     * @access private
1044
     */
1045
    function _recursive_stripslashes(&$var)
1046
    {
1047
        if (is_array($var)) {
1048
            foreach (array_keys($var) as $k) {
1049
                $this->_recursive_stripslashes($var[$k]);
1050
            }
1051
        } else {
1052
            $var = stripslashes($var);
1053
        }
1054
    }
1055
 
1056
    // }}}
1057
    // {{{ _recursive_urldecode()
1058
 
1059
    /**
1060
     * Helper method
1061
     *
1062
     * @param string|array &$var variable to decode
1063
     *
1064
     * @return void
1065
     * @access private
1066
     */
1067
    function _recursive_urldecode(&$var)
1068
    {
1069
        if (is_array($var)) {
1070
            foreach (array_keys($var) as $k) {
1071
                $this->_recursive_urldecode($var[$k]);
1072
            }
1073
        } else {
1074
            $trans_tbl = array_flip(get_html_translation_table(HTML_ENTITIES));
1075
            $var = strtr($var, $trans_tbl);
1076
        }
1077
    }
1078
 
1079
    // }}}
1080
    // {{{ _getBackLink()
1081
 
1082
    /**
1083
     * Returns back link
1084
     *
1085
     * @param string $url  URL to use in the link  [deprecated: use the factory instead]
1086
     * @param string $link HTML to use as the link [deprecated: use the factory instead]
1087
     *
1088
     * @return string The link
1089
     * @access private
1090
     */
1091
    function _getBackLink($url='', $link='')
1092
    {
1093
        //legacy settings... the preferred way to set an option
1094
        //now is passing it to the factory
1095
        if (!empty($url)) {
1096
            $this->_path = $url;
1097
        }
1098
        if (!empty($link)) {
1099
            $this->_prevImg = $link;
1100
        }
1101
        $back = '';
1102
        if ($this->_currentPage > 1) {
1103
            $this->_linkData[$this->_urlVar] = $this->getPreviousPageID();
1104
            $back = $this->_renderLink($this->_altPrev, $this->_prevImg)
1105
                  . $this->_spacesBefore . $this->_spacesAfter;
1106
        } else if ($this->_prevImgEmpty !== null && $this->_totalPages > 1) {
1107
            $back = $this->_prevImgEmpty
1108
                  . $this->_spacesBefore . $this->_spacesAfter;
1109
        }
1110
        return $back;
1111
    }
1112
 
1113
    // }}}
1114
    // {{{ _getPageLinks()
1115
 
1116
    /**
1117
     * Returns pages link
1118
     *
1119
     * @param string $url URL to use in the link [deprecated: use the factory instead]
1120
     *
1121
     * @return string Links
1122
     * @access private
1123
     */
1124
    function _getPageLinks($url='')
1125
    {
1126
        $msg = 'function "_getPageLinks()" not implemented.';
1127
        return $this->raiseError($msg, ERROR_PAGER_NOT_IMPLEMENTED);
1128
    }
1129
 
1130
    // }}}
1131
    // {{{ _getNextLink()
1132
 
1133
    /**
1134
     * Returns next link
1135
     *
1136
     * @param string $url  URL to use in the link  [deprecated: use the factory instead]
1137
     * @param string $link HTML to use as the link [deprecated: use the factory instead]
1138
     *
1139
     * @return string The link
1140
     * @access private
1141
     */
1142
    function _getNextLink($url='', $link='')
1143
    {
1144
        //legacy settings... the preferred way to set an option
1145
        //now is passing it to the factory
1146
        if (!empty($url)) {
1147
            $this->_path = $url;
1148
        }
1149
        if (!empty($link)) {
1150
            $this->_nextImg = $link;
1151
        }
1152
        $next = '';
1153
        if ($this->_currentPage < $this->_totalPages) {
1154
            $this->_linkData[$this->_urlVar] = $this->getNextPageID();
1155
            $next = $this->_spacesAfter
1156
                  . $this->_renderLink($this->_altNext, $this->_nextImg)
1157
                  . $this->_spacesBefore . $this->_spacesAfter;
1158
        } else if ($this->_nextImgEmpty !== null && $this->_totalPages > 1) {
1159
            $next = $this->_spacesAfter
1160
                  . $this->_nextImgEmpty
1161
                  . $this->_spacesBefore . $this->_spacesAfter;
1162
        }
1163
        return $next;
1164
    }
1165
 
1166
    // }}}
1167
    // {{{ _getFirstLinkTag()
1168
 
1169
    /**
1170
     * Returns first link tag
1171
     *
1172
     * @param bool $raw should tag returned as array
1173
     *
1174
     * @return mixed string with html link tag or separated as array
1175
     * @access private
1176
     */
1177
    function _getFirstLinkTag($raw = false)
1178
    {
1179
        if ($this->isFirstPage() || ($this->_httpMethod != 'GET')) {
1180
            return $raw ? array() : '';
1181
        }
1182
        if ($raw) {
1183
            return array(
1184
                'url'   => $this->_getLinkTagUrl(1),
1185
                'title' => $this->_firstLinkTitle
1186
            );
1187
        }
1188
        return sprintf('<link rel="first" href="%s" title="%s" />'."\n",
1189
            $this->_getLinkTagUrl(1),
1190
            $this->_firstLinkTitle
1191
        );
1192
    }
1193
 
1194
    // }}}
1195
    // {{{ _getPrevLinkTag()
1196
 
1197
    /**
1198
     * Returns previous link tag
1199
     *
1200
     * @param bool $raw should tag returned as array
1201
     *
1202
     * @return mixed string with html link tag or separated as array
1203
     * @access private
1204
     */
1205
    function _getPrevLinkTag($raw = false)
1206
    {
1207
        if ($this->isFirstPage() || ($this->_httpMethod != 'GET')) {
1208
            return $raw ? array() : '';
1209
        }
1210
        if ($raw) {
1211
            return array(
1212
                'url'   => $this->_getLinkTagUrl($this->getPreviousPageID()),
1213
                'title' => $this->_prevLinkTitle
1214
            );
1215
        }
1216
        return sprintf('<link rel="previous" href="%s" title="%s" />'."\n",
1217
            $this->_getLinkTagUrl($this->getPreviousPageID()),
1218
            $this->_prevLinkTitle
1219
        );
1220
    }
1221
 
1222
    // }}}
1223
    // {{{ _getNextLinkTag()
1224
 
1225
    /**
1226
     * Returns next link tag
1227
     *
1228
     * @param bool $raw should tag returned as array
1229
     *
1230
     * @return mixed string with html link tag or separated as array
1231
     * @access private
1232
     */
1233
    function _getNextLinkTag($raw = false)
1234
    {
1235
        if ($this->isLastPage() || ($this->_httpMethod != 'GET')) {
1236
            return $raw ? array() : '';
1237
        }
1238
        if ($raw) {
1239
            return array(
1240
                'url'   => $this->_getLinkTagUrl($this->getNextPageID()),
1241
                'title' => $this->_nextLinkTitle
1242
            );
1243
        }
1244
        return sprintf('<link rel="next" href="%s" title="%s" />'."\n",
1245
            $this->_getLinkTagUrl($this->getNextPageID()),
1246
            $this->_nextLinkTitle
1247
        );
1248
    }
1249
 
1250
    // }}}
1251
    // {{{ _getLastLinkTag()
1252
 
1253
    /**
1254
     * Returns last link tag
1255
     *
1256
     * @param bool $raw should tag returned as array
1257
     *
1258
     * @return mixed string with html link tag or separated as array
1259
     * @access private
1260
     */
1261
    function _getLastLinkTag($raw = false)
1262
    {
1263
        if ($this->isLastPage() || ($this->_httpMethod != 'GET')) {
1264
            return $raw ? array() : '';
1265
        }
1266
        if ($raw) {
1267
            return array(
1268
                'url'   => $this->_getLinkTagUrl($this->_totalPages),
1269
                'title' => $this->_lastLinkTitle
1270
            );
1271
        }
1272
        return sprintf('<link rel="last" href="%s" title="%s" />'."\n",
1273
            $this->_getLinkTagUrl($this->_totalPages),
1274
            $this->_lastLinkTitle
1275
        );
1276
    }
1277
 
1278
    // }}}
1279
    // {{{ _getLinkTagUrl()
1280
 
1281
    /**
1282
     * Helper method
1283
     *
1284
     * @param integer $pageID page ID
1285
     *
1286
     * @return string the link tag url
1287
     * @access private
1288
     */
1289
    function _getLinkTagUrl($pageID)
1290
    {
1291
        $this->_linkData[$this->_urlVar] = $pageID;
1292
        if ($this->_append) {
1293
            $href = '?' . $this->_http_build_query_wrapper($this->_linkData);
1294
        } else {
1295
            $href = str_replace('%d', $this->_linkData[$this->_urlVar], $this->_fileName);
1296
        }
1297
        return htmlentities($this->_url . $href, ENT_COMPAT, 'UTF-8');
1298
    }
1299
 
1300
    // }}}
1301
    // {{{ getPerPageSelectBox()
1302
 
1303
    /**
1304
     * Returns a string with a XHTML SELECT menu,
1305
     * useful for letting the user choose how many items per page should be
1306
     * displayed. If parameter useSessions is TRUE, this value is stored in
1307
     * a session var. The string isn't echoed right now so you can use it
1308
     * with template engines.
1309
     *
1310
     * @param integer $start       starting value for the select menu
1311
     * @param integer $end         ending value for the select menu
1312
     * @param integer $step        step between values in the select menu
1313
     * @param boolean $showAllData If true, perPage is set equal to totalItems.
1314
     * @param array   $extraParams (or string $optionText for BC reasons)
1315
     *                - 'optionText': text to show in each option.
1316
     *                  Use '%d' where you want to see the number of pages selected.
1317
     *                - 'attributes': (html attributes) Tag attributes or
1318
     *                  HTML attributes (id="foo" pairs), will be inserted in the
1319
     *                  <select> tag
1320
     *
1321
     * @return string xhtml select box
1322
     * @access public
1323
     */
1324
    function getPerPageSelectBox($start=5, $end=30, $step=5, $showAllData=false, $extraParams=array())
1325
    {
1326
        include_once 'Pager/HtmlWidgets.php';
1327
        $widget = new Pager_HtmlWidgets($this);
1328
        return $widget->getPerPageSelectBox($start, $end, $step, $showAllData, $extraParams);
1329
    }
1330
 
1331
    // }}}
1332
    // {{{ getPageSelectBox()
1333
 
1334
    /**
1335
     * Returns a string with a XHTML SELECT menu with the page numbers,
1336
     * useful as an alternative to the links
1337
     *
1338
     * @param array  $params          - 'optionText': text to show in each option.
1339
     *                                  Use '%d' where you want to see the number
1340
     *                                  of pages selected.
1341
     *                                - 'autoSubmit': if TRUE, add some js code
1342
     *                                  to submit the form on the onChange event
1343
     * @param string $extraAttributes (html attributes) Tag attributes or
1344
     *                                HTML attributes (id="foo" pairs), will be
1345
     *                                inserted in the <select> tag
1346
     *
1347
     * @return string xhtml select box
1348
     * @access public
1349
     */
1350
    function getPageSelectBox($params = array(), $extraAttributes = '')
1351
    {
1352
        include_once 'Pager/HtmlWidgets.php';
1353
        $widget = new Pager_HtmlWidgets($this);
1354
        return $widget->getPageSelectBox($params, $extraAttributes);
1355
    }
1356
 
1357
    // }}}
1358
    // {{{ _printFirstPage()
1359
 
1360
    /**
1361
     * Print [1]
1362
     *
1363
     * @return string String with link to 1st page,
1364
     *                or empty string if this is the 1st page.
1365
     * @access private
1366
     */
1367
    function _printFirstPage()
1368
    {
1369
        if ($this->isFirstPage()) {
1370
            return '';
1371
        }
1372
        $this->_linkData[$this->_urlVar] = 1;
1373
        return $this->_renderLink(
1374
                str_replace('%d', 1, $this->_altFirst),
1375
                $this->_firstPagePre . $this->_firstPageText . $this->_firstPagePost
1376
        ) . $this->_spacesBefore . $this->_spacesAfter;
1377
    }
1378
 
1379
    // }}}
1380
    // {{{ _printLastPage()
1381
 
1382
    /**
1383
     * Print [numPages()]
1384
     *
1385
     * @return string String with link to last page,
1386
     *                or empty string if this is the 1st page.
1387
     * @access private
1388
     */
1389
    function _printLastPage()
1390
    {
1391
        if ($this->isLastPage()) {
1392
            return '';
1393
        }
1394
        $this->_linkData[$this->_urlVar] = $this->_totalPages;
1395
        return $this->_renderLink(
1396
                str_replace('%d', $this->_totalPages, $this->_altLast),
1397
                $this->_lastPagePre . $this->_lastPageText . $this->_lastPagePost
1398
        );
1399
    }
1400
 
1401
    // }}}
1402
    // {{{ _setFirstLastText()
1403
 
1404
    /**
1405
     * sets the private _firstPageText, _lastPageText variables
1406
     * based on whether they were set in the options
1407
     *
1408
     * @return void
1409
     * @access private
1410
     */
1411
    function _setFirstLastText()
1412
    {
1413
        if ($this->_firstPageText == '') {
1414
            $this->_firstPageText = '1';
1415
        }
1416
        if ($this->_lastPageText == '') {
1417
            $this->_lastPageText = $this->_totalPages;
1418
        }
1419
    }
1420
 
1421
    // }}}
1422
    // {{{ _http_build_query_wrapper()
1423
 
1424
    /**
1425
     * This is a slightly modified version of the http_build_query() function;
1426
     * it heavily borrows code from PHP_Compat's http_build_query().
1427
     * The main change is the usage of htmlentities instead of urlencode,
1428
     * since it's too aggressive
1429
     *
1430
     * @param array $data array of querystring values
1431
     *
1432
     * @return string
1433
     * @access private
1434
     */
1435
    function _http_build_query_wrapper($data)
1436
    {
1437
        $data = (array)$data;
1438
        if (empty($data)) {
1439
            return '';
1440
        }
1441
        $separator = ini_get('arg_separator.output');
1442
        if ($separator == '&amp;') {
1443
            $separator = '&'; //the string is escaped by htmlentities anyway...
1444
        }
1445
        $tmp = array ();
1446
        foreach ($data as $key => $val) {
1447
            if (is_scalar($val)) {
1448
                //array_push($tmp, $key.'='.$val);
1449
                $val = urlencode($val);
1450
                array_push($tmp, $key .'='. str_replace('%2F', '/', $val));
1451
                continue;
1452
            }
1453
            // If the value is an array, recursively parse it
1454
            if (is_array($val)) {
1455
                array_push($tmp, $this->__http_build_query($val, urlencode($key)));
1456
                continue;
1457
            }
1458
        }
1459
        return implode($separator, $tmp);
1460
    }
1461
 
1462
    // }}}
1463
    // {{{ __http_build_query()
1464
 
1465
    /**
1466
     * Helper function
1467
     *
1468
     * @param array  $array array of querystring values
1469
     * @param string $name  key
1470
     *
1471
     * @return string
1472
     * @access private
1473
     */
1474
    function __http_build_query($array, $name)
1475
    {
1476
        $tmp = array ();
1477
        $separator = ini_get('arg_separator.output');
1478
        if ($separator == '&amp;') {
1479
            $separator = '&'; //the string is escaped by htmlentities anyway...
1480
        }
1481
        foreach ($array as $key => $value) {
1482
            if (is_array($value)) {
1483
                //array_push($tmp, $this->__http_build_query($value, sprintf('%s[%s]', $name, $key)));
1484
                array_push($tmp, $this->__http_build_query($value, $name.'%5B'.$key.'%5D'));
1485
            } elseif (is_scalar($value)) {
1486
                //array_push($tmp, sprintf('%s[%s]=%s', $name, htmlentities($key), htmlentities($value)));
1487
                array_push($tmp, $name.'%5B'.urlencode($key).'%5D='.urlencode($value));
1488
            } elseif (is_object($value)) {
1489
                //array_push($tmp, $this->__http_build_query(get_object_vars($value), sprintf('%s[%s]', $name, $key)));
1490
                array_push($tmp, $this->__http_build_query(get_object_vars($value), $name.'%5B'.$key.'%5D'));
1491
            }
1492
        }
1493
        return implode($separator, $tmp);
1494
    }
1495
 
1496
    // }}}
1497
    // {{{ _isEncoded()
1498
 
1499
    /**
1500
     * Helper function
1501
     * Check if a string is an encoded multibyte string
1502
     *
1503
     * @param string $string string to check
1504
     *
1505
     * @return boolean
1506
     * @access private
1507
     */
1508
 
1509
    function _isEncoded($string)
1510
    {
1511
        $hexchar = '&#[\dA-Fx]{2,};';
1512
        return preg_match("/^(\s|($hexchar))*$/Uims", $string) ? true : false;
1513
    }
1514
 
1515
    // }}}
1516
    // {{{ raiseError()
1517
 
1518
    /**
1519
     * conditionally includes PEAR base class and raise an error
1520
     *
1521
     * @param string  $msg  Error message
1522
     * @param integer $code Error code
1523
     *
1524
     * @return PEAR_Error
1525
     * @access private
1526
     */
1527
    function raiseError($msg, $code)
1528
    {
1529
        include_once 'PEAR.php';
1530
        if (empty($this->_pearErrorMode)) {
1531
            $this->_pearErrorMode = PEAR_ERROR_RETURN;
1532
        }
1533
        return PEAR::raiseError($msg, $code, $this->_pearErrorMode);
1534
    }
1535
 
1536
    // }}}
1537
    // {{{ setOptions()
1538
 
1539
    /**
1540
     * Set and sanitize options
1541
     *
1542
     * @param mixed $options An associative array of option names and their values
1543
     *
1544
     * @return integer error code (PAGER_OK on success)
1545
     * @access public
1546
     */
1547
    function setOptions($options)
1548
    {
1549
        foreach ($options as $key => $value) {
1550
            if (in_array($key, $this->_allowed_options) && (!is_null($value))) {
1551
                $this->{'_' . $key} = $value;
1552
            }
1553
        }
1554
 
1555
        //autodetect http method
1556
        if (!isset($options['httpMethod'])
1557
            && !isset($_GET[$this->_urlVar])
1558
            && isset($_POST[$this->_urlVar])
1559
        ) {
1560
            $this->_httpMethod = 'POST';
1561
        } else {
1562
            $this->_httpMethod = strtoupper($this->_httpMethod);
1563
        }
1564
 
1565
        if (substr($this->_path, -1, 1) == '/') {
1566
            $this->_fileName = ltrim($this->_fileName, '/');  //strip leading slash
1567
        }
1568
 
1569
        if ($this->_append) {
1570
            if ($this->_fixFileName) {
1571
                $this->_fileName = PAGER_CURRENT_FILENAME; //avoid possible user error;
1572
            }
1573
            $this->_url = $this->_path.(empty($this->_path) ? '' : '/').$this->_fileName;
1574
        } else {
1575
            $this->_url = $this->_path;
1576
            if (0 != strncasecmp($this->_fileName, 'javascript', 10)) {
1577
                $this->_url .= (empty($this->_path) ? '' : '/');
1578
            }
1579
            if (false === strpos($this->_fileName, '%d')) {
1580
                trigger_error($this->errorMessage(ERROR_PAGER_INVALID_USAGE), E_USER_WARNING);
1581
            }
1582
        }
1583
        if (substr($this->_url, 0, 2) == '//') {
1584
            $this->_url = substr($this->_url, 1);
1585
        }
1586
        if (false === strpos($this->_altPage, '%d')) {
1587
            //by default, append page number at the end
1588
            $this->_altPage .= ' %d';
1589
        }
1590
 
1591
        $this->_classString = '';
1592
        if (strlen($this->_linkClass)) {
1593
            $this->_classString = 'class="'.$this->_linkClass.'"';
1594
        }
1595
 
1596
        if (strlen($this->_curPageLinkClassName)) {
1597
            $this->_curPageSpanPre  .= '<span class="'.$this->_curPageLinkClassName.'">';
1598
            $this->_curPageSpanPost = '</span>' . $this->_curPageSpanPost;
1599
        }
1600
 
1601
        $this->_perPage = max($this->_perPage, 1); //avoid possible user errors
1602
 
1603
        if ($this->_useSessions && !isset($_SESSION)) {
1604
            session_start();
1605
        }
1606
        if (!empty($_REQUEST[$this->_sessionVar])) {
1607
            $this->_perPage = max(1, (int)$_REQUEST[$this->_sessionVar]);
1608
            if ($this->_useSessions) {
1609
                $_SESSION[$this->_sessionVar] = $this->_perPage;
1610
            }
1611
        }
1612
 
1613
        if (!empty($_SESSION[$this->_sessionVar]) && $this->_useSessions) {
1614
             $this->_perPage = $_SESSION[$this->_sessionVar];
1615
        }
1616
 
1617
        if ($this->_closeSession) {
1618
            session_write_close();
1619
        }
1620
 
1621
        $this->_spacesBefore = str_repeat('&nbsp;', $this->_spacesBeforeSeparator);
1622
        $this->_spacesAfter  = str_repeat('&nbsp;', $this->_spacesAfterSeparator);
1623
 
1624
        if (isset($_REQUEST[$this->_urlVar]) && empty($options['currentPage'])) {
1625
            $this->_currentPage = (int)$_REQUEST[$this->_urlVar];
1626
        }
1627
        $this->_currentPage = max($this->_currentPage, 1);
1628
        $this->_linkData = $this->_getLinksData();
1629
 
1630
        return PAGER_OK;
1631
    }
1632
 
1633
    // }}}
1634
    // {{{ getOption()
1635
 
1636
    /**
1637
     * Return the current value of a given option
1638
     *
1639
     * @param string $name option name
1640
     *
1641
     * @return mixed option value
1642
     * @access public
1643
     */
1644
    function getOption($name)
1645
    {
1646
        if (!in_array($name, $this->_allowed_options)) {
1647
            $msg = 'invalid option: '.$name;
1648
            return $this->raiseError($msg, ERROR_PAGER_INVALID);
1649
        }
1650
        return $this->{'_' . $name};
1651
    }
1652
 
1653
    // }}}
1654
    // {{{ getOptions()
1655
 
1656
    /**
1657
     * Return an array with all the current pager options
1658
     *
1659
     * @return array list of all the pager options
1660
     * @access public
1661
     */
1662
    function getOptions()
1663
    {
1664
        $options = array();
1665
        foreach ($this->_allowed_options as $option) {
1666
            $options[$option] = $this->{'_' . $option};
1667
        }
1668
        return $options;
1669
    }
1670
 
1671
    // }}}
1672
    // {{{ errorMessage()
1673
 
1674
    /**
1675
     * Return a textual error message for a PAGER error code
1676
     *
1677
     * @param integer $code error code
1678
     *
1679
     * @return string error message
1680
     * @access public
1681
     */
1682
    function errorMessage($code)
1683
    {
1684
        static $errorMessages;
1685
        if (!isset($errorMessages)) {
1686
            $errorMessages = array(
1687
                ERROR_PAGER                     => 'unknown error',
1688
                ERROR_PAGER_INVALID             => 'invalid',
1689
                ERROR_PAGER_INVALID_PLACEHOLDER => 'invalid format - use "%d" as placeholder.',
1690
                ERROR_PAGER_INVALID_USAGE       => 'if $options[\'append\'] is set to false, '
1691
                                                  .' $options[\'fileName\'] MUST contain the "%d" placeholder.',
1692
                ERROR_PAGER_NOT_IMPLEMENTED     => 'not implemented'
1693
            );
1694
        }
1695
 
1696
        return (isset($errorMessages[$code]) ?
1697
            $errorMessages[$code] : $errorMessages[ERROR_PAGER]);
1698
    }
1699
 
1700
    // }}}
1701
}
1702
?>