WP_Widget

Core base class extended to register widgets.

Defined (1)

The class is defined in the following location(s).

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