]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiPlugin.php
Updated strings to provide localized error messages. Added FIXME note: $op == '|...
[SourceForge/phpwiki.git] / lib / WikiPlugin.php
1 <?php //-*-php-*-
2 rcs_id('$Id: WikiPlugin.php,v 1.8 2002-01-07 04:19:05 carstenklapp 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(sprintf(_("argument '%s' not declared by plugin"),$arg),
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                 // FIXME: doesn't work for multiple args
101                 // e.g. <plugin RecentChanges days||=1 show_all||=0 show_minor||=0>
102                 //      url: RecentChanges?days=1+show_all=1+show_minor=0
103                 assert($op == '||=');
104                 $defaults[$arg] = $val;
105             }
106         }
107         
108         if ($argstr) {
109             trigger_error(sprintf(_("trailing cruft in plugin args: '%s'"),$argstr), E_USER_WARNING);
110         }
111
112         return array($args, $defaults);
113     }
114     
115
116     function getDefaultLinkArguments() {
117         return array('targetpage' => $this->getName(),
118                      'linktext' => $this->getName(),
119                      'description' => $this->getDescription(),
120                      'class' => 'wikiaction');
121     }
122     
123     function makeLink($argstr, $request) {
124         $defaults = $this->getDefaultArguments();
125         $link_defaults = $this->getDefaultLinkArguments();
126         $defaults = array_merge($defaults, $link_defaults);
127
128         $args = $this->getArgs($argstr, $request, $defaults);
129         $plugin = $this->getName();
130         
131         $query_args = array();
132         foreach ($args as $arg => $val) {
133             if (isset($link_defaults[$arg]))
134                 continue;
135             if ($val != $defaults[$arg])
136                 $query_args[$arg] = $val;
137         }
138         
139         $attr = array('href' => WikiURL($args['targetpage'], $query_args),
140                       'class' => $args['class']);
141
142         if ($args['description']) {
143             $attr['title'] = $args['description'];
144             $attr['onmouseover'] = sprintf("window.status='%s';return true;",
145                                            str_replace("'", "\\'", $args['description']));
146             $attr['onmouseout'] = "window.status='';return true;";
147         }
148         return QElement('a', $attr, $args['linktext']);
149     }
150
151     function getDefaultFormArguments() {
152         return array('targetpage' => $this->getName(),
153                      'buttontext' => $this->getName(),
154                      'class' => 'wikiaction',
155                      'method' => 'get',
156                      'textinput' => 's',
157                      'description' => false,
158                      'formsize' => 30);
159     }
160
161     function makeForm($argstr, $request) {
162         $form_defaults = $this->getDefaultFormArguments();
163         $defaults = array_merge($this->getDefaultArguments(),
164                                 $form_defaults);
165
166         $args = $this->getArgs($argstr, $request, $defaults);
167         $plugin = $this->getName();
168         $textinput = $args['textinput'];
169         assert(!empty($textinput) && isset($args['textinput']));
170
171         $formattr = array('action' => WikiURL($args['targetpage']),
172                           'method' => $args['method'],
173                           'class' => $args['class']);
174         $contents = '';
175         foreach ($args as $arg => $val) {
176             if (isset($form_defaults[$arg]))
177                 continue;
178             if ($arg != $textinput && $val == $defaults[$arg])
179                 continue;
180             
181             $attr = array('name' => $arg, 'value' => $val);
182             
183             if ($arg == $textinput) {
184                 //if ($inputs[$arg] == 'file')
185                 //    $attr['type'] = 'file';
186                 //else
187                 $attr['type'] = 'text';
188                 $attr['size'] = $args['formsize'];
189                 if ($args['description']) {
190                     $attr['title'] = $args['description'];
191                     $attr['onmouseover'] = sprintf("window.status='%s';return true;",
192                                                    str_replace("'", "\\'", $args['description']));
193                     $attr['onmouseout'] = "window.status='';return true;";
194                 }
195             }
196             else {
197                 $attr['type'] = 'hidden';
198             }
199             
200             $contents .= Element('input', $attr);
201
202             // FIXME: hackage
203             if ($attr['type'] == 'file') {
204                 $formattr['enctype'] = 'multipart/form-data';
205                 $formattr['method'] = 'post';
206                 $contents .= Element('input',
207                                      array('name' => 'MAX_FILE_SIZE',
208                                            'value' => MAX_UPLOAD_SIZE,
209                                            'type' => 'hidden'));
210             }
211         }
212
213         if (!empty($args['buttontext'])) {
214             $contents .= Element('input',
215                                  array('type' => 'submit',
216                                        'class' => 'button',
217                                        'value' => $args['buttontext']));
218         }
219
220         //FIXME: can we do without this table?
221         return Element('form', $formattr,
222                        Element('table',
223                                Element('tr',
224                                        Element('td', $contents))));
225     }
226 }
227
228 class WikiPluginLoader {
229     var $_errors;
230     
231     function expandPI($pi, $dbi, $request) {
232         if (!preg_match('/^\s*<\?(plugin(?:-form|-link)?)\s+(\w+)\s*(.*?)\s*\?>\s*$/s', $pi, $m))
233             return $this->_error(sprintf(_("Bad %s"),'PI'));
234
235         list(, $pi_name, $plugin_name, $plugin_args) = $m;
236         $plugin = $this->getPlugin($plugin_name);
237         if (!is_object($plugin)) {
238             return QElement($pi_name == 'plugin-link' ? 'span' : 'p',
239                             array('class' => 'plugin-error'),
240                             $this->getErrorDetail());
241         }
242         switch ($pi_name) {
243         case 'plugin':
244             return $plugin->run($dbi, $plugin_args, $request);
245         case 'plugin-link':
246             return $plugin->makeLink($plugin_args, $request);
247         case 'plugin-form':
248             return $plugin->makeForm($plugin_args, $request);
249         }
250     }
251     
252     function getPlugin($plugin_name) {
253
254         // Note that there seems to be no way to trap parse errors
255         // from this include.  (At least not via set_error_handler().)
256         $plugin_source = "lib/plugin/$plugin_name.php";
257         
258         if (!include_once("lib/plugin/$plugin_name.php")) {
259             if (!empty($GLOBALS['php_errormsg']))
260                 return $this->_error($GLOBALS['php_errormsg']);
261             // If the plugin source has already been included, the include_once()
262             // will fail, so we don't want to crap out just yet.
263             $include_failed = true;
264         } else {
265             // this avoids: lib/WikiPlugin.php:265: Notice[8]: Undefined variable: include_failed
266             $include_failed = false;
267         }
268         
269         $plugin_class = "WikiPlugin_$plugin_name";
270         if (!class_exists($plugin_class)) {
271             if ($include_failed)
272                 return $this->_error(sprintf(_("Include of '%s' failed"),$plugin_source));
273             return $this->_error(sprintf(_("%s: no such class"),$plugin_class));
274         }
275         
276     
277         $plugin = new $plugin_class;
278         if (!is_subclass_of($plugin, "WikiPlugin"))
279             return $this->_error(sprintf(_("%s: not a subclass of WikiPlugin"),$plugin_class));
280
281         return $plugin;
282     }
283
284     function getErrorDetail() {
285         return htmlspecialchars($this->_errors);
286     }
287     
288     function _error($message) {
289         $this->_errors = $message;
290         return false;
291     }
292
293         
294 };
295
296 // (c-file-style: "gnu")
297 // Local Variables:
298 // mode: php
299 // tab-width: 8
300 // c-basic-offset: 4
301 // c-hanging-comment-ender-p: nil
302 // indent-tabs-mode: nil
303 // End:   
304 ?>