/wp-includes/widgets.php

  1. <?php 
  2. /** 
  3. * Core Widgets API 
  4. * 
  5. * This API is used for creating dynamic sidebar without hardcoding functionality into 
  6. * themes 
  7. * 
  8. * Includes both internal WordPress routines and theme-use routines. 
  9. * 
  10. * This functionality was found in a plugin before the WordPress 2.2 release, which 
  11. * included it in the core from that point on. 
  12. * 
  13. * @link https://codex.wordpress.org/Plugins/WordPress_Widgets WordPress Widgets 
  14. * @link https://codex.wordpress.org/Plugins/WordPress_Widgets_Api Widgets API 
  15. * 
  16. * @package WordPress 
  17. * @subpackage Widgets 
  18. * @since 2.2.0 
  19. */ 
  20.  
  21. // 
  22. // Global Variables 
  23. // 
  24.   
  25. /** @ignore */ 
  26. global $wp_registered_sidebars, $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_widget_updates; 
  27.  
  28. /** 
  29. * Stores the sidebars, since many themes can have more than one. 
  30. * 
  31. * @global array $wp_registered_sidebars 
  32. * @since 2.2.0 
  33. */ 
  34. $wp_registered_sidebars = array(); 
  35.  
  36. /** 
  37. * Stores the registered widgets. 
  38. * 
  39. * @global array $wp_registered_widgets 
  40. * @since 2.2.0 
  41. */ 
  42. $wp_registered_widgets = array(); 
  43.  
  44. /** 
  45. * Stores the registered widget control (options). 
  46. * 
  47. * @global array $wp_registered_widget_controls 
  48. * @since 2.2.0 
  49. */ 
  50. $wp_registered_widget_controls = array(); 
  51. /** 
  52. * @global array $wp_registered_widget_updates 
  53. */ 
  54. $wp_registered_widget_updates = array(); 
  55.  
  56. /** 
  57. * Private 
  58. * 
  59. * @global array $_wp_sidebars_widgets 
  60. */ 
  61. $_wp_sidebars_widgets = array(); 
  62.  
  63. /** 
  64. * Private 
  65. * 
  66. * @global array $_wp_deprecated_widgets_callbacks 
  67. */ 
  68. $GLOBALS['_wp_deprecated_widgets_callbacks'] = array( 
  69. 'wp_widget_pages',  
  70. 'wp_widget_pages_control',  
  71. 'wp_widget_calendar',  
  72. 'wp_widget_calendar_control',  
  73. 'wp_widget_archives',  
  74. 'wp_widget_archives_control',  
  75. 'wp_widget_links',  
  76. 'wp_widget_meta',  
  77. 'wp_widget_meta_control',  
  78. 'wp_widget_search',  
  79. 'wp_widget_recent_entries',  
  80. 'wp_widget_recent_entries_control',  
  81. 'wp_widget_tag_cloud',  
  82. 'wp_widget_tag_cloud_control',  
  83. 'wp_widget_categories',  
  84. 'wp_widget_categories_control',  
  85. 'wp_widget_text',  
  86. 'wp_widget_text_control',  
  87. 'wp_widget_rss',  
  88. 'wp_widget_rss_control',  
  89. 'wp_widget_recent_comments',  
  90. 'wp_widget_recent_comments_control' 
  91. ); 
  92.  
  93. // 
  94.  // Template tags & API functions 
  95. // 
  96.   
  97. /** 
  98. * Register a widget 
  99. * 
  100. * Registers a WP_Widget widget 
  101. * 
  102. * @since 2.8.0 
  103. * 
  104. * @see WP_Widget 
  105. * 
  106. * @global WP_Widget_Factory $wp_widget_factory 
  107. * 
  108. * @param string $widget_class The name of a class that extends WP_Widget 
  109. */ 
  110. function register_widget($widget_class) { 
  111. global $wp_widget_factory; 
  112.  
  113. $wp_widget_factory->register($widget_class); 
  114.  
  115. /** 
  116. * Unregisters a widget. 
  117. * 
  118. * Unregisters a WP_Widget widget. Useful for un-registering default widgets. 
  119. * Run within a function hooked to the {@see 'widgets_init'} action. 
  120. * 
  121. * @since 2.8.0 
  122. * 
  123. * @see WP_Widget 
  124. * 
  125. * @global WP_Widget_Factory $wp_widget_factory 
  126. * 
  127. * @param string $widget_class The name of a class that extends WP_Widget. 
  128. */ 
  129. function unregister_widget($widget_class) { 
  130. global $wp_widget_factory; 
  131.  
  132. $wp_widget_factory->unregister($widget_class); 
  133.  
  134. /** 
  135. * Creates multiple sidebars. 
  136. * 
  137. * If you wanted to quickly create multiple sidebars for a theme or internally. 
  138. * This function will allow you to do so. If you don't pass the 'name' and/or 
  139. * 'id' in `$args`, then they will be built for you. 
  140. * 
  141. * @since 2.2.0 
  142. * 
  143. * @see register_sidebar() The second parameter is documented by register_sidebar() and is the same here. 
  144. * 
  145. * @global array $wp_registered_sidebars 
  146. * 
  147. * @param int $number Optional. Number of sidebars to create. Default 1. 
  148. * @param array|string $args { 
  149. * Optional. Array or string of arguments for building a sidebar. 
  150. * 
  151. * @type string $id The base string of the unique identifier for each sidebar. If provided, and multiple 
  152. * sidebars are being defined, the id will have "-2" appended, and so on. 
  153. * Default 'sidebar-' followed by the number the sidebar creation is currently at. 
  154. * @type string $name The name or title for the sidebars displayed in the admin dashboard. If registering 
  155. * more than one sidebar, include '%d' in the string as a placeholder for the uniquely 
  156. * assigned number for each sidebar. 
  157. * Default 'Sidebar' for the first sidebar, otherwise 'Sidebar %d'. 
  158. * } 
  159. */ 
  160. function register_sidebars( $number = 1, $args = array() ) { 
  161. global $wp_registered_sidebars; 
  162. $number = (int) $number; 
  163.  
  164. if ( is_string($args) ) 
  165. parse_str($args, $args); 
  166.  
  167. for ( $i = 1; $i <= $number; $i++ ) { 
  168. $_args = $args; 
  169.  
  170. if ( $number > 1 ) 
  171. $_args['name'] = isset($args['name']) ? sprintf($args['name'], $i) : sprintf(__('Sidebar %d'), $i); 
  172. else 
  173. $_args['name'] = isset($args['name']) ? $args['name'] : __('Sidebar'); 
  174.  
  175. // Custom specified ID's are suffixed if they exist already. 
  176. // Automatically generated sidebar names need to be suffixed regardless starting at -0 
  177. if ( isset($args['id']) ) { 
  178. $_args['id'] = $args['id']; 
  179. $n = 2; // Start at -2 for conflicting custom ID's 
  180. while ( is_registered_sidebar( $_args['id'] ) ) { 
  181. $_args['id'] = $args['id'] . '-' . $n++; 
  182. } else { 
  183. $n = count( $wp_registered_sidebars ); 
  184. do { 
  185. $_args['id'] = 'sidebar-' . ++$n; 
  186. } while ( is_registered_sidebar( $_args['id'] ) ); 
  187. register_sidebar($_args); 
  188.  
  189. /** 
  190. * Builds the definition for a single sidebar and returns the ID. 
  191. * 
  192. * Accepts either a string or an array and then parses that against a set 
  193. * of default arguments for the new sidebar. WordPress will automatically 
  194. * generate a sidebar ID and name based on the current number of registered 
  195. * sidebars if those arguments are not included. 
  196. * 
  197. * When allowing for automatic generation of the name and ID parameters, keep 
  198. * in mind that the incrementor for your sidebar can change over time depending 
  199. * on what other plugins and themes are installed. 
  200. * 
  201. * If theme support for 'widgets' has not yet been added when this function is 
  202. * called, it will be automatically enabled through the use of add_theme_support() 
  203. * 
  204. * @since 2.2.0 
  205. * 
  206. * @global array $wp_registered_sidebars Stores the new sidebar in this array by sidebar ID. 
  207. * 
  208. * @param array|string $args { 
  209. * Optional. Array or string of arguments for the sidebar being registered. 
  210. * 
  211. * @type string $name The name or title of the sidebar displayed in the Widgets 
  212. * interface. Default 'Sidebar $instance'. 
  213. * @type string $id The unique identifier by which the sidebar will be called. 
  214. * Default 'sidebar-$instance'. 
  215. * @type string $description Description of the sidebar, displayed in the Widgets interface. 
  216. * Default empty string. 
  217. * @type string $class Extra CSS class to assign to the sidebar in the Widgets interface. 
  218. * Default empty. 
  219. * @type string $before_widget HTML content to prepend to each widget's HTML output when 
  220. * assigned to this sidebar. Default is an opening list item element. 
  221. * @type string $after_widget HTML content to append to each widget's HTML output when 
  222. * assigned to this sidebar. Default is a closing list item element. 
  223. * @type string $before_title HTML content to prepend to the sidebar title when displayed. 
  224. * Default is an opening h2 element. 
  225. * @type string $after_title HTML content to append to the sidebar title when displayed. 
  226. * Default is a closing h2 element. 
  227. * } 
  228. * @return string Sidebar ID added to $wp_registered_sidebars global. 
  229. */ 
  230. function register_sidebar($args = array()) { 
  231. global $wp_registered_sidebars; 
  232.  
  233. $i = count($wp_registered_sidebars) + 1; 
  234.  
  235. $id_is_empty = empty( $args['id'] ); 
  236.  
  237. $defaults = array( 
  238. 'name' => sprintf(__('Sidebar %d'), $i ),  
  239. 'id' => "sidebar-$i",  
  240. 'description' => '',  
  241. 'class' => '',  
  242. 'before_widget' => '<li id="%1$s" class="widget %2$s">',  
  243. 'after_widget' => "</li>\n",  
  244. 'before_title' => '<h2 class="widgettitle">',  
  245. 'after_title' => "</h2>\n",  
  246. ); 
  247.  
  248. $sidebar = wp_parse_args( $args, $defaults ); 
  249.  
  250. if ( $id_is_empty ) { 
  251. /** translators: 1: the id argument, 2: sidebar name, 3: recommended id value */ 
  252. _doing_it_wrong( __FUNCTION__, sprintf( __( 'No %1$s was set in the arguments array for the "%2$s" sidebar. Defaulting to "%3$s". Manually set the %1$s to "%3$s" to silence this notice and keep existing sidebar content.' ), '<code>id</code>', $sidebar['name'], $sidebar['id'] ), '4.2.0' ); 
  253.  
  254. $wp_registered_sidebars[$sidebar['id']] = $sidebar; 
  255.  
  256. add_theme_support('widgets'); 
  257.  
  258. /** 
  259. * Fires once a sidebar has been registered. 
  260. * 
  261. * @since 3.0.0 
  262. * 
  263. * @param array $sidebar Parsed arguments for the registered sidebar. 
  264. */ 
  265. do_action( 'register_sidebar', $sidebar ); 
  266.  
  267. return $sidebar['id']; 
  268.  
  269. /** 
  270. * Removes a sidebar from the list. 
  271. * 
  272. * @since 2.2.0 
  273. * 
  274. * @global array $wp_registered_sidebars Stores the new sidebar in this array by sidebar ID. 
  275. * 
  276. * @param string $name The ID of the sidebar when it was added. 
  277. */ 
  278. function unregister_sidebar( $name ) { 
  279. global $wp_registered_sidebars; 
  280.  
  281. unset( $wp_registered_sidebars[ $name ] ); 
  282.  
  283. /** 
  284. * Checks if a sidebar is registered. 
  285. * 
  286. * @since 4.4.0 
  287. * 
  288. * @global array $wp_registered_sidebars Registered sidebars. 
  289. * 
  290. * @param string|int $sidebar_id The ID of the sidebar when it was registered. 
  291. * @return bool True if the sidebar is registered, false otherwise. 
  292. */ 
  293. function is_registered_sidebar( $sidebar_id ) { 
  294. global $wp_registered_sidebars; 
  295.  
  296. return isset( $wp_registered_sidebars[ $sidebar_id ] ); 
  297.  
  298. /** 
  299. * Register an instance of a widget. 
  300. * 
  301. * The default widget option is 'classname' that can be overridden. 
  302. * 
  303. * The function can also be used to un-register widgets when `$output_callback` 
  304. * parameter is an empty string. 
  305. * 
  306. * @since 2.2.0 
  307. * 
  308. * @global array $wp_registered_widgets Uses stored registered widgets. 
  309. * @global array $wp_register_widget_defaults Retrieves widget defaults. 
  310. * @global array $wp_registered_widget_updates 
  311. * @global array $_wp_deprecated_widgets_callbacks 
  312. * 
  313. * @param int|string $id Widget ID. 
  314. * @param string $name Widget display title. 
  315. * @param callable $output_callback Run when widget is called. 
  316. * @param array $options { 
  317. * Optional. An array of supplementary widget options for the instance. 
  318. * 
  319. * @type string $classname Class name for the widget's HTML container. Default is a shortened 
  320. * version of the output callback name. 
  321. * @type string $description Widget description for display in the widget administration 
  322. * panel and/or theme. 
  323. * } 
  324. */ 
  325. function wp_register_sidebar_widget( $id, $name, $output_callback, $options = array() ) { 
  326. global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_widget_updates, $_wp_deprecated_widgets_callbacks; 
  327.  
  328. $id = strtolower($id); 
  329.  
  330. if ( empty($output_callback) ) { 
  331. unset($wp_registered_widgets[$id]); 
  332. return; 
  333.  
  334. $id_base = _get_widget_id_base($id); 
  335. if ( in_array($output_callback, $_wp_deprecated_widgets_callbacks, true) && !is_callable($output_callback) ) { 
  336. unset( $wp_registered_widget_controls[ $id ] ); 
  337. unset( $wp_registered_widget_updates[ $id_base ] ); 
  338. return; 
  339.  
  340. $defaults = array('classname' => $output_callback); 
  341. $options = wp_parse_args($options, $defaults); 
  342. $widget = array( 
  343. 'name' => $name,  
  344. 'id' => $id,  
  345. 'callback' => $output_callback,  
  346. 'params' => array_slice(func_get_args(), 4) 
  347. ); 
  348. $widget = array_merge($widget, $options); 
  349.  
  350. if ( is_callable($output_callback) && ( !isset($wp_registered_widgets[$id]) || did_action( 'widgets_init' ) ) ) { 
  351.  
  352. /** 
  353. * Fires once for each registered widget. 
  354. * 
  355. * @since 3.0.0 
  356. * 
  357. * @param array $widget An array of default widget arguments. 
  358. */ 
  359. do_action( 'wp_register_sidebar_widget', $widget ); 
  360. $wp_registered_widgets[$id] = $widget; 
  361.  
  362. /** 
  363. * Retrieve description for widget. 
  364. * 
  365. * When registering widgets, the options can also include 'description' that 
  366. * describes the widget for display on the widget administration panel or 
  367. * in the theme. 
  368. * 
  369. * @since 2.5.0 
  370. * 
  371. * @global array $wp_registered_widgets 
  372. * 
  373. * @param int|string $id Widget ID. 
  374. * @return string|void Widget description, if available. 
  375. */ 
  376. function wp_widget_description( $id ) { 
  377. if ( !is_scalar($id) ) 
  378. return; 
  379.  
  380. global $wp_registered_widgets; 
  381.  
  382. if ( isset($wp_registered_widgets[$id]['description']) ) 
  383. return esc_html( $wp_registered_widgets[$id]['description'] ); 
  384.  
  385. /** 
  386. * Retrieve description for a sidebar. 
  387. * 
  388. * When registering sidebars a 'description' parameter can be included that 
  389. * describes the sidebar for display on the widget administration panel. 
  390. * 
  391. * @since 2.9.0 
  392. * 
  393. * @global array $wp_registered_sidebars 
  394. * 
  395. * @param string $id sidebar ID. 
  396. * @return string|void Sidebar description, if available. 
  397. */ 
  398. function wp_sidebar_description( $id ) { 
  399. if ( !is_scalar($id) ) 
  400. return; 
  401.  
  402. global $wp_registered_sidebars; 
  403.  
  404. if ( isset($wp_registered_sidebars[$id]['description']) ) 
  405. return esc_html( $wp_registered_sidebars[$id]['description'] ); 
  406.  
  407. /** 
  408. * Remove widget from sidebar. 
  409. * 
  410. * @since 2.2.0 
  411. * 
  412. * @param int|string $id Widget ID. 
  413. */ 
  414. function wp_unregister_sidebar_widget($id) { 
  415.  
  416. /** 
  417. * Fires just before a widget is removed from a sidebar. 
  418. * 
  419. * @since 3.0.0 
  420. * 
  421. * @param int $id The widget ID. 
  422. */ 
  423. do_action( 'wp_unregister_sidebar_widget', $id ); 
  424.  
  425. wp_register_sidebar_widget($id, '', ''); 
  426. wp_unregister_widget_control($id); 
  427.  
  428. /** 
  429. * Registers widget control callback for customizing options. 
  430. * 
  431. * @since 2.2.0 
  432. * 
  433. * @todo `$params` parameter? 
  434. * 
  435. * @global array $wp_registered_widget_controls 
  436. * @global array $wp_registered_widget_updates 
  437. * @global array $wp_registered_widgets 
  438. * @global array $_wp_deprecated_widgets_callbacks 
  439. * 
  440. * @param int|string $id Sidebar ID. 
  441. * @param string $name Sidebar display name. 
  442. * @param callable $control_callback Run when sidebar is displayed. 
  443. * @param array $options { 
  444. * Optional. Array or string of control options. Default empty array. 
  445. * 
  446. * @type int $height Never used. Default 200. 
  447. * @type int $width Width of the fully expanded control form (but try hard to use the default width). 
  448. * Default 250. 
  449. * @type int|string $id_base Required for multi-widgets, i.e widgets that allow multiple instances such as the 
  450. * text widget. The widget id will end up looking like `{$id_base}-{$unique_number}`. 
  451. * } 
  452. */ 
  453. function wp_register_widget_control( $id, $name, $control_callback, $options = array() ) { 
  454. global $wp_registered_widget_controls, $wp_registered_widget_updates, $wp_registered_widgets, $_wp_deprecated_widgets_callbacks; 
  455.  
  456. $id = strtolower($id); 
  457. $id_base = _get_widget_id_base($id); 
  458.  
  459. if ( empty($control_callback) ) { 
  460. unset($wp_registered_widget_controls[$id]); 
  461. unset($wp_registered_widget_updates[$id_base]); 
  462. return; 
  463.  
  464. if ( in_array($control_callback, $_wp_deprecated_widgets_callbacks, true) && !is_callable($control_callback) ) { 
  465. unset( $wp_registered_widgets[ $id ] ); 
  466. return; 
  467.  
  468. if ( isset($wp_registered_widget_controls[$id]) && !did_action( 'widgets_init' ) ) 
  469. return; 
  470.  
  471. $defaults = array('width' => 250, 'height' => 200 ); // height is never used 
  472. $options = wp_parse_args($options, $defaults); 
  473. $options['width'] = (int) $options['width']; 
  474. $options['height'] = (int) $options['height']; 
  475.  
  476. $widget = array( 
  477. 'name' => $name,  
  478. 'id' => $id,  
  479. 'callback' => $control_callback,  
  480. 'params' => array_slice(func_get_args(), 4) 
  481. ); 
  482. $widget = array_merge($widget, $options); 
  483.  
  484. $wp_registered_widget_controls[$id] = $widget; 
  485.  
  486. if ( isset($wp_registered_widget_updates[$id_base]) ) 
  487. return; 
  488.  
  489. if ( isset($widget['params'][0]['number']) ) 
  490. $widget['params'][0]['number'] = -1; 
  491.  
  492. unset($widget['width'], $widget['height'], $widget['name'], $widget['id']); 
  493. $wp_registered_widget_updates[$id_base] = $widget; 
  494.  
  495. /** 
  496. * Registers the update callback for a widget. 
  497. * 
  498. * @since 2.8.0 
  499. * 
  500. * @global array $wp_registered_widget_updates 
  501. * 
  502. * @param string $id_base The base ID of a widget created by extending WP_Widget. 
  503. * @param callable $update_callback Update callback method for the widget. 
  504. * @param array $options Optional. Widget control options. See wp_register_widget_control(). 
  505. * Default empty array. 
  506. */ 
  507. function _register_widget_update_callback( $id_base, $update_callback, $options = array() ) { 
  508. global $wp_registered_widget_updates; 
  509.  
  510. if ( isset($wp_registered_widget_updates[$id_base]) ) { 
  511. if ( empty($update_callback) ) 
  512. unset($wp_registered_widget_updates[$id_base]); 
  513. return; 
  514.  
  515. $widget = array( 
  516. 'callback' => $update_callback,  
  517. 'params' => array_slice(func_get_args(), 3) 
  518. ); 
  519.  
  520. $widget = array_merge($widget, $options); 
  521. $wp_registered_widget_updates[$id_base] = $widget; 
  522.  
  523. /** 
  524. * Registers the form callback for a widget. 
  525. * 
  526. * @since 2.8.0 
  527. * 
  528. * @global array $wp_registered_widget_controls 
  529. * 
  530. * @param int|string $id Widget ID. 
  531. * @param string $name Name attribute for the widget. 
  532. * @param callable $form_callback Form callback. 
  533. * @param array $options Optional. Widget control options. See wp_register_widget_control(). 
  534. * Default empty array. 
  535. */ 
  536. function _register_widget_form_callback($id, $name, $form_callback, $options = array()) { 
  537. global $wp_registered_widget_controls; 
  538.  
  539. $id = strtolower($id); 
  540.  
  541. if ( empty($form_callback) ) { 
  542. unset($wp_registered_widget_controls[$id]); 
  543. return; 
  544.  
  545. if ( isset($wp_registered_widget_controls[$id]) && !did_action( 'widgets_init' ) ) 
  546. return; 
  547.  
  548. $defaults = array('width' => 250, 'height' => 200 ); 
  549. $options = wp_parse_args($options, $defaults); 
  550. $options['width'] = (int) $options['width']; 
  551. $options['height'] = (int) $options['height']; 
  552.  
  553. $widget = array( 
  554. 'name' => $name,  
  555. 'id' => $id,  
  556. 'callback' => $form_callback,  
  557. 'params' => array_slice(func_get_args(), 4) 
  558. ); 
  559. $widget = array_merge($widget, $options); 
  560.  
  561. $wp_registered_widget_controls[$id] = $widget; 
  562.  
  563. /** 
  564. * Remove control callback for widget. 
  565. * 
  566. * @since 2.2.0 
  567. * 
  568. * @param int|string $id Widget ID. 
  569. */ 
  570. function wp_unregister_widget_control($id) { 
  571. wp_register_widget_control( $id, '', '' ); 
  572.  
  573. /** 
  574. * Display dynamic sidebar. 
  575. * 
  576. * By default this displays the default sidebar or 'sidebar-1'. If your theme specifies the 'id' or 
  577. * 'name' parameter for its registered sidebars you can pass an id or name as the $index parameter. 
  578. * Otherwise, you can pass in a numerical index to display the sidebar at that index. 
  579. * 
  580. * @since 2.2.0 
  581. * 
  582. * @global array $wp_registered_sidebars 
  583. * @global array $wp_registered_widgets 
  584. * 
  585. * @param int|string $index Optional, default is 1. Index, name or ID of dynamic sidebar. 
  586. * @return bool True, if widget sidebar was found and called. False if not found or not called. 
  587. */ 
  588. function dynamic_sidebar( $index = 1 ) { 
  589. global $wp_registered_sidebars, $wp_registered_widgets; 
  590.  
  591. if ( is_int( $index ) ) { 
  592. $index = "sidebar-$index"; 
  593. } else { 
  594. $index = sanitize_title( $index ); 
  595. foreach ( (array) $wp_registered_sidebars as $key => $value ) { 
  596. if ( sanitize_title( $value['name'] ) == $index ) { 
  597. $index = $key; 
  598. break; 
  599.  
  600. $sidebars_widgets = wp_get_sidebars_widgets(); 
  601. if ( empty( $wp_registered_sidebars[ $index ] ) || empty( $sidebars_widgets[ $index ] ) || ! is_array( $sidebars_widgets[ $index ] ) ) { 
  602. /** This action is documented in wp-includes/widget.php */ 
  603. do_action( 'dynamic_sidebar_before', $index, false ); 
  604. /** This action is documented in wp-includes/widget.php */ 
  605. do_action( 'dynamic_sidebar_after', $index, false ); 
  606. /** This filter is documented in wp-includes/widget.php */ 
  607. return apply_filters( 'dynamic_sidebar_has_widgets', false, $index ); 
  608.  
  609. /** 
  610. * Fires before widgets are rendered in a dynamic sidebar. 
  611. * 
  612. * Note: The action also fires for empty sidebars, and on both the front end 
  613. * and back end, including the Inactive Widgets sidebar on the Widgets screen. 
  614. * 
  615. * @since 3.9.0 
  616. * 
  617. * @param int|string $index Index, name, or ID of the dynamic sidebar. 
  618. * @param bool $has_widgets Whether the sidebar is populated with widgets. 
  619. * Default true. 
  620. */ 
  621. do_action( 'dynamic_sidebar_before', $index, true ); 
  622. $sidebar = $wp_registered_sidebars[$index]; 
  623.  
  624. $did_one = false; 
  625. foreach ( (array) $sidebars_widgets[$index] as $id ) { 
  626.  
  627. if ( !isset($wp_registered_widgets[$id]) ) continue; 
  628.  
  629. $params = array_merge( 
  630. array( array_merge( $sidebar, array('widget_id' => $id, 'widget_name' => $wp_registered_widgets[$id]['name']) ) ),  
  631. (array) $wp_registered_widgets[$id]['params'] 
  632. ); 
  633.  
  634. // Substitute HTML id and class attributes into before_widget 
  635. $classname_ = ''; 
  636. foreach ( (array) $wp_registered_widgets[$id]['classname'] as $cn ) { 
  637. if ( is_string($cn) ) 
  638. $classname_ .= '_' . $cn; 
  639. elseif ( is_object($cn) ) 
  640. $classname_ .= '_' . get_class($cn); 
  641. $classname_ = ltrim($classname_, '_'); 
  642. $params[0]['before_widget'] = sprintf($params[0]['before_widget'], $id, $classname_); 
  643.  
  644. /** 
  645. * Filters the parameters passed to a widget's display callback. 
  646. * 
  647. * Note: The filter is evaluated on both the front end and back end,  
  648. * including for the Inactive Widgets sidebar on the Widgets screen. 
  649. * 
  650. * @since 2.5.0 
  651. * 
  652. * @see register_sidebar() 
  653. * 
  654. * @param array $params { 
  655. * @type array $args { 
  656. * An array of widget display arguments. 
  657. * 
  658. * @type string $name Name of the sidebar the widget is assigned to. 
  659. * @type string $id ID of the sidebar the widget is assigned to. 
  660. * @type string $description The sidebar description. 
  661. * @type string $class CSS class applied to the sidebar container. 
  662. * @type string $before_widget HTML markup to prepend to each widget in the sidebar. 
  663. * @type string $after_widget HTML markup to append to each widget in the sidebar. 
  664. * @type string $before_title HTML markup to prepend to the widget title when displayed. 
  665. * @type string $after_title HTML markup to append to the widget title when displayed. 
  666. * @type string $widget_id ID of the widget. 
  667. * @type string $widget_name Name of the widget. 
  668. * } 
  669. * @type array $widget_args { 
  670. * An array of multi-widget arguments. 
  671. * 
  672. * @type int $number Number increment used for multiples of the same widget. 
  673. * } 
  674. * } 
  675. */ 
  676. $params = apply_filters( 'dynamic_sidebar_params', $params ); 
  677.  
  678. $callback = $wp_registered_widgets[$id]['callback']; 
  679.  
  680. /** 
  681. * Fires before a widget's display callback is called. 
  682. * 
  683. * Note: The action fires on both the front end and back end, including 
  684. * for widgets in the Inactive Widgets sidebar on the Widgets screen. 
  685. * 
  686. * The action is not fired for empty sidebars. 
  687. * 
  688. * @since 3.0.0 
  689. * 
  690. * @param array $widget_id { 
  691. * An associative array of widget arguments. 
  692. * 
  693. * @type string $name Name of the widget. 
  694. * @type string $id Widget ID. 
  695. * @type array|callable $callback When the hook is fired on the front end, $callback is an array 
  696. * containing the widget object. Fired on the back end, $callback 
  697. * is 'wp_widget_control', see $_callback. 
  698. * @type array $params An associative array of multi-widget arguments. 
  699. * @type string $classname CSS class applied to the widget container. 
  700. * @type string $description The widget description. 
  701. * @type array $_callback When the hook is fired on the back end, $_callback is populated 
  702. * with an array containing the widget object, see $callback. 
  703. * } 
  704. */ 
  705. do_action( 'dynamic_sidebar', $wp_registered_widgets[ $id ] ); 
  706.  
  707. if ( is_callable($callback) ) { 
  708. call_user_func_array($callback, $params); 
  709. $did_one = true; 
  710.  
  711. /** 
  712. * Fires after widgets are rendered in a dynamic sidebar. 
  713. * 
  714. * Note: The action also fires for empty sidebars, and on both the front end 
  715. * and back end, including the Inactive Widgets sidebar on the Widgets screen. 
  716. * 
  717. * @since 3.9.0 
  718. * 
  719. * @param int|string $index Index, name, or ID of the dynamic sidebar. 
  720. * @param bool $has_widgets Whether the sidebar is populated with widgets. 
  721. * Default true. 
  722. */ 
  723. do_action( 'dynamic_sidebar_after', $index, true ); 
  724.  
  725. /** 
  726. * Filters whether a sidebar has widgets. 
  727. * 
  728. * Note: The filter is also evaluated for empty sidebars, and on both the front end 
  729. * and back end, including the Inactive Widgets sidebar on the Widgets screen. 
  730. * 
  731. * @since 3.9.0 
  732. * 
  733. * @param bool $did_one Whether at least one widget was rendered in the sidebar. 
  734. * Default false. 
  735. * @param int|string $index Index, name, or ID of the dynamic sidebar. 
  736. */ 
  737. return apply_filters( 'dynamic_sidebar_has_widgets', $did_one, $index ); 
  738.  
  739. /** 
  740. * Whether widget is displayed on the front end. 
  741. * 
  742. * Either $callback or $id_base can be used 
  743. * $id_base is the first argument when extending WP_Widget class 
  744. * Without the optional $widget_id parameter, returns the ID of the first sidebar 
  745. * in which the first instance of the widget with the given callback or $id_base is found. 
  746. * With the $widget_id parameter, returns the ID of the sidebar where 
  747. * the widget with that callback/$id_base AND that ID is found. 
  748. * 
  749. * NOTE: $widget_id and $id_base are the same for single widgets. To be effective 
  750. * this function has to run after widgets have initialized, at action {@see 'init'} or later. 
  751. * 
  752. * @since 2.2.0 
  753. * 
  754. * @global array $wp_registered_widgets 
  755. * 
  756. * @param string|false $callback Optional, Widget callback to check. Default false. 
  757. * @param int|false $widget_id Optional. Widget ID. Optional, but needed for checking. Default false. 
  758. * @param string|false $id_base Optional. The base ID of a widget created by extending WP_Widget. Default false. 
  759. * @param bool $skip_inactive Optional. Whether to check in 'wp_inactive_widgets'. Default true. 
  760. * @return string|false False if widget is not active or id of sidebar in which the widget is active. 
  761. */ 
  762. function is_active_widget( $callback = false, $widget_id = false, $id_base = false, $skip_inactive = true ) { 
  763. global $wp_registered_widgets; 
  764.  
  765. $sidebars_widgets = wp_get_sidebars_widgets(); 
  766.  
  767. if ( is_array($sidebars_widgets) ) { 
  768. foreach ( $sidebars_widgets as $sidebar => $widgets ) { 
  769. if ( $skip_inactive && ( 'wp_inactive_widgets' === $sidebar || 'orphaned_widgets' === substr( $sidebar, 0, 16 ) ) ) { 
  770. continue; 
  771.  
  772. if ( is_array($widgets) ) { 
  773. foreach ( $widgets as $widget ) { 
  774. if ( ( $callback && isset($wp_registered_widgets[$widget]['callback']) && $wp_registered_widgets[$widget]['callback'] == $callback ) || ( $id_base && _get_widget_id_base($widget) == $id_base ) ) { 
  775. if ( !$widget_id || $widget_id == $wp_registered_widgets[$widget]['id'] ) 
  776. return $sidebar; 
  777. return false; 
  778.  
  779. /** 
  780. * Whether the dynamic sidebar is enabled and used by theme. 
  781. * 
  782. * @since 2.2.0 
  783. * 
  784. * @global array $wp_registered_widgets 
  785. * @global array $wp_registered_sidebars 
  786. * 
  787. * @return bool True, if using widgets. False, if not using widgets. 
  788. */ 
  789. function is_dynamic_sidebar() { 
  790. global $wp_registered_widgets, $wp_registered_sidebars; 
  791. $sidebars_widgets = get_option('sidebars_widgets'); 
  792. foreach ( (array) $wp_registered_sidebars as $index => $sidebar ) { 
  793. if ( ! empty( $sidebars_widgets[ $index ] ) ) { 
  794. foreach ( (array) $sidebars_widgets[$index] as $widget ) 
  795. if ( array_key_exists($widget, $wp_registered_widgets) ) 
  796. return true; 
  797. return false; 
  798.  
  799. /** 
  800. * Whether a sidebar is in use. 
  801. * 
  802. * @since 2.8.0 
  803. * 
  804. * @param string|int $index Sidebar name, id or number to check. 
  805. * @return bool true if the sidebar is in use, false otherwise. 
  806. */ 
  807. function is_active_sidebar( $index ) { 
  808. $index = ( is_int($index) ) ? "sidebar-$index" : sanitize_title($index); 
  809. $sidebars_widgets = wp_get_sidebars_widgets(); 
  810. $is_active_sidebar = ! empty( $sidebars_widgets[$index] ); 
  811.  
  812. /** 
  813. * Filters whether a dynamic sidebar is considered "active". 
  814. * 
  815. * @since 3.9.0 
  816. * 
  817. * @param bool $is_active_sidebar Whether or not the sidebar should be considered "active". 
  818. * In other words, whether the sidebar contains any widgets. 
  819. * @param int|string $index Index, name, or ID of the dynamic sidebar. 
  820. */ 
  821. return apply_filters( 'is_active_sidebar', $is_active_sidebar, $index ); 
  822.  
  823. // 
  824.  // Internal Functions 
  825. // 
  826.   
  827. /** 
  828. * Retrieve full list of sidebars and their widget instance IDs. 
  829. * 
  830. * Will upgrade sidebar widget list, if needed. Will also save updated list, if 
  831. * needed. 
  832. * 
  833. * @since 2.2.0 
  834. * @access private 
  835. * 
  836. * @global array $_wp_sidebars_widgets 
  837. * @global array $sidebars_widgets 
  838. * 
  839. * @param bool $deprecated Not used (argument deprecated). 
  840. * @return array Upgraded list of widgets to version 3 array format when called from the admin. 
  841. */ 
  842. function wp_get_sidebars_widgets( $deprecated = true ) { 
  843. if ( $deprecated !== true ) 
  844. _deprecated_argument( __FUNCTION__, '2.8.1' ); 
  845.  
  846. global $_wp_sidebars_widgets, $sidebars_widgets; 
  847.  
  848. // If loading from front page, consult $_wp_sidebars_widgets rather than options 
  849. // to see if wp_convert_widget_settings() has made manipulations in memory. 
  850. if ( !is_admin() ) { 
  851. if ( empty($_wp_sidebars_widgets) ) 
  852. $_wp_sidebars_widgets = get_option('sidebars_widgets', array()); 
  853.  
  854. $sidebars_widgets = $_wp_sidebars_widgets; 
  855. } else { 
  856. $sidebars_widgets = get_option('sidebars_widgets', array()); 
  857.  
  858. if ( is_array( $sidebars_widgets ) && isset($sidebars_widgets['array_version']) ) 
  859. unset($sidebars_widgets['array_version']); 
  860.  
  861. /** 
  862. * Filters the list of sidebars and their widgets. 
  863. * 
  864. * @since 2.7.0 
  865. * 
  866. * @param array $sidebars_widgets An associative array of sidebars and their widgets. 
  867. */ 
  868. return apply_filters( 'sidebars_widgets', $sidebars_widgets ); 
  869.  
  870. /** 
  871. * Set the sidebar widget option to update sidebars. 
  872. * 
  873. * @since 2.2.0 
  874. * @access private 
  875. * 
  876. * @param array $sidebars_widgets Sidebar widgets and their settings. 
  877. */ 
  878. function wp_set_sidebars_widgets( $sidebars_widgets ) { 
  879. if ( !isset( $sidebars_widgets['array_version'] ) ) 
  880. $sidebars_widgets['array_version'] = 3; 
  881. update_option( 'sidebars_widgets', $sidebars_widgets ); 
  882.  
  883. /** 
  884. * Retrieve default registered sidebars list. 
  885. * 
  886. * @since 2.2.0 
  887. * @access private 
  888. * 
  889. * @global array $wp_registered_sidebars 
  890. * 
  891. * @return array 
  892. */ 
  893. function wp_get_widget_defaults() { 
  894. global $wp_registered_sidebars; 
  895.  
  896. $defaults = array(); 
  897.  
  898. foreach ( (array) $wp_registered_sidebars as $index => $sidebar ) 
  899. $defaults[$index] = array(); 
  900.  
  901. return $defaults; 
  902.  
  903. /** 
  904. * Convert the widget settings from single to multi-widget format. 
  905. * 
  906. * @since 2.8.0 
  907. * 
  908. * @global array $_wp_sidebars_widgets 
  909. * 
  910. * @param string $base_name 
  911. * @param string $option_name 
  912. * @param array $settings 
  913. * @return array 
  914. */ 
  915. function wp_convert_widget_settings($base_name, $option_name, $settings) { 
  916. // This test may need expanding. 
  917. $single = $changed = false; 
  918. if ( empty($settings) ) { 
  919. $single = true; 
  920. } else { 
  921. foreach ( array_keys($settings) as $number ) { 
  922. if ( 'number' == $number ) 
  923. continue; 
  924. if ( !is_numeric($number) ) { 
  925. $single = true; 
  926. break; 
  927.  
  928. if ( $single ) { 
  929. $settings = array( 2 => $settings ); 
  930.  
  931. // If loading from the front page, update sidebar in memory but don't save to options 
  932. if ( is_admin() ) { 
  933. $sidebars_widgets = get_option('sidebars_widgets'); 
  934. } else { 
  935. if ( empty($GLOBALS['_wp_sidebars_widgets']) ) 
  936. $GLOBALS['_wp_sidebars_widgets'] = get_option('sidebars_widgets', array()); 
  937. $sidebars_widgets = &$GLOBALS['_wp_sidebars_widgets']; 
  938.  
  939. foreach ( (array) $sidebars_widgets as $index => $sidebar ) { 
  940. if ( is_array($sidebar) ) { 
  941. foreach ( $sidebar as $i => $name ) { 
  942. if ( $base_name == $name ) { 
  943. $sidebars_widgets[$index][$i] = "$name-2"; 
  944. $changed = true; 
  945. break 2; 
  946.  
  947. if ( is_admin() && $changed ) 
  948. update_option('sidebars_widgets', $sidebars_widgets); 
  949.  
  950. $settings['_multiwidget'] = 1; 
  951. if ( is_admin() ) 
  952. update_option( $option_name, $settings ); 
  953.  
  954. return $settings; 
  955.  
  956. /** 
  957. * Output an arbitrary widget as a template tag. 
  958. * 
  959. * @since 2.8.0 
  960. * 
  961. * @global WP_Widget_Factory $wp_widget_factory 
  962. * 
  963. * @param string $widget The widget's PHP class name (see class-wp-widget.php). 
  964. * @param array $instance Optional. The widget's instance settings. Default empty array. 
  965. * @param array $args { 
  966. * Optional. Array of arguments to configure the display of the widget. 
  967. * 
  968. * @type string $before_widget HTML content that will be prepended to the widget's HTML output. 
  969. * Default `<div class="widget %s">`, where `%s` is the widget's class name. 
  970. * @type string $after_widget HTML content that will be appended to the widget's HTML output. 
  971. * Default `</div>`. 
  972. * @type string $before_title HTML content that will be prepended to the widget's title when displayed. 
  973. * Default `<h2 class="widgettitle">`. 
  974. * @type string $after_title HTML content that will be appended to the widget's title when displayed. 
  975. * Default `</h2>`. 
  976. * } 
  977. */ 
  978. function the_widget( $widget, $instance = array(), $args = array() ) { 
  979. global $wp_widget_factory; 
  980.  
  981. $widget_obj = $wp_widget_factory->widgets[$widget]; 
  982. if ( ! ( $widget_obj instanceof WP_Widget ) ) { 
  983. return; 
  984.  
  985. $default_args = array( 
  986. 'before_widget' => '<div class="widget %s">',  
  987. 'after_widget' => "</div>",  
  988. 'before_title' => '<h2 class="widgettitle">',  
  989. 'after_title' => '</h2>',  
  990. ); 
  991. $args = wp_parse_args( $args, $default_args ); 
  992. $args['before_widget'] = sprintf( $args['before_widget'], $widget_obj->widget_options['classname'] ); 
  993.  
  994. $instance = wp_parse_args($instance); 
  995.  
  996. /** 
  997. * Fires before rendering the requested widget. 
  998. * 
  999. * @since 3.0.0 
  1000. * 
  1001. * @param string $widget The widget's class name. 
  1002. * @param array $instance The current widget instance's settings. 
  1003. * @param array $args An array of the widget's sidebar arguments. 
  1004. */ 
  1005. do_action( 'the_widget', $widget, $instance, $args ); 
  1006.  
  1007. $widget_obj->_set(-1); 
  1008. $widget_obj->widget($args, $instance); 
  1009.  
  1010. /** 
  1011. * Retrieves the widget ID base value. 
  1012. * 
  1013. * @since 2.8.0 
  1014. * 
  1015. * @param string $id Widget ID. 
  1016. * @return string Widget ID base. 
  1017. */ 
  1018. function _get_widget_id_base( $id ) { 
  1019. return preg_replace( '/-[0-9]+$/', '', $id ); 
  1020.  
  1021. /** 
  1022. * Handle sidebars config after theme change 
  1023. * 
  1024. * @access private 
  1025. * @since 3.3.0 
  1026. * 
  1027. * @global array $sidebars_widgets 
  1028. */ 
  1029. function _wp_sidebars_changed() { 
  1030. global $sidebars_widgets; 
  1031.  
  1032. if ( ! is_array( $sidebars_widgets ) ) 
  1033. $sidebars_widgets = wp_get_sidebars_widgets(); 
  1034.  
  1035. retrieve_widgets(true); 
  1036.  
  1037. /** 
  1038. * Look for "lost" widgets, this has to run at least on each theme change. 
  1039. * 
  1040. * @since 2.8.0 
  1041. * 
  1042. * @global array $wp_registered_sidebars 
  1043. * @global array $sidebars_widgets 
  1044. * @global array $wp_registered_widgets 
  1045. * 
  1046. * @param string|bool $theme_changed Whether the theme was changed as a boolean. A value 
  1047. * of 'customize' defers updates for the Customizer. 
  1048. * @return array|void 
  1049. */ 
  1050. function retrieve_widgets( $theme_changed = false ) { 
  1051. global $wp_registered_sidebars, $sidebars_widgets, $wp_registered_widgets; 
  1052.  
  1053. $registered_sidebar_keys = array_keys( $wp_registered_sidebars ); 
  1054. $orphaned = 0; 
  1055.  
  1056. $old_sidebars_widgets = get_theme_mod( 'sidebars_widgets' ); 
  1057. if ( is_array( $old_sidebars_widgets ) ) { 
  1058. // time() that sidebars were stored is in $old_sidebars_widgets['time'] 
  1059. $_sidebars_widgets = $old_sidebars_widgets['data']; 
  1060.  
  1061. if ( 'customize' !== $theme_changed ) { 
  1062. remove_theme_mod( 'sidebars_widgets' ); 
  1063.  
  1064. foreach ( $_sidebars_widgets as $sidebar => $widgets ) { 
  1065. if ( 'wp_inactive_widgets' === $sidebar || 'orphaned_widgets' === substr( $sidebar, 0, 16 ) ) { 
  1066. continue; 
  1067.  
  1068. if ( !in_array( $sidebar, $registered_sidebar_keys ) ) { 
  1069. $_sidebars_widgets['orphaned_widgets_' . ++$orphaned] = $widgets; 
  1070. unset( $_sidebars_widgets[$sidebar] ); 
  1071. } else { 
  1072. if ( empty( $sidebars_widgets ) ) 
  1073. return; 
  1074.  
  1075. unset( $sidebars_widgets['array_version'] ); 
  1076.  
  1077. $old = array_keys($sidebars_widgets); 
  1078. sort($old); 
  1079. sort($registered_sidebar_keys); 
  1080.  
  1081. if ( $old == $registered_sidebar_keys ) 
  1082. return; 
  1083.  
  1084. $_sidebars_widgets = array( 
  1085. 'wp_inactive_widgets' => !empty( $sidebars_widgets['wp_inactive_widgets'] ) ? $sidebars_widgets['wp_inactive_widgets'] : array() 
  1086. ); 
  1087.  
  1088. unset( $sidebars_widgets['wp_inactive_widgets'] ); 
  1089.  
  1090. foreach ( $wp_registered_sidebars as $id => $settings ) { 
  1091. if ( $theme_changed ) { 
  1092. $_sidebars_widgets[$id] = array_shift( $sidebars_widgets ); 
  1093. } else { 
  1094. // no theme change, grab only sidebars that are currently registered 
  1095. if ( isset( $sidebars_widgets[$id] ) ) { 
  1096. $_sidebars_widgets[$id] = $sidebars_widgets[$id]; 
  1097. unset( $sidebars_widgets[$id] ); 
  1098.  
  1099. foreach ( $sidebars_widgets as $val ) { 
  1100. if ( is_array($val) && ! empty( $val ) ) 
  1101. $_sidebars_widgets['orphaned_widgets_' . ++$orphaned] = $val; 
  1102.  
  1103. // discard invalid, theme-specific widgets from sidebars 
  1104. $shown_widgets = array(); 
  1105.  
  1106. foreach ( $_sidebars_widgets as $sidebar => $widgets ) { 
  1107. if ( !is_array($widgets) ) 
  1108. continue; 
  1109.  
  1110. $_widgets = array(); 
  1111. foreach ( $widgets as $widget ) { 
  1112. if ( isset($wp_registered_widgets[$widget]) ) 
  1113. $_widgets[] = $widget; 
  1114.  
  1115. $_sidebars_widgets[$sidebar] = $_widgets; 
  1116. $shown_widgets = array_merge($shown_widgets, $_widgets); 
  1117.  
  1118. $sidebars_widgets = $_sidebars_widgets; 
  1119. unset($_sidebars_widgets, $_widgets); 
  1120.  
  1121. // find hidden/lost multi-widget instances 
  1122. $lost_widgets = array(); 
  1123. foreach ( $wp_registered_widgets as $key => $val ) { 
  1124. if ( in_array($key, $shown_widgets, true) ) 
  1125. continue; 
  1126.  
  1127. $number = preg_replace('/.+?-([0-9]+)$/', '$1', $key); 
  1128.  
  1129. if ( 2 > (int) $number ) 
  1130. continue; 
  1131.  
  1132. $lost_widgets[] = $key; 
  1133.  
  1134. $sidebars_widgets['wp_inactive_widgets'] = array_merge($lost_widgets, (array) $sidebars_widgets['wp_inactive_widgets']); 
  1135. if ( 'customize' !== $theme_changed ) { 
  1136. wp_set_sidebars_widgets( $sidebars_widgets ); 
  1137.  
  1138. return $sidebars_widgets; 
  1139.  
  1140. /** 
  1141. * Display the RSS entries in a list. 
  1142. * 
  1143. * @since 2.5.0 
  1144. * 
  1145. * @param string|array|object $rss RSS url. 
  1146. * @param array $args Widget arguments. 
  1147. */ 
  1148. function wp_widget_rss_output( $rss, $args = array() ) { 
  1149. if ( is_string( $rss ) ) { 
  1150. $rss = fetch_feed($rss); 
  1151. } elseif ( is_array($rss) && isset($rss['url']) ) { 
  1152. $args = $rss; 
  1153. $rss = fetch_feed($rss['url']); 
  1154. } elseif ( !is_object($rss) ) { 
  1155. return; 
  1156.  
  1157. if ( is_wp_error($rss) ) { 
  1158. if ( is_admin() || current_user_can('manage_options') ) 
  1159. echo '<p><strong>' . __( 'RSS Error:' ) . '</strong> ' . $rss->get_error_message() . '</p>'; 
  1160. return; 
  1161.  
  1162. $default_args = array( 'show_author' => 0, 'show_date' => 0, 'show_summary' => 0, 'items' => 0 ); 
  1163. $args = wp_parse_args( $args, $default_args ); 
  1164.  
  1165. $items = (int) $args['items']; 
  1166. if ( $items < 1 || 20 < $items ) 
  1167. $items = 10; 
  1168. $show_summary = (int) $args['show_summary']; 
  1169. $show_author = (int) $args['show_author']; 
  1170. $show_date = (int) $args['show_date']; 
  1171.  
  1172. if ( !$rss->get_item_quantity() ) { 
  1173. echo '<ul><li>' . __( 'An error has occurred, which probably means the feed is down. Try again later.' ) . '</li></ul>'; 
  1174. $rss->__destruct(); 
  1175. unset($rss); 
  1176. return; 
  1177.  
  1178. echo '<ul>'; 
  1179. foreach ( $rss->get_items( 0, $items ) as $item ) { 
  1180. $link = $item->get_link(); 
  1181. while ( stristr( $link, 'http' ) != $link ) { 
  1182. $link = substr( $link, 1 ); 
  1183. $link = esc_url( strip_tags( $link ) ); 
  1184.  
  1185. $title = esc_html( trim( strip_tags( $item->get_title() ) ) ); 
  1186. if ( empty( $title ) ) { 
  1187. $title = __( 'Untitled' ); 
  1188.  
  1189. $desc = @html_entity_decode( $item->get_description(), ENT_QUOTES, get_option( 'blog_charset' ) ); 
  1190. $desc = esc_attr( wp_trim_words( $desc, 55, ' […]' ) ); 
  1191.  
  1192. $summary = ''; 
  1193. if ( $show_summary ) { 
  1194. $summary = $desc; 
  1195.  
  1196. // Change existing [...] to […]. 
  1197. if ( '[...]' == substr( $summary, -5 ) ) { 
  1198. $summary = substr( $summary, 0, -5 ) . '[…]'; 
  1199.  
  1200. $summary = '<div class="rssSummary">' . esc_html( $summary ) . '</div>'; 
  1201.  
  1202. $date = ''; 
  1203. if ( $show_date ) { 
  1204. $date = $item->get_date( 'U' ); 
  1205.  
  1206. if ( $date ) { 
  1207. $date = ' <span class="rss-date">' . date_i18n( get_option( 'date_format' ), $date ) . '</span>'; 
  1208.  
  1209. $author = ''; 
  1210. if ( $show_author ) { 
  1211. $author = $item->get_author(); 
  1212. if ( is_object($author) ) { 
  1213. $author = $author->get_name(); 
  1214. $author = ' <cite>' . esc_html( strip_tags( $author ) ) . '</cite>'; 
  1215.  
  1216. if ( $link == '' ) { 
  1217. echo "<li>$title{$date}{$summary}{$author}</li>"; 
  1218. } elseif ( $show_summary ) { 
  1219. echo "<li><a class='rsswidget' href='$link'>$title</a>{$date}{$summary}{$author}</li>"; 
  1220. } else { 
  1221. echo "<li><a class='rsswidget' href='$link'>$title</a>{$date}{$author}</li>"; 
  1222. echo '</ul>'; 
  1223. $rss->__destruct(); 
  1224. unset($rss); 
  1225.  
  1226. /** 
  1227. * Display RSS widget options form. 
  1228. * 
  1229. * The options for what fields are displayed for the RSS form are all booleans 
  1230. * and are as follows: 'url', 'title', 'items', 'show_summary', 'show_author',  
  1231. * 'show_date'. 
  1232. * 
  1233. * @since 2.5.0 
  1234. * 
  1235. * @param array|string $args Values for input fields. 
  1236. * @param array $inputs Override default display options. 
  1237. */ 
  1238. function wp_widget_rss_form( $args, $inputs = null ) { 
  1239. $default_inputs = array( 'url' => true, 'title' => true, 'items' => true, 'show_summary' => true, 'show_author' => true, 'show_date' => true ); 
  1240. $inputs = wp_parse_args( $inputs, $default_inputs ); 
  1241.  
  1242. $args['title'] = isset( $args['title'] ) ? $args['title'] : ''; 
  1243. $args['url'] = isset( $args['url'] ) ? $args['url'] : ''; 
  1244. $args['items'] = isset( $args['items'] ) ? (int) $args['items'] : 0; 
  1245.  
  1246. if ( $args['items'] < 1 || 20 < $args['items'] ) { 
  1247. $args['items'] = 10; 
  1248.  
  1249. $args['show_summary'] = isset( $args['show_summary'] ) ? (int) $args['show_summary'] : (int) $inputs['show_summary']; 
  1250. $args['show_author'] = isset( $args['show_author'] ) ? (int) $args['show_author'] : (int) $inputs['show_author']; 
  1251. $args['show_date'] = isset( $args['show_date'] ) ? (int) $args['show_date'] : (int) $inputs['show_date']; 
  1252.  
  1253. if ( ! empty( $args['error'] ) ) { 
  1254. echo '<p class="widget-error"><strong>' . __( 'RSS Error:' ) . '</strong> ' . $args['error'] . '</p>'; 
  1255.  
  1256. $esc_number = esc_attr( $args['number'] ); 
  1257. if ( $inputs['url'] ) : 
  1258. ?> 
  1259. <p><label for="rss-url-<?php echo $esc_number; ?>"><?php _e( 'Enter the RSS feed URL here:' ); ?></label> 
  1260. <input class="widefat" id="rss-url-<?php echo $esc_number; ?>" name="widget-rss[<?php echo $esc_number; ?>][url]" type="text" value="<?php echo esc_url( $args['url'] ); ?>" /></p> 
  1261. <?php endif; if ( $inputs['title'] ) : ?> 
  1262. <p><label for="rss-title-<?php echo $esc_number; ?>"><?php _e( 'Give the feed a title (optional):' ); ?></label> 
  1263. <input class="widefat" id="rss-title-<?php echo $esc_number; ?>" name="widget-rss[<?php echo $esc_number; ?>][title]" type="text" value="<?php echo esc_attr( $args['title'] ); ?>" /></p> 
  1264. <?php endif; if ( $inputs['items'] ) : ?> 
  1265. <p><label for="rss-items-<?php echo $esc_number; ?>"><?php _e( 'How many items would you like to display?' ); ?></label> 
  1266. <select id="rss-items-<?php echo $esc_number; ?>" name="widget-rss[<?php echo $esc_number; ?>][items]"> 
  1267. <?php 
  1268. for ( $i = 1; $i <= 20; ++$i ) { 
  1269. echo "<option value='$i' " . selected( $args['items'], $i, false ) . ">$i</option>"; 
  1270. ?> 
  1271. </select></p> 
  1272. <?php endif; if ( $inputs['show_summary'] ) : ?> 
  1273. <p><input id="rss-show-summary-<?php echo $esc_number; ?>" name="widget-rss[<?php echo $esc_number; ?>][show_summary]" type="checkbox" value="1" <?php checked( $args['show_summary'] ); ?> /> 
  1274. <label for="rss-show-summary-<?php echo $esc_number; ?>"><?php _e( 'Display item content?' ); ?></label></p> 
  1275. <?php endif; if ( $inputs['show_author'] ) : ?> 
  1276. <p><input id="rss-show-author-<?php echo $esc_number; ?>" name="widget-rss[<?php echo $esc_number; ?>][show_author]" type="checkbox" value="1" <?php checked( $args['show_author'] ); ?> /> 
  1277. <label for="rss-show-author-<?php echo $esc_number; ?>"><?php _e( 'Display item author if available?' ); ?></label></p> 
  1278. <?php endif; if ( $inputs['show_date'] ) : ?> 
  1279. <p><input id="rss-show-date-<?php echo $esc_number; ?>" name="widget-rss[<?php echo $esc_number; ?>][show_date]" type="checkbox" value="1" <?php checked( $args['show_date'] ); ?>/> 
  1280. <label for="rss-show-date-<?php echo $esc_number; ?>"><?php _e( 'Display item date?' ); ?></label></p> 
  1281. <?php 
  1282. endif; 
  1283. foreach ( array_keys($default_inputs) as $input ) : 
  1284. if ( 'hidden' === $inputs[$input] ) : 
  1285. $id = str_replace( '_', '-', $input ); 
  1286. ?> 
  1287. <input type="hidden" id="rss-<?php echo esc_attr( $id ); ?>-<?php echo $esc_number; ?>" name="widget-rss[<?php echo $esc_number; ?>][<?php echo esc_attr( $input ); ?>]" value="<?php echo esc_attr( $args[ $input ] ); ?>" /> 
  1288. <?php 
  1289. endif; 
  1290. endforeach; 
  1291.  
  1292. /** 
  1293. * Process RSS feed widget data and optionally retrieve feed items. 
  1294. * 
  1295. * The feed widget can not have more than 20 items or it will reset back to the 
  1296. * default, which is 10. 
  1297. * 
  1298. * The resulting array has the feed title, feed url, feed link (from channel),  
  1299. * feed items, error (if any), and whether to show summary, author, and date. 
  1300. * All respectively in the order of the array elements. 
  1301. * 
  1302. * @since 2.5.0 
  1303. * 
  1304. * @param array $widget_rss RSS widget feed data. Expects unescaped data. 
  1305. * @param bool $check_feed Optional, default is true. Whether to check feed for errors. 
  1306. * @return array 
  1307. */ 
  1308. function wp_widget_rss_process( $widget_rss, $check_feed = true ) { 
  1309. $items = (int) $widget_rss['items']; 
  1310. if ( $items < 1 || 20 < $items ) 
  1311. $items = 10; 
  1312. $url = esc_url_raw( strip_tags( $widget_rss['url'] ) ); 
  1313. $title = isset( $widget_rss['title'] ) ? trim( strip_tags( $widget_rss['title'] ) ) : ''; 
  1314. $show_summary = isset( $widget_rss['show_summary'] ) ? (int) $widget_rss['show_summary'] : 0; 
  1315. $show_author = isset( $widget_rss['show_author'] ) ? (int) $widget_rss['show_author'] :0; 
  1316. $show_date = isset( $widget_rss['show_date'] ) ? (int) $widget_rss['show_date'] : 0; 
  1317.  
  1318. if ( $check_feed ) { 
  1319. $rss = fetch_feed($url); 
  1320. $error = false; 
  1321. $link = ''; 
  1322. if ( is_wp_error($rss) ) { 
  1323. $error = $rss->get_error_message(); 
  1324. } else { 
  1325. $link = esc_url(strip_tags($rss->get_permalink())); 
  1326. while ( stristr($link, 'http') != $link ) 
  1327. $link = substr($link, 1); 
  1328.  
  1329. $rss->__destruct(); 
  1330. unset($rss); 
  1331.  
  1332. return compact( 'title', 'url', 'link', 'items', 'error', 'show_summary', 'show_author', 'show_date' ); 
  1333.  
  1334. /** 
  1335. * Registers all of the default WordPress widgets on startup. 
  1336. * 
  1337. * Calls {@see 'widgets_init'} action after all of the WordPress widgets have been registered. 
  1338. * 
  1339. * @since 2.2.0 
  1340. */ 
  1341. function wp_widgets_init() { 
  1342. if ( !is_blog_installed() ) 
  1343. return; 
  1344.  
  1345. register_widget('WP_Widget_Pages'); 
  1346.  
  1347. register_widget('WP_Widget_Calendar'); 
  1348.  
  1349. register_widget('WP_Widget_Archives'); 
  1350.  
  1351. if ( get_option( 'link_manager_enabled' ) ) 
  1352. register_widget('WP_Widget_Links'); 
  1353.  
  1354. register_widget('WP_Widget_Meta'); 
  1355.  
  1356. register_widget('WP_Widget_Search'); 
  1357.  
  1358. register_widget('WP_Widget_Text'); 
  1359.  
  1360. register_widget('WP_Widget_Categories'); 
  1361.  
  1362. register_widget('WP_Widget_Recent_Posts'); 
  1363.  
  1364. register_widget('WP_Widget_Recent_Comments'); 
  1365.  
  1366. register_widget('WP_Widget_RSS'); 
  1367.  
  1368. register_widget('WP_Widget_Tag_Cloud'); 
  1369.  
  1370. register_widget('WP_Nav_Menu_Widget'); 
  1371.  
  1372. /** 
  1373. * Fires after all default WordPress widgets have been registered. 
  1374. * 
  1375. * @since 2.2.0 
  1376. */ 
  1377. do_action( 'widgets_init' ); 
.