OSDN Git Service

BugTrack/2470 Lengthen Footnote title max-length to 100 chars
[pukiwiki/pukiwiki.git] / plugin / map.inc.php
1 <?php
2 // PukiWiki - Yet another WikiWikiWeb clone.
3 // map.inc.php
4 // Copyright 2002-2017 PukiWiki Development Team
5 // License: GPL v2 or (at your option) any later version
6 //
7 // Site map plugin
8
9 /*
10  * プラグイン map: サイトマップ(のようなもの)を表示
11  * Usage : http://.../pukiwiki.php?plugin=map
12  * パラメータ
13  *   &refer=ページ名
14  *     起点となるページを指定
15  *   &reverse=true
16  *     あるページがどこからリンクされているかを一覧。
17 */
18
19 // Show $non_list files
20 define('PLUGIN_MAP_SHOW_HIDDEN', 0); // 0, 1
21
22 function plugin_map_action()
23 {
24         global $vars, $whatsnew, $defaultpage, $non_list;
25
26         $reverse = isset($vars['reverse']);
27         $refer   = isset($vars['refer']) ? $vars['refer'] : '';
28         if ($refer == '' || ! is_page($refer))
29                 $vars['refer'] = $refer = $defaultpage;
30
31         $retval['msg']  = $reverse ? 'Relation map (link from)' : 'Relation map, from $1';
32         $retval['body'] = '';
33
34         // Get pages
35         $pages = array_values(array_diff(get_existpages(), array($whatsnew)));
36         if (! PLUGIN_MAP_SHOW_HIDDEN)
37                 $pages = array_diff($pages, preg_grep('/' . $non_list . '/', $pages));
38         if (empty($pages)) {
39                 $retval['body'] = 'No pages.';
40                 return $retval;
41         } else {
42                 $retval['body'] .= '<p>' . "\n" .  'Total: ' . count($pages) .
43                         ' page(s) on this site.' . "\n" . '</p>' . "\n";
44         }
45
46         // Generate a tree
47         $nodes = array();
48         foreach ($pages as $page)
49                 $nodes[$page] = new MapNode($page, $reverse);
50
51         // Node not found: Because of filtererd by $non_list
52         if (! isset($nodes[$refer])) $vars['refer'] = $refer = $defaultpage;
53
54         if ($reverse) {
55                 $keys = array_keys($nodes);
56                 sort($keys, SORT_STRING);
57                 $alone = array();
58                 $retval['body'] .= '<ul>' . "\n";
59                 foreach ($keys as $page) {
60                         if (! empty($nodes[$page]->rels)) {
61                                 $retval['body'] .= $nodes[$page]->toString($nodes, 1, $nodes[$page]->parent_id);
62                         } else {
63                                 $alone[] = $page;
64                         }
65                 }
66                 $retval['body'] .= '</ul>' . "\n";
67                 if (! empty($alone)) {
68                         $retval['body'] .= '<hr />' . "\n" .
69                                 '<p>No link from anywhere in this site.</p>' . "\n";
70                         $retval['body'] .= '<ul>' . "\n";
71                         foreach ($alone as $page)
72                                 $retval['body'] .= $nodes[$page]->toString($nodes, 1, $nodes[$page]->parent_id);
73                         $retval['body'] .= '</ul>' . "\n";
74                 }
75         } else {
76                 $nodes[$refer]->chain($nodes);
77                 $retval['body'] .= '<ul>' . "\n" . $nodes[$refer]->toString($nodes) . '</ul>' . "\n";
78                 $retval['body'] .= '<hr />' . "\n" .
79                         '<p>Not related from ' . htmlsc($refer) . '</p>' . "\n";
80                 $keys = array_keys($nodes);
81                 sort($keys, SORT_STRING);
82                 $retval['body'] .= '<ul>' . "\n";
83                 foreach ($keys as $page) {
84                         if (! $nodes[$page]->done) {
85                                 $nodes[$page]->chain($nodes);
86                                 $retval['body'] .= $nodes[$page]->toString($nodes, 1, $nodes[$page]->parent_id);
87                         }
88                 }
89                 $retval['body'] .= '</ul>' . "\n";
90         }
91
92         // 終了
93         return $retval;
94 }
95
96 class MapNode
97 {
98         var $page;
99         var $is_page;
100         var $link;
101         var $id;
102         var $rels;
103         var $parent_id = 0;
104         var $done;
105         var $hide_pattern;
106
107         function MapNode($page, $reverse = FALSE)
108         {
109                 $this->__construct($page, $reverse);
110         }
111         function __construct($page, $reverse = FALSE)
112         {
113                 global $non_list;
114
115                 static $id = 0;
116
117                 $this->page    = $page;
118                 $this->is_page = is_page($page);
119                 $this->cache   = CACHE_DIR . encode($page);
120                 $this->done    = ! $this->is_page;
121                 $this->link    = make_pagelink($page);
122                 $this->id      = ++$id;
123                 $this->hide_pattern = '/' . $non_list . '/';
124
125                 $this->rels = $reverse ? $this->ref() : $this->rel();
126                 $mark       = $reverse ? '' : '<sup>+</sup>';
127                 $this->mark = '<a id="rel_' . $this->id . '" href="' . get_base_uri() .
128                         '?plugin=map&amp;refer=' . rawurlencode($this->page) . '">' .
129                         $mark . '</a>';
130         }
131
132         function hide(& $pages)
133         {
134                 if (! PLUGIN_MAP_SHOW_HIDDEN)
135                         $pages = array_diff($pages, preg_grep($this->hide_pattern, $pages));
136                 return $pages;
137         }
138
139         function ref()
140         {
141                 $refs = array();
142                 $file = $this->cache . '.ref';
143                 if (file_exists($file)) {
144                         foreach (file($file) as $line) {
145                                 $ref = explode("\t", $line);
146                                 $refs[] = $ref[0];
147                         }
148                         $this->hide($refs);
149                         sort($refs, SORT_STRING);
150                 }
151                 return $refs;
152         }
153
154         function rel()
155         {
156                 $rels = array();
157                 $file = $this->cache . '.rel';
158                 if (file_exists($file)) {
159                         $data = file($file);
160                         $rels = explode("\t", trim($data[0]));
161                         $this->hide($rels);
162                         sort($rels, SORT_STRING);
163                 }
164                 return $rels;
165         }
166
167         function chain(& $nodes)
168         {
169                 if ($this->done) return;
170
171                 $this->done = TRUE;
172                 if ($this->parent_id == 0) $this->parent_id = -1;
173
174                 foreach ($this->rels as $page) {
175                         if (! isset($nodes[$page])) $nodes[$page] = new MapNode($page);
176                         if ($nodes[$page]->parent_id == 0)
177                                 $nodes[$page]->parent_id = $this->id;
178                 }
179                 foreach ($this->rels as $page)
180                         $nodes[$page]->chain($nodes);
181         }
182
183         function toString(& $nodes, $level = 1, $parent_id = -1)
184         {
185                 $indent = str_repeat(' ', $level);
186
187                 if (! $this->is_page) {
188                         return $indent . '<li>' . $this->link . '</li>' . "\n";
189                 } else if ($this->parent_id != $parent_id) {
190                         return $indent . '<li>' . $this->link .
191                                 '<a href="#rel_' . $this->id . '">...</a></li>' . "\n";
192                 }
193                 $retval = $indent . '<li>' . $this->mark . $this->link . "\n";
194                 if (! empty($this->rels)) {
195                         $childs = array();
196                         $level += 2;
197                         foreach ($this->rels as $page)
198                                 if (isset($nodes[$page]) && $this->parent_id != $nodes[$page]->id)
199                                         $childs[] = $nodes[$page]->toString($nodes, $level, $this->id);
200
201                         if (! empty($childs))
202                                 $retval .= $indent . ' <ul>' . "\n" .
203                                         join('', $childs) . $indent . ' </ul>' . "\n";
204                 }
205                 $retval .= $indent . '</li>' . "\n";
206
207                 return $retval;
208         }
209 }