Skip to content
This repository has been archived by the owner on Jan 13, 2022. It is now read-only.

Commit

Permalink
Merge pull request #15 from WP-API/get_widget_endpoint
Browse files Browse the repository at this point in the history
Get widget endpoint
  • Loading branch information
westonruter committed Jan 31, 2016
2 parents 406de4b + 90aa7bc commit ac0b9d6
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 17 deletions.
197 changes: 181 additions & 16 deletions lib/class-wp-rest-widgets-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,27 @@ class WP_REST_Widgets_Controller extends WP_REST_Controller {
*/
public $widgets;

/**
* Registered widgets.
*/
public $registered_widgets;

/**
* Sidebars
*/
public $sidebars;

/**
* WP_REST_Widgets_Controller constructor.
*
* @param WP_Widget[] $widgets Widget objects.
*/
public function __construct( $widgets ) {
public function __construct( $widgets, $registered_widgets ) {
$this->namespace = 'wp/v2';
$this->rest_base = 'widgets';
$this->widgets = $widgets;
$this->registered_widgets = $registered_widgets;
$this->sidebars = wp_get_sidebars_widgets();

// @todo Now given $this->widgets, inject schema information for Core widgets in lieu of them being in core now. See #35574.

Expand Down Expand Up @@ -121,14 +133,105 @@ public function get_items_permissions_check( $request ) {
return true;
}

/**
* Get a collection of widgets
*
* @param WP_REST_Request $request Full details about the request.
* @return WP_Error|WP_REST_Response
*/
public function get_items( $request ) {
if ( empty( $this->registered_widgets ) ) {
return rest_ensure_response( array() );
};

$args = array();
$args['sidebar'] = $request['sidebar'];

// TODO pagination

$widgets = array();
foreach( $this->registered_widgets as $instance_id => $widget ) {
if ( !$this->get_instance_permissions_check( $instance_id ) ) {
continue;
}
if ( !is_null( $args['sidebar'] ) && $args['sidebar'] !== $this->get_instance_sidebar( $instance_id ) ) {
continue;
}
$data = $this->prepare_item_for_response( $widget, $request );
$widgets[] = $this->prepare_response_for_collection( $data );
}

if ( !empty( $widgets ) && !is_null( $args['sidebar'] ) ) {
$widgets = $this->sort_widgets_by_sidebar_order( $args['sidebar'], $widgets );
}

return rest_ensure_response( $widgets );
}

public function get_item_permissions_check( $request ) {
return true;
}

/**
* Check if current user can get the widget instance.
*
* @param string $instance_id Instance id
* @return bool
*/
public function get_instance_permissions_check( $instance_id ) {
// Require `edit_theme_options` to view unassigned widgets
$sidebar = $this->get_instance_sidebar( $instance_id );
if ( $sidebar === false || $sidebar == 'wp_inactive_widgets' ) {
return current_user_can( 'edit_theme_options' );
}

return true;
}

/**
* Get the sidebar a widget instance is assigned to
*
* @param string id Widget instance id
* @return bool|string Sidebar id it is assigned to or false if not found. Will
* return `wp_inactive_widgets` as sidebar for unassigned widgets
*/
public function get_instance_sidebar( $id ) {
foreach( $this->sidebars as $sidebar_id => $widgets ) {
if ( in_array( $id, $widgets ) ) {
return $sidebar_id;
}
}

return false;
}

/**
* Sort the widgets by their order in the sidebar.
*
* Widgets not assigned to the specified sidebar will be discarded.
*
* @param string sidebar Sidebar id
* @param array widgets Widgets to sort
* @return array
*/
public function sort_widgets_by_sidebar_order( $sidebar, $widgets ) {
if ( empty( $this->sidebars[$sidebar] ) ) {
return array();
}

$new_widgets = array();
foreach( $this->sidebars[$sidebar] as $widget_id ) {
foreach( $widgets as $widget ) {
if ( $widget_id === $widget['id'] ) {
$new_widgets[] = $widget;
break;
}
}
}

return $new_widgets;
}

public function get_item( $request ) {

}
Expand All @@ -141,16 +244,81 @@ public function delete_item( $request ) {

}

public function prepare_item_for_response( $item, $request ) {
/**
* Prepare a single widget output for response
*
* @param array $widget Widget instance
* @param WP_REST_Request $request Request object.
* @return WP_REST_Response $data
*/
public function prepare_item_for_response( $widget, $request ) {

$id = $widget['id'];
$id_base = $widget['callback'][0]->id_base;
$array_key = $widget['params'][0]['number'];

$values = array(
'id' => $id,
'type' => $id_base,
);
if ( !empty( $array_key ) ) {
$widgets = get_option( 'widget_' . $id_base );
if ( isset( $widgets[$array_key] ) ) {
$values = array_merge( $values, $widgets[$array_key] );
}
}

$schema = $this->get_type_schema( $widget['callback'][0]->id_base );

$data = array();
foreach( $schema['properties'] as $property_id => $property ) {

// TODO check for public visibility of property and run permissions
// check for private properties.

if ( isset( $values[$property_id] ) && gettype( $values[$property_id] ) === $property['type'] ) {
$data[$property_id] = $values[$property_id];
} elseif ( isset( $property['default'] ) ) {
$data[$property_id] = $property['default'];
}
}

$response = rest_ensure_response( $data );

// @TODO Add _link to sidebar if assigned?
/**
* Filter the widget data for a response.
*
* @param WP_REST_Response $response The response object.
* @param array $widget Widget instance.
* @param WP_REST_Request $request Request object.
*/
return apply_filters( 'rest_prepare_widget', $response, $widget, $request );
}

public function get_item_schema() {

}

/**
* Get the query params for collections of attachments.
*
* @return array
*/
public function get_collection_params() {
return array();
$params = parent::get_collection_params();

$params['context']['default'] = 'view';

$params['sidebar'] = array(
'description' => __( 'Limit result set to widgets assigned to this sidebar.' ),
'type' => 'string',
'default' => null,
'sanitize_callback' => 'sanitize_key',
);

return $params;
}

/**
Expand Down Expand Up @@ -185,17 +353,17 @@ public function get_types( $request ) {
*/
public function get_type( $request ) {

if ( empty( $request['type'] ) ) {
return new WP_Error( 'rest_widget_missing_type', __( 'Request missing widget type.' ), array( 'status' => 400 ) );
}
if ( empty( $request['type'] ) ) {
return new WP_Error( 'rest_widget_missing_type', __( 'Request missing widget type.' ), array( 'status' => 400 ) );
}

$schema = $this->get_type_schema( $request['type'] );
$schema = $this->get_type_schema( $request['type'] );

if ( $schema === false ) {
return new WP_Error( 'rest_widget_type_not_found', __( 'Requested widget type was not found.' ), array( 'status' => 404 ) );
}
if ( $schema === false ) {
return new WP_Error( 'rest_widget_type_not_found', __( 'Requested widget type was not found.' ), array( 'status' => 404 ) );
}

return rest_ensure_response( $schema );
return rest_ensure_response( $schema );
}

/**
Expand All @@ -211,9 +379,6 @@ public function get_types_permissions_check( $request ) {
/**
* Return a schema matching this widget type
*
* TODO this is a placeholder. A final implementation needs to look up a
* schema which would specify the visibility and type of widget control options.
*
* @param string $id_base Registered widget type
* @return array $schema
*/
Expand Down Expand Up @@ -292,13 +457,13 @@ public function get_type_schema( $id_base ) {
'default' => '',
),
),
'recent_comments' => array(
'recent-comments' => array(
'number' => array(
'type' => 'integer',
'default' => 5,
),
),
'recent_posts' => array(
'recent-posts' => array(
'number' => array(
'type' => 'integer',
'default' => 5,
Expand Down
7 changes: 6 additions & 1 deletion plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ function wp_api_nav_menus_widgets_init_controllers() {
*/
global $wp_widget_factory;

$widgets_controller = new WP_REST_Widgets_Controller( $wp_widget_factory->widgets );
/**
* @type array $wp_registered_widgets
*/
global $wp_registered_widgets;

$widgets_controller = new WP_REST_Widgets_Controller( $wp_widget_factory->widgets, $wp_registered_widgets );
$widgets_controller->register_routes();
}

0 comments on commit ac0b9d6

Please sign in to comment.