[ 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 PHP 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 if ( ! empty( $id_base ) ) { 164 $id_base = strtolower( $id_base ); 165 } else { 166 $id_base = preg_replace( '/(wp_)?widget_/', '', strtolower( get_class( $this ) ) ); 167 } 168 169 $this->id_base = $id_base; 170 $this->name = $name; 171 $this->option_name = 'widget_' . $this->id_base; 172 $this->widget_options = wp_parse_args( 173 $widget_options, 174 array( 175 'classname' => str_replace( '\\', '_', $this->option_name ), 176 'customize_selective_refresh' => false, 177 ) 178 ); 179 $this->control_options = wp_parse_args( $control_options, array( 'id_base' => $this->id_base ) ); 180 } 181 182 /** 183 * PHP4 constructor. 184 * 185 * @since 2.8.0 186 * @deprecated 4.3.0 Use __construct() instead. 187 * 188 * @see WP_Widget::__construct() 189 * 190 * @param string $id_base Optional. Base ID for the widget, lowercase and unique. If left empty, 191 * a portion of the widget's PHP class name will be used. Has to be unique. 192 * @param string $name Name for the widget displayed on the configuration page. 193 * @param array $widget_options Optional. Widget options. See wp_register_sidebar_widget() for 194 * information on accepted arguments. Default empty array. 195 * @param array $control_options Optional. Widget control options. See wp_register_widget_control() for 196 * information on accepted arguments. Default empty array. 197 */ 198 public function WP_Widget( $id_base, $name, $widget_options = array(), $control_options = array() ) { 199 _deprecated_constructor( 'WP_Widget', '4.3.0', get_class( $this ) ); 200 WP_Widget::__construct( $id_base, $name, $widget_options, $control_options ); 201 } 202 203 /** 204 * Constructs name attributes for use in form() fields 205 * 206 * This function should be used in form() methods to create name attributes for fields 207 * to be saved by update() 208 * 209 * @since 2.8.0 210 * @since 4.4.0 Array format field names are now accepted. 211 * 212 * @param string $field_name Field name. 213 * @return string Name attribute for `$field_name`. 214 */ 215 public function get_field_name( $field_name ) { 216 $pos = strpos( $field_name, '[' ); 217 218 if ( false !== $pos ) { 219 // Replace the first occurrence of '[' with ']['. 220 $field_name = '[' . substr_replace( $field_name, '][', $pos, strlen( '[' ) ); 221 } else { 222 $field_name = '[' . $field_name . ']'; 223 } 224 225 return 'widget-' . $this->id_base . '[' . $this->number . ']' . $field_name; 226 } 227 228 /** 229 * Constructs id attributes for use in WP_Widget::form() fields. 230 * 231 * This function should be used in form() methods to create id attributes 232 * for fields to be saved by WP_Widget::update(). 233 * 234 * @since 2.8.0 235 * @since 4.4.0 Array format field IDs are now accepted. 236 * 237 * @param string $field_name Field name. 238 * @return string ID attribute for `$field_name`. 239 */ 240 public function get_field_id( $field_name ) { 241 $field_name = str_replace( array( '[]', '[', ']' ), array( '', '-', '' ), $field_name ); 242 $field_name = trim( $field_name, '-' ); 243 244 return 'widget-' . $this->id_base . '-' . $this->number . '-' . $field_name; 245 } 246 247 /** 248 * Register all widget instances of this widget class. 249 * 250 * @since 2.8.0 251 */ 252 public function _register() { 253 $settings = $this->get_settings(); 254 $empty = true; 255 256 // When $settings is an array-like object, get an intrinsic array for use with array_keys(). 257 if ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) { 258 $settings = $settings->getArrayCopy(); 259 } 260 261 if ( is_array( $settings ) ) { 262 foreach ( array_keys( $settings ) as $number ) { 263 if ( is_numeric( $number ) ) { 264 $this->_set( $number ); 265 $this->_register_one( $number ); 266 $empty = false; 267 } 268 } 269 } 270 271 if ( $empty ) { 272 // If there are none, we register the widget's existence with a generic template. 273 $this->_set( 1 ); 274 $this->_register_one(); 275 } 276 } 277 278 /** 279 * Sets the internal order number for the widget instance. 280 * 281 * @since 2.8.0 282 * 283 * @param int $number The unique order number of this widget instance compared to other 284 * instances of the same class. 285 */ 286 public function _set( $number ) { 287 $this->number = $number; 288 $this->id = $this->id_base . '-' . $number; 289 } 290 291 /** 292 * Retrieves the widget display callback. 293 * 294 * @since 2.8.0 295 * 296 * @return callable Display callback. 297 */ 298 public function _get_display_callback() { 299 return array( $this, 'display_callback' ); 300 } 301 302 /** 303 * Retrieves the widget update callback. 304 * 305 * @since 2.8.0 306 * 307 * @return callable Update callback. 308 */ 309 public function _get_update_callback() { 310 return array( $this, 'update_callback' ); 311 } 312 313 /** 314 * Retrieves the form callback. 315 * 316 * @since 2.8.0 317 * 318 * @return callable Form callback. 319 */ 320 public function _get_form_callback() { 321 return array( $this, 'form_callback' ); 322 } 323 324 /** 325 * Determines whether the current request is inside the Customizer preview. 326 * 327 * If true -- the current request is inside the Customizer preview, then 328 * the object cache gets suspended and widgets should check this to decide 329 * whether they should store anything persistently to the object cache, 330 * to transients, or anywhere else. 331 * 332 * @since 3.9.0 333 * 334 * @global WP_Customize_Manager $wp_customize 335 * 336 * @return bool True if within the Customizer preview, false if not. 337 */ 338 public function is_preview() { 339 global $wp_customize; 340 return ( isset( $wp_customize ) && $wp_customize->is_preview() ); 341 } 342 343 /** 344 * Generates the actual widget content (Do NOT override). 345 * 346 * Finds the instance and calls WP_Widget::widget(). 347 * 348 * @since 2.8.0 349 * 350 * @param array $args Display arguments. See WP_Widget::widget() for information 351 * on accepted arguments. 352 * @param int|array $widget_args { 353 * Optional. Internal order number of the widget instance, or array of multi-widget arguments. 354 * Default 1. 355 * 356 * @type int $number Number increment used for multiples of the same widget. 357 * } 358 */ 359 public function display_callback( $args, $widget_args = 1 ) { 360 if ( is_numeric( $widget_args ) ) { 361 $widget_args = array( 'number' => $widget_args ); 362 } 363 364 $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) ); 365 $this->_set( $widget_args['number'] ); 366 $instances = $this->get_settings(); 367 368 if ( isset( $instances[ $this->number ] ) ) { 369 $instance = $instances[ $this->number ]; 370 371 /** 372 * Filters the settings for a particular widget instance. 373 * 374 * Returning false will effectively short-circuit display of the widget. 375 * 376 * @since 2.8.0 377 * 378 * @param array $instance The current widget instance's settings. 379 * @param WP_Widget $widget The current widget instance. 380 * @param array $args An array of default widget arguments. 381 */ 382 $instance = apply_filters( 'widget_display_callback', $instance, $this, $args ); 383 384 if ( false === $instance ) { 385 return; 386 } 387 388 $was_cache_addition_suspended = wp_suspend_cache_addition(); 389 if ( $this->is_preview() && ! $was_cache_addition_suspended ) { 390 wp_suspend_cache_addition( true ); 391 } 392 393 $this->widget( $args, $instance ); 394 395 if ( $this->is_preview() ) { 396 wp_suspend_cache_addition( $was_cache_addition_suspended ); 397 } 398 } 399 } 400 401 /** 402 * Handles changed settings (Do NOT override). 403 * 404 * @since 2.8.0 405 * 406 * @global array $wp_registered_widgets 407 * 408 * @param int $deprecated Not used. 409 */ 410 public function update_callback( $deprecated = 1 ) { 411 global $wp_registered_widgets; 412 413 $all_instances = $this->get_settings(); 414 415 // We need to update the data. 416 if ( $this->updated ) { 417 return; 418 } 419 420 if ( isset( $_POST['delete_widget'] ) && $_POST['delete_widget'] ) { 421 // Delete the settings for this instance of the widget. 422 if ( isset( $_POST['the-widget-id'] ) ) { 423 $del_id = $_POST['the-widget-id']; 424 } else { 425 return; 426 } 427 428 if ( isset( $wp_registered_widgets[ $del_id ]['params'][0]['number'] ) ) { 429 $number = $wp_registered_widgets[ $del_id ]['params'][0]['number']; 430 431 if ( $this->id_base . '-' . $number == $del_id ) { 432 unset( $all_instances[ $number ] ); 433 } 434 } 435 } else { 436 if ( isset( $_POST[ 'widget-' . $this->id_base ] ) && is_array( $_POST[ 'widget-' . $this->id_base ] ) ) { 437 $settings = $_POST[ 'widget-' . $this->id_base ]; 438 } elseif ( isset( $_POST['id_base'] ) && $_POST['id_base'] == $this->id_base ) { 439 $num = $_POST['multi_number'] ? (int) $_POST['multi_number'] : (int) $_POST['widget_number']; 440 $settings = array( $num => array() ); 441 } else { 442 return; 443 } 444 445 foreach ( $settings as $number => $new_instance ) { 446 $new_instance = stripslashes_deep( $new_instance ); 447 $this->_set( $number ); 448 449 $old_instance = isset( $all_instances[ $number ] ) ? $all_instances[ $number ] : array(); 450 451 $was_cache_addition_suspended = wp_suspend_cache_addition(); 452 if ( $this->is_preview() && ! $was_cache_addition_suspended ) { 453 wp_suspend_cache_addition( true ); 454 } 455 456 $instance = $this->update( $new_instance, $old_instance ); 457 458 if ( $this->is_preview() ) { 459 wp_suspend_cache_addition( $was_cache_addition_suspended ); 460 } 461 462 /** 463 * Filters a widget's settings before saving. 464 * 465 * Returning false will effectively short-circuit the widget's ability 466 * to update settings. 467 * 468 * @since 2.8.0 469 * 470 * @param array $instance The current widget instance's settings. 471 * @param array $new_instance Array of new widget settings. 472 * @param array $old_instance Array of old widget settings. 473 * @param WP_Widget $widget The current widget instance. 474 */ 475 $instance = apply_filters( 'widget_update_callback', $instance, $new_instance, $old_instance, $this ); 476 477 if ( false !== $instance ) { 478 $all_instances[ $number ] = $instance; 479 } 480 481 break; // Run only once. 482 } 483 } 484 485 $this->save_settings( $all_instances ); 486 $this->updated = true; 487 } 488 489 /** 490 * Generates the widget control form (Do NOT override). 491 * 492 * @since 2.8.0 493 * 494 * @param int|array $widget_args { 495 * Optional. Internal order number of the widget instance, or array of multi-widget arguments. 496 * Default 1. 497 * 498 * @type int $number Number increment used for multiples of the same widget. 499 * } 500 * @return string|null 501 */ 502 public function form_callback( $widget_args = 1 ) { 503 if ( is_numeric( $widget_args ) ) { 504 $widget_args = array( 'number' => $widget_args ); 505 } 506 507 $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) ); 508 $all_instances = $this->get_settings(); 509 510 if ( -1 == $widget_args['number'] ) { 511 // We echo out a form where 'number' can be set later. 512 $this->_set( '__i__' ); 513 $instance = array(); 514 } else { 515 $this->_set( $widget_args['number'] ); 516 $instance = $all_instances[ $widget_args['number'] ]; 517 } 518 519 /** 520 * Filters the widget instance's settings before displaying the control form. 521 * 522 * Returning false effectively short-circuits display of the control form. 523 * 524 * @since 2.8.0 525 * 526 * @param array $instance The current widget instance's settings. 527 * @param WP_Widget $widget The current widget instance. 528 */ 529 $instance = apply_filters( 'widget_form_callback', $instance, $this ); 530 531 $return = null; 532 533 if ( false !== $instance ) { 534 $return = $this->form( $instance ); 535 536 /** 537 * Fires at the end of the widget control form. 538 * 539 * Use this hook to add extra fields to the widget form. The hook 540 * is only fired if the value passed to the 'widget_form_callback' 541 * hook is not false. 542 * 543 * Note: If the widget has no form, the text echoed from the default 544 * form method can be hidden using CSS. 545 * 546 * @since 2.8.0 547 * 548 * @param WP_Widget $widget The widget instance (passed by reference). 549 * @param null $return Return null if new fields are added. 550 * @param array $instance An array of the widget's settings. 551 */ 552 do_action_ref_array( 'in_widget_form', array( &$this, &$return, $instance ) ); 553 } 554 555 return $return; 556 } 557 558 /** 559 * Registers an instance of the widget class. 560 * 561 * @since 2.8.0 562 * 563 * @param int $number Optional. The unique order number of this widget instance 564 * compared to other instances of the same class. Default -1. 565 */ 566 public function _register_one( $number = -1 ) { 567 wp_register_sidebar_widget( 568 $this->id, 569 $this->name, 570 $this->_get_display_callback(), 571 $this->widget_options, 572 array( 'number' => $number ) 573 ); 574 575 _register_widget_update_callback( 576 $this->id_base, 577 $this->_get_update_callback(), 578 $this->control_options, 579 array( 'number' => -1 ) 580 ); 581 582 _register_widget_form_callback( 583 $this->id, 584 $this->name, 585 $this->_get_form_callback(), 586 $this->control_options, 587 array( 'number' => $number ) 588 ); 589 } 590 591 /** 592 * Saves the settings for all instances of the widget class. 593 * 594 * @since 2.8.0 595 * 596 * @param array $settings Multi-dimensional array of widget instance settings. 597 */ 598 public function save_settings( $settings ) { 599 $settings['_multiwidget'] = 1; 600 update_option( $this->option_name, $settings ); 601 } 602 603 /** 604 * Retrieves the settings for all instances of the widget class. 605 * 606 * @since 2.8.0 607 * 608 * @return array Multi-dimensional array of widget instance settings. 609 */ 610 public function get_settings() { 611 612 $settings = get_option( $this->option_name ); 613 614 if ( false === $settings ) { 615 if ( isset( $this->alt_option_name ) ) { 616 $settings = get_option( $this->alt_option_name ); 617 } else { 618 // Save an option so it can be autoloaded next time. 619 $this->save_settings( array() ); 620 } 621 } 622 623 if ( ! is_array( $settings ) && ! ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) ) { 624 $settings = array(); 625 } 626 627 if ( ! empty( $settings ) && ! isset( $settings['_multiwidget'] ) ) { 628 // Old format, convert if single widget. 629 $settings = wp_convert_widget_settings( $this->id_base, $this->option_name, $settings ); 630 } 631 632 unset( $settings['_multiwidget'], $settings['__i__'] ); 633 634 return $settings; 635 } 636 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 10 01:00:03 2024 | Cross-referenced by PHPXref 0.7.1 |