REST API Changes in WordPress 5.8

The following is a snapshot of some of the changes to the REST APIREST API The REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) https://developer.wordpress.org/rest-api/. in WordPress 5.8. For more details, see the full list of closed tickets.

Widgets

WordPress 5.8 sees the introduction of a new blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience.-based widgets editor and with it the creation of several REST API endpoints dedicated to widgetWidget A WordPress Widget is a small block that performs a specific function. You can add these widgets in sidebars also known as widget-ready areas on your web page. WordPress widgets were originally created to provide a simple and easy-to-use way of giving design and structure control of the WordPress theme to the user. management. Before diving in to how the new endpoints operate, I’d like to provide some background about how widgets work that should make the following sections more clear.

Instance Widgets

The predominant way to create widgets is to subclass the WP_Widget base class and register the widget with register_widget. These are referred to as “multi” widgets. These widgets have multiple instances that are identified by their number, an incrementing integer for each widget type.

Each instance has its own setting values. These are stored and fetched by WP_Widget which allows for the REST API to include these values. However, since a widget’s instance can contain arbitrary data, for example a DateTime object, the REST API cannot always serialize a widget to JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML.. As such, a widget’s data is always serialized using the PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher serialize function and then base64 encoded. This data is also exposed with a hash value which is a wp_hash signature of this value to prevent clients from sending arbitrary data to be deserialized with unserialize.

For widgets that can be safely accept and expose their instance data as JSON, pass the show_instance_in_rest flag in the $widget_options parameter.

class ExampleWidget extends WP_Widget {
    ...
    /**
     * Sets up the widget
     */
    public function __construct() {
        $widget_ops = array(
            // ...other options here
            'show_instance_in_rest' => true,
            // ...other options here
        );
        parent::__construct( 'example_widget', 'ExampleWidget', $widget_ops );
    }
    ...
}

Reference Widgets

Far less common, but still supported, are widgets that are registered using wp_register_sidebar_widget and wp_register_widget_control directly. These are referred to as “reference”, “function-based”, or “non-multi” widgets. These widgets can store their data in an arbitrary location. As such, their instance values are never included in the REST API.

Widget Types

Accessible via /wp/v2/widget-types, the widget types endpoint describes the different widget types that are registered on the server. The endpoint is accessible to users who have permission to edit_theme_options. By default, this is limited to Administrator users.

Response Format

{
  "id": "pages",
  "name": "Pages",
  "description": "A list of your site’s Pages.",
  "is_multi": true,
  "classname": "widget_pages",
  "_links": {
    "collection": [
      {
        "href": "https://trunk.test/wp-json/wp/v2/widget-types"
      }
    ],
    "self": [
      {
        "href": "https://trunk.test/wp-json/wp/v2/widget-types/pages"
      }
    ]
  }
}

Encode Endpoint

Multi widgets have access to the /wp/v2/widget-types/<widget>/encode endpoint. This endpoint is used to convert htmlHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. form data for the widget to the next instance for the widget, render the widget form, and render the widget preview.

For example, let’s say we want to interact with the MetaMeta Meta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress. widget. First, we’ll want to request the widget form from the server.

POST /wp/v2/widget-types/meta/encode
{
  "instance": {},
  "number": 1
}

For now, let’s assume we’re working with a new widget. The instance is empty because this is a new widget, so we’ll be rendering an empty form. The number argument can be omitted, but including one is recommended to provide stable input ids. You’ll receive a response similar to this. The widget preview has been snipped for brevity.

{
  "form": "<p><label for=\"widget-meta-1-title\">Title:</label><input class=\"widefat\" id=\"widget-meta-1-title\" name=\"widget-meta[1][title]\" type=\"text\" value=\"\" /></p>",
  "preview": "<div class=\"widget widget_meta\">...</div>",
  "instance": {
    "encoded": "YToxOntzOjU6InRpdGxlIjtzOjA6IiI7fQ==",
    "hash": "77e9f20acb54fa4f77de5a865333c0e6",
    "raw": {
      "title": ""
    }
  }
}

