[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Widget API: WP_Widget base class 4 * 5 * @package WordPress 6 * @subpackage Widgets 7 * @since 4.4.0 8 */ 9 10 /** 11 * Core base class extended to register widgets. 12 * 13 * This class must be extended for each widget, and WP_Widget::widget() must be overridden. 14 * 15 * If adding widget options, WP_Widget::update() and WP_Widget::form() should also be overridden. 16 * 17 * @since 2.8.0 18 * @since 4.4.0 Moved to its own file from wp-includes/widgets.php 19 */ 20 class WP_Widget { 21 22 /** 23 * Root ID for all widgets of this type. 24 * 25 * @since 2.8.0 26 * @var mixed|string 27 */ 28 public $id_base; 29 30 /** 31 * Name for this widget type. 32 * 33 * @since 2.8.0 34 * @var string 35 */ 36 public $name; 37 38 /** 39 * Option name for this widget type. 40 * 41 * @since 2.8.0 42 * @var string 43 */ 44 public $option_name; 45 46 /** 47 * Alt option name for this widget type. 48 * 49 * @since 2.8.0 50 * @var string 51 */ 52 public $alt_option_name; 53 54 /** 55 * Option array passed to wp_register_sidebar_widget(). 56 * 57 * @since 2.8.0 58 * @var array 59 */ 60 public $widget_options; 61 62 /** 63 * Option array passed to wp_register_widget_control(). 64 * 65 * @since 2.8.0 66 * @var array 67 */ 68 public $control_options; 69 70 /** 71 * Unique ID number of the current instance. 72 * 73 * @since 2.8.0 74 * @var bool|int 75 */ 76 public $number = false; 77 78 /** 79 * Unique ID string of the current instance (id_base-number). 80 * 81 * @since 2.8.0 82 * @var bool|string 83 */ 84 public $id = false; 85 86 /** 87 * Whether the widget data has been updated. 88 * 89 * Set to true when the data is updated after a POST submit - ensures it does 90 * not happen twice. 91 * 92 * @since 2.8.0 93 * @var bool 94 */ 95 public $updated = false; 96 97 // 98 // Member functions that must be overridden by subclasses. 99 // 100 101 /** 102 * Echoes the widget content. 103 * 104 * Subclasses should override this function to generate their widget code. 105 * 106 * @since 2.8.0 107 * 108 * @param array $args Display arguments including 'before_title', 'after_title', 109 * 'before_widget', and 'after_widget'. 110 * @param array $instance The settings for the particular instance of the widget. 111 */ 112 public function widget( $args, $instance ) { 113 die( 'function WP_Widget::widget() must be overridden in a subclass.' ); 114 } 115 116 /** 117 * Updates a particular instance of a widget. 118 * 119 * This function should check that `$new_instance` is set correctly. The newly-calculated 120 * value of `$instance` should be returned. If false is returned, the instance won't be 121 * saved/updated. 122 * 123 * @since 2.8.0 124 * 125 * @param array $new_instance New settings for this instance as input by the user via 126 * WP_Widget::form(). 127 * @param array $old_instance Old settings for this instance. 128 * @return array Settings to save or bool false to cancel saving. 129 */ 130 public function update( $new_instance, $old_instance ) { 131 return $new_instance; 132 } 133 134 /** 135 * Outputs the settings update form. 136 * 137 * @since 2.8.0 138 * 139 * @param array $instance Current settings. 140 * @return string Default return is 'noform'. 141 */ 142 public function form( $instance ) { 143 echo '<p class="no-options-widget">' . __( 'There are no options for this widget.' ) . '</p>'; 144 return 'noform'; 145 } 146 147 // Functions you'll need to call. 148 149 /** 150 * PHP5 constructor. 151 * 152 * @since 2.8.0 153 * 154 * @param string $id_base Optional. Base ID for the widget, lowercase and unique. If left empty, 155 * a portion of the widget's class name will be used. Has to be unique. 156 * @param string $name Name for the widget displayed on the configuration page. 157 * @param array $widget_options Optional. Widget options. See wp_register_sidebar_widget() for 158 * information on accepted arguments. Default empty array. 159 * @param array $control_options Optional. Widget control options. See wp_register_widget_control() for 160 * information on accepted arguments. Default empty array. 161 */ 162 public function __construct( $id_base, $name, $widget_options = array(), $control_options = array() ) { 163 $this->id_base = empty( $id_base ) ? preg_replace( '/(wp_)?widget_/', '', strtolower( get_class( $this ) ) ) : strtolower( $id_base ); 164 $this->name = $name; 165 $this->option_name = 'widget_' . $this->id_base; 166 $this->widget_options = wp_parse_args( 167 $widget_options, 168 array( 169 'classname' => $this->option_name, 170 'customize_selective_refresh' => false, 171 ) 172 ); 173 $this->control_options = wp_parse_args( $control_options, array( 'id_base' => $this->id_base ) ); 174 } 175 176 /** 177 * PHP4 constructor. 178 * 179 * @since 2.8.0 180 * @deprecated 4.3.0 Use __construct() instead. 181 * 182 * @see WP_Widget::__construct() 183 * 184 * @param string $id_base Optional. Base ID for the widget, lowercase and unique. If left empty, 185 * a portion of the widget's class name will be used. Has to be unique. 186 * @param string $name Name for the widget displayed on the configuration page. 187 * @param array $widget_options Optional. Widget options. See wp_register_sidebar_widget() for 188 * information on accepted arguments. Default empty array. 189 * @param array $control_options Optional. Widget control options. See wp_register_widget_control() for 190 * information on accepted arguments. Default empty array. 191 */ 192 public function WP_Widget( $id_base, $name, $widget_options = array(), $control_options = array() ) { 193 _deprecated_constructor( 'WP_Widget', '4.3.0', get_class( $this ) ); 194 WP_Widget::__construct( $id_base, $name, $widget_options, $control_options ); 195 } 196 197 /** 198 * Constructs name attributes for use in form() fields 199 * 200 * This function should be used in form() methods to create name attributes for fields 201 * to be saved by update() 202 * 203 * @since 2.8.0 204 * @since 4.4.0 Array format field names are now accepted. 205 * 206 * @param string $field_name Field name 207 * @return string Name attribute for $field_name 208 */ 209 public function get_field_name( $field_name ) { 210 $pos = strpos( $field_name, '[' ); 211 if ( false === $pos ) { 212 return 'widget-' . $this->id_base . '[' . $this->number . '][' . $field_name . ']'; 213 } else { 214 return 'widget-' . $this->id_base . '[' . $this->number . '][' . substr_replace( $field_name, '][', $pos, strlen( '[' ) ); 215 } 216 } 217 218 /** 219 * Constructs id attributes for use in WP_Widget::form() fields. 220 * 221 * This function should be used in form() methods to create id attributes 222 * for fields to be saved by WP_Widget::update(). 223 * 224 * @since 2.8.0 225 * @since 4.4.0 Array format field IDs are now accepted. 226 * 227 * @param string $field_name Field name. 228 * @return string ID attribute for `$field_name`. 229 */ 230 public function get_field_id( $field_name ) { 231 return 'widget-' . $this->id_base . '-' . $this->number . '-' . trim( str_replace( array( '[]', '[', ']' ), array( '', '-', '' ), $field_name ), '-' ); 232 } 233 234 /** 235 * Register all widget instances of this widget class. 236 * 237 * @since 2.8.0 238 */ 239 public function _register() { 240 $settings = $this->get_settings(); 241 $empty = true; 242 243 // When $settings is an array-like object, get an intrinsic array for use with array_keys(). 244 if ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) { 245 $settings = $settings->getArrayCopy(); 246 } 247 248 if ( is_array( $settings ) ) { 249 foreach ( array_keys( $settings ) as $number ) { 250 if ( is_numeric( $number ) ) { 251 $this->_set( $number ); 252 $this->_register_one( $number ); 253 $empty = false; 254 } 255 } 256 } 257 258 if ( $empty ) { 259 // If there are none, we register the widget's existence with a generic template. 260 $this->_set( 1 ); 261 $this->_register_one(); 262 } 263 } 264 265 /** 266 * Sets the internal order number for the widget instance. 267 * 268 * @since 2.8.0 269 * 270 * @param int $number The unique order number of this widget instance compared to other 271 * instances of the same class. 272 */ 273 public function _set( $number ) { 274 $this->number = $number; 275 $this->id = $this->id_base . '-' . $number; 276 } 277 278 /** 279 * Retrieves the widget display callback. 280 * 281 * @since 2.8.0 282 * 283 * @return callable Display callback. 284 */ 285 public function _get_display_callback() { 286 return array( $this, 'display_callback' ); 287 } 288 289 /** 290 * Retrieves the widget update callback. 291 * 292 * @since 2.8.0 293 * 294 * @return callable Update callback. 295 */ 296 public function _get_update_callback() { 297 return array( $this, 'update_callback' ); 298 } 299 300 /** 301 * Retrieves the form callback. 302 * 303 * @since 2.8.0 304 * 305 * @return callable Form callback. 306 */ 307 public function _get_form_callback() { 308 return array( $this, 'form_callback' ); 309 } 310 311 /** 312 * Determines whether the current request is inside the Customizer preview. 313 * 314 * If true -- the current request is inside the Customizer preview, then 315 * the object cache gets suspended and widgets should check this to decide 316 * whether they should store anything persistently to the object cache, 317 * to transients, or anywhere else. 318 * 319 * @since 3.9.0 320 * 321 * @global WP_Customize_Manager $wp_customize 322 * 323 * @return bool True if within the Customizer preview, false if not. 324 */ 325 public function is_preview() { 326 global $wp_customize; 327 return ( isset( $wp_customize ) && $wp_customize->is_preview() ); 328 } 329 330 /** 331 * Generates the actual widget content (Do NOT override). 332 * 333 * Finds the instance and calls WP_Widget::widget(). 334 * 335 * @since 2.8.0 336 * 337 * @param array $args Display arguments. See WP_Widget::widget() for information 338 * on accepted arguments. 339 * @param int|array $widget_args { 340 * Optional. Internal order number of the widget instance, or array of multi-widget arguments. 341 * Default 1. 342 * 343 * @type int $number Number increment used for multiples of the same widget. 344 * } 345 */ 346 public function display_callback( $args, $widget_args = 1 ) { 347 if ( is_numeric( $widget_args ) ) { 348 $widget_args = array( 'number' => $widget_args ); 349 } 350 351 $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) ); 352 $this->_set( $widget_args['number'] ); 353 $instances = $this->get_settings(); 354 355 if ( array_key_exists( $this->number, $instances ) ) { 356 $instance = $instances[ $this->number ]; 357 358 /** 359 * Filters the settings for a particular widget instance. 360 * 361 * Returning false will effectively short-circuit display of the widget. 362 * 363 * @since 2.8.0 364 * 365 * @param array $instance The current widget instance's settings. 366 * @param WP_Widget $widget The current widget instance. 367 * @param array $args An array of default widget arguments. 368 */ 369 $instance = apply_filters( 'widget_display_callback', $instance, $this, $args ); 370 371 if ( false === $instance ) { 372 return; 373 } 374 375 $was_cache_addition_suspended = wp_suspend_cache_addition(); 376 if ( $this->is_preview() && ! $was_cache_addition_suspended ) { 377 wp_suspend_cache_addition( true ); 378 } 379 380 $this->widget( $args, $instance ); 381 382 if ( $this->is_preview() ) { 383 wp_suspend_cache_addition( $was_cache_addition_suspended ); 384 } 385 } 386 } 387 388 /** 389 * Handles changed settings (Do NOT override). 390 * 391 * @since 2.8.0 392 * 393 * @global array $wp_registered_widgets 394 * 395 * @param int $deprecated Not used. 396 */ 397 public function update_callback( $deprecated = 1 ) { 398 global $wp_registered_widgets; 399 400 $all_instances = $this->get_settings(); 401 402 // We need to update the data. 403 if ( $this->updated ) { 404 return; 405 } 406 407 if ( isset( $_POST['delete_widget'] ) && $_POST['delete_widget'] ) { 408 // Delete the settings for this instance of the widget. 409 if ( isset( $_POST['the-widget-id'] ) ) { 410 $del_id = $_POST['the-widget-id']; 411 } else { 412 return; 413 } 414 415 if ( isset( $wp_registered_widgets[ $del_id ]['params'][0]['number'] ) ) { 416 $number = $wp_registered_widgets[ $del_id ]['params'][0]['number']; 417 418 if ( $this->id_base . '-' . $number == $del_id ) { 419 unset( $all_instances[ $number ] ); 420 } 421 } 422 } else { 423 if ( isset( $_POST[ 'widget-' . $this->id_base ] ) && is_array( $_POST[ 'widget-' . $this->id_base ] ) ) { 424 $settings = $_POST[ 'widget-' . $this->id_base ]; 425 } elseif ( isset( $_POST['id_base'] ) && $_POST['id_base'] == $this->id_base ) { 426 $num = $_POST['multi_number'] ? (int) $_POST['multi_number'] : (int) $_POST['widget_number']; 427 $settings = array( $num => array() ); 428 } else { 429 return; 430 } 431 432 foreach ( $settings as $number => $new_instance ) { 433 $new_instance = stripslashes_deep( $new_instance ); 434 $this->_set( $number ); 435 436 $old_instance = isset( $all_instances[ $number ] ) ? $all_instances[ $number ] : array(); 437 438 $was_cache_addition_suspended = wp_suspend_cache_addition(); 439 if ( $this->is_preview() && ! $was_cache_addition_suspended ) { 440 wp_suspend_cache_addition( true ); 441 } 442 443 $instance = $this->update( $new_instance, $old_instance ); 444 445 if ( $this->is_preview() ) { 446 wp_suspend_cache_addition( $was_cache_addition_suspended ); 447 } 448 449 /** 450 * Filters a widget's settings before saving. 451 * 452 * Returning false will effectively short-circuit the widget's ability 453 * to update settings. 454 * 455 * @since 2.8.0 456 * 457 * @param array $instance The current widget instance's settings. 458 * @param array $new_instance Array of new widget settings. 459 * @param array $old_instance Array of old widget settings. 460 * @param WP_Widget $widget The current widget instance. 461 */ 462 $instance = apply_filters( 'widget_update_callback', $instance, $new_instance, $old_instance, $this ); 463 if ( false !== $instance ) { 464 $all_instances[ $number ] = $instance; 465 } 466 467 break; // Run only once. 468 } 469 } 470 471 $this->save_settings( $all_instances ); 472 $this->updated = true; 473 } 474 475 /** 476 * Generates the widget control form (Do NOT override). 477 * 478 * @since 2.8.0 479 * 480 * @param int|array $widget_args { 481 * Optional. Internal order number of the widget instance, or array of multi-widget arguments. 482 * Default 1. 483 * 484 * @type int $number Number increment used for multiples of the same widget. 485 * } 486 * @return string|null 487 */ 488 public function form_callback( $widget_args = 1 ) { 489 if ( is_numeric( $widget_args ) ) { 490 $widget_args = array( 'number' => $widget_args ); 491 } 492 493 $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) ); 494 $all_instances = $this->get_settings(); 495 496 if ( -1 == $widget_args['number'] ) { 497 // We echo out a form where 'number' can be set later. 498 $this->_set( '__i__' ); 499 $instance = array(); 500 } else { 501 $this->_set( $widget_args['number'] ); 502 $instance = $all_instances[ $widget_args['number'] ]; 503 } 504 505 /** 506 * Filters the widget instance's settings before displaying the control form. 507 * 508 * Returning false effectively short-circuits display of the control form. 509 * 510 * @since 2.8.0 511 * 512 * @param array $instance The current widget instance's settings. 513 * @param WP_Widget $widget The current widget instance. 514 */ 515 $instance = apply_filters( 'widget_form_callback', $instance, $this ); 516 517 $return = null; 518 if ( false !== $instance ) { 519 $return = $this->form( $instance ); 520 521 /** 522 * Fires at the end of the widget control form. 523 * 524 * Use this hook to add extra fields to the widget form. The hook 525 * is only fired if the value passed to the 'widget_form_callback' 526 * hook is not false. 527 * 528 * Note: If the widget has no form, the text echoed from the default 529 * form method can be hidden using CSS. 530 * 531 * @since 2.8.0 532 * 533 * @param WP_Widget $widget The widget instance (passed by reference). 534 * @param null $return Return null if new fields are added. 535 * @param array $instance An array of the widget's settings. 536 */ 537 do_action_ref_array( 'in_widget_form', array( &$this, &$return, $instance ) ); 538 } 539 return $return; 540 } 541 542 /** 543 * Registers an instance of the widget class. 544 * 545 * @since 2.8.0 546 * 547 * @param int $number Optional. The unique order number of this widget instance 548 * compared to other instances of the same class. Default -1. 549 */ 550 public function _register_one( $number = -1 ) { 551 wp_register_sidebar_widget( $this->id, $this->name, $this->_get_display_callback(), $this->widget_options, array( 'number' => $number ) ); 552 _register_widget_update_callback( $this->id_base, $this->_get_update_callback(), $this->control_options, array( 'number' => -1 ) ); 553 _register_widget_form_callback( $this->id, $this->name, $this->_get_form_callback(), $this->control_options, array( 'number' => $number ) ); 554 } 555 556 /** 557 * Saves the settings for all instances of the widget class. 558 * 559 * @since 2.8.0 560 * 561 * @param array $settings Multi-dimensional array of widget instance settings. 562 */ 563 public function save_settings( $settings ) { 564 $settings['_multiwidget'] = 1; 565 update_option( $this->option_name, $settings ); 566 } 567 568 /** 569 * Retrieves the settings for all instances of the widget class. 570 * 571 * @since 2.8.0 572 * 573 * @return array Multi-dimensional array of widget instance settings. 574 */ 575 public function get_settings() { 576 577 $settings = get_option( $this->option_name ); 578 579 if ( false === $settings ) { 580 if ( isset( $this->alt_option_name ) ) { 581 $settings = get_option( $this->alt_option_name ); 582 } else { 583 // Save an option so it can be autoloaded next time. 584 $this->save_settings( array() ); 585 } 586 } 587 588 if ( ! is_array( $settings ) && ! ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) ) { 589 $settings = array(); 590 } 591 592 if ( ! empty( $settings ) && ! isset( $settings['_multiwidget'] ) ) { 593 // Old format, convert if single widget. 594 $settings = wp_convert_widget_settings( $this->id_base, $this->option_name, $settings ); 595 } 596 597 unset( $settings['_multiwidget'], $settings['__i__'] ); 598 return $settings; 599 } 600 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Mar 1 01:00:03 2021 | Cross-referenced by PHPXref 0.7.1 |