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