diff --git a/wp-includes/classes.php b/wp-includes/classes.php index f01e46b0b..02669a1c3 100644 --- a/wp-includes/classes.php +++ b/wp-includes/classes.php @@ -1590,4 +1590,218 @@ class WP_Ajax_Response { } } +/** + * This class must be extended for each widget and WP_Widgets::widget(), WP_Widgets::update() + * and WP_Widgets::form() need to be over-ridden. + * + * @package WordPress + * @since 2.8 + */ +class WP_Widgets { + + var $id_base; // Root id for all widgets of this type. + var $name; // Name for this widget type. + var $widget_options; // Option array passed to wp_register_sidebar_widget() + var $control_options; // Option array passed to wp_register_widget_control() + + var $number = false; // Unique ID number of the current instance. + var $id = false; // Unique ID string of the current instance (id_base-number) + var $updated = false; // Set true when we update the data after a POST submit - makes sure we don't do it twice. + + // Member functions that you must over-ride. + + /** Echo the actual widget content. Subclasses should over-ride this function + * to generate their widget code. */ + function widget($args, $instance) { + die('function WP_Widgets::widget() must be over-ridden in a sub-class.'); + } + + /** Update a particular instance. + * This function should check that $new_instance is set correctly. + * The newly calculated value of $instance should be returned. */ + function update($new_instance, $old_instance) { + die('function WP_Widgets::update() must be over-ridden in a sub-class.'); + } + + /** Echo a control form for the current instance. */ + function form($instance) { + die('function WP_Widgets::form() must be over-ridden in a sub-class.'); + } + + // Functions you'll need to call. + + /** + * PHP4 constructor + */ + function WP_Widgets( $id_base, $name, $widget_options = array(), $control_options = array() ) { + $this->__construct( $id_base, $name, $widget_options, $control_options ); + } + + /** + * PHP5 constructor + * widget_options: passed to wp_register_sidebar_widget() + * - description + * - classname + * control_options: passed to wp_register_widget_control() + * - width + * - height + */ + function __construct( $id_base, $name, $widget_options = array(), $control_options = array() ) { + $this->id_base = $id_base; + $this->name = $name; + $this->option_name = 'wp_widget_' . $id_base; + $this->widget_options = wp_parse_args( $widget_options, array('classname' => $this->option_name) ); + $this->control_options = wp_parse_args( $control_options, array('id_base' => $this->id_base) ); + + //add_action( 'widgets_init', array( &$this, 'register' ) ); + } + + /** Helper function to be called by form(). + * Returns an HTML name for the field. */ + function get_field_name($field_name) { + return 'widget-' . $this->id_base . '[' . $this->number . '][' . $field_name . ']'; + } + + /** Helper function to be called by form(). + * Returns an HTML id for the field. */ + function get_field_id($field_name) { + return 'widget-' . $this->id_base . '-' . $this->number . '-' . $field_name; + } + + /** Registers this widget-type. + * Called during the 'widgets_init' action. */ + function register() { + if ( ! $all_instances = get_option($this->option_name) ) + $all_instances = array(); + + $registered = false; + foreach( array_keys($all_instances) as $number ) { + // Old widgets can have null values for some reason + if ( !isset($all_instances[$number]['_multiwidget']) ) + continue; + + $this->_set($number); + $registered = true; + $this->_register_one($number); + } + + // If there are none, we register the widget's existance with a + // generic template + if ( !$registered ) { + $this->_set(1); + $this->_register_one(); + } + } + + // Private Functions. Don't worry about these. + + function _set($number) { + $this->number = $number; + $this->id = $this->id_base . '-' . $number; + } + + function _get_display_callback() { + return array(&$this, 'display_callback'); + } + + function _get_control_callback() { + return array(&$this, 'control_callback'); + } + + /** Generate the actual widget content. + * Just finds the instance and calls widget(). + * Do NOT over-ride this function. */ + function display_callback( $args, $widget_args = 1 ) { + if ( is_numeric($widget_args) ) + $widget_args = array( 'number' => $widget_args ); + + $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) ); + $this->_set( $widget_args['number'] ); + + // Data is stored as array: + // array( number => data for that instance of the widget, ... ) + $all_instances = get_option($this->option_name); + if ( isset($all_instances[$this->number]) ) + $this->widget($args, $all_instances[$this->number]); + } + + /** Deal with changed settings and generate the control form. + * Do NOT over-ride this function. */ + function control_callback( $widget_args = 1 ) { + global $wp_registered_widgets; + + if ( is_numeric($widget_args) ) + $widget_args = array( 'number' => $widget_args ); + + $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) ); + + // Data is stored as array: + // array( number => data for that instance of the widget, ... ) + $all_instances = get_option($this->option_name); + if ( !is_array($all_instances) ) + $all_instances = array(); + + // We need to update the data + if ( !$this->updated && !empty($_POST['sidebar']) ) { + // Tells us what sidebar to put the data in + $sidebar = (string) $_POST['sidebar']; + + $sidebars_widgets = wp_get_sidebars_widgets(); + if ( isset($sidebars_widgets[$sidebar]) ) + $this_sidebar =& $sidebars_widgets[$sidebar]; + else + $this_sidebar = array(); + + foreach ( $this_sidebar as $_widget_id ) { + // Remove all widgets of this type from the sidebar. We'll add the + // new data in a second. This makes sure we don't get any duplicate + // data since widget ids aren't necessarily persistent across multiple + // updates + if ( $this->_get_display_callback() == $wp_registered_widgets[$_widget_id]['callback'] && isset($wp_registered_widgets[$_widget_id]['params'][0]['number']) ) { + $number = $wp_registered_widgets[$_widget_id]['params'][0]['number']; + if( !in_array( $this->id_base . '-' . $number, (array)$_POST['widget-id'] ) ) { + // the widget has been removed. + unset($all_instances[$number]); + } + } + } + + foreach( (array) $_POST['widget-' . $this->id_base] as $number => $new_instance ) { + $this->_set($number); + if ( isset($all_instances[$number]) ) + $instance = $this->update($new_instance, $all_instances[$number]); + else + $instance = $this->update($new_instance, array()); + + if ( !empty($instance) ) { + $instance['_multiwidget'] = $number; + $all_instances[$number] = $instance; + } + } + + update_option($this->option_name, $all_instances); + $this->updated = true; // So that we don't go through this more than once + } + + // Here we echo out the form + if ( -1 == $widget_args['number'] ) { + // We echo out a template for a form which can be converted to a + // specific form later via JS + $this->_set('%i%'); + $instance = array(); + } else { + $this->_set($widget_args['number']); + $instance = $all_instances[ $widget_args['number'] ]; + } + $this->form($instance); + } + + /** Helper function: Registers a single instance. */ + function _register_one($number = -1) { + wp_register_sidebar_widget( $this->id, $this->name, $this->_get_display_callback(), $this->widget_options, array( 'number' => $number ) ); + wp_register_widget_control( $this->id, $this->name, $this->_get_control_callback(), $this->control_options, array( 'number' => $number ) ); + } + +} + ?> diff --git a/wp-includes/widgets.php b/wp-includes/widgets.php index 2a6971491..1229cf2c4 100644 --- a/wp-includes/widgets.php +++ b/wp-includes/widgets.php @@ -739,68 +739,71 @@ function wp_widget_pages_control() { } /** - * Display links widget. - * - * @since 2.2.0 - * - * @param array $args Widget arguments. - */ -function wp_widget_links($args) { - extract($args, EXTR_SKIP); - - $link_options = get_option('widget_links'); - $show_description = isset($link_options['description']) ? $link_options['description'] : false; - $show_name = isset($link_options['name']) ? $link_options['name'] : false; - $show_rating = isset($link_options['rating']) ? $link_options['rating'] : false; - $show_images = isset($link_options['images']) ? $link_options['images'] : true; - - $before_widget = preg_replace('/id="[^"]*"/','id="%id"', $before_widget); - wp_list_bookmarks(apply_filters('widget_links_args', array( - 'title_before' => $before_title, 'title_after' => $after_title, - 'category_before' => $before_widget, 'category_after' => $after_widget, - 'show_images' => $show_images, 'show_description' => $show_description, - 'show_name' => $show_name, 'show_rating' => $show_rating, - 'class' => 'linkcat widget' - ))); -} - -/** - * Display and process links widget options form. + * Links widget class * * @since 2.8.0 */ -function wp_widget_links_control() { - $options = $newoptions = get_option('widget_links'); +class WP_Widget_Links extends WP_Widgets { + + function widget( $args, $instance ) { + extract($args, EXTR_SKIP); - //Defaults - if ( ! $newoptions ) - $newoptions = array( 'images' => true, 'name' => true, 'description' => false, 'rating' => false); + $show_description = isset($instance['description']) ? $instance['description'] : false; + $show_name = isset($instance['name']) ? $instance['name'] : false; + $show_rating = isset($instance['rating']) ? $instance['rating'] : false; + $show_images = isset($instance['images']) ? $instance['images'] : true; + + $before_widget = preg_replace('/id="[^"]*"/','id="%id"', $before_widget); + wp_list_bookmarks(apply_filters('widget_links_args', array( + 'title_before' => $before_title, 'title_after' => $after_title, + 'category_before' => $before_widget, 'category_after' => $after_widget, + 'show_images' => $show_images, 'show_description' => $show_description, + 'show_name' => $show_name, 'show_rating' => $show_rating, + 'class' => 'linkcat widget' + ))); + } + + function update( $new_instance, $old_instance ) { + if( !isset($new_instance['submit']) ) // user clicked cancel? + return false; - if ( isset($_POST['links-submit']) ) { - $newoptions['description'] = isset($_POST['links-description']); - $newoptions['name'] = isset($_POST['links-name']); - $newoptions['rating'] = isset($_POST['links-rating']); - $newoptions['images'] = isset($_POST['links-images']); - } - if ( $options != $newoptions ) { - $options = $newoptions; - update_option('widget_links', $options); + return $new_instance; } + + function form( $instance ) { + + //Defaults + $instance = wp_parse_args( (array) $instance, array( 'images' => true, 'name' => true, 'description' => false, 'rating' => false) ); +/* + if ( isset($_POST['links-submit']) ) { + $newoptions = array(); + $newoptions['description'] = isset($_POST['links-description']); + $newoptions['name'] = isset($_POST['links-name']); + $newoptions['rating'] = isset($_POST['links-rating']); + $newoptions['images'] = isset($_POST['links-images']); + + if ( $instance != $newoptions ) { + $instance = $newoptions; + update_option('widget_links', $instance); + } + } +*/ ?> -

- -
- -
- -
- -

- +

+
+
+
+ + +

'widget_links', 'description' => __( "Your blogroll") ); - wp_register_sidebar_widget('links', __('Links'), 'wp_widget_links', $widget_ops); - wp_register_widget_control('links', __('Links'), 'wp_widget_links_control' ); + $widget_ops = array('description' => __( "Your blogroll" ) ); + $wp_widget_links = new WP_Widget_Links('links', __('Links'), $widget_ops); + $wp_widget_links->register(); $widget_ops = array('classname' => 'widget_meta', 'description' => __( "Log in/out, admin, feed and WordPress links") ); wp_register_sidebar_widget('meta', __('Meta'), 'wp_widget_meta', $widget_ops);