|
1 <?php |
|
2 |
|
3 // ====================================================================================== |
|
4 // This library is free software; you can redistribute it and/or |
|
5 // modify it under the terms of the GNU Lesser General Public |
|
6 // License as published by the Free Software Foundation; either |
|
7 // version 2.1 of the License, or (at your option) any later version. |
|
8 // |
|
9 // This library is distributed in the hope that it will be useful, |
|
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 // Lesser General Public License for more details. |
|
13 // ====================================================================================== |
|
14 // @author John Godley (http://urbangiraffe.com) |
|
15 // @version 0.1.25 |
|
16 // @copyright Copyright © 2007 John Godley, All Rights Reserved |
|
17 // ====================================================================================== |
|
18 // 0.1.6 - Corrected WP locale functions |
|
19 // 0.1.7 - Add phpdoc comments |
|
20 // 0.1.8 - Support for Admin SSL |
|
21 // 0.1.9 - URL encoding, defer localization until init |
|
22 // 0.1.10 - Better URL encoding |
|
23 // 0.1.11 - Make work in WP 2.0, fix HTTPS issue on IIS |
|
24 // 0.1.12 - Activation/deactivation actions that take into account the directory |
|
25 // 0.1.13 - Add realpath function |
|
26 // 0.1.14 - Add select/checked functions, fix locale loader |
|
27 // 0.1.15 - Remove dependency on prototype |
|
28 // 0.1.16 - Add support for homedir in realpath |
|
29 // 0.1.17 - Added widget class |
|
30 // 0.1.18 - Expand checked function |
|
31 // 0.1.19 - Make url() cope with sites with no trailing slash |
|
32 // 0.1.20 - Change init function to prevent overloading |
|
33 // 0.1.21 - Make widget work for WP 2.1 |
|
34 // 0.1.22 - Make select work with option groups, RSS compatability fix |
|
35 // 0.1.23 - Make widget count work better, fix widgets in K2 |
|
36 // 0.1.24 - Make realpath better |
|
37 // 0.1.25 - Add description to widget class |
|
38 // ====================================================================================== |
|
39 |
|
40 |
|
41 /** |
|
42 * Wraps up several useful functions for WordPress plugins and provides a method to separate |
|
43 * display HTML from PHP code. |
|
44 * |
|
45 * <h4>Display Rendering</h4> |
|
46 * The class uses a similar technique to Ruby On Rails views, whereby the display HTML is kept |
|
47 * in a separate directory and file from the main code. A display is 'rendered' (sent to the browser) |
|
48 * or 'captured' (returned to the calling function). |
|
49 * |
|
50 * Template files are separated into two areas: admin and user. Admin templates are only for display in |
|
51 * the WordPress admin interface, while user templates are typically for display on the site (although neither |
|
52 * of these are enforced). All templates are PHP code, but are referred to without .php extension. |
|
53 * |
|
54 * The reason for this separation is that one golden rule of plugin creation is that someone will always want to change |
|
55 * the formatting and style of your output. Rather than forcing them to modify the plugin (bad), or modify files within |
|
56 * the plugin (equally bad), the class allows user templates to be overridden with files contained within the theme. |
|
57 * |
|
58 * An additional benefit is that it leads to code re-use, especially with regards to Ajax (i.e. your display code can be called from |
|
59 * many locations) |
|
60 * |
|
61 * Template files are located within the 'view' subdirectory of the plugins base (specified when registering the plugin): |
|
62 * |
|
63 * <pre>myplugin/view/admin |
|
64 * myplugin/view/myplugin</pre> |
|
65 * |
|
66 * Admin templates are contained within 'admin', and user templates are contained within a directory of the same name as the plugin. |
|
67 * |
|
68 * User files can be overridden within the theme by creating a similar directory structure: |
|
69 * |
|
70 * <pre>/themes/mytheme/view/myplugin</pre> |
|
71 * |
|
72 * The class will first look in the theme and then defaults to the plugin. A plugin should always provide default templates. |
|
73 * |
|
74 * <h4>Display Parameters</h4> |
|
75 * Also similar to Ruby On Rails, when you display a template you must supply the parameters that the template has access to. This tries |
|
76 * to ensure a very clean separation between code and display. Parameters are supplied as an associative array mapping variable name to variable value. |
|
77 * |
|
78 * For example, |
|
79 * |
|
80 * array ('message' => 'Your data was processed', 'items' => 103); |
|
81 * |
|
82 * <h4>How it works in practice</h4> |
|
83 * You create a template file to display how many items have been processed. You store this in 'view/admin/processed.php': |
|
84 * |
|
85 * <pre><p>You processed <?php echo $items ?> items</p></pre> |
|
86 * |
|
87 * When you want to display this in your plugin you use: |
|
88 * |
|
89 * <pre> $this->render_admin ('processed', array ('items' => 100)); |
|
90 * |
|
91 * @package WordPress base library |
|
92 * @author John Godley |
|
93 * @copyright Copyright (C) John Godley |
|
94 **/ |
|
95 |
|
96 class AJAX_Calendar_Plugin |
|
97 { |
|
98 /** |
|
99 * Plugin name |
|
100 * @var string |
|
101 **/ |
|
102 var $plugin_name; |
|
103 |
|
104 /** |
|
105 * Plugin 'view' directory |
|
106 * @var string Directory |
|
107 **/ |
|
108 var $plugin_base; |
|
109 |
|
110 |
|
111 /** |
|
112 * Register your plugin with a name and base directory. This <strong>must</strong> be called once. |
|
113 * |
|
114 * @param string $name Name of your plugin. Is used to determine the plugin locale domain |
|
115 * @param string $base Directory containing the plugin's 'view' files. |
|
116 * @return void |
|
117 **/ |
|
118 |
|
119 function register_plugin ($name, $base) |
|
120 { |
|
121 $this->plugin_base = rtrim (dirname ($base), '/'); |
|
122 $this->plugin_name = $name; |
|
123 |
|
124 $this->add_action ('init', 'load_locale'); |
|
125 } |
|
126 |
|
127 function load_locale () |
|
128 { |
|
129 // Here we manually fudge the plugin locale as WP doesnt allow many options |
|
130 $locale = get_locale (); |
|
131 if ( empty($locale) ) |
|
132 $locale = 'en_US'; |
|
133 |
|
134 $mofile = dirname (__FILE__)."/locale/$locale.mo"; |
|
135 load_textdomain ($this->plugin_name, $mofile); |
|
136 } |
|
137 |
|
138 |
|
139 /** |
|
140 * Register a WordPress action and map it back to the calling object |
|
141 * |
|
142 * @param string $action Name of the action |
|
143 * @param string $function Function name (optional) |
|
144 * @param int $priority WordPress priority (optional) |
|
145 * @param int $accepted_args Number of arguments the function accepts (optional) |
|
146 * @return void |
|
147 **/ |
|
148 |
|
149 function add_action ($action, $function = '', $priority = 10, $accepted_args = 1) |
|
150 { |
|
151 add_action ($action, array (&$this, $function == '' ? $action : $function), $priority, $accepted_args); |
|
152 } |
|
153 |
|
154 |
|
155 /** |
|
156 * Register a WordPress filter and map it back to the calling object |
|
157 * |
|
158 * @param string $action Name of the action |
|
159 * @param string $function Function name (optional) |
|
160 * @param int $priority WordPress priority (optional) |
|
161 * @param int $accepted_args Number of arguments the function accepts (optional) |
|
162 * @return void |
|
163 **/ |
|
164 |
|
165 function add_filter ($filter, $function = '', $priority = 10, $accepted_args = 1) |
|
166 { |
|
167 add_filter ($filter, array (&$this, $function == '' ? $filter : $function), $priority, $accepted_args); |
|
168 } |
|
169 |
|
170 |
|
171 /** |
|
172 * Special activation function that takes into account the plugin directory |
|
173 * |
|
174 * @param string $pluginfile The plugin file location (i.e. __FILE__) |
|
175 * @param string $function Optional function name, or default to 'activate' |
|
176 * @return void |
|
177 **/ |
|
178 |
|
179 function register_activation ($pluginfile, $function = '') |
|
180 { |
|
181 add_action ('activate_'.basename (dirname ($pluginfile)).'/'.basename ($pluginfile), array (&$this, $function == '' ? 'activate' : $function)); |
|
182 } |
|
183 |
|
184 |
|
185 /** |
|
186 * Special deactivation function that takes into account the plugin directory |
|
187 * |
|
188 * @param string $pluginfile The plugin file location (i.e. __FILE__) |
|
189 * @param string $function Optional function name, or default to 'deactivate' |
|
190 * @return void |
|
191 **/ |
|
192 |
|
193 function register_deactivation ($pluginfile, $function = '') |
|
194 { |
|
195 add_action ('deactivate_'.basename (dirname ($pluginfile)).'/'.basename ($pluginfile), array (&$this, $function == '' ? 'deactivate' : $function)); |
|
196 } |
|
197 |
|
198 |
|
199 /** |
|
200 * Renders an admin section of display code |
|
201 * |
|
202 * @param string $ug_name Name of the admin file (without extension) |
|
203 * @param string $array Array of variable name=>value that is available to the display code (optional) |
|
204 * @return void |
|
205 **/ |
|
206 |
|
207 function render_admin ($ug_name, $ug_vars = array ()) |
|
208 { |
|
209 global $plugin_base; |
|
210 foreach ($ug_vars AS $key => $val) |
|
211 $$key = $val; |
|
212 |
|
213 if (file_exists ("{$this->plugin_base}/view/admin/$ug_name.php")) |
|
214 include ("{$this->plugin_base}/view/admin/$ug_name.php"); |
|
215 else |
|
216 echo "<p>Rendering of admin template {$this->plugin_base}/view/admin/$ug_name.php failed</p>"; |
|
217 } |
|
218 |
|
219 |
|
220 /** |
|
221 * Renders a section of user display code. The code is first checked for in the current theme display directory |
|
222 * before defaulting to the plugin |
|
223 * |
|
224 * @param string $ug_name Name of the admin file (without extension) |
|
225 * @param string $array Array of variable name=>value that is available to the display code (optional) |
|
226 * @return void |
|
227 **/ |
|
228 |
|
229 function render ($ug_name, $ug_vars = array ()) |
|
230 { |
|
231 foreach ($ug_vars AS $key => $val) |
|
232 $$key = $val; |
|
233 |
|
234 if (file_exists (TEMPLATEPATH."/view/{$this->plugin_name}/$ug_name.php")) |
|
235 include (TEMPLATEPATH."/view/{$this->plugin_name}/$ug_name.php"); |
|
236 else if (file_exists ("{$this->plugin_base}/view/{$this->plugin_name}/$ug_name.php")) |
|
237 include ("{$this->plugin_base}/view/{$this->plugin_name}/$ug_name.php"); |
|
238 else |
|
239 echo "<p>Rendering of template $ug_name.php failed</p>"; |
|
240 } |
|
241 |
|
242 |
|
243 /** |
|
244 * Renders a section of user display code. The code is first checked for in the current theme display directory |
|
245 * before defaulting to the plugin |
|
246 * |
|
247 * @param string $ug_name Name of the admin file (without extension) |
|
248 * @param string $array Array of variable name=>value that is available to the display code (optional) |
|
249 * @return void |
|
250 **/ |
|
251 |
|
252 function capture ($ug_name, $ug_vars = array ()) |
|
253 { |
|
254 ob_start (); |
|
255 $this->render ($ug_name, $ug_vars); |
|
256 $output = ob_get_contents (); |
|
257 ob_end_clean (); |
|
258 return $output; |
|
259 } |
|
260 |
|
261 |
|
262 /** |
|
263 * Captures an admin section of display code |
|
264 * |
|
265 * @param string $ug_name Name of the admin file (without extension) |
|
266 * @param string $array Array of variable name=>value that is available to the display code (optional) |
|
267 * @return string Captured code |
|
268 **/ |
|
269 |
|
270 function capture_admin ($ug_name, $ug_vars = array ()) |
|
271 { |
|
272 ob_start (); |
|
273 $this->render_admin ($ug_name, $ug_vars); |
|
274 $output = ob_get_contents (); |
|
275 ob_end_clean (); |
|
276 return $output; |
|
277 } |
|
278 |
|
279 |
|
280 /** |
|
281 * Display a standard error message (using CSS ID 'message' and classes 'fade' and 'error) |
|
282 * |
|
283 * @param string $message Message to display |
|
284 * @return void |
|
285 **/ |
|
286 |
|
287 function render_error ($message) |
|
288 { |
|
289 ?> |
|
290 <div class="fade error" id="message"> |
|
291 <p><?php echo $message ?></p> |
|
292 </div> |
|
293 <?php |
|
294 } |
|
295 |
|
296 |
|
297 /** |
|
298 * Display a standard notice (using CSS ID 'message' and class 'updated'). |
|
299 * Note that the notice can be made to automatically disappear, and can be removed |
|
300 * by clicking on it. |
|
301 * |
|
302 * @param string $message Message to display |
|
303 * @param int $timeout Number of seconds to automatically remove the message (optional) |
|
304 * @return void |
|
305 **/ |
|
306 |
|
307 function render_message ($message, $timeout = 0) |
|
308 { |
|
309 ?> |
|
310 <div class="updated" id="message" onclick="this.parentNode.removeChild (this)"> |
|
311 <p><?php echo $message ?></p> |
|
312 </div> |
|
313 <?php |
|
314 } |
|
315 |
|
316 |
|
317 /** |
|
318 * Get the plugin's base directory |
|
319 * |
|
320 * @return string Base directory |
|
321 **/ |
|
322 |
|
323 function dir () |
|
324 { |
|
325 return $this->plugin_base; |
|
326 } |
|
327 |
|
328 |
|
329 /** |
|
330 * Get a URL to the plugin. Useful for specifying JS and CSS files |
|
331 * |
|
332 * For example, <img src="<?php echo $this->url () ?>/myimage.png"/> |
|
333 * |
|
334 * @return string URL |
|
335 **/ |
|
336 |
|
337 function url ($url = '') |
|
338 { |
|
339 if ($url) |
|
340 return str_replace ('\\', urlencode ('\\'), str_replace ('&amp', '&', str_replace ('&', '&', $url))); |
|
341 else |
|
342 { |
|
343 $url = substr ($this->plugin_base, strlen ($this->realpath (ABSPATH))); |
|
344 if (DIRECTORY_SEPARATOR != '/') |
|
345 $url = str_replace (DIRECTORY_SEPARATOR, '/', $url); |
|
346 |
|
347 $url = get_bloginfo ('wpurl').'/'.ltrim ($url, '/'); |
|
348 |
|
349 // Do an SSL check - only works on Apache |
|
350 global $is_IIS; |
|
351 if (isset ($_SERVER['HTTPS']) && !$is_IIS) |
|
352 $url = str_replace ('http://', 'https://', $url); |
|
353 } |
|
354 return $url; |
|
355 } |
|
356 |
|
357 |
|
358 |
|
359 /** |
|
360 * Performs a version update check using an RSS feed. The function ensures that the feed is only |
|
361 * hit once every given number of days, and the data is cached using the WordPress Magpie library |
|
362 * |
|
363 * @param string $url URL of the RSS feed |
|
364 * @param int $days Number of days before next check |
|
365 * @return string Text to display |
|
366 **/ |
|
367 |
|
368 function version_update ($url, $days = 7) |
|
369 { |
|
370 if (!function_exists ('fetch_rss')) |
|
371 { |
|
372 if (!file_exists (ABSPATH.'wp-includes/rss.php')) |
|
373 return ''; |
|
374 include (ABSPATH.'wp-includes/rss.php'); |
|
375 } |
|
376 |
|
377 $now = time (); |
|
378 |
|
379 $checked = get_option ('plugin_urbangiraffe_rss'); |
|
380 |
|
381 // Use built-in Magpie caching |
|
382 if (function_exists ('fetch_rss') && (!isset ($checked[$this->plugin_name]) || $now > $checked[$this->plugin_name] + ($days * 24 * 60 * 60))) |
|
383 { |
|
384 $rss = fetch_rss ($url); |
|
385 if (count ($rss->items) > 0) |
|
386 { |
|
387 foreach ($rss->items AS $pos => $item) |
|
388 { |
|
389 if (isset ($checked[$this->plugin_name]) && strtotime ($item['pubdate']) < $checked[$this->plugin_name]) |
|
390 unset ($rss->items[$pos]); |
|
391 } |
|
392 } |
|
393 |
|
394 $checked[$this->plugin_name] = $now; |
|
395 update_option ('plugin_urbangiraffe_rss', $checked); |
|
396 return $rss; |
|
397 } |
|
398 } |
|
399 |
|
400 |
|
401 /** |
|
402 * Version of realpath that will work on systems without realpath |
|
403 * |
|
404 * @param string $path The path to canonicalize |
|
405 * @return string Canonicalized path |
|
406 **/ |
|
407 |
|
408 function realpath ($path) |
|
409 { |
|
410 if (function_exists ('realpath')) |
|
411 return realpath ($path); |
|
412 else if (DIRECTORY_SEPARATOR == '/') |
|
413 { |
|
414 $path = preg_replace ('/^~/', $_SERVER['DOCUMENT_ROOT'], $path); |
|
415 |
|
416 // canonicalize |
|
417 $path = explode (DIRECTORY_SEPARATOR, $path); |
|
418 $newpath = array (); |
|
419 for ($i = 0; $i < sizeof ($path); $i++) |
|
420 { |
|
421 if ($path[$i] === '' || $path[$i] === '.') |
|
422 continue; |
|
423 |
|
424 if ($path[$i] === '..') |
|
425 { |
|
426 array_pop ($newpath); |
|
427 continue; |
|
428 } |
|
429 |
|
430 array_push ($newpath, $path[$i]); |
|
431 } |
|
432 |
|
433 $finalpath = DIRECTORY_SEPARATOR.implode (DIRECTORY_SEPARATOR, $newpath); |
|
434 return $finalpath; |
|
435 } |
|
436 |
|
437 return $path; |
|
438 } |
|
439 |
|
440 |
|
441 function checked ($item, $field = '') |
|
442 { |
|
443 if ($field && is_array ($item)) |
|
444 { |
|
445 if (isset ($item[$field]) && $item[$field]) |
|
446 echo ' checked="checked"'; |
|
447 } |
|
448 else if (!empty ($item)) |
|
449 echo ' checked="checked"'; |
|
450 } |
|
451 |
|
452 function select ($items, $default = '') |
|
453 { |
|
454 if (count ($items) > 0) |
|
455 { |
|
456 foreach ($items AS $key => $value) |
|
457 { |
|
458 if (is_array ($value)) |
|
459 { |
|
460 echo '<optgroup label="'.$key.'">'; |
|
461 foreach ($value AS $sub => $subvalue) |
|
462 echo '<option value="'.$sub.'"'.($sub == $default ? ' selected="selected"' : '').'>'.$subvalue.'</option>'; |
|
463 echo '</optgroup>'; |
|
464 } |
|
465 else |
|
466 echo '<option value="'.$key.'"'.($key == $default ? ' selected="selected"' : '').'>'.$value.'</option>'; |
|
467 } |
|
468 } |
|
469 } |
|
470 } |
|
471 |
|
472 if (!class_exists ('Widget_AJAX_Calendar')) |
|
473 { |
|
474 class Widget_AJAX_Calendar |
|
475 { |
|
476 function Widget_AJAX_Calendar ($name, $max = 1, $id = '', $args = '') |
|
477 { |
|
478 $this->name = $name; |
|
479 $this->id = $id; |
|
480 $this->widget_max = $max; |
|
481 $this->args = $args; |
|
482 |
|
483 if ($this->id == '') |
|
484 $this->id = strtolower (preg_replace ('/[^A-Za-z]/', '-', $this->name)); |
|
485 |
|
486 $this->widget_available = 1; |
|
487 if ($this->widget_max > 1) |
|
488 { |
|
489 $this->widget_available = get_option ('widget_available_'.$this->id ()); |
|
490 if ($this->widget_available === false) |
|
491 $this->widget_available = 1; |
|
492 } |
|
493 |
|
494 add_action ('init', array (&$this, 'initialize')); |
|
495 } |
|
496 |
|
497 function initialize () |
|
498 { |
|
499 // Compatability functions for WP 2.1 |
|
500 if (!function_exists ('wp_register_sidebar_widget')) |
|
501 { |
|
502 function wp_register_sidebar_widget ($id, $name, $output_callback, $classname = '') |
|
503 { |
|
504 register_sidebar_widget($name, $output_callback, $classname); |
|
505 } |
|
506 } |
|
507 |
|
508 if (!function_exists ('wp_register_widget_control')) |
|
509 { |
|
510 function wp_register_widget_control($name, $control_callback, $width = 300, $height = 200) |
|
511 { |
|
512 register_widget_control($name, $control_callback, $width, $height); |
|
513 } |
|
514 } |
|
515 |
|
516 if (function_exists ('wp_register_sidebar_widget')) |
|
517 { |
|
518 if ($this->widget_max > 1) |
|
519 { |
|
520 add_action ('sidebar_admin_setup', array (&$this, 'setup_save')); |
|
521 add_action ('sidebar_admin_page', array (&$this, 'setup_display')); |
|
522 } |
|
523 |
|
524 $this->load_widgets (); |
|
525 } |
|
526 } |
|
527 |
|
528 function load_widgets () |
|
529 { |
|
530 for ($pos = 1; $pos <= $this->widget_max; $pos++) |
|
531 { |
|
532 wp_register_sidebar_widget ($this->id ($pos), $this->name ($pos), $pos <= $this->widget_available ? array (&$this, 'show_display') : '', $this->args (), $pos); |
|
533 |
|
534 if ($this->has_config ()) |
|
535 wp_register_widget_control ($this->id ($pos), $this->name ($pos), $pos <= $this->widget_available ? array (&$this, 'show_config') : '', $this->args (), $pos); |
|
536 } |
|
537 } |
|
538 |
|
539 function args () |
|
540 { |
|
541 if ($this->args) |
|
542 $args = $this->args; |
|
543 else |
|
544 $args = array ('classname' => ''); |
|
545 |
|
546 if ($this->description ()) |
|
547 $args['description'] = $this->description (); |
|
548 return $args; |
|
549 } |
|
550 |
|
551 function description () { return ''; } |
|
552 |
|
553 function name ($pos) |
|
554 { |
|
555 if ($this->widget_available > 1) |
|
556 return $this->name.' ('.$pos.')'; |
|
557 return $this->name; |
|
558 } |
|
559 |
|
560 function id ($pos = 0) |
|
561 { |
|
562 if ($pos == 0) |
|
563 return $this->id; |
|
564 return $this->id.'-'.$pos; |
|
565 } |
|
566 |
|
567 function show_display ($args, $number = 1) |
|
568 { |
|
569 $config = get_option ('widget_config_'.$this->id ($number)); |
|
570 if ($config === false) |
|
571 $config = array (); |
|
572 |
|
573 $this->load ($config); |
|
574 $this->display ($args); |
|
575 } |
|
576 |
|
577 function show_config ($position) |
|
578 { |
|
579 if (isset ($_POST['widget_config_save_'.$this->id ($position)])) |
|
580 { |
|
581 $data = $_POST[$this->id ()]; |
|
582 if (count ($data) > 0) |
|
583 { |
|
584 $newdata = array (); |
|
585 foreach ($data AS $item => $values) |
|
586 $newdata[$item] = $values[$position]; |
|
587 $data = $newdata; |
|
588 } |
|
589 |
|
590 update_option ('widget_config_'.$this->id ($position), $this->save ($data)); |
|
591 } |
|
592 |
|
593 $options = get_option ('widget_config_'.$this->id ($position)); |
|
594 if ($options === false) |
|
595 $options = array (); |
|
596 |
|
597 $this->config ($options, $position); |
|
598 echo '<input type="hidden" name="widget_config_save_'.$this->id ($position).'" value="1" />'; |
|
599 } |
|
600 |
|
601 function has_config () { return false; } |
|
602 function save ($data) |
|
603 { |
|
604 return array (); |
|
605 } |
|
606 |
|
607 function setup_save () |
|
608 { |
|
609 if (isset ($_POST['widget_setup_save_'.$this->id ()])) |
|
610 { |
|
611 $this->widget_available = intval ($_POST['widget_setup_count_'.$this->id ()]); |
|
612 if ($this->widget_available < 1) |
|
613 $this->widget_available = 1; |
|
614 else if ($this->widget_available > $this->widget_max) |
|
615 $this->widget_available = $this->widget_max; |
|
616 |
|
617 update_option ('widget_available_'.$this->id (), $this->widget_available); |
|
618 |
|
619 $this->load_widgets (); |
|
620 } |
|
621 } |
|
622 |
|
623 function config_name ($field, $pos) |
|
624 { |
|
625 return $this->id ().'['.$field.']['.$pos.']'; |
|
626 } |
|
627 |
|
628 function setup_display () |
|
629 { |
|
630 ?> |
|
631 <div class="wrap"> |
|
632 <form method="post"> |
|
633 <h2><?php echo $this->name ?></h2> |
|
634 <p style="line-height: 30px;"><?php _e('How many widgets would you like?', $this->id); ?> |
|
635 <select name="widget_setup_count_<?php echo $this->id () ?>" value="<?php echo $options; ?>"> |
|
636 <?php for ( $i = 1; $i <= $this->widget_max; ++$i ) : ?> |
|
637 <option value="<?php echo $i ?>"<?php if ($this->widget_available == $i) echo ' selected="selected"' ?>><?php echo $i ?></option> |
|
638 <?php endfor; ?> |
|
639 </select> |
|
640 <span class="submit"> |
|
641 <input type="submit" name="widget_setup_save_<?php echo $this->id () ?>" value="<?php echo attribute_escape(__('Save', $this->id)); ?>" /> |
|
642 </span> |
|
643 </p> |
|
644 </form> |
|
645 </div> |
|
646 <?php |
|
647 } |
|
648 } |
|
649 } |
|
650 ?> |