WordPress.org

Make WordPress Core


Ignore:
Timestamp:
08/26/2015 02:39:50 AM (6 years ago)
Author:
wonderboymusic
Message:

Widgets: move classes into their own files, widgets.php loads the new files, so this is 100% BC if someone is loading widgets.php directly. New files created using svn cp.

Creates:
class-wp-widget.php
class-wp-widget-factory.php
widget-functions.php

widgets.php contains only top-level code. Class files only contain classes. Functions file only contains functions.

See #33413.

File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/widget-functions.php

    r33745 r33746  
    11<?php
    22/**
    3  * API for creating dynamic sidebar without hardcoding functionality into
    4  * themes. Includes both internal WordPress routines and theme use routines.
    5  *
    6  * This functionality was found in a plugin before WordPress 2.2 release which
    7  * included it in the core from that point on.
    8  *
    9  * @link https://codex.wordpress.org/Plugins/WordPress_Widgets WordPress Widgets
    10  * @link https://codex.wordpress.org/Plugins/WordPress_Widgets_Api Widgets API
    11  *
    123 * @package WordPress
    134 * @subpackage Widgets
    145 */
    15 
    16 /**
    17  * This class must be extended for each widget and WP_Widget::widget(), WP_Widget::update()
    18  * and WP_Widget::form() need to be over-ridden.
    19  *
    20  * @package WordPress
    21  * @subpackage Widgets
    22  * @since 2.8.0
    23  */
    24 class WP_Widget {
    25 
    26     /**
    27      * Root ID for all widgets of this type.
    28      *
    29      * @since 2.8.0
    30      * @access public
    31      * @var mixed|string
    32      */
    33     public $id_base;
    34 
    35     /**
    36      * Name for this widget type.
    37      *
    38      * @since 2.8.0
    39      * @access public
    40      * @var string
    41      */
    42     public $name;
    43 
    44     /**
    45      * Option array passed to {@see wp_register_sidebar_widget()}.
    46      *
    47      * @since 2.8.0
    48      * @access public
    49      * @var array
    50      */
    51     public $widget_options;
    52 
    53     /**
    54      * Option array passed to {@see wp_register_widget_control()}.
    55      *
    56      * @since 2.8.0
    57      * @access public
    58      * @var array
    59      */
    60     public $control_options;
    61 
    62     /**
    63      * Unique ID number of the current instance.
    64      *
    65      * @since 2.8.0
    66      * @access public
    67      * @var bool|int
    68      */
    69     public $number = false;
    70 
    71     /**
    72      * Unique ID string of the current instance (id_base-number).
    73      *
    74      * @since 2.8.0
    75      * @access public
    76      * @var bool|string
    77      */
    78     public $id = false;
    79 
    80     /**
    81      * Whether the widget data has been updated.
    82      *
    83      * Set to true when the data is updated after a POST submit - ensures it does
    84      * not happen twice.
    85      *
    86      * @since 2.8.0
    87      * @access public
    88      * @var bool
    89      */
    90     public $updated = false;
    91 
    92     // Member functions that you must over-ride.
    93 
    94     /**
    95      * Echo the widget content.
    96      *
    97      * Subclasses should over-ride this function to generate their widget code.
    98      *
    99      * @since 2.8.0
    100      * @access public
    101      *
    102      * @param array $args     Display arguments including before_title, after_title,
    103      *                        before_widget, and after_widget.
    104      * @param array $instance The settings for the particular instance of the widget.
    105      */
    106     public function widget( $args, $instance ) {
    107         die('function WP_Widget::widget() must be over-ridden in a sub-class.');
    108     }
    109 
    110     /**
    111      * Update a particular instance.
    112      *
    113      * This function should check that $new_instance is set correctly. The newly-calculated
    114      * value of `$instance` should be returned. If false is returned, the instance won't be
    115      * saved/updated.
    116      *
    117      * @since 2.8.0
    118      * @access public
    119      *
    120      * @param array $new_instance New settings for this instance as input by the user via
    121      *                            {@see WP_Widget::form()}.
    122      * @param array $old_instance Old settings for this instance.
    123      * @return array Settings to save or bool false to cancel saving.
    124      */
    125     public function update( $new_instance, $old_instance ) {
    126         return $new_instance;
    127     }
    128 
    129     /**
    130      * Output the settings update form.
    131      *
    132      * @since 2.8.0
    133      * @access public
    134      *
    135      * @param array $instance Current settings.
    136      * @return string Default return is 'noform'.
    137      */
    138     public function form($instance) {
    139         echo '<p class="no-options-widget">' . __('There are no options for this widget.') . '</p>';
    140         return 'noform';
    141     }
    142 
    143     // Functions you'll need to call.
    144 
    145     /**
    146      * PHP5 constructor.
    147      *
    148      * @since 2.8.0
    149      * @access public
    150      *
    151      * @param string $id_base         Optional Base ID for the widget, lowercase and unique. If left empty,
    152      *                                a portion of the widget's class name will be used Has to be unique.
    153      * @param string $name            Name for the widget displayed on the configuration page.
    154      * @param array  $widget_options  Optional. Widget options. See {@see wp_register_sidebar_widget()} for
    155      *                                information on accepted arguments. Default empty array.
    156      * @param array  $control_options Optional. Widget control options. See {@see wp_register_widget_control()}
    157      *                                for information on accepted arguments. Default empty array.
    158      */
    159     public function __construct( $id_base, $name, $widget_options = array(), $control_options = array() ) {
    160         $this->id_base = empty($id_base) ? preg_replace( '/(wp_)?widget_/', '', strtolower(get_class($this)) ) : strtolower($id_base);
    161         $this->name = $name;
    162         $this->option_name = 'widget_' . $this->id_base;
    163         $this->widget_options = wp_parse_args( $widget_options, array('classname' => $this->option_name) );
    164         $this->control_options = wp_parse_args( $control_options, array('id_base' => $this->id_base) );
    165     }
    166 
    167     /**
    168      * PHP4 constructor
    169      *
    170      * @param string $id_base
    171      * @param string $name
    172      * @param array  $widget_options
    173      * @param array  $control_options
    174      */
    175     public function WP_Widget( $id_base, $name, $widget_options = array(), $control_options = array() ) {
    176         _deprecated_constructor( 'WP_Widget', '4.3.0' );
    177         WP_Widget::__construct( $id_base, $name, $widget_options, $control_options );
    178     }
    179 
    180     /**
    181      * Constructs name attributes for use in form() fields
    182      *
    183      * This function should be used in form() methods to create name attributes for fields to be saved by update()
    184      *
    185      * @param string $field_name Field name
    186      * @return string Name attribute for $field_name
    187      */
    188     public function get_field_name($field_name) {
    189         return 'widget-' . $this->id_base . '[' . $this->number . '][' . $field_name . ']';
    190     }
    191 
    192     /**
    193      * Constructs id attributes for use in {@see WP_Widget::form()} fields.
    194      *
    195      * This function should be used in form() methods to create id attributes
    196      * for fields to be saved by {@see WP_Widget::update()}.
    197      *
    198      * @since 2.8.0
    199      * @access public
    200      *
    201      * @param string $field_name Field name.
    202      * @return string ID attribute for `$field_name`.
    203      */
    204     public function get_field_id( $field_name ) {
    205         return 'widget-' . $this->id_base . '-' . $this->number . '-' . $field_name;
    206     }
    207 
    208     /**
    209      * Register all widget instances of this widget class.
    210      *
    211      * @since 2.8.0
    212      * @access private
    213      */
    214     public function _register() {
    215         $settings = $this->get_settings();
    216         $empty = true;
    217 
    218         // When $settings is an array-like object, get an intrinsic array for use with array_keys().
    219         if ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) {
    220             $settings = $settings->getArrayCopy();
    221         }
    222 
    223         if ( is_array( $settings ) ) {
    224             foreach ( array_keys( $settings ) as $number ) {
    225                 if ( is_numeric( $number ) ) {
    226                     $this->_set( $number );
    227                     $this->_register_one( $number );
    228                     $empty = false;
    229                 }
    230             }
    231         }
    232 
    233         if ( $empty ) {
    234             // If there are none, we register the widget's existence with a generic template.
    235             $this->_set( 1 );
    236             $this->_register_one();
    237         }
    238     }
    239 
    240     /**
    241      * Set the internal order number for the widget instance.
    242      *
    243      * @since 2.8.0
    244      * @access private
    245      *
    246      * @param int $number The unique order number of this widget instance compared to other
    247      *                    instances of the same class.
    248      */
    249     public function _set($number) {
    250         $this->number = $number;
    251         $this->id = $this->id_base . '-' . $number;
    252     }
    253 
    254     /**
    255      * @return callback
    256      */
    257     public function _get_display_callback() {
    258         return array($this, 'display_callback');
    259     }
    260     /**
    261      * @return callback
    262      */
    263     public function _get_update_callback() {
    264         return array($this, 'update_callback');
    265     }
    266     /**
    267      * @return callback
    268      */
    269     public function _get_form_callback() {
    270         return array($this, 'form_callback');
    271     }
    272 
    273     /**
    274      * Determine whether the current request is inside the Customizer preview.
    275      *
    276      * If true -- the current request is inside the Customizer preview, then
    277      * the object cache gets suspended and widgets should check this to decide
    278      * whether they should store anything persistently to the object cache,
    279      * to transients, or anywhere else.
    280      *
    281      * @since 3.9.0
    282      * @access public
    283      *
    284      * @global WP_Customize_Manager $wp_customize
    285      *
    286      * @return bool True if within the Customizer preview, false if not.
    287      */
    288     public function is_preview() {
    289         global $wp_customize;
    290         return ( isset( $wp_customize ) && $wp_customize->is_preview() ) ;
    291     }
    292 
    293     /**
    294      * Generate the actual widget content (Do NOT override).
    295      *
    296      * Finds the instance and calls {@see WP_Widget::widget()}.
    297      *
    298      * @since 2.8.0
    299      * @access public
    300      *
    301      * @param array     $args        Display arguments. See {@see WP_Widget::widget()} for information
    302      *                               on accepted arguments.
    303      * @param int|array $widget_args {
    304      *     Optional. Internal order number of the widget instance, or array of multi-widget arguments.
    305      *     Default 1.
    306      *
    307      *     @type int $number Number increment used for multiples of the same widget.
    308      * }
    309      */
    310     public function display_callback( $args, $widget_args = 1 ) {
    311         if ( is_numeric( $widget_args ) ) {
    312             $widget_args = array( 'number' => $widget_args );
    313         }
    314 
    315         $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
    316         $this->_set( $widget_args['number'] );
    317         $instances = $this->get_settings();
    318 
    319         if ( array_key_exists( $this->number, $instances ) ) {
    320             $instance = $instances[ $this->number ];
    321 
    322             /**
    323              * Filter the settings for a particular widget instance.
    324              *
    325              * Returning false will effectively short-circuit display of the widget.
    326              *
    327              * @since 2.8.0
    328              *
    329              * @param array     $instance The current widget instance's settings.
    330              * @param WP_Widget $this     The current widget instance.
    331              * @param array     $args     An array of default widget arguments.
    332              */
    333             $instance = apply_filters( 'widget_display_callback', $instance, $this, $args );
    334 
    335             if ( false === $instance ) {
    336                 return;
    337             }
    338 
    339             $was_cache_addition_suspended = wp_suspend_cache_addition();
    340             if ( $this->is_preview() && ! $was_cache_addition_suspended ) {
    341                 wp_suspend_cache_addition( true );
    342             }
    343 
    344             $this->widget( $args, $instance );
    345 
    346             if ( $this->is_preview() ) {
    347                 wp_suspend_cache_addition( $was_cache_addition_suspended );
    348             }
    349         }
    350     }
    351 
    352     /**
    353      * Deal with changed settings (Do NOT override).
    354      *
    355      * @since 2.8.0
    356      * @access public
    357      *
    358      * @global array $wp_registered_widgets
    359      *
    360      * @param int $deprecated Not used.
    361      */
    362     public function update_callback( $deprecated = 1 ) {
    363         global $wp_registered_widgets;
    364 
    365         $all_instances = $this->get_settings();
    366 
    367         // We need to update the data
    368         if ( $this->updated )
    369             return;
    370 
    371         if ( isset($_POST['delete_widget']) && $_POST['delete_widget'] ) {
    372             // Delete the settings for this instance of the widget
    373             if ( isset($_POST['the-widget-id']) )
    374                 $del_id = $_POST['the-widget-id'];
    375             else
    376                 return;
    377 
    378             if ( isset($wp_registered_widgets[$del_id]['params'][0]['number']) ) {
    379                 $number = $wp_registered_widgets[$del_id]['params'][0]['number'];
    380 
    381                 if ( $this->id_base . '-' . $number == $del_id )
    382                     unset($all_instances[$number]);
    383             }
    384         } else {
    385             if ( isset($_POST['widget-' . $this->id_base]) && is_array($_POST['widget-' . $this->id_base]) ) {
    386                 $settings = $_POST['widget-' . $this->id_base];
    387             } elseif ( isset($_POST['id_base']) && $_POST['id_base'] == $this->id_base ) {
    388                 $num = $_POST['multi_number'] ? (int) $_POST['multi_number'] : (int) $_POST['widget_number'];
    389                 $settings = array( $num => array() );
    390             } else {
    391                 return;
    392             }
    393 
    394             foreach ( $settings as $number => $new_instance ) {
    395                 $new_instance = stripslashes_deep($new_instance);
    396                 $this->_set($number);
    397 
    398                 $old_instance = isset($all_instances[$number]) ? $all_instances[$number] : array();
    399 
    400                 $was_cache_addition_suspended = wp_suspend_cache_addition();
    401                 if ( $this->is_preview() && ! $was_cache_addition_suspended ) {
    402                     wp_suspend_cache_addition( true );
    403                 }
    404 
    405                 $instance = $this->update( $new_instance, $old_instance );
    406 
    407                 if ( $this->is_preview() ) {
    408                     wp_suspend_cache_addition( $was_cache_addition_suspended );
    409                 }
    410 
    411                 /**
    412                  * Filter a widget's settings before saving.
    413                  *
    414                  * Returning false will effectively short-circuit the widget's ability
    415                  * to update settings.
    416                  *
    417                  * @since 2.8.0
    418                  *
    419                  * @param array     $instance     The current widget instance's settings.
    420                  * @param array     $new_instance Array of new widget settings.
    421                  * @param array     $old_instance Array of old widget settings.
    422                  * @param WP_Widget $this         The current widget instance.
    423                  */
    424                 $instance = apply_filters( 'widget_update_callback', $instance, $new_instance, $old_instance, $this );
    425                 if ( false !== $instance ) {
    426                     $all_instances[$number] = $instance;
    427                 }
    428 
    429                 break; // run only once
    430             }
    431         }
    432 
    433         $this->save_settings($all_instances);
    434         $this->updated = true;
    435     }
    436 
    437     /**
    438      * Generate the widget control form (Do NOT override).
    439      *
    440      * @since 2.8.0
    441      * @access public
    442      *
    443      * @param int|array $widget_args Widget instance number or array of widget arguments.
    444      * @return string|null
    445      */
    446     public function form_callback( $widget_args = 1 ) {
    447         if ( is_numeric($widget_args) )
    448             $widget_args = array( 'number' => $widget_args );
    449 
    450         $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
    451         $all_instances = $this->get_settings();
    452 
    453         if ( -1 == $widget_args['number'] ) {
    454             // We echo out a form where 'number' can be set later
    455             $this->_set('__i__');
    456             $instance = array();
    457         } else {
    458             $this->_set($widget_args['number']);
    459             $instance = $all_instances[ $widget_args['number'] ];
    460         }
    461 
    462         /**
    463          * Filter the widget instance's settings before displaying the control form.
    464          *
    465          * Returning false effectively short-circuits display of the control form.
    466          *
    467          * @since 2.8.0
    468          *
    469          * @param array     $instance The current widget instance's settings.
    470          * @param WP_Widget $this     The current widget instance.
    471          */
    472         $instance = apply_filters( 'widget_form_callback', $instance, $this );
    473 
    474         $return = null;
    475         if ( false !== $instance ) {
    476             $return = $this->form($instance);
    477 
    478             /**
    479              * Fires at the end of the widget control form.
    480              *
    481              * Use this hook to add extra fields to the widget form. The hook
    482              * is only fired if the value passed to the 'widget_form_callback'
    483              * hook is not false.
    484              *
    485              * Note: If the widget has no form, the text echoed from the default
    486              * form method can be hidden using CSS.
    487              *
    488              * @since 2.8.0
    489              *
    490              * @param WP_Widget $this     The widget instance, passed by reference.
    491              * @param null      $return   Return null if new fields are added.
    492              * @param array     $instance An array of the widget's settings.
    493              */
    494             do_action_ref_array( 'in_widget_form', array( &$this, &$return, $instance ) );
    495         }
    496         return $return;
    497     }
    498 
    499     /**
    500      * Register an instance of the widget class.
    501      *
    502      * @since 2.8.0
    503      * @access private
    504      *
    505      * @param integer $number Optional. The unique order number of this widget instance
    506      *                        compared to other instances of the same class. Default -1.
    507      */
    508     public function _register_one( $number = -1 ) {
    509         wp_register_sidebar_widget( $this->id, $this->name, $this->_get_display_callback(), $this->widget_options, array( 'number' => $number ) );
    510         _register_widget_update_callback( $this->id_base, $this->_get_update_callback(), $this->control_options, array( 'number' => -1 ) );
    511         _register_widget_form_callback( $this->id, $this->name, $this->_get_form_callback(), $this->control_options, array( 'number' => $number ) );
    512     }
    513 
    514     /**
    515      * Save the settings for all instances of the widget class.
    516      *
    517      * @since 2.8.0
    518      * @access public
    519      *
    520      * @param array $settings Multi-dimensional array of widget instance settings.
    521      */
    522     public function save_settings( $settings ) {
    523         $settings['_multiwidget'] = 1;
    524         update_option( $this->option_name, $settings );
    525     }
    526 
    527     /**
    528      * Get the settings for all instances of the widget class.
    529      *
    530      * @since 2.8.0
    531      * @access public
    532      *
    533      * @return array Multi-dimensional array of widget instance settings.
    534      */
    535     public function get_settings() {
    536 
    537         $settings = get_option( $this->option_name );
    538 
    539         if ( false === $settings && isset( $this->alt_option_name ) ) {
    540             $settings = get_option( $this->alt_option_name );
    541         }
    542 
    543         if ( ! is_array( $settings ) && ! ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) ) {
    544             $settings = array();
    545         }
    546 
    547         if ( ! empty( $settings ) && ! isset( $settings['_multiwidget'] ) ) {
    548             // Old format, convert if single widget.
    549             $settings = wp_convert_widget_settings( $this->id_base, $this->option_name, $settings );
    550         }
    551 
    552         unset( $settings['_multiwidget'], $settings['__i__'] );
    553         return $settings;
    554     }
    555 }
    556 
    557 /**
    558  * Singleton that registers and instantiates WP_Widget classes.
    559  *
    560  * @package WordPress
    561  * @subpackage Widgets
    562  * @since 2.8.0
    563  */
    564 class WP_Widget_Factory {
    565     public $widgets = array();
    566 
    567     /**
    568      * PHP5 constructor.
    569      */
    570     public function __construct() {
    571         add_action( 'widgets_init', array( $this, '_register_widgets' ), 100 );
    572     }
    573 
    574     /**
    575      * PHP4 constructor.
    576      */
    577     public function WP_Widget_Factory() {
    578         _deprecated_constructor( 'WP_Widget_Factory', '4.2.0' );
    579         self::__construct();
    580     }
    581 
    582     /**
    583      * Register a widget subclass.
    584      *
    585      * @since 2.8.0
    586      * @access public
    587      *
    588      * @param string $widget_class The name of a {@see WP_Widget} subclass.
    589      */
    590     public function register( $widget_class ) {
    591         $this->widgets[$widget_class] = new $widget_class();
    592     }
    593 
    594     /**
    595      * Un-register a widget subclass.
    596      *
    597      * @since 2.8.0
    598      * @access public
    599      *
    600      * @param string $widget_class The name of a {@see WP_Widget} subclass.
    601      */
    602     public function unregister( $widget_class ) {
    603         unset( $this->widgets[ $widget_class ] );
    604     }
    605 
    606     /**
    607      * Utility method for adding widgets to the registered widgets global.
    608      *
    609      * @since 2.8.0
    610      * @access public
    611      *
    612      * @global array $wp_registered_widgets
    613      */
    614     public function _register_widgets() {
    615         global $wp_registered_widgets;
    616         $keys = array_keys($this->widgets);
    617         $registered = array_keys($wp_registered_widgets);
    618         $registered = array_map('_get_widget_id_base', $registered);
    619 
    620         foreach ( $keys as $key ) {
    621             // don't register new widget if old widget with the same id is already registered
    622             if ( in_array($this->widgets[$key]->id_base, $registered, true) ) {
    623                 unset($this->widgets[$key]);
    624                 continue;
    625             }
    626 
    627             $this->widgets[$key]->_register();
    628         }
    629     }
    630 }
    631 
    632 /* Global Variables */
    633 
    634 /** @ignore */
    635 global $wp_registered_sidebars, $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_widget_updates;
    636 
    637 /**
    638  * Stores the sidebars, since many themes can have more than one.
    639  *
    640  * @global array $wp_registered_sidebars
    641  * @since 2.2.0
    642  */
    643 $wp_registered_sidebars = array();
    644 
    645 /**
    646  * Stores the registered widgets.
    647  *
    648  * @global array $wp_registered_widgets
    649  * @since 2.2.0
    650  */
    651 $wp_registered_widgets = array();
    652 
    653 /**
    654  * Stores the registered widget control (options).
    655  *
    656  * @global array $wp_registered_widget_controls
    657  * @since 2.2.0
    658  */
    659 $wp_registered_widget_controls = array();
    660 /**
    661  * @global array $wp_registered_widget_updates
    662  */
    663 $wp_registered_widget_updates = array();
    664 
    665 /**
    666  * Private
    667  *
    668  * @global array $_wp_sidebars_widgets
    669  */
    670 $_wp_sidebars_widgets = array();
    671 
    672 /**
    673  * Private
    674  *
    675  * @global array $_wp_deprecated_widgets_callbacks
    676  */
    677 $GLOBALS['_wp_deprecated_widgets_callbacks'] = array(
    678     'wp_widget_pages',
    679     'wp_widget_pages_control',
    680     'wp_widget_calendar',
    681     'wp_widget_calendar_control',
    682     'wp_widget_archives',
    683     'wp_widget_archives_control',
    684     'wp_widget_links',
    685     'wp_widget_meta',
    686     'wp_widget_meta_control',
    687     'wp_widget_search',
    688     'wp_widget_recent_entries',
    689     'wp_widget_recent_entries_control',
    690     'wp_widget_tag_cloud',
    691     'wp_widget_tag_cloud_control',
    692     'wp_widget_categories',
    693     'wp_widget_categories_control',
    694     'wp_widget_text',
    695     'wp_widget_text_control',
    696     'wp_widget_rss',
    697     'wp_widget_rss_control',
    698     'wp_widget_recent_comments',
    699     'wp_widget_recent_comments_control'
    700 );
    7016
    7027/* Template tags & API functions */
Note: See TracChangeset for help on using the changeset viewer.