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