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