Skip to content

Commit cc81250

Browse files
committed
REST API: Add sites endpoints
Introduces WP_REST_Sites_Controller plus tests. See #40365.
1 parent 5c7205d commit cc81250

5 files changed

Lines changed: 638 additions & 34 deletions

File tree

‎src/wp-includes/rest-api.php‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -325,10 +325,8 @@ function create_initial_rest_routes() {
325325
$controller->register_routes();
326326

327327
// Sites.
328-
if ( is_multisite() ) {
329-
$controller = new WP_REST_Sites_Controller();
330-
$controller->register_routes();
331-
}
328+
$controller = new WP_REST_Sites_Controller();
329+
$controller->register_routes();
332330

333331
$search_handlers = array(
334332
new WP_REST_Post_Search_Handler(),

‎src/wp-includes/rest-api/endpoints/class-wp-rest-sites-controller.php‎

Lines changed: 95 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,10 @@ public function get_item_permissions_check( $request ) {
408408
return new WP_Error( 'rest_multisite_not_installed', __( 'Multisite is not installed' ), array( 'status' => 400 ) );
409409
}
410410

411+
if ( is_super_admin() ) {
412+
return true;
413+
}
414+
411415
if ( ! empty( $request['context'] ) && 'edit' === $request['context'] && ! current_user_can( 'manage_sites' ) ) {
412416
return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit sites.' ), array( 'status' => rest_authorization_required_code() ) );
413417
}
@@ -452,6 +456,10 @@ public function create_item_permissions_check( $request ) {
452456
return new WP_Error( 'rest_multisite_not_installed', __( 'Multisite is not installed' ), array( 'status' => 400 ) );
453457
}
454458

459+
if ( is_super_admin() ) {
460+
return true;
461+
}
462+
455463
return current_user_can( 'create_sites' );
456464
}
457465

@@ -519,7 +527,16 @@ public function create_item( $request ) {
519527

520528
$schema = $this->get_item_schema();
521529

522-
if ( ! empty( $schema['properties']['meta'] ) && isset( $request['meta'] ) ) {
530+
if ( isset( $request['meta'] ) ) {
531+
if ( empty( $schema['properties']['meta'] ) ) {
532+
return new WP_Error(
533+
'rest_site_meta_not_supported',
534+
/* translators: %s: database table name */
535+
sprintf( __( 'The %s table is not installed. Please run the network database upgrade.' ), $GLOBALS['wpdb']->blogmeta ),
536+
array( 'status' => 400 )
537+
);
538+
}
539+
523540
$meta_update = $this->meta->update_value( $request['meta'], $site_id );
524541

525542
if ( is_wp_error( $meta_update ) ) {
@@ -613,14 +630,13 @@ public function update_item( $request ) {
613630

614631
$schema = $this->get_item_schema();
615632

616-
if ( ! empty( $schema['properties']['meta'] ) && isset( $request['meta'] ) ) {
617-
if ( function_exists( 'is_site_meta_supported' ) && ! is_site_meta_supported() ) {
618-
633+
if ( isset( $request['meta'] ) ) {
634+
if ( empty( $schema['properties']['meta'] ) ) {
619635
return new WP_Error(
620-
'reset_site_meta_not_supported',
636+
'rest_site_meta_not_supported',
621637
/* translators: %s: database table name */
622638
sprintf( __( 'The %s table is not installed. Please run the network database upgrade.' ), $GLOBALS['wpdb']->blogmeta ),
623-
array( 'status' => 500 )
639+
array( 'status' => 400 )
624640
);
625641
}
626642

@@ -666,7 +682,7 @@ public function delete_item_permissions_check( $request ) {
666682
return new WP_Error( 'rest_multisite_not_installed', __( 'Multisite is not installed' ), array( 'status' => 400 ) );
667683
}
668684

669-
if ( ! current_user_can( 'delete_sites' ) ) {
685+
if ( ! current_user_can( 'delete_sites' ) && ! is_super_admin() ) {
670686
return new WP_Error( 'rest_cannot_delete', __( 'Sorry, you are not allowed to delete this site.' ), array( 'status' => rest_authorization_required_code() ) );
671687
}
672688

@@ -749,25 +765,65 @@ public function prepare_item_for_response( $site, $request ) {
749765
return apply_filters( 'rest_prepare_site', new WP_REST_Response( array() ), $site, $request );
750766
}
751767

752-
$data = array(
753-
'id' => (int) $site->blog_id,
754-
'network' => (int) $site->site_id,
755-
'domain' => $site->domain,
756-
'path' => $site->path,
757-
'registered' => $this->prepare_date_response( $site->registered ),
758-
'registered_gmt' => $this->prepare_date_response( $site->registered, true ),
759-
'last_updated' => $this->prepare_date_response( $site->last_updated ),
760-
'last_updated_gmt' => $this->prepare_date_response( $site->last_updated, true ),
761-
'public' => (bool) $site->public,
762-
'archived' => (bool) $site->archived,
763-
'mature' => (bool) $site->mature,
764-
'spam' => (bool) $site->spam,
765-
'deleted' => (bool) $site->deleted,
766-
'lang_id' => (int) $site->lang_id,
767-
);
768-
768+
$data = array();
769769
$fields = $this->get_fields_for_response( $request );
770770

771+
if ( rest_is_field_included( 'id', $fields ) ) {
772+
$data['id'] = (int) $site->blog_id;
773+
}
774+
775+
if ( rest_is_field_included( 'network', $fields ) ) {
776+
$data['network'] = (int) $site->site_id;
777+
}
778+
779+
if ( rest_is_field_included( 'domain', $fields ) ) {
780+
$data['domain'] = $site->domain;
781+
}
782+
783+
if ( rest_is_field_included( 'path', $fields ) ) {
784+
$data['path'] = $site->path;
785+
}
786+
787+
if ( rest_is_field_included( 'registered', $fields ) ) {
788+
$data['registered'] = $this->prepare_date_response( $site->registered );
789+
}
790+
791+
if ( rest_is_field_included( 'registered_gmt', $fields ) ) {
792+
$data['registered_gmt'] = $this->prepare_date_response( $site->registered, true );
793+
}
794+
795+
if ( rest_is_field_included( 'last_updated', $fields ) ) {
796+
$data['last_updated'] = $this->prepare_date_response( $site->last_updated );
797+
}
798+
799+
if ( rest_is_field_included( 'last_updated_gmt', $fields ) ) {
800+
$data['last_updated_gmt'] = $this->prepare_date_response( $site->last_updated, true );
801+
}
802+
803+
if ( rest_is_field_included( 'public', $fields ) ) {
804+
$data['public'] = (bool) $site->public;
805+
}
806+
807+
if ( rest_is_field_included( 'archived', $fields ) ) {
808+
$data['archived'] = (bool) $site->archived;
809+
}
810+
811+
if ( rest_is_field_included( 'mature', $fields ) ) {
812+
$data['mature'] = (bool) $site->mature;
813+
}
814+
815+
if ( rest_is_field_included( 'spam', $fields ) ) {
816+
$data['spam'] = (bool) $site->spam;
817+
}
818+
819+
if ( rest_is_field_included( 'deleted', $fields ) ) {
820+
$data['deleted'] = (bool) $site->deleted;
821+
}
822+
823+
if ( rest_is_field_included( 'lang_id', $fields ) ) {
824+
$data['lang_id'] = (int) $site->lang_id;
825+
}
826+
771827
// These four are not columns of the sites table. Reading one switches to the site.
772828
if ( rest_is_field_included( 'blogname', $fields ) ) {
773829
$data['blogname'] = $site->blogname;
@@ -943,6 +999,10 @@ protected function prepare_item_for_database( $request ) {
943999
* @return array
9441000
*/
9451001
public function get_item_schema() {
1002+
if ( $this->schema ) {
1003+
return $this->add_additional_fields_schema( $this->schema );
1004+
}
1005+
9461006
$schema = array(
9471007
'$schema' => 'http://json-schema.org/schema#',
9481008
'title' => 'site',
@@ -1074,9 +1134,14 @@ public function get_item_schema() {
10741134
),
10751135
);
10761136

1077-
$schema['properties']['meta'] = $this->meta->get_field_schema();
1137+
// Not all sites support site meta, do not register if the site does not support it.
1138+
if ( is_site_meta_supported() ) {
1139+
$schema['properties']['meta'] = $this->meta->get_field_schema();
1140+
}
1141+
1142+
$this->schema = $schema;
10781143

1079-
return $this->add_additional_fields_schema( $schema );
1144+
return $this->add_additional_fields_schema( $this->schema );
10801145
}
10811146

10821147
/**
@@ -1273,6 +1338,10 @@ protected function check_edit_permission( $site ) {
12731338
return false;
12741339
}
12751340

1341+
if ( is_super_admin() ) {
1342+
return true;
1343+
}
1344+
12761345
return current_user_can( 'manage_sites' );
12771346
}
12781347
}

‎tests/phpunit/tests/rest-api/rest-schema-setup.php‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ public function test_expected_routes_in_schema() {
138138
'/wp/v2/users/(?P<user_id>(?:[\\d]+|me))/application-passwords/(?P<uuid>[\\w\\-]+)',
139139
'/wp/v2/comments',
140140
'/wp/v2/comments/(?P<id>[\\d]+)',
141+
'/wp/v2/sites',
142+
'/wp/v2/sites/(?P<id>[\\d]+)',
141143
'/wp/v2/global-styles/(?P<id>[\/\d+]+)',
142144
'/wp/v2/global-styles/(?P<parent>[\d]+)/revisions',
143145
'/wp/v2/global-styles/(?P<parent>[\d]+)/revisions/(?P<id>[\d]+)',

0 commit comments

Comments
 (0)