diff --git a/includes/wp-api-menus-v1.php b/includes/wp-api-menus-v1.php index ea5b97d..a4af3ba 100644 --- a/includes/wp-api-menus-v1.php +++ b/includes/wp-api-menus-v1.php @@ -40,6 +40,10 @@ public function register_routes( $routes ) { $routes['/menus/(?P\d+)'] = array( array( array( $this, 'get_menu' ), WP_JSON_Server::READABLE ), ); + // a specific menu rendered in html + $routes['/menu-html/(?P[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 ), @@ -48,6 +52,10 @@ public function register_routes( $routes ) { $routes['/menu-locations/(?P[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[a-zA-Z0-9_-]+)'] = array( + array( array( $this, 'get_menu_html_location' ), WP_JSON_Server::READABLE ), + ); return $routes; } @@ -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; @@ -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; @@ -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. * @@ -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 ) : @@ -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; @@ -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. diff --git a/includes/wp-api-menus-v2.php b/includes/wp-api-menus-v2.php index ff5fe8f..bbdfa48 100644 --- a/includes/wp-api-menus-v2.php +++ b/includes/wp-api-menus-v2.php @@ -72,6 +72,19 @@ public function register_routes() { ) ) ); + + register_rest_route( self::get_plugin_namespace(), '/menu-html/(?P[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, @@ -86,6 +99,13 @@ public function register_routes() { ) ) ); + register_rest_route( self::get_plugin_namespace(), '/menu-html-location/(?P[a-zA-Z0-9_-]+)', array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_menu_html_location' ), + ) + ) ); + } @@ -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; @@ -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; @@ -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(); @@ -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. @@ -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 ) : @@ -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; @@ -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 ) ) { @@ -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. * diff --git a/readme.txt b/readme.txt index 0fbc452..817c6bd 100644 --- a/readme.txt +++ b/readme.txt @@ -18,8 +18,10 @@ The new routes available will be: * `/menus` list of every registered menu. * `/menus/` data for a specific menu. +* `/menu-html/` menu rendered in html for a specificed menu by id or slug. * `/menu-locations` list of all registered theme locations. * `/menu-locations/` data for menu in specified menu in theme location. +* `/menu-html-location/` menu rendered in html for a specified menu in theme location. Currently, the `menu-locations/` 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/` 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. @@ -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. \ No newline at end of file +API V2 only: mind lowercase `id` instead of uppercase `ID` in API responses, to match the standard for `id` used across WP REST API.