From time to time I need to change widget content after it’s getting saved. Unfortunately, it’s not obvious how to get access to it. And additionally, it depends on how you’re using widgets in general.

If you’re using a block theme with the site editor, you’re out. The site editor doesn’t know the concept of widgets and thus you cannot use it. However, that’s not a problem at all, since you can define the layout already to your liking.

However, depending on your theme and plugins you either have the legacy widget area as before WordPress 5.8, e.g. with the Classic Widgets plugin or the widget blocks introducing in WordPress 5.8.

Using the classic widgets, there’s a hook widget_update_callback, which allows you to access the widget object after it has been added or updated. You can then access the widget’s settings, which include every data of the widget. You can access the content of the widget either via the content or text array index, like this:

function my_update_widget_content( array $instance ): array {
	$content = ! empty( $instance['text'] ) ? $instance['text'] : ( $instance['content'] ?? '' ); 
	
	// do something
	
	return $instance;
}

add_filter( 'widget_update_callback', 'my_update_widget_content' );
Code language: PHP (php)

Note: There are additional attributes available to this hook, please check the documentation for more information.

The other way using widget blocks uses another hook since the update mechanism is completely different and uses the REST API. This hook is called rest_after_save_widget and is built differently. Besides the widget ID, sidebar ID and whether the widget is created or updated, the whole REST request is available as parameter to this hook. Additionally, it’s not a filter but an action. So to update its content during this action, you must trigger an update manually as well as make sure the action then doesn’t run, since it’s otherwise result in an endless loop.

You can get the widget settings instance via the instance parameter:

function my_update_rest_widget_content( $id, $sidebar_id, $request ): void {
	if ( ! $request->get_param( 'instance' ) || ! isset( $request->get_param( 'instance' )['raw']['content'] ) ) {
		return;
	}
	
	$new_content = ''; // do something
	
	if ( $new_content !== $request->get_param( 'instance' )['raw']['content'] ) {
		remove_action( 'rest_after_save_widget', 'my_update_rest_widget_content', 10, 3 );
		
		$request->set_param( 'instance', [ 'raw' => [ 'content' => $new_content ] ] );
		( new WP_REST_Widgets_Controller() )->update_item( $request );
		
		add_action( 'rest_after_save_widget', 'my_update_rest_widget_content', 10, 3 );
	}
}

add_action( 'rest_after_save_widget', 'my_update_rest_widget_content', 10, 3 );
Code language: PHP (php)

Leave a Reply

Your email address will not be published. Required fields are marked *