OSDN Git Service

Import current code.
[osdn-codes/wiki-parser.git] / sfjp / wiki / processor / base.php
1 <?php
2 namespace sfjp\Wiki\Processor;
3 use sfjp\Wiki\Exception;
4 abstract class Base {
5         private $context;
6         public $is_vary;
7         public $text;
8         public $formatted_text;
9         public $preproc;
10         public $postproc;
11         public $formatter;
12         public $args = array();
13
14         protected static $reserved = array('__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor');
15
16         protected static $context_key_rename_rules = array(
17                 'plugin_include_path' => 'extension.additional_include_path',
18                 'plugin.order' => 'extension.acl_order',
19                 'plugin.allow' => 'extension.allow',
20                 'plugin.deny' => 'extension.deny',
21                 'supress_plugin_error' => 'extension.hide_error',
22         );
23
24         function __construct($args = null) {
25                 $default_ctx = array("wiki_baseurl"  => ".",
26                                      "site_root_url" => (empty($_SERVER['HTTPS']) ? 'http' : 'https') . "://" . (empty($_SERVER['HTTP_HOST']) ? 'localhost.localdomain' : $_SERVER['HTTP_HOST']),
27                                      "svn_base_url"  => "http://svn.sourceforge.jp/view",
28                                      "cvs_base_url"  => "http://cvs.sourceforge.jp/view",
29                                      "sfjp.group_name"    => null,
30                                      "sfjp.group_id"      => null,
31                                      "extension.additional_include_path" => null,
32                                      "extension.acl_order" => "deny,allow",
33                                      "extension.allow"  => array(),
34                                      "extension.deny"   => array(),
35                                      "extension.hide_error" => false,
36                                      "self_url"      => array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : '',
37                                      "cache_manager" => null,
38                                      "cache_depends" => array(),
39                                      "whole_page_cachable" => true,
40                                      "head_excess"   => 0,
41                                      "gen_head_id"   => true,
42                                      "internal_url_regex" => null,
43                                      "nofollow_on_external_links" => true,
44                                      );
45                 $this->context = $default_ctx;
46                 $this->clearPreProc();
47                 $this->clearPostProc();
48         }
49
50         function __destruct() {
51                 unset($this->formatter);
52         }
53
54         public function setArgs($args) {
55                 if (!is_array($args))
56                         $args = array($args);
57                 $this->args = $args;
58         }
59
60         public function getArgs($pos = null) {
61                 if (is_null($pos))
62                         return $this->args;
63                 return $this->args[$pos];
64         }
65
66         public function getContext($key = null) {
67                 if (isset($key)) {
68                         $key = static::renameContextKey($key);
69                         return array_key_exists($key, $this->context) ? $this->context[$key] : null;
70                 } else {
71                         return $this->context;
72                 }
73         }
74
75         static public function renameContextKey($key) {
76                 if (!array_key_exists($key, static::$context_key_rename_rules))
77                         return $key;
78                 return static::$context_key_rename_rules[$key];
79         }
80
81
82         public function hasContext($key) {
83                 return array_key_exists(static::renameContextKey($key), $this->context);
84         }
85
86         public function setContext($c) {
87                 foreach ($c as $key => $val) {
88                         $key = static::renameContextKey($key);
89                         $this->context[$key] = $val;
90                 }
91                 $this->context = array_merge($this->context, $c);
92         }
93
94         public function removeContext($key) {
95                 unset($this->context[static::renameContextKey($key)]);
96         }
97   
98         public function clearContext() {
99                 $this->context = array();
100         }
101
102         public function incrementCounter($name) {
103                 $c = &$this->getCounter($name);
104                 return ++$c;
105         }
106
107         public function &getCounter($name) {
108                 $c = &$this->context["counters"];
109                 if (!isset($c[$name])) {
110                         $c[$name] = 0;
111                 }
112                 return $c[$name];
113         }
114
115         public function setCounter($name, $val) {
116                 $c = &$this->context["counters"];
117                 $c[$name] = $val;
118         }
119
120         public function clearCounter($name = null) {
121                 if (isset($name)) {
122                         $this->setCounter($name, 0);
123                 } else {
124                         $this->setContext(array("counters" => array()));
125                 }
126         }
127
128         public function &getCacheDepends() {
129                 return $this->context["cache_depends"];
130         }
131
132         public function addCacheDepends($deps) {
133                 if (empty($deps)) return;
134                 if (!is_array($deps)) $deps = array($deps);
135                 $c = &$this->context["cache_depends"];
136                 foreach ($deps as $dep) {
137                         $c []= $dep;
138                 }
139         }
140
141         public function clearCacheDepends() {
142                 $this->context["cache_depends"] = array();
143         }
144
145         public function reset() {
146                 $this->is_vary = false;
147                 $this->text = "";
148                 $this->formatted_text = "";
149                 $this->clearCounter();
150                 $this->clearPreProc();
151                 $this->clearPostProc();
152                 $this->clearCacheDepends();
153                 if ($this->getFormatter())
154                         $this->getFormatter()->reset();
155         }
156
157         public function isVary() {
158                 return $this->is_vary;
159         }
160
161         public function setText($text) {
162                 $old = $this->text;
163                 $this->text = $text;
164                 return $old;
165         }
166
167         public function getText() {
168                 return $this->text;
169         }
170
171         public function getFormattedText() {
172                 $ret = '';
173                 foreach ($this->preproc as $p) {
174                         $ret .= $p->process();
175                 }
176                 $ret .= $this->formatted_text;
177                 foreach ($this->postproc as $p) {
178                         $ret .= $p->process();
179                 }
180                 return $ret;
181         }
182
183         public function get_plugin_instance($class_name) {
184                 $check_name = str_replace('\\', '/', $class_name);
185                 $name = basename($check_name);
186
187                 if (!$this->check_plugin_allowed($check_name))
188                         throw new Exception\Plugin_Error("Load Denied: $name");
189                 if (!preg_match('/^[A-Za-z0-9._-]+$/', $name))
190                         throw new Exception\Plugin_error("Wrong Plugin Name: $name");
191
192                 if (in_array(strtolower($name), self::$reserved)) {
193                         $class_name = substr($class_name, 0, strlen($class_name) - strlen($name)) . "_{$name}";
194                 }
195
196                 try {
197                         $orig_include_path = null;
198                         if ($this->getContext('extension.additional_include_path')) {
199                                 $orig_include_path = ini_get('include_path');
200                                 ini_set('include_path', $this->getContext('extension.additional_include_path').":$orig_include_path");
201                         }
202                         $class = new \ReflectionClass("\\sfjp\\Wiki\\{$class_name}");
203                         if ($orig_include_path)
204                                 ini_set('include_path', $orig_include_path);
205                         $instance = $class->newInstance($this);
206                         if (!is_callable(array($instance, "process")))
207                                 throw new \ReflectionException();
208                 } catch (\ReflectionException $e) {
209                         ini_set('include_path', $orig_include_path);
210                         error_log("Plugin '$name' load failed.");
211                         throw new Exception\Plugin_Error("Not Found: {$name}");
212                 }
213                 return $instance;
214         }
215
216
217
218         protected function check_plugin_allowed($name) {
219                 $order = $this->getContext("plugin.order");
220                 $allow = $this->getContext("plugin.allow");
221                 $deny  = $this->getContext("plugin.deny");
222                 $ret   = false;
223                 if (!$order) $order = "deny,allow";
224                 $order = strtolower($order);
225                 if (!is_array($allow)) $allow = array($allow);
226                 if (!is_array($deny)) $deny = array($deny);
227                 $deny  = array_map('strtolower', $deny);
228                 $allow = array_map('strtolower', $allow);
229                 $name  = strtolower($name);
230
231                 if ($order === "deny,allow") {
232                         $ret = true;
233                         if (in_array('all', $deny))  $ret = false;
234                         if (in_array($name, $deny))  $ret = false;
235                         if (in_array('all', $allow)) return true;
236                         if (in_array($name, $allow)) return true;
237                 } else { # "allow,deny"
238                                 $ret = false;
239                         if (in_array('all', $allow)) $ret = true;
240                         if (in_array($name, $allow)) $ret = true;
241                         if (in_array('all', $deny))  return false;
242                         if (in_array($name, $deny))  return false;
243                 }
244                 return $ret;
245         }
246
247         public function addPreProc($obj) {
248                 $this->preproc[] = $obj;
249         }
250
251         public function clearPreProc() {
252                 $this->preproc = array();
253         }
254
255         public function addPostProc($obj) {
256                 $this->postproc[] = $obj;
257         }
258
259         public function clearPostProc() {
260                 $this->postproc = array();
261         }
262
263         public function getFormatter() {
264                 return $this->formatter;
265         }
266
267         public function setFormatter($f) {
268                 $this->formatter = $f;
269                 if (!$this->formatter->getProcessor())
270                         $this->formatter->setProcessor($this);
271         }
272
273         public function __($text, $args=array()) {
274                 if (!$this->hasContext('i18n')) {
275                         return $text;
276                 } else {
277                         return $this->getContext('i18n')->__($text, $args);
278                 }
279         }
280 }