The provided form can then be rendered and edited by the user. When you want to render a new preview or are ready to begin saving, call the encode endpoint again with the url encoded form data and the instance value returned from the first response.

POST /wp/v2/widget-types/meta/encode
{
  "instance": {
    "encoded": "YToxOntzOjU6InRpdGxlIjtzOjA6IiI7fQ==",
    "hash": "77e9f20acb54fa4f77de5a865333c0e6",
    "raw": {
      "title": ""
    }
  },
  "number": 1,
  "form_data": "widget-meta%5B1%5D%5Btitle%5D=Site+Info"
}

The REST API will call the widget’s update function to calculate the new instance based on the provided form data. The instance object can then be used to save a widget via the widgets endpoint.

{
  "form": "<p><label for=\"widget-meta-1-title\">Title:</label><input class=\"widefat\" id=\"widget-meta-1-title\" name=\"widget-meta[1][title]\" type=\"text\" value=\"Site Info\" /></p>",
  "preview": "<div class=\"widget widget_meta\">...</div>",
  "instance": {
    "encoded": "YToxOntzOjU6InRpdGxlIjtzOjk6IlNpdGUgSW5mbyI7fQ==",
    "hash": "0e9a5bff2d28cba322c8cd27cd4e77af",
    "raw": {
      "title": "Site Info"
    }
  }
}

Widgets Endpoint

The widgets endpoint is used for performing CRUDCRUD Create, read, update and delete, the four basic functions of storing data. (More on Wikipedia.) operations on the saved widgets. Like the widget types endpoint, the widgets endpoints required the edit_theme_options capability to access.

To retrieve widgets, make a GET request to the /wp/v2/widgets endpoint. The sidebar parameter can be used to limit the response to widgets belonging to the requested sidebarSidebar A sidebar in WordPress is referred to a widget-ready area used by WordPress themes to display information that is not a part of the main content. It is not always a vertical column on the side. It can be a horizontal rectangle below or above the content area, footer, header, or any where in the theme..

To create a widget, for instance the widget from our previous example, make a POST request to the /wp/v2/widgets endpoint. The instance is the same value returned from the encode endpoint. The id_base is the unique identifier for the widget type and sidebar is the id of the sidebar to assign the widget to. Both are required.

POST /wp/v2/widgets
{
	"instance": {
		"encoded": "YToxOntzOjU6InRpdGxlIjtzOjk6IlNpdGUgSW5mbyI7fQ==",
		"hash": "0e9a5bff2d28cba322c8cd27cd4e77af",
		"raw": {
			"title": "Site Info"
		}
	},
	"sidebar": "sidebar-1",
	"id_base": "meta"
}

The endpoint will return information about the newly created widget.

{
  "id": "meta-1",
  "id_base": "meta",
  "sidebar": "sidebar-1",
  "rendered": "<div class=\"widget widget_meta\">...</div>",
  "rendered_form": "<p><label for=\"widget-meta-1-title\">Title:</label><input class=\"widefat\" id=\"widget-meta-1-title\" name=\"widget-meta[1][title]\" type=\"text\" value=\"Site Info\" /></p>",
  "instance": {
    "encoded": "YToxOntzOjU6InRpdGxlIjtzOjk6IlNpdGUgTWV0YSI7fQ==",
    "hash": "dac44c3ebfa0428fed61829fa151e4e8",
    "raw": {
      "title": "Site Info"
    }
  },
  "_links": {
    "self": [
      {
        "href": "https://trunk.test/wp-json/wp/v2/widgets/meta-1"
      }
    ],
    "collection": [
      {
        "href": "https://trunk.test/wp-json/wp/v2/widgets"
      }
    ],
    "about": [
      {
        "embeddable": true,
        "href": "https://trunk.test/wp-json/wp/v2/widget-types/meta"
      }
    ],
    "wp:sidebar": [
      {
        "href": "https://trunk.test/wp-json/wp/v2/sidebars/sidebar-1/"
      }
    ],
    "curies": [
      {
        "name": "wp",
        "href": "https://api.w.org/{rel}",
        "templated": true
      }
    ]
  }
}

