WP_REST_Widgets_Controller::save_widget( WP_REST_Request $request, string $sidebar_id ): string|WP_Error

In this article

Saves the widget in the request object.

Parameters

$requestWP_REST_Requestrequired
Full details about the request.
$sidebar_idstringrequired
ID of the sidebar the widget belongs to.

Return

string|WP_Error The saved widget ID.

Source

protected function save_widget( $request, $sidebar_id ) {
	global $wp_widget_factory, $wp_registered_widget_updates;

	require_once ABSPATH . 'wp-admin/includes/widgets.php'; // For next_widget_id_number().

	if ( isset( $request['id'] ) ) {
		// Saving an existing widget.
		$id            = $request['id'];
		$parsed_id     = wp_parse_widget_id( $id );
		$id_base       = $parsed_id['id_base'];
		$number        = isset( $parsed_id['number'] ) ? $parsed_id['number'] : null;
		$widget_object = $wp_widget_factory->get_widget_object( $id_base );
		$creating      = false;
	} elseif ( $request['id_base'] ) {
		// Saving a new widget.
		$id_base       = $request['id_base'];
		$widget_object = $wp_widget_factory->get_widget_object( $id_base );
		$number        = $widget_object ? next_widget_id_number( $id_base ) : null;
		$id            = $widget_object ? $id_base . '-' . $number : $id_base;
		$creating      = true;
	} else {
		return new WP_Error(
			'rest_invalid_widget',
			__( 'Widget type (id_base) is required.' ),
			array( 'status' => 400 )
		);
	}

	if ( ! isset( $wp_registered_widget_updates[ $id_base ] ) ) {
		return new WP_Error(
			'rest_invalid_widget',
			__( 'The provided widget type (id_base) cannot be updated.' ),
			array( 'status' => 400 )
		);
	}

	if ( isset( $request['instance'] ) ) {
		if ( ! $widget_object ) {
			return new WP_Error(
				'rest_invalid_widget',
				__( 'Cannot set instance on a widget that does not extend WP_Widget.' ),
				array( 'status' => 400 )
			);
		}

		if ( isset( $request['instance']['raw'] ) ) {
			if ( empty( $widget_object->widget_options['show_instance_in_rest'] ) ) {
				return new WP_Error(
					'rest_invalid_widget',
					__( 'Widget type does not support raw instances.' ),
					array( 'status' => 400 )
				);
			}
			$instance = $request['instance']['raw'];
		} elseif ( isset( $request['instance']['encoded'], $request['instance']['hash'] ) ) {
			$serialized_instance = base64_decode( $request['instance']['encoded'] );
			if ( ! hash_equals( wp_hash( $serialized_instance ), $request['instance']['hash'] ) ) {
				return new WP_Error(
					'rest_invalid_widget',
					__( 'The provided instance is malformed.' ),
					array( 'status' => 400 )
				);
			}
			$instance = unserialize( $serialized_instance );
		} else {
			return new WP_Error(
				'rest_invalid_widget',
				__( 'The provided instance is invalid. Must contain raw OR encoded and hash.' ),
				array( 'status' => 400 )
			);
		}

		$form_data = array(
			"widget-$id_base" => array(
				$number => $instance,
			),
			'sidebar'         => $sidebar_id,
		);
	} elseif ( isset( $request['form_data'] ) ) {
		$form_data = $request['form_data'];
	} else {
		$form_data = array();
	}

	$original_post    = $_POST;
	$original_request = $_REQUEST;

	foreach ( $form_data as $key => $value ) {
		$slashed_value    = wp_slash( $value );
		$_POST[ $key ]    = $slashed_value;
		$_REQUEST[ $key ] = $slashed_value;
	}

	$callback = $wp_registered_widget_updates[ $id_base ]['callback'];
	$params   = $wp_registered_widget_updates[ $id_base ]['params'];

	if ( is_callable( $callback ) ) {
		ob_start();
		call_user_func_array( $callback, $params );
		ob_end_clean();
	}

	$_POST    = $original_post;
	$_REQUEST = $original_request;

	if ( $widget_object ) {
		// Register any multi-widget that the update callback just created.
		$widget_object->_set( $number );
		$widget_object->_register_one( $number );

		/*
		 * WP_Widget sets `updated = true` after an update to prevent more than one widget
		 * from being saved per request. This isn't what we want in the REST API, though,
		 * as we support batch requests.
		 */
		$widget_object->updated = false;
	}

	/**
	 * Fires after a widget is created or updated via the REST API.
	 *
	 * @since 5.8.0
	 *
	 * @param string          $id         ID of the widget being saved.
	 * @param string          $sidebar_id ID of the sidebar containing the widget being saved.
	 * @param WP_REST_Request $request    Request object.
	 * @param bool            $creating   True when creating a widget, false when updating.
	 */
	do_action( 'rest_after_save_widget', $id, $sidebar_id, $request, $creating );

	return $id;
}

Hooks

do_action( ‘rest_after_save_widget’, string $id, string $sidebar_id, WP_REST_Request $request, bool $creating )

Fires after a widget is created or updated via the REST API.

Changelog

VersionDescription
5.8.0Introduced.

User Contributed Notes

You must log in before being able to contribute a note or feedback.