]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiPlugin.php
Jeff's hacks II.
[SourceForge/phpwiki.git] / lib / WikiPlugin.php
1 <?php //-*-php-*-
2 rcs_id('$Id: WikiPlugin.php,v 1.1 2001-09-18 19:16:23 dairiki Exp $');
3
4 class WikiPlugin
5 {
6     function getDefaultArguments() {
7         return array();
8     }
9
10
11     // FIXME: args?
12     function run ($argstr, $request) {
13         trigger_error("WikiPlugin::run: pure virtual function",
14                       E_USER_ERROR);
15     }
16
17     function getName() {
18         return $this->name;
19     }
20
21     
22     function getArgs($argstr, $request, $defaults = false) {
23         if ($defaults === false)
24             $defaults = $this->getDefaultArguments();
25
26         list ($argstr_args, $argstr_defaults) = $this->parseArgStr($argstr);
27
28         foreach ($defaults as $arg => $default_val) {
29             if (isset($argstr_args[$arg]))
30                 $args[$arg] = $argstr_args[$arg];
31             elseif ( ($argval = $request->getArg($arg)) )
32                 $args[$arg] = $argval;
33             elseif (isset($argstr_defaults[$arg]))
34                 $args[$arg] = (string) $argstr_defaults[$arg];
35             else
36                 $args[$arg] = $default_val;
37
38             $args[$arg] = $this->expandArg($args[$arg], $request);
39             
40             unset($argstr_args[$arg]);
41             unset($argstr_defaults[$arg]);
42         }
43
44         foreach (array_merge($argstr_args, $argstr_defaults) as $arg => $val) {
45             trigger_error("$arg: argument not declared by plugin",
46                           E_USER_NOTICE);
47         }
48         
49         return $args;
50     }
51
52     function expandArg($argval, $request) {
53         return preg_replace('/\[(\w[\w\d]*)\]/e', '$request->getArg("$1")', $argval);
54     }
55     
56         
57     function parseArgStr($argstr) {
58         $arg_p = '\w+';
59         $op_p = '(?:\|\|)?=';
60         $word_p = '\S+';
61         $qq_p = '"[^"]*"';
62         $q_p = "'[^']*'";
63         $opt_ws = '\s*';
64         $argspec_p = "($arg_p) $opt_ws ($op_p) $opt_ws ($qq_p|$q_p|$word_p)";
65
66         $args = array();
67         $defaults = array();
68         
69         while (preg_match("/^$opt_ws $argspec_p $opt_ws/x", $argstr, $m)) {
70             @ list(,$arg,$op,$val) = $m;
71             $argstr = substr($argstr, strlen($m[0]));
72
73             // Remove quotes from string values.
74             if ($val && ($val[0] == '"' || $val[0] == "'"))
75                 $val = substr($val, 1, strlen($val) - 2);
76
77             if ($op == '=') {
78                 $args[$arg] = $val;
79             }
80             else {
81                 assert($op == '||=');
82                 $defaults[$arg] = $val;
83             }
84         }
85         
86         if ($argstr) {
87             trigger_error("trailing cruft in plugin args: '$argstr'", E_USER_WARNING);
88         }
89
90         return array($args, $defaults);
91     }
92     
93
94     function getDefaultLinkArguments() {
95         return array('targetpage' => $this->getName(),
96                      'linktext' => $this->getName(),
97                      'description' => false,
98                      'class' => 'wikiaction');
99     }
100     
101     function makeLink($argstr, $request) {
102         $defaults = $this->getDefaultArguments();
103         $link_defaults = $this->getDefaultLinkArguments();
104         $defaults = array_merge($defaults, $link_defaults);
105         
106         $args = $this->getArgs($argstr, $request, $defaults);
107         $plugin = $this->getName();
108         
109         $query_args = array();
110         foreach ($args as $arg => $val) {
111             if (isset($link_defaults[$arg]))
112                 continue;
113             if ($val != $defaults[$arg])
114                 $query_args[$arg] = $val;
115         }
116         
117         $attr = array('href' => WikiURL($args['targetpage'], $query_args),
118                       'class' => $args['class']);
119
120         if ($args['description']) {
121             $attr['title'] = $args['description'];
122             $attr['onmouseover'] = sprintf("window.status='%s';return true;",
123                                            str_replace("'", "\\'", $args['description']));
124             $attr['onmouseout'] = "window.status='';return true;";
125         }
126         return QElement('a', $attr, $args['linktext']);
127     }
128
129     function getDefaultFormArguments() {
130         return array('targetpage' => $this->getName(),
131                      'buttontext' => $this->getName(),
132                      'class' => 'wikiaction',
133                      'method' => 'get',
134                      'textinput' => 's',
135                      'description' => false,
136                      'formsize' => 30);
137     }
138
139     function makeForm($argstr, $request) {
140         $form_defaults = $this->getDefaultFormArguments();
141         $defaults = array_merge($this->getDefaultArguments(),
142                                 $form_defaults);
143
144         $args = $this->getArgs($argstr, $request, $defaults);
145         $plugin = $this->getName();
146         $textinput = $args['textinput'];
147         assert(!empty($textinput) && isset($args['textinput']));
148
149         $formattr = array('action' => WikiURL($args['targetpage']),
150                           'method' => $args['method'],
151                           'class' => $args['class']);
152         $contents = '';
153         foreach ($args as $arg => $val) {
154             if (isset($form_defaults[$arg]))
155                 continue;
156             if ($arg != $textinput && $val == $defaults[$arg])
157                 continue;
158             
159             $attr = array('name' => $arg, 'value' => $val);
160             
161             if ($arg == $textinput) {
162                 //if ($inputs[$arg] == 'file')
163                 //    $attr['type'] = 'file';
164                 //else
165                 $attr['type'] = 'text';
166                 $attr['size'] = $args['formsize'];
167                 if ($args['description']) {
168                     $attr['title'] = $args['description'];
169                     $attr['onmouseover'] = sprintf("window.status='%s';return true;",
170                                                    str_replace("'", "\\'", $args['description']));
171                     $attr['onmouseout'] = "window.status='';return true;";
172                 }
173             }
174             else {
175                 $attr['type'] = 'hidden';
176             }
177             
178             $contents .= Element('input', $attr);
179
180             // FIXME: hackage
181             if ($attr['type'] == 'file') {
182                 $formattr['enctype'] = 'multipart/form-data';
183                 $formattr['method'] = 'post';
184                 $contents .= Element('input',
185                                      array('name' => 'MAX_FILE_SIZE',
186                                            'value' => MAX_UPLOAD_SIZE,
187                                            'type' => 'hidden'));
188             }
189         }
190
191         if (!empty($args['buttontext'])) {
192             $contents .= Element('input',
193                                  array('type' => 'submit',
194                                        'class' => 'button',
195                                        'value' => $args['buttontext']));
196         }
197
198         //FIXME: can we do without this table?
199         return Element('form', $formattr,
200                        Element('table',
201                                Element('tr',
202                                        Element('td', $contents))));
203     }
204 }
205
206 class WikiPluginLoader {
207     var $_errors;
208     
209     function expandPI($pi, $dbi, $request) {
210         if (!preg_match('/^\s*<\?(plugin(?:-form|-link)?)\s+(\w+)\s*(.*?)\s*\?>\s*$/s', $pi, $m))
211             return $this->_error("Bad PI");
212
213         list(, $pi_name, $plugin_name, $plugin_args) = $m;
214         $plugin = $this->getPlugin($plugin_name);
215         if (!is_object($plugin)) {
216             return QElement($pi_name == 'plugin-link' ? 'span' : 'p',
217                             array('class' => 'plugin-error'),
218                             $this->getErrorDetail());
219         }
220         switch ($pi_name) {
221         case 'plugin':
222             return $plugin->run($dbi, $plugin_args, $request);
223         case 'plugin-link':
224             return $plugin->makeLink($plugin_args, $request);
225         case 'plugin-form':
226             return $plugin->makeForm($plugin_args, $request);
227         }
228     }
229     
230     function getPlugin($plugin_name) {
231
232         // Note that there seems to be no way to trap parse errors
233         // from this include.  (At least not via set_error_handler().)
234         $plugin_source = "lib/plugin/$plugin_name.php";
235         
236         if (!include_once("lib/plugin/$plugin_name.php")) {
237             if (!empty($GLOBALS['php_errormsg']))
238                 return $this->_error($GLOBALS['php_errormsg']);
239             // If the plugin source has already been included, the include_once()
240             // will fail, so we don't want to crap out just yet.
241             $include_failed = true;
242         }
243         
244         $plugin_class = "WikiPlugin_$plugin_name";
245         if (!class_exists($plugin_class)) {
246             if ($include_failed)
247                 return $this->_error("Include of '$plugin_source' failed");
248             return $this->_error("$plugin_class: no such class");
249         }
250         
251     
252         $plugin = new $plugin_class;
253         if (!is_subclass_of($plugin, "WikiPlugin"))
254             return $this->_error("$plugin_class: not a subclass of WikiPlugin");
255
256         return $plugin;
257     }
258
259     function getErrorDetail() {
260         return htmlspecialchars($this->_errors);
261     }
262     
263     function _error($message) {
264         $this->_errors = $message;
265         return false;
266     }
267
268         
269 };
270
271 // (c-file-style: "gnu")
272 // Local Variables:
273 // mode: php
274 // tab-width: 8
275 // c-basic-offset: 4
276 // c-hanging-comment-ender-p: nil
277 // indent-tabs-mode: nil
278 // End:   
279 ?>