Skip to content
Open
90 changes: 90 additions & 0 deletions includes/wp-api-menus-v1.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ public function register_routes( $routes ) {
$routes['/menus/(?P<id>\d+)'] = array(
array( array( $this, 'get_menu' ), WP_JSON_Server::READABLE ),
);
// a specific menu rendered in html
$routes['/menu-html/(?P<id>[a-zA-Z0-9_-]+)'] = array(
array( array( $this, 'get_menu_html' ), WP_JSON_Server::READABLE ),
);
// all registered menu locations
$routes['/menu-locations'] = array(
array( array( $this, 'get_menu_locations' ), WP_JSON_Server::READABLE ),
Expand All @@ -48,6 +52,10 @@ public function register_routes( $routes ) {
$routes['/menu-locations/(?P<location>[a-zA-Z0-9_-]+)'] = array(
array( array( $this, 'get_menu_location' ), WP_JSON_Server::READABLE ),
);
// menu for given location rendered in html
$routes['/menu-html-location/(?P<location>[a-zA-Z0-9_-]+)'] = array(
array( array( $this, 'get_menu_html_location' ), WP_JSON_Server::READABLE ),
);

return $routes;
}
Expand All @@ -62,6 +70,7 @@ public function register_routes( $routes ) {
public static function get_menus() {

$json_url = get_json_url() . '/menus/';
$json_url_base = get_json_url();
$wp_menus = wp_get_nav_menus();

$i = 0;
Expand All @@ -79,6 +88,7 @@ public static function get_menus() {

$json_menus[ $i ]['meta']['links']['collection'] = $json_url;
$json_menus[ $i ]['meta']['links']['self'] = $json_url . $menu['term_id'];
$json_menus[ $i ]['meta']['links']['self'] = $json_url_base . '/menu-html/' . $menu['term_id'];

$i ++;
endforeach;
Expand Down Expand Up @@ -126,6 +136,43 @@ public function get_menu( $id ) {
}


/**
* Get a menu rendered in html.
*
* @since 1.0.0
* @param int $id ID of the menu
* @return array Menu data
*/
public function get_menu_html( $menu_id ) {

$json_url_base = get_json_url();
$wp_menu_object = $menu_id ? wp_get_nav_menu_object( $menu_id ) : array();
$wp_menu_items = $menu_id ? wp_get_nav_menu_items( $menu_id ) : array();

$json_menu = array();

if ( $wp_menu_object ) :

$menu = (array) $wp_menu_object;
$json_menu['ID'] = abs( $menu['term_id'] );
$json_menu['name'] = $menu['name'];
$json_menu['slug'] = $menu['slug'];
$json_menu['description'] = $menu['description'];
$json_menu['count'] = abs( $menu['count'] );

ob_start();
wp_nav_menu( array( 'menu' => $menu_id ) );
$json_menu['html']=ob_get_clean();

$json_menu['meta']['links']['collection'] = $json_url_base . '/menus/';
$json_menu['meta']['links']['self'] = $json_url_base . '/menu-html/' . $menu_id;

endif;

return $json_menu;
}


/**
* Get menu locations.
*
Expand All @@ -137,6 +184,7 @@ public static function get_menu_locations() {
$locations = get_nav_menu_locations();
$registered_menus = get_registered_nav_menus();
$json_url = get_json_url() . '/menu-locations/';
$json_url_base = get_json_url();
$json_menus = array();

if ( $locations && $registered_menus ) :
Expand All @@ -152,6 +200,7 @@ public static function get_menu_locations() {
$json_menus[ $slug ]['label'] = $label;
$json_menus[ $slug ]['meta']['links']['collection'] = $json_url;
$json_menus[ $slug ]['meta']['links']['self'] = $json_url . $slug;
$json_menus[ $slug ]['meta']['links']['html'] = $json_url_base . '/menu-html-location/' . $slug;

endforeach;

Expand Down Expand Up @@ -214,6 +263,47 @@ public function get_menu_location( $location ) {
return $menu;
}

/**
* Get menu rendered in html for location.
*
* @since 1.x.0
* @param string $location The theme location menu name
* @return array The menu for the corresponding location
*/
public static function get_menu_html_location( $location ) {

$locations = get_nav_menu_locations();
if ( ! isset( $locations[ $location ] ) ) {
return array();
}

$wp_menu_object = get_term( $locations[$location], 'nav_menu' );
$json_url_base = get_json_url();

$json_menu = array();

if ( $wp_menu_object ) :

$menu = (array) $wp_menu_object;
$json_menu['ID'] = abs( $menu['term_id'] );
$json_menu['name'] = $menu['name'];
$json_menu['slug'] = $menu['slug'];
$json_menu['location_slug'] = $location;
$json_menu['description'] = $menu['description'];
$json_menu['count'] = abs( $menu['count'] );

ob_start();
wp_nav_menu( array( 'menu' => $location ) );
$json_menu['html']=ob_get_clean();

$json_menu['meta']['links']['collection'] = $json_url_base . '/menu-locations/';
$json_menu['meta']['links']['self'] = $json_url_base . '/menu-html-location/' . $location;

endif;

return $json_menu;
}


/**
* Returns all child nav_menu_items under a specific parent.
Expand Down
115 changes: 111 additions & 4 deletions includes/wp-api-menus-v2.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ public function register_routes() {
)
) );


register_rest_route( self::get_plugin_namespace(), '/menu-html/(?P<menu_id>[a-zA-Z0-9_-]+)', array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_menu_html' ),
'args' => array(
'context' => array(
'default' => 'view',
),
),
)
) );

register_rest_route( self::get_plugin_namespace(), '/menu-locations', array(
array(
'methods' => WP_REST_Server::READABLE,
Expand All @@ -86,6 +99,13 @@ public function register_routes() {
)
) );

register_rest_route( self::get_plugin_namespace(), '/menu-html-location/(?P<location>[a-zA-Z0-9_-]+)', array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_menu_html_location' ),
)
) );

}


Expand All @@ -98,6 +118,7 @@ public function register_routes() {
public static function get_menus() {

$rest_url = trailingslashit( get_rest_url() . self::get_plugin_namespace() . '/menus/' );
$rest_url_base = get_rest_url() . self::get_plugin_namespace();
$wp_menus = wp_get_nav_menus();

$i = 0;
Expand All @@ -115,6 +136,7 @@ public static function get_menus() {

$rest_menus[ $i ]['meta']['links']['collection'] = $rest_url;
$rest_menus[ $i ]['meta']['links']['self'] = $rest_url . $menu['term_id'];
$rest_menus[ $i ]['meta']['links']['html'] = $rest_url_base . '/menu-html/' . $menu['term_id'];

$i ++;
endforeach;
Expand All @@ -133,7 +155,7 @@ public static function get_menus() {
public function get_menu( $request ) {

$id = (int) $request['id'];
$rest_url = get_rest_url() . self::get_api_namespace() . '/menus/';
$rest_url = get_rest_url() . self::get_plugin_namespace() . '/menus/';
$wp_menu_object = $id ? wp_get_nav_menu_object( $id ) : array();
$wp_menu_items = $id ? wp_get_nav_menu_items( $id ) : array();

Expand Down Expand Up @@ -164,6 +186,44 @@ public function get_menu( $request ) {
return apply_filters( 'rest_menus_format_menu', $rest_menu );
}

/**
* Get a menu rendered in html.
*
* @since 1.x.0
* @param $request
* @return array Menu data
*/
public function get_menu_html( $request ) {

$menu_id = $request['menu_id'];
$rest_url_base = get_rest_url() . self::get_plugin_namespace();
$wp_menu_object = $menu_id ? wp_get_nav_menu_object( $menu_id) : array();
$wp_menu_items = $menu_id ? wp_get_nav_menu_items( $menu_id ) : array();

$rest_menu = array();

if ( $wp_menu_object ) :

$menu = (array) $wp_menu_object;
$rest_menu['ID'] = abs( $menu['term_id'] );
$rest_menu['name'] = $menu['name'];
$rest_menu['slug'] = $menu['slug'];
$rest_menu['description'] = $menu['description'];
$rest_menu['count'] = abs( $menu['count'] );

ob_start();
wp_nav_menu( array( 'menu' => $menu_id ) );
$rest_menu['html']=ob_get_clean();

$rest_menu['meta']['links']['collection'] = $rest_url_base . '/menus/';
$rest_menu['meta']['links']['self'] = $rest_url_base . '/menu-html/' . $menu_id;

endif;

return apply_filters( 'rest_menus_format_menu', $rest_menu );
}



/**
* Handle nested menu items.
Expand Down Expand Up @@ -227,7 +287,8 @@ public static function get_menu_locations( $request ) {

$locations = get_nav_menu_locations();
$registered_menus = get_registered_nav_menus();
$rest_url = get_rest_url() . self::get_api_namespace() . '/menu-locations/';
$rest_url = get_rest_url() . self::get_plugin_namespace() . '/menu-locations/';
$rest_url_base = get_rest_url() . self::get_plugin_namespace();
$rest_menus = array();

if ( $locations && $registered_menus ) :
Expand All @@ -243,6 +304,7 @@ public static function get_menu_locations( $request ) {
$rest_menus[ $slug ]['label'] = $label;
$rest_menus[ $slug ]['meta']['links']['collection'] = $rest_url;
$rest_menus[ $slug ]['meta']['links']['self'] = $rest_url . $slug;
$rest_menus[ $slug ]['meta']['links']['html'] = $rest_url_base . '/menu-html-location/' . $slug;

endforeach;

Expand Down Expand Up @@ -302,9 +364,9 @@ public function get_menu_location( $request ) {
if ( array_key_exists ( $item->ID , $cache ) ) {
$formatted['children'] = array_reverse ( $cache[ $item->ID ] );
}

$formatted = apply_filters( 'rest_menus_format_menu_item', $formatted );

if ( $item->menu_item_parent != 0 ) {
// Wait for parent to pick me up
if ( array_key_exists ( $item->menu_item_parent , $cache ) ) {
Expand All @@ -320,6 +382,51 @@ public function get_menu_location( $request ) {
}


/**
* Get menu rendered in html for location.
*
* @since 1.x.0
* @param $request
* @return array The menu for the corresponding location
*/
public function get_menu_html_location( $request ) {

$params = $request->get_params();
$location = $params['location'];
$locations = get_nav_menu_locations();

//Check if location exists and return empty array if it doesn't
if ( ! isset( $locations[ $location ] ) ) {
return array();
}

$rest_url_base = get_rest_url() . self::get_plugin_namespace();
$wp_menu_object = get_term( $locations[$location], 'nav_menu' );
$rest_menu = array();

if ( $wp_menu_object ) :

$menu = (array) $wp_menu_object;
$rest_menu['ID'] = abs( $menu['term_id'] );
$rest_menu['name'] = $menu['name'];
$rest_menu['slug'] = $menu['slug'];
$rest_menu['location_slug'] = $location;
$rest_menu['description'] = $menu['description'];
$rest_menu['count'] = abs( $menu['count'] );

ob_start();
wp_nav_menu( array( 'theme_location' => $location ) );
$rest_menu['html']=ob_get_clean();

$rest_menu['meta']['links']['collection'] = $rest_url_base . '/menu-locations/';
$rest_menu['meta']['links']['self'] = $rest_url_base . '/menu-html-location/' . $location;

endif;

return $rest_menu;
}


/**
* Returns all child nav_menu_items under a specific parent.
*
Expand Down
4 changes: 3 additions & 1 deletion readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ The new routes available will be:

* `/menus` list of every registered menu.
* `/menus/<id>` data for a specific menu.
* `/menu-html/<menu_identifier>` menu rendered in html for a specificed menu by id or slug.
* `/menu-locations` list of all registered theme locations.
* `/menu-locations/<location>` data for menu in specified menu in theme location.
* `/menu-html-location/<location>` menu rendered in html for a specified menu in theme location.

Currently, the `menu-locations/<location>` route for individual menus will return a tree with full menu hierarchy, with correct menu item order and listing children for each menu item. The `menus/<id>` route will output menu details and a flat array of menu items. Item order or if each item has a parent will be indicated in each item attributes, but this route won't output items as a tree.

Expand Down Expand Up @@ -99,4 +101,4 @@ Nothing to show really, this plugin has no settings or frontend, it just extends

= 1.2.1 =

API V2 only: mind lowercase `id` instead of uppercase `ID` in API responses, to match the standard for `id` used across WP REST API.
API V2 only: mind lowercase `id` instead of uppercase `ID` in API responses, to match the standard for `id` used across WP REST API.