OSDN Git Service

BugTrack/302: infinite loop bug fix when circular references of no-related pages.
[pukiwiki/pukiwiki.git] / plugin / map.inc.php
1 <?php
2 /////////////////////////////////////////////////
3 // PukiWiki - Yet another WikiWikiWeb clone.
4 //
5 // $Id: map.inc.php,v 1.10 2003/04/17 02:09:01 arino Exp $
6 //
7 /*
8 ¥×¥é¥°¥¤¥ó map
9
10 ¥µ¥¤¥È¥Þ¥Ã¥×(¤Î¤è¤¦¤Ê¤â¤Î)¤òɽ¼¨
11
12 Usage : http://.../pukiwiki.php?plugin=map
13
14 ¥Ñ¥é¥á¡¼¥¿
15
16 &refer=¥Ú¡¼¥¸Ì¾
17  µ¯ÅÀ¤È¤Ê¤ë¥Ú¡¼¥¸¤ò»ØÄê
18
19 &reverse=true
20  ¤¢¤ë¥Ú¡¼¥¸¤¬¤É¤³¤«¤é¥ê¥ó¥¯¤µ¤ì¤Æ¤¤¤ë¤«¤ò°ìÍ÷¡£
21
22 */
23
24 function plugin_map_action()
25 {
26         global $vars,$whatsnew,$defaultpage;
27         
28         $reverse = array_key_exists('reverse',$vars);
29         
30         $refer = array_key_exists('refer',$vars) ? $vars['refer'] : '';
31         
32         if ($refer == '' or !is_page($refer))
33         {
34                 $vars['refer'] = $refer = $defaultpage;
35         }
36         
37         $retval['msg'] = $reverse ? 'Relation map (link from)' : 'Relation map, from $1';
38         $retval['body'] = '';
39         
40         $pages = array_values(array_diff(get_existpages(),array($whatsnew)));
41         
42         $count = count($pages);
43         
44         if ($count == 0)
45         {
46                 $retval['body'] = 'no pages.';
47                 return $retval;
48         }
49         
50         // ¥Ú¡¼¥¸¿ô
51         $retval['body'] .= "<p>\ntotal: $count page(s) on this site.\n</p>\n";
52         
53         // ¥Ä¥ê¡¼ºîÀ®
54         $nodes = array();
55         foreach ($pages as $page)
56         {
57                 $nodes[$page] = & new MapNode($page,$reverse);
58         }
59         
60         if ($reverse)
61         {
62                 $keys = array_keys($nodes);
63                 sort($keys);
64                 $alone = array();
65                 $retval['body'] .= "<ul>\n";
66                 foreach ($keys as $page)
67                 {
68                         if (count($nodes[$page]->rels))
69                         {
70                                 $retval['body'] .= $nodes[$page]->toString($nodes,1,$nodes[$page]->parent_id);
71                         }
72                         else
73                         {
74                                 $alone[] = $page;
75                         }
76                 }
77                 $retval['body'] .= "</ul>\n";
78                 if (count($alone))
79                 {
80                         $retval['body'] .= "<hr />\n<p>no link from anywhere in this site.</p>\n";
81                         $retval['body'] .= "<ul>\n";
82                         foreach ($alone as $page)
83                         {
84                                 $retval['body'] .= $nodes[$page]->toString($nodes,1,$nodes[$page]->parent_id);
85                         }
86                         $retval['body'] .= "</ul>\n";
87                 }
88         }
89         else
90         {
91                 $nodes[$refer]->chain($nodes);
92                 $retval['body'] .= "<ul>\n".$nodes[$refer]->toString($nodes)."</ul>\n";
93                 $retval['body'] .= "<hr /><p>not related from ".htmlspecialchars($refer)."</p>\n";
94                 $keys = array_keys($nodes);
95                 sort($keys);
96                 $retval['body'] .= "<ul>\n";
97                 foreach ($keys as $page)
98                 {
99                         if (!$nodes[$page]->done)
100                         {
101                                 $nodes[$page]->chain($nodes);
102                                 $retval['body'] .= $nodes[$page]->toString($nodes,1,$nodes[$page]->parent_id);
103                         }
104                 }
105                 $retval['body'] .= "</ul>\n";
106         }
107         // ½ªÎ»
108         return $retval;
109 }
110
111 class MapNode
112 {
113         var $page;
114         var $is_page;
115         var $link;
116         var $id;
117         var $rels;
118         var $parent_id = 0;
119         var $done;
120         
121         function MapNode($page,$reverse=FALSE)
122         {
123                 global $script;
124                 
125                 static $id = 0;
126                 
127                 $this->page = $page;
128                 $this->is_page = is_page($page);
129                 $this->cache = CACHE_DIR.encode($page);
130                 $this->done = !$this->is_page;
131                 $this->link = make_pagelink($page);
132                 $this->id = ++$id;
133
134                 $this->rels = $reverse ? $this->ref() : $this->rel();
135                 $mark = $reverse ? '' : '<sup>+</sup>';
136                 $this->mark = "<a id=\"rel_{$this->id}\" href=\"$script?plugin=map&amp;refer=".rawurlencode($this->page)."\">$mark</a>";
137         }
138         function ref()
139         {
140                 $refs = array();
141                 if (file_exists($this->cache.'.ref'))
142                 {
143                         foreach (file($this->cache.'.ref') as $line)
144                         {
145                                 $ref = explode("\t",$line);
146                                 $refs[] = $ref[0];
147                         }
148                         sort($refs);
149                 }
150                 return $refs;
151         }
152         function rel()
153         {
154                 $rels = array();
155                 if (file_exists($this->cache.'.rel'))
156                 {
157                         $file = file($this->cache.'.rel');
158                         $rels = explode("\t",trim($file[0]));
159                         sort($rels);
160                 }
161                 return $rels;
162         }
163         function chain(&$nodes)
164         {
165                 if ($this->done)
166                 {
167                         return;
168                 }
169                 $this->done = TRUE;
170                 
171                 if ($this->parent_id == 0)
172                 {
173                         $this->parent_id = -1;
174                 }
175                 
176                 foreach ($this->rels as $page)
177                 {
178                         if (!array_key_exists($page,$nodes))
179                         {
180                                 $nodes[$page] = &new MapNode($page);
181                         }
182                         if ($nodes[$page]->parent_id == 0)
183                         {
184                                 $nodes[$page]->parent_id = $this->id;
185                         }
186                 }
187                 foreach ($this->rels as $page)
188                 {
189                         $nodes[$page]->chain($nodes);
190                 }
191         }
192         function toString(&$nodes,$level=1,$parent_id=-1)
193         {
194                 $indent = str_repeat(' ',$level);
195                 
196                 if (!$this->is_page)
197                 {
198                         return $indent."<li>{$this->link}</li>\n";
199                 }
200                 else if ($this->parent_id != $parent_id)
201                 {
202                         return $indent."<li>{$this->link}<a href=\"#rel_{$this->id}\">...</a></li>\n";
203                 }
204                 $retval = $indent."<li>{$this->mark}{$this->link}\n";
205                 if (count($this->rels))
206                 {
207                         $childs = array();
208                         $level += 2;
209                         foreach ($this->rels as $page)
210                         {
211                                 if ($this->parent_id != $nodes[$page]->id)
212                                 {
213                                         $childs[] = $nodes[$page]->toString($nodes,$level,$this->id);
214                                 }
215                         }
216                         if (count($childs))
217                         {
218                                 $retval .= $indent." <ul>\n".join('',$childs).$indent." </ul>\n";
219                         }
220                 }
221                 $retval .= $indent."</li>\n";
222                 
223                 return $retval;
224         }
225 }
226 ?>