Ticket #4169: widgets.php

File widgets.php, 45.6 kB (added by ryan, 1 year ago)

wordpress.com version of widgets.php

Line 
1 <?php
2 /*
3 Plugin Name: Sidebar Widgets
4 Plugin URI: http://svn.wp-plugins.org/widgets/trunk
5 Description: Adds "Sidebar Widgets" panel under Presentation menu
6 Author: Automattic, Inc.
7 Author URI: http://automattic.com/
8 Version: 1.0.20060724
9 */
10
11
12 //////////////////////////////////////////////////////////// Global Variables
13
14 $registered_sidebars = array();
15 $registered_widgets = array();
16 $registered_widget_controls = array();
17 $registered_widget_styles = array();
18 $register_widget_defaults = false; // When true, registration is non-destructive.
19
20 //////////////////////////////////////////////////////////// Public Functions
21
22 function register_sidebars($number = 1, $args = array()) {
23     global $registered_sidebars;
24
25     $number = (int) $number;
26
27     if ( is_string($args) )
28         parse_str($args, $args);
29
30     $i = 1;
31
32     while ( $i <= $number ) {
33         $_args = $args;
34         if ( $number > 1 ) {
35             $_args['name'] = isset($args['name']) ? $args['name'] : sprintf(__('Sidebar %d', 'widgets'), $i);
36         } else {
37             $_args['name'] = isset($args['name']) ? $args['name'] : __('Sidebar', 'widgets');
38         }
39         $_args['id'] = isset($args['id']) ? $args['id'] : "sidebar-$i";
40         register_sidebar($_args);
41         ++$i;
42     }
43 }
44
45 function register_sidebar($args = array()) {
46     global $registered_sidebars;
47
48     if ( is_string($args) )
49         parse_str($args, $args);
50
51     $i = count($registered_sidebars) + 1;
52
53     $defaults = array(
54         'name' => sprintf(__('Sidebar %d', 'widgets'), count($registered_sidebars) + 1 ),
55         'id' => "sidebar-$i",
56         'before_widget' => '<li id="%1$s" class="widget %2$s">',
57         'after_widget' => "</li>\n",
58         'before_title' => '<h2 class="widgettitle">',
59         'after_title' => "</h2>\n",
60     );
61
62     $sidebar = array_merge($defaults, $args);
63
64     $registered_sidebars[$sidebar['id']] = $sidebar;
65
66     return $sidebar['id'];
67 }
68
69 function unregister_sidebar($index) {
70     global $registered_sidebars;
71
72     unset( $registered_sidebars[$index] );
73 }
74
75 function register_sidebar_widget($name, $output_callback, $classname = '', $id = '') {
76     global $registered_widgets, $register_widget_defaults;
77
78     // Compat
79     if ( is_array($name) ) {
80         if ( count($name) == 3 )
81             $name = sprintf($name[0], $name[2]);
82         else
83             $name = $name[0];
84     }
85
86     // Last resort -- this can be broken when names get translated so please provide a unique id.
87     if ( !isset($id) )
88         $id = sanitize_title($name);
89
90     if ( (!isset($classname) || empty($classname) || !is_string($classname)) && is_string($output_callback) )
91             $classname = $output_callback;
92
93     $widget = array(
94         'name' => $name,
95         'id' => $id,
96         'callback' => $output_callback,
97         'classname' => $classname,
98         'params' => array_slice(func_get_args(), 4)
99     );
100
101     if ( empty($output_callback) )
102         unset($registered_widgets[$id]);
103     elseif ( is_callable($output_callback) && ( !isset($registered_widgets[$id]) || !$register_widget_defaults) )
104         $registered_widgets[$id] = $widget;
105 }
106
107 function unregister_sidebar_widget($id) {
108     $id = sanitize_title($id);
109     register_sidebar_widget('', '', '', $id);
110     unregister_widget_control($id);
111 }
112
113 function register_widget_control($name, $control_callback, $width = 300, $height = 200, $id = '') {
114     global $registered_widget_controls, $register_widget_defaults;
115
116     // Compat
117     if ( is_array($name) ) {
118         if ( count($name) == 3 )
119             $name = sprintf($name[0], $name[2]);
120         else
121             $name = $name[0];
122     }
123
124     if ( !isset($id) || empty($id) )
125         $id = $name;
126
127     $id = sanitize_title($id);
128
129     $width = (int) $width > 90 ? (int) $width + 60 : 360;
130     $height = (int) $height > 60 ? (int) $height + 40 : 240;
131
132     if ( empty($control_callback) )
133         unset($registered_widget_controls[$name]);
134     elseif ( !isset($registered_widget_controls[$name]) || !$register_widget_defaults )
135         $registered_widget_controls[$id] = array(
136             'name' => $name,
137             'id' => $id,
138             'callback' => $control_callback,
139             'width' => $width,
140             'height' => $height,
141             'params' => array_slice(func_get_args(), 5)
142         );
143 }
144
145 function unregister_widget_control($id) {
146     $id = sanitize_title($id);
147     return register_widget_control($id, '');
148 }
149
150 function dynamic_sidebar($index = 1) {
151     global $registered_sidebars, $registered_widgets;
152
153     if ( is_int($index) ) {
154         $index = "sidebar-$index";
155     } else {
156         $index = sanitize_title($index);
157     }
158
159     $sidebars_widgets = get_sidebars_widgets();
160
161     if ( empty($registered_sidebars[$index]) || !is_array($sidebars_widgets[$index]) || empty($sidebars_widgets[$index]) )
162         return false;
163
164     $sidebar = $registered_sidebars[$index];
165
166     $did_one = false;
167     foreach ( $sidebars_widgets[$index] as $id ) {
168         $callback = $registered_widgets[$id]['callback'];
169
170         $params = array_merge(array($sidebar), (array) $registered_widgets[$id]['params']);
171
172         // Substitute HTML id and class attributes into before_widget
173         $params[0]['before_widget'] = sprintf($params[0]['before_widget'], $id, $registered_widgets[$id]['classname']);
174
175         if ( is_callable($callback) ) {
176             call_user_func_array($callback, $params);
177             $did_one = true;
178         }
179     }
180
181     return $did_one;
182 }
183
184 function is_active_widget($callback) {
185     global $registered_widgets;
186
187     $sidebars_widgets = get_sidebars_widgets(false);
188
189     if ( is_array($sidebars_widgets) ) foreach ( $sidebars_widgets as $sidebar => $widgets )
190         if ( is_array($widgets) ) foreach ( $widgets as $widget )
191             if ( $registered_widgets[$widget]['callback'] == $callback )
192                 return true;
193
194     return false;
195 }
196
197 function is_dynamic_sidebar() {
198     global $registered_widgets, $registered_sidebars;
199     $sidebars_widgets = get_option('sidebars_widgets');
200     foreach ( $registered_sidebars as $index => $sidebar ) {
201         if ( count($sidebars_widgets[$index]) ) {
202             foreach ( $sidebars_widgets[$index] as $widget )
203                 if ( array_key_exists($widget, $registered_widgets) )
204                     return true;
205         }
206     }
207     return false;
208 }
209
210 //////////////////////////////////////////////////////////// Private Functions
211
212 function get_sidebars_widgets($update = true) {
213     global $registered_widgets;
214
215     $sidebars_widgets = get_option('sidebars_widgets');
216     $_sidebars_widgets = array();
217
218     if ( !isset($sidebars_widgets['array_version']) )
219         $sidebars_widgets['array_version'] = 1;
220
221     switch ( $sidebars_widgets['array_version'] ) {
222         case 1 :
223             foreach ( $sidebars_widgets as $index => $sidebar )
224             if ( is_array($sidebar) )
225             foreach ( $sidebar as $i => $name ) {
226                 $id = strtolower($name);
227                 if ( isset($registered_widgets[$id]) ) {
228                     $_sidebars_widgets[$index][$i] = $id;
229                     continue;
230                 }
231                 $id = sanitize_title($name);
232                 if ( isset($registered_widgets[$id]) ) {
233                     $_sidebars_widgets[$index][$i] = $id;
234                     continue;
235                 }
236                 unset($_sidebars_widgets[$index][$i]);
237             }
238             $_sidebars_widgets['array_version'] = 2;
239             if ( $update )
240                 update_option('sidebars_widgets', $_sidebars_widgets);
241             break;
242         case 2 :
243             $_sidebars_widgets = $sidebars_widgets;
244             break;
245     }
246
247     unset($_sidebars_widgets['array_version']);
248
249     return $_sidebars_widgets;
250 }
251
252 function sidebar_admin_setup() {
253     global $registered_sidebars, $registered_widgets;
254     if ( count($registered_sidebars) < 1 )
255         return;
256     $page = preg_replace('!^.*[\\\\/]wp-content[\\\\/][^\\\\/]*plugins[\\\\/]!', '', __FILE__);
257     $page = str_replace('\\', '/', $page);
258     add_submenu_page('themes.php', __('Sidebar Widgets', 'widgets'), __('Sidebar Widgets', 'widgets'), 5, $page, 'sidebar_admin_page');
259     if ( $_GET['page'] == $page ) {
260         if ( isset($_POST['action']) && $_POST['action'] == 'save_widget_order' ) {
261             check_admin_referer('widgets-save-widget-order');
262             $sidebars_widgets = array();
263             foreach ( $registered_sidebars as $index => $sidebar ) {
264                 $postindex = $index . 'order';
265                 parse_str($_POST[$postindex], $order);
266                 $new_order = $order[$index];
267                 if ( is_array($new_order) )
268                     foreach ( $new_order as $_id )
269                         foreach ( $registered_widgets as $id => $widget )
270                             if ( $_id == $id )
271                                 $sidebars_widgets[$index][] = $id;
272             }
273             $sidebars_widgets['array_version'] = 2;
274             $saved = update_option('sidebars_widgets', $sidebars_widgets) ? 'yes' : 'no';
275             wp_redirect(get_option('siteurl')."/wp-admin/themes.php?page=$page&saved=$saved");
276         }
277         wp_enqueue_script( 'scriptaculous-dragdrop' );
278         add_action('admin_head', 'sidebar_admin_head');
279         do_action('sidebar_admin_setup');
280     }
281 }
282
283 function sidebar_admin_head() {
284     global $registered_widgets, $registered_sidebars, $registered_widget_controls;
285
286     $width = 1 + 262 * ( count($registered_sidebars));
287     $height = 35 * count($registered_widgets);
288     ?>
289     <style type="text/css">
290     body {
291         height: 100%;
292     }
293     #sbadmin #zones {
294         width: <?php echo $width; ?>px;
295         -moz-user-select: none;
296         -khtml-user-select: none;
297         user-select: none;
298     }
299     #sbreset {
300         float: left;
301         margin: 1px 0;
302     }
303     .dropzone {
304         float: left;
305         margin-right: 10px;
306         padding: 5px;
307         border: 1px solid #bbb;
308         background-color: #f0f8ff;
309     }
310     .dropzone h3 {
311         text-align: center;
312         color: #333;
313     }
314     .dropzone ul {
315         list-style-type: none;
316         width: 240px;
317         height: <?php echo $height; ?>px;
318         float: left;
319         margin: 0;
320         padding: 0;
321     }
322     * .module, #lastmodule {
323         width: 238px;
324         padding: 0;
325         margin: 5px 0;
326         cursor: move;
327         display: block;
328         border: 1px solid #ccc;
329         background-color: #fbfbfb;
330         text-align: left;
331         line-height: 25px;
332     }
333     * .handle, #lastmodule span {
334         display: block;
335         width: 216px;
336         padding: 0 10px;
337         border-top: 1px solid #f2f2f2;
338         border-right: 1px solid #e8e8e8;
339         border-bottom: 1px solid #e8e8e8;
340         border-left: 1px solid #f2f2f2;
341     }
342     * .popper {
343         margin: 0;
344         display: inline;
345         position: absolute;
346         top: 3px;
347         right: 3px;
348         overflow: hidden;
349         text-align: center;
350         height: 16px;
351         font-size: 18px;
352         line-height: 14px;
353         cursor: pointer;
354         padding: 0 3px 1px;
355         border-top: 4px solid #6da6d1;
356         background: url( images/fade-butt.png ) -5px 0px;
357     }
358     * html .popper {
359         padding: 1px 6px 0;
360         font-size: 16px;
361     }
362     #sbadmin p.submit {
363         padding-right: 10px;
364         clear: left;
365     }
366     .placematt {
367         position: absolute;
368         cursor: default;
369         margin: 10px 0 0;
370         padding: 0;
371         width: 238px;
372         background-color: #ffe;
373     }
374     * html .placematt {
375         margin-top: 5px;
376     }
377     .placematt h4 {
378         text-align: center;
379         margin-bottom: 5px;
380     }
381     .placematt span {
382         padding: 0 10px 10px;
383         text-align: justify;
384     }
385     #palettediv {
386         border: 1px solid #bbb;
387         background-color: #f0f8ff;
388         height: 180px;
389         margin-top: 10px;
390     }
391     #palettediv h3 {
392         text-align: center;
393         color: #333;
394     }
395     #palettediv ul {
396         padding: 0 0 0 10px;
397     }
398     #palettediv .module, #lastmodule {
399         margin-right: 10px;
400         float: left;
401         width: 120px;
402     }
403     #palettediv .handle, #lastmodule span {
404         height: 40px;
405         font-size: 0.9em;
406         line-height: 1.6em;
407         width: 110px;
408         padding: 0 5px;
409     }
410     #palettediv .popper {
411         visibility: hidden;
412     }
413     #lastmodule {
414         visibility: hidden;
415     }
416     * html #palettediv ul {
417         margin: 0;
418         padding: 0 0 0 10px;
419     }
420     * html #palettediv .module {
421         float: none;
422         display: inline;
423     }
424     #controls {
425         height: 0px;
426     }
427     .control {
428         position: absolute;
429         display: block;
430         background: #f9fcfe;
431         padding: 0;
432     }
433     .controlhandle {
434         cursor: move;
435         background-color: #6da6d1;
436         border-bottom: 2px solid #448abd;
437         color: #333;
438         display: block;
439         margin: 0 0 5px;
440         padding: 4px;
441         font-size: 120%;
442     }
443     .controlcloser {
444         cursor: pointer;
445         font-size: 120%;
446         display: block;
447         position: absolute;
448         top: 2px;
449         right: 8px;
450         padding: 0 3px;
451         font-weight: bold;
452     }
453     .controlform {
454         margin: 20px 30px;
455     }
456     .controlform p {
457         text-align: center;
458     }
459     .control .checkbox {
460         border: none;
461         background: transparent;
462     }
463     .hidden {
464         display: none;
465     }
466     #shadow {
467         background: black;
468         display: none;
469         position: absolute;
470         top: 0px;
471         left: 0px;
472         width: 100%;
473     }
474     </style>
475
476     <script type="text/javascript">
477         // <![CDATA[
478         var cols = [<?php $a = array(); foreach ( $registered_sidebars as $index => $sidebar ) $a[] = "'$index'"; echo implode(', ', $a); ?>];
479         var widgets = [<?php $a = array(); foreach ( $registered_widgets as $name => $widget ) $a[] = "'{$widget['id']}'"; echo implode(', ', $a); ?>];
480         var controldims = new Array;
481 <?php foreach ( $registered_widget_controls as $id => $widget ) : ?>
482             controldims['<?php echo $id; ?>control'] = new Array;
483             controldims['<?php echo $id; ?>control']['width'] = <?php echo (int) $widget['width']; ?>;
484             controldims['<?php echo $id; ?>control']['height'] = <?php echo (int) $widget['height']; ?>;
485 <?php endforeach; ?>
486         function initWidgets() {
487 <?php foreach ( $registered_widget_controls as $name => $widget ) : ?>
488             $('<?php echo $widget['id']; ?>popper').onclick = function() {popControl('<?php echo $widget['id']; ?>control');};
489             $('<?php echo $widget['id']; ?>closer').onclick = function() {unpopControl('<?php echo $widget['id']; ?>control');};
490             new Draggable('<?php echo $widget['id']; ?>control', {revert:false,handle:'controlhandle',starteffect:function(){},endeffect:function(){},change:function(o){dragChange(o);}});
491             if ( true && window.opera )
492                 $('<?php echo $widget['id']; ?>control').style.border = '1px solid #bbb';
493 <?php endforeach; ?>
494             if ( true && window.opera )
495                 $('shadow').style.background = 'transparent';
496             new Effect.Opacity('shadow', {to:0.0});
497             widgets.map(function(o) {o='widgetprefix-'+o; Position.absolutize(o); Position.relativize(o);} );
498             $A(Draggables.drags).map(function(o) {o.startDrag(null); o.finishDrag(null);});
499             for ( var n in Draggables.drags ) {
500                 if ( Draggables.drags[n].element.id == 'lastmodule' ) {
501                     Draggables.drags[n].destroy();
502                     break;
503                 }
504             }
505             resetPaletteHeight();
506         }
507         function resetDroppableHeights() {
508             var max = 6;
509             cols.map(function(o) {var c = $(o).childNodes.length; if ( c > max ) max = c;} );
510             var height = 35 * ( max + 1);
511             cols.map(function(o) {h = (($(o).childNodes.length + 1) * 35); $(o).style.height = (h > 280 ? h : 280) + 'px';} );
512         }
513         function resetPaletteHeight() {
514             var p = $('palette'), pd = $('palettediv'), last = $('lastmodule');
515             p.appendChild(last);
516             if ( Draggables.activeDraggable && last.id == Draggables.activeDraggable.element.id )
517                 last = last.previousSibling;
518             var y1 = Position.cumulativeOffset(last)[1] + last.offsetHeight;
519             var y2 = Position.cumulativeOffset(pd)[1] + pd.offsetHeight;
520             var dy = y1 - y2;
521             pd.style.height = (pd.offsetHeight + dy + 9) + "px";
522         }
523         function maxHeight(elm) {
524             htmlheight = document.body.parentNode.clientHeight;
525             bodyheight = document.body.clientHeight;
526             var height = htmlheight > bodyheight ? htmlheight : bodyheight;
527             $(elm).style.height = height + 'px';
528         }
529         function dragChange(o) {
530             el = o.element ? o.element : $(o);
531             var p = Position.page(el);
532             var right = p[0];
533             var top = p[1];
534             var left = $('shadow').offsetWidth - (el.offsetWidth + left);
535             var bottom = $('shadow').offsetHeight - (el.offsetHeight + top);
536             if ( right < 1 ) el.style.left = 0;
537             if ( top < 1 ) el.style.top = 0;
538             if ( left < 1 ) el.style.left = (left + right) + 'px';
539             if ( bottom < 1 ) el.style.top = (top + bottom) + 'px';
540         }
541         function popControl(elm) {
542             el = $(elm);
543             el.style.width = controldims[elm]['width'] + 'px';
544             el.style.height = controldims[elm]['height'] + 'px';
545             var x = ( document.body.clientWidth - controldims[elm]['width'] ) / 2;
546             var y = ( document.body.parentNode.clientHeight - controldims[elm]['height'] ) / 2;
547             el.style.position = 'absolute';
548             el.style.right = '' + x + 'px';
549             el.style.top = '' + y + 'px';
550             el.style.zIndex = 1000;
551             el.className='control';
552             $('shadow').onclick = function() {unpopControl(elm);};
553             window.onresize = function(){maxHeight('shadow');dragChange(elm);};
554             popShadow();
555         }
556         function popShadow() {
557             maxHeight('shadow');
558             var shadow = $('shadow');
559             shadow.style.zIndex = 999;
560             shadow.style.display = 'block';
561             new Effect.Opacity('shadow', {duration:0.5, from:0.0, to:0.2});
562         }
563         function unpopShadow() {
564             new Effect.Opacity('shadow', {to:0.0});
565             $('shadow').style.display = 'none';
566         }
567         function unpopControl(el) {
568             $(el).className='hidden';
569             unpopShadow();
570         }
571         function serializeAll() {
572 <?php foreach ( $registered_sidebars as $index => $sidebar ) : ?>
573             $('<?php echo $index; ?>order').value = Sortable.serialize('<?php echo $index; ?>');
574 <?php endforeach; ?>
575         }
576         function updateAll() {
577             resetDroppableHeights();
578             resetPaletteHeight();
579             cols.map(function(o){
580                 var pm = $(o+'placematt');
581                 if ( $(o).childNodes.length == 0 ) {
582                     pm.style.display = 'block';
583                     Position.absolutize(o+'placematt');
584                 } else {
585                     pm.style.display = 'none';
586                 }
587             });
588         }
589         function noSelection(event) {
590             if ( document.selection ) {
591                 var range = document.selection.createRange();
592                 range.collapse(false);
593                 range.select();
594                 return false;
595             }
596         }
597         addLoadEvent(updateAll);
598         addLoadEvent(initWidgets);
599         Event.observe(window, 'resize', resetPaletteHeight);
600         // ]]>
601     </script>
602     <?php
603     do_action('sidebar_admin_head');
604 }
605
606 function sidebar_admin_page() {
607     global $registered_widgets, $registered_sidebars, $registered_widget_controls;
608
609     if ( count($registered_sidebars) < 1 ) {
610 ?>
611     <div class="wrap">
612     <h2><?php _e('About Dynamic Sidebars'); ?></h2>
613     <p><?php _e("You can modify your theme's sidebar, rearranging and configuring widgets right in this screen! Well, you could if you had a compatible theme. You're seeing this message because your theme isn't ready for widgets. <a href='http://automattic.com/code/widgets/'>Get it ready!</a>"); ?></p>
614    
615     </div>
616 <?php
617         return;
618     }
619     $sidebars_widgets = get_sidebars_widgets();
620     if ( empty($sidebars_widgets) ) {
621         $sidebars_widgets = get_widget_defaults();
622     }
623
624     ksort($registered_widgets);
625
626     $inactive_widgets = array();
627     foreach ( $registered_widgets as $id => $widget ) {
628         $is_active = false;
629         foreach ( $registered_sidebars as $index => $sidebar ) {
630             if ( is_array($sidebars_widgets[$index]) && in_array($id, $sidebars_widgets[$index]) ) {
631                 $is_active = true;
632                 break;
633             }
634         }
635         if ( ! $is_active )
636             $inactive_widgets[] = $id;
637     }
638
639     $containers = array('palette');
640     foreach ( $registered_sidebars as $index => $sidebar )
641         $containers[] = $index;
642     $c_string = '';
643     foreach ( $containers as $container )
644         $c_string .= "\"$container\",";
645     $c_string = substr($c_string, 0, -1);
646     ?>
647     <?php if ( $_GET['saved'] ) { ?>
648     <div class="fade updated" id="message">
649     <p><?php printf(__('Sidebar Updated. <a href="%s">View site &raquo;</a>', 'widgets'), get_option('home') . '/'); ?></p>
650     </div>
651     <?php } ?>
652     <div class="wrap">
653     <h2><?php _e('Sidebar Arrangement'); ?></h2>
654 &