OSDN Git Service

BugTrack/2247 External link cushion page - external_link (PHP4.x)
[pukiwiki/pukiwiki.git] / lib / config.php
1 <?php
2 // PukiWiki - Yet another WikiWikiWeb clone.
3 // config.php
4 // Copyright 2003-2016 PukiWiki Development Team
5 // License: GPL v2 or (at your option) any later version
6 //
7 // Parse a PukiWiki page as a configuration page
8
9 /*
10  * $obj = new Config('plugin/plugin_name/')
11  * $obj->read();
12  * $array = & $obj->get($title);
13  * $array[] = array(4, 5, 6);           // Add - directly
14  * $obj->add($title, array(4, 5, 6));   // Add - method of Config object
15  * $array = array(1=>array(1, 2, 3));           // Replace - directly
16  * $obj->put($title, array(1=>array(1, 2, 3));  // Replace - method of Config object
17  * $obj->put_values($title, NULL);      // Delete
18  * $obj->write();
19  */
20
21 // Fixed prefix of configuration-page's name
22 define('PKWK_CONFIG_PREFIX', ':config/');
23
24 // Configuration-page manager
25 class Config
26 {
27         var $name, $page; // Page name
28         var $objs = array();
29
30         function Config($name)
31         {
32                 $this->__construct($name);
33         }
34         function __construct($name)
35         {
36                 $this->name = $name;
37                 $this->page = PKWK_CONFIG_PREFIX . $name;
38         }
39
40         // Load the configuration-page
41         function read()
42         {
43                 if (! is_page($this->page)) return FALSE;
44
45                 $this->objs = array();
46                 $obj        = new ConfigTable('');
47                 $matches = array();
48
49                 foreach (get_source($this->page) as $line) {
50                         if ($line == '') continue;
51
52                         $head  = $line{0};      // The first letter
53                         $level = strspn($line, $head);
54
55                         if ($level > 3) {
56                                 $obj->add_line($line);
57
58                         } else if ($head == '*') {
59                                 // Cut fixed-heading anchors
60                                 $line = preg_replace('/^(\*{1,3}.*)\[#[A-Za-z][\w-]+\](.*)$/', '$1$2', $line);
61
62                                 if ($level == 1) {
63                                         $this->objs[$obj->title] = $obj;
64                                         $obj = new ConfigTable($line);
65                                 } else {
66                                         if (! is_a($obj, 'ConfigTable_Direct'))
67                                                 $obj = new ConfigTable_Direct('', $obj);
68                                         $obj->set_key($line);
69                                 }
70                                 
71                         } else if ($head == '-' && $level > 1) {
72                                 if (! is_a($obj, 'ConfigTable_Direct'))
73                                         $obj = new ConfigTable_Direct('', $obj);
74                                 $obj->add_value($line);
75
76                         } else if ($head == '|' && preg_match('/^\|(.+)\|\s*$/', $line, $matches)) {
77                                 // Table row
78                                 if (! is_a($obj, 'ConfigTable_Sequential'))
79                                         $obj = new ConfigTable_Sequential('', $obj);
80                                 // Trim() each table cell
81                                 $obj->add_value(array_map('trim', explode('|', $matches[1])));
82                         } else {
83                                 $obj->add_line($line);
84                         }
85                 }
86                 $this->objs[$obj->title] = $obj;
87
88                 return TRUE;
89         }
90
91         // Get an array
92         function & get($title)
93         {
94                 $obj = & $this->get_object($title);
95                 return $obj->values;
96         }
97
98         // Set an array (Override)
99         function put($title, $values)
100         {
101                 $obj         = & $this->get_object($title);
102                 $obj->values = $values;
103         }
104
105         // Add a line
106         function add($title, $value)
107         {
108                 $obj = & $this->get_object($title);
109                 $obj->values[] = $value;
110         }
111
112         // Get an object (or create it)
113         function & get_object($title)
114         {
115                 if (! isset($this->objs[$title]))
116                         $this->objs[$title] = new ConfigTable('*' . trim($title) . "\n");
117                 return $this->objs[$title];
118         }
119
120         function write()
121         {
122                 page_write($this->page, $this->toString());
123         }
124
125         function toString()
126         {
127                 $retval = '';
128                 foreach ($this->objs as $title=>$obj)
129                         $retval .= $obj->toString();
130                 return $retval;
131         }
132 }
133
134 // Class holds array values
135 class ConfigTable
136 {
137         var $title  = '';       // Table title
138         var $before = array();  // Page contents (except table ones)
139         var $after  = array();  // Page contents (except table ones)
140         var $values = array();  // Table contents
141
142         function ConfigTable($title, $obj = NULL)
143         {
144                 $this->__construct($title, $obj);
145         }
146         function __construct($title, $obj = NULL)
147         {
148                 if ($obj !== NULL) {
149                         $this->title  = $obj->title;
150                         $this->before = array_merge($obj->before, $obj->after);
151                 } else {
152                         $this->title  = trim(substr($title, strspn($title, '*')));
153                         $this->before[] = $title;
154                 }
155         }
156
157         // Addi an  explanation
158         function add_line($line)
159         {
160                 $this->after[] = $line;
161         }
162
163         function toString()
164         {
165                 return join('', $this->before) . join('', $this->after);
166         }
167 }
168
169 class ConfigTable_Sequential extends ConfigTable
170 {
171         // Add a line
172         function add_value($value)
173         {
174                 $this->values[] = (count($value) == 1) ? $value[0] : $value;
175         }
176
177         function toString()
178         {
179                 $retval = join('', $this->before);
180                 if (is_array($this->values)) {
181                         foreach ($this->values as $value) {
182                                 $value   = is_array($value) ? join('|', $value) : $value;
183                                 $retval .= '|' . $value . '|' . "\n";
184                         }
185                 }
186                 $retval .= join('', $this->after);
187                 return $retval;
188         }
189 }
190
191 class ConfigTable_Direct extends ConfigTable
192 {
193         var $_keys = array();   // Used at initialization phase
194
195         function set_key($line)
196         {
197                 $level = strspn($line, '*');
198                 $this->_keys[$level] = trim(substr($line, $level));
199         }
200
201         // Add a line
202         function add_value($line)
203         {
204                 $level = strspn($line, '-');
205                 $arr   = & $this->values;
206                 for ($n = 2; $n <= $level; $n++)
207                         $arr = & $arr[$this->_keys[$n]];
208                 $arr[] = trim(substr($line, $level));
209         }
210
211         function toString($values = NULL, $level = 2)
212         {
213                 $retval = '';
214                 $root   = ($values === NULL);
215                 if ($root) {
216                         $retval = join('', $this->before);
217                         $values = & $this->values;
218                 }
219                 foreach ($values as $key=>$value) {
220                         if (is_array($value)) {
221                                 $retval .= str_repeat('*', $level) . $key . "\n";
222                                 $retval .= $this->toString($value, $level + 1);
223                         } else {
224                                 $retval .= str_repeat('-', $level - 1) . $value . "\n";
225                         }
226                 }
227                 if ($root) $retval .= join('', $this->after);
228
229                 return $retval;
230         }
231 }