OSDN Git Service

BugTrack2/361 Simplify URL. Keep slash / and colon : in page name URL
[pukiwiki/pukiwiki.git] / plugin / navi.inc.php
1 <?php
2 // PukiWiki - Yet another WikiWikiWeb clone.
3 // $Id: navi.inc.php,v 1.24 2011/01/25 15:01:01 henoheno Exp $
4 //
5 // Navi plugin: Show DocBook-like navigation bar and contents
6
7 /*
8  * Usage:
9  *   #navi(contents-page-name)   <for ALL child pages>
10  *   #navi([contents-page-name][,reverse]) <for contents page>
11  *
12  * Parameter:
13  *   contents-page-name - Page name of home of the navigation (default:itself)
14  *   reverse            - Show contents revese
15  *
16  * Behaviour at contents page:
17  *   Always show child-page list like 'ls' plugin
18  *
19  * Behaviour at child pages:
20  *
21  *   The first plugin call - Show a navigation bar like a DocBook header
22  *
23  *     Prev  <contents-page-name>  Next
24  *     --------------------------------
25  *
26  *   The second call - Show a navigation bar like a DocBook footer
27  *
28  *     --------------------------------
29  *     Prev          Home          Next
30  *     <pagename>     Up     <pagename>
31  *
32  * Page-construction example:
33  *   foobar    - Contents page, includes '#navi' or '#navi(foobar)'
34  *   foobar/1  - One of child pages, includes one or two '#navi(foobar)'
35  *   foobar/2  - One of child pages, includes one or two '#navi(foobar)'
36  */
37
38 // Exclusive regex pattern of child pages
39 define('PLUGIN_NAVI_EXCLUSIVE_REGEX', '');
40 //define('PLUGIN_NAVI_EXCLUSIVE_REGEX', '#/_#'); // Ignore 'foobar/_memo' etc.
41
42 // Insert <link rel=... /> tags into XHTML <head></head>
43 define('PLUGIN_NAVI_LINK_TAGS', FALSE); // FALSE, TRUE
44
45 // ----
46
47 function plugin_navi_convert()
48 {
49         global $vars, $script, $head_tags;
50         global $_navi_prev, $_navi_next, $_navi_up, $_navi_home;
51         static $navi = array();
52
53         $current = $vars['page'];
54         $reverse = FALSE;
55         if (func_num_args()) {
56                 list($home, $reverse) = array_pad(func_get_args(), 2, '');
57                 // strip_bracket() is not necessary but compatible
58                 $home    = get_fullname(strip_bracket($home), $current);
59                 $is_home = ($home == $current);
60                 if (! is_page($home)) {
61                         return '#navi(contents-page-name): No such page: ' .
62                                 htmlsc($home) . '<br />';
63                 } else if (! $is_home &&
64                     ! preg_match('/^' . preg_quote($home, '/') . '/', $current)) {
65                         return '#navi(' . htmlsc($home) .
66                                 '): Not a child page like: ' .
67                                 htmlsc($home . '/' . basename($current)) .
68                                 '<br />';
69                 }
70                 $reverse = (strtolower($reverse) == 'reverse');
71         } else {
72                 $home    = $vars['page'];
73                 $is_home = TRUE; // $home == $current
74         }
75
76         $pages  = array();
77         $footer = isset($navi[$home]); // The first time: FALSE, the second: TRUE
78         if (! $footer) {
79                 $navi[$home] = array(
80                         'up'   =>'',
81                         'prev' =>'',
82                         'prev1'=>'',
83                         'next' =>'',
84                         'next1'=>'',
85                         'home' =>'',
86                         'home1'=>'',
87                 );
88
89                 $pages = preg_grep('/^' . preg_quote($home, '/') .
90                         '($|\/)/', get_existpages());
91                 if (PLUGIN_NAVI_EXCLUSIVE_REGEX != '') {
92                         // If old PHP could use preg_grep(,,PREG_GREP_INVERT)...
93                         $pages = array_diff($pages,
94                                 preg_grep(PLUGIN_NAVI_EXCLUSIVE_REGEX, $pages));
95                 }
96                 $pages[] = $current; // Sentinel :)
97                 $pages   = array_unique($pages);
98                 natcasesort($pages);
99                 if ($reverse) $pages = array_reverse($pages);
100
101                 $prev = $home;
102                 foreach ($pages as $page) {
103                         if ($page === $current) break;
104                         $prev = $page;
105                 }
106                 $next = current($pages);
107
108                 $pos = strrpos($current, '/');
109                 $up = '';
110                 if ($pos > 0) {
111                         $up = substr($current, 0, $pos);
112                         $navi[$home]['up']    = make_pagelink($up, $_navi_up);
113                 }
114                 if (! $is_home) {
115                         $navi[$home]['prev']  = make_pagelink($prev);
116                         $navi[$home]['prev1'] = make_pagelink($prev, $_navi_prev);
117                 }
118                 if ($next != '') {
119                         $navi[$home]['next']  = make_pagelink($next);
120                         $navi[$home]['next1'] = make_pagelink($next, $_navi_next);
121                 }
122                 $navi[$home]['home']  = make_pagelink($home);
123                 $navi[$home]['home1'] = make_pagelink($home, $_navi_home);
124
125                 // Generate <link> tag: start next prev(previous) parent(up)
126                 // Not implemented: contents(toc) search first(begin) last(end)
127                 if (PLUGIN_NAVI_LINK_TAGS) {
128                         foreach (array('start'=>$home, 'next'=>$next,
129                             'prev'=>$prev, 'up'=>$up) as $rel=>$_page) {
130                                 if ($_page != '') {
131                                         $s_page = htmlsc($_page);
132                                         $r_page = pagename_urlencode($_page);
133                                         $head_tags[] = ' <link rel="' .
134                                                 $rel . '" href="' . $script .
135                                                 '?' . $r_page . '" title="' .
136                                                 $s_page . '" />';
137                                 }
138                         }
139                 }
140         }
141
142         $ret = '';
143
144         if ($is_home) {
145                 // Show contents
146                 $count = count($pages);
147                 if ($count == 0) {
148                         return '#navi(contents-page-name): You already view the result<br />';
149                 } else if ($count == 1) {
150                         // Sentinel only: Show usage and warning
151                         $home = htmlsc($home);
152                         $ret .= '#navi(' . $home . '): No child page like: ' .
153                                 $home . '/Foo';
154                 } else {
155                         $ret .= '<ul>';
156                         foreach ($pages as $page)
157                                 if ($page !== $home)
158                                         $ret .= ' <li>' . make_pagelink($page) . '</li>';
159                         $ret .= '</ul>';
160                 }
161
162         } else if (! $footer) {
163                 // Header
164                 $ret = <<<EOD
165 <ul class="navi">
166  <li class="navi_left">{$navi[$home]['prev1']}</li>
167  <li class="navi_right">{$navi[$home]['next1']}</li>
168  <li class="navi_none">{$navi[$home]['home']}</li>
169 </ul>
170 <hr class="full_hr" />
171 EOD;
172
173         } else {
174                 // Footer
175                 $ret = <<<EOD
176 <hr class="full_hr" />
177 <ul class="navi">
178  <li class="navi_left">{$navi[$home]['prev1']}<br />{$navi[$home]['prev']}</li>
179  <li class="navi_right">{$navi[$home]['next1']}<br />{$navi[$home]['next']}</li>
180  <li class="navi_none">{$navi[$home]['home1']}<br />{$navi[$home]['up']}</li>
181 </ul>
182 EOD;
183         }
184         return $ret;
185 }
186