Since the meta widget (and all other built-in widgets) is registered with show_instance_in_rest enabled you could bypass the encode endpoint and use instance.raw instead. For example, if we wanted to update the widget to have a new title, we could make the following PUT request to /wp/v2/widgets/meta-1.

PUT /wp/v2/widgets/meta-1
{
	"instance": {
		"raw": {
			"title": "Site Meta"
		}
	}
}

A PUT request can also be made to update the sidebar assigned to a widget by passing a new sidebar id in the request.

To delete a widget, send a DELETE request to the individual widget route. By default, deleting a widget will move a widget to the Inactive Widgets area. To permanently delete a widget, use the force parameter. For example: DELETE /wp/v2/widgets/meta-1?force=true.

Sidebars Endpoints

Found under /wp/v2/sidebars, the sidebars endpoint is used to manage a site’s registered sidebars (widget areas) and their assigned widgets. For example, the following is the response for the first footer area in the Twenty Twenty theme.

{
  "id": "sidebar-1",
  "name": "Footer #1",
  "description": "Widgets in this area will be displayed in the first column in the footer.",
  "class": "",
  "before_widget": "<div class=\"widget %2$s\"><div class=\"widget-content\">",
  "after_widget": "</div></div>",
  "before_title": "<h2 class=\"widget-title subheading heading-size-3\">",
  "after_title": "</h2>",
  "status": "active",
  "widgets": [
    "recent-posts-2",
    "recent-comments-2",
    "meta-1"
  ],
  "_links": {
    "collection": [
      {
        "href": "https://trunk.test/wp-json/wp/v2/sidebars"
      }
    ],
    "self": [
      {
        "href": "https://trunk.test/wp-json/wp/v2/sidebars/sidebar-1"
      }
    ],
    "wp:widget": [
      {
        "embeddable": true,
        "href": "https://trunk.test/wp-json/wp/v2/widgets?sidebar=sidebar-1"
      }
    ],
    "curies": [
      {
        "name": "wp",
        "href": "https://api.w.org/{rel}",
        "templated": true
      }
    ]
  }
}

The widgets property contains an ordered list of widget ids. While all other properties are readonly, the widgets property can be used to reorder a sidebar’s assigned widgets. Any widget ids omitted when updating the sidebar will be assigned to the Inactive Widgets sidebar area.

For example, making a PUT request to /wp/v2/sidebars/sidebar-1 with the following body will remove the Recent Comments widget, and move the Meta widget to the top of the sidebar.

PUT /wp/v2/sidebars/sidebar-1
{
  "widgets": [
    "meta-1",
    "recent-posts-2"
  ]
}

For more information about the changes to widgets in 5.8, check out the Block-based Widgets Editor dev notedev note Each important change in WordPress Core is documented in a developers note, (usually called dev note). Good dev notes generally include a description of the change, the decision that led to this change, and a description of how developers are supposed to work with that change. Dev notes are published on Make/Core blog during the beta phase of WordPress release cycle. Publishing dev notes is particularly important when plugin/theme authors and WordPress developers need to be aware of those changes.In general, all dev notes are compiled into a Field Guide at the beginning of the release candidate phase..

Additional Changes

Posts Collection Tax Query Accepts operator

By default, a post must contain at least one of the requested terms to be included in the response. As of [51026], the REST API accepts a new operator property that can be set to AND to require a post to contain all of the requested terms.

For example, /wp/v2/posts?tags[terms]=1,2,3&tags[operator]=AND will return posts that have tags with the ids of 1, 2, and 3.

See #41287 for more details.

Props to @noisysocks for reviewing.

#5-8, #dev-notes, #rest-api