PageRenderTime 35ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/wp-includes/class-wp-widget.php

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