Skip to content

Commit 9a80466

Browse files
committed
New recursive function to check menu's relatives (fix #16)
1 parent 4eb209c commit 9a80466

File tree

1 file changed

+177
-144
lines changed

1 file changed

+177
-144
lines changed

wp-rest-api-v2-menus.php

Lines changed: 177 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -11,178 +11,211 @@
1111
* Get all registered menus
1212
* @return array List of menus with slug and description
1313
*/
14-
function wp_api_v2_menus_get_all_menus () {
15-
$menus = get_terms('nav_menu', array('hide_empty' => true ) );
16-
17-
foreach($menus as $key => $menu) {
18-
// check if there is acf installed
19-
if( class_exists('acf') ) {
20-
$fields = get_fields($menu);
21-
if(!empty($fields)) {
22-
foreach($fields as $field_key => $item) {
23-
// add all acf custom fields
24-
$menus[$key]->$field_key = $item;
25-
}
26-
}
27-
}
28-
}
29-
30-
return $menus;
14+
function wp_api_v2_menus_get_all_menus() {
15+
$menus = get_terms( 'nav_menu', array( 'hide_empty' => true ) );
16+
17+
foreach ( $menus as $key => $menu ) {
18+
// check if there is acf installed
19+
if ( class_exists( 'acf' ) ) {
20+
$fields = get_fields( $menu );
21+
if ( ! empty( $fields ) ) {
22+
foreach ( $fields as $field_key => $item ) {
23+
// add all acf custom fields
24+
$menus[ $key ]->$field_key = $item;
25+
}
26+
}
27+
}
28+
}
29+
30+
return $menus;
3131
}
3232

3333
/**
3434
* Get all locations
3535
* @return array List of locations
3636
**/
3737

38-
function wp_api_v2_menu_get_all_locations () {
39-
$nav_menu_locations = get_nav_menu_locations();
40-
$locations = new stdClass;
41-
foreach ($nav_menu_locations as $location_slug => $menu_id) {
42-
if(get_term($location_slug) !== NULL) {
43-
$locations->{$location_slug} = get_term($location_slug);
44-
} else {
45-
$locations->{$location_slug} = new stdClass;
46-
}
47-
$locations->{$location_slug}->slug = $location_slug;
48-
$locations->{$location_slug}->menu = get_term($menu_id);
49-
}
50-
return $locations;
38+
function wp_api_v2_menu_get_all_locations() {
39+
$nav_menu_locations = get_nav_menu_locations();
40+
$locations = new stdClass;
41+
foreach ( $nav_menu_locations as $location_slug => $menu_id ) {
42+
if ( get_term( $location_slug ) !== null ) {
43+
$locations->{$location_slug} = get_term( $location_slug );
44+
} else {
45+
$locations->{$location_slug} = new stdClass;
46+
}
47+
$locations->{$location_slug}->slug = $location_slug;
48+
$locations->{$location_slug}->menu = get_term( $menu_id );
49+
}
50+
51+
return $locations;
5152
}
5253

5354
/**
5455
* Get menu's data from his id
55-
* @param array $data WP REST API data variable
56+
*
57+
* @param array $data WP REST API data variable
58+
*
5659
* @return object Menu's data with his items
5760
*/
58-
function wp_api_v2_locations_get_menu_data ( $data ) {
59-
// Create default empty object
60-
$menu = new stdClass;
61-
62-
// this could be replaced with `if (has_nav_menu($data['id']))`
63-
if (($locations = get_nav_menu_locations()) && isset($locations[$data['id']])) {
64-
// Replace default empty object with the location object
65-
$menu = get_term( $locations[ $data['id'] ] );
66-
$menu->items = wp_api_v2_menus_get_menu_items($locations[$data['id']]);
67-
} else {
68-
return new WP_Error( 'not_found', 'No location has been found with this id or slug: `'.$data['id'].'`. Please ensure you passed an existing location ID or location slug.', array( 'status' => 404 ) );
69-
}
70-
71-
// check if there is acf installed
72-
if( class_exists('acf') ) {
73-
$fields = get_fields($menu);
74-
if(!empty($fields)) {
75-
foreach($fields as $field_key => $item) {
76-
// add all acf custom fields
77-
$menu->$field_key = $item;
78-
}
79-
}
80-
}
81-
82-
return $menu;
61+
function wp_api_v2_locations_get_menu_data( $data ) {
62+
// Create default empty object
63+
$menu = new stdClass;
64+
65+
// this could be replaced with `if (has_nav_menu($data['id']))`
66+
if ( ( $locations = get_nav_menu_locations() ) && isset( $locations[ $data['id'] ] ) ) {
67+
// Replace default empty object with the location object
68+
$menu = get_term( $locations[ $data['id'] ] );
69+
$menu->items = wp_api_v2_menus_get_menu_items( $locations[ $data['id'] ] );
70+
} else {
71+
return new WP_Error( 'not_found', 'No location has been found with this id or slug: `' . $data['id'] . '`. Please ensure you passed an existing location ID or location slug.', array( 'status' => 404 ) );
72+
}
73+
74+
// check if there is acf installed
75+
if ( class_exists( 'acf' ) ) {
76+
$fields = get_fields( $menu );
77+
if ( ! empty( $fields ) ) {
78+
foreach ( $fields as $field_key => $item ) {
79+
// add all acf custom fields
80+
$menu->$field_key = $item;
81+
}
82+
}
83+
}
84+
85+
return $menu;
86+
}
87+
88+
/**
89+
* Check if a menu item is child of one of the menu's element passed as reference
90+
*
91+
* @param $parents Menu's items
92+
* @param $child Menu's item to check
93+
*
94+
* @return bool True if the parent is found, false otherwise
95+
*/
96+
function wp_api_v2_menus_dna_test( &$parents, $child ) {
97+
foreach ( $parents as $key => $item ) {
98+
if ( $child->menu_item_parent == $item->ID ) {
99+
if ( ! $item->child_items ) {
100+
$item->child_items = [];
101+
}
102+
array_push( $item->child_items, $child );
103+
return true;
104+
}
105+
106+
if($item->child_items) {
107+
if(wp_api_v2_menus_dna_test($item->child_items, $child)) {
108+
return true;
109+
}
110+
}
111+
}
112+
113+
return false;
83114
}
84115

85116
/**
86117
* Retrieve items for a specific menu
118+
*
87119
* @param $id Menu id
120+
*
88121
* @return array List of menu items
89122
*/
90-
function wp_api_v2_menus_get_menu_items($id) {
91-
$menu_items = wp_get_nav_menu_items($id);
92-
93-
// wordpress does not group child menu items with parent menu items
94-
$child_items = [];
95-
// pull all child menu items into separate object
96-
foreach ($menu_items as $key => $item) {
97-
if ($item->menu_item_parent) {
98-
array_push($child_items, $item);
99-
unset($menu_items[$key]);
100-
}
101-
}
102-
103-
// push child items into their parent item in the original object
104-
foreach ($menu_items as $item) {
105-
foreach ($child_items as $key => $child) {
106-
if ($child->menu_item_parent == $item->ID) {
107-
if (!$item->child_items) $item->child_items = [];
108-
array_push($item->child_items, $child);
109-
unset($child_items[$key]);
110-
}
111-
}
112-
}
113-
114-
// check if there is acf installed
115-
if (class_exists('acf')) {
116-
foreach ($menu_items as $menu_key => $menu_item) {
117-
$fields = get_fields($menu_item->ID);
118-
if (!empty($fields)) {
119-
foreach ($fields as $field_key => $item) {
120-
// add all acf custom fields
121-
$menu_items[$menu_key]->$field_key = $item;
122-
}
123-
}
124-
}
125-
}
126-
return $menu_items;
123+
function wp_api_v2_menus_get_menu_items( $id ) {
124+
$menu_items = wp_get_nav_menu_items( $id );
125+
126+
// wordpress does not group child menu items with parent menu items
127+
$child_items = [];
128+
// pull all child menu items into separate object
129+
foreach ( $menu_items as $key => $item ) {
130+
if ( $item->menu_item_parent ) {
131+
array_push( $child_items, $item );
132+
unset( $menu_items[ $key ] );
133+
}
134+
}
135+
136+
// push child items into their parent item in the original object
137+
do {
138+
foreach($child_items as $key => $child_item) {
139+
if(wp_api_v2_menus_dna_test($menu_items, $child_item)) {
140+
unset($child_items[$key]);
141+
}
142+
}
143+
} while(count($child_items));
144+
145+
// check if there is acf installed
146+
if ( class_exists( 'acf' ) ) {
147+
foreach ( $menu_items as $menu_key => $menu_item ) {
148+
$fields = get_fields( $menu_item->ID );
149+
if ( ! empty( $fields ) ) {
150+
foreach ( $fields as $field_key => $item ) {
151+
// add all acf custom fields
152+
$menu_items[ $menu_key ]->$field_key = $item;
153+
}
154+
}
155+
}
156+
}
157+
158+
return $menu_items;
127159
}
128160

129161
/**
130162
* Get menu's data from his id.
131163
* It ensures compatibility for previous versions when this endpoint
132164
* was allowing locations id in place of menus id)
133165
*
134-
* @param array $data WP REST API data variable
166+
* @param array $data WP REST API data variable
167+
*
135168
* @return object Menu's data with his items
136169
*/
137-
function wp_api_v2_menus_get_menu_data ( $data ) {
138-
// This ensure retro compatibility with versions `<= 0.5` when this endpoint
139-
// was allowing locations id in place of menus id
140-
if (has_nav_menu($data['id'])) {
141-
$menu = wp_api_v2_locations_get_menu_data($data);
142-
} else if (is_nav_menu($data['id'])) {
143-
if (is_int($data['id'])) {
144-
$id = $data['id'];
145-
} else {
146-
$id = wp_get_nav_menu_object($data['id']);
147-
}
148-
$menu = get_term($id);
149-
$menu->items = wp_api_v2_menus_get_menu_items($id);
150-
} else {
151-
return new WP_Error( 'not_found', 'No menu has been found with this id or slug: `'.$data['id'].'`. Please ensure you passed an existing menu ID, menu slug, location ID or location slug.', array( 'status' => 404 ) );
152-
}
153-
154-
// check if there is acf installed
155-
if( class_exists('acf') ) {
156-
$fields = get_fields($menu);
157-
if(!empty($fields)) {
158-
foreach($fields as $field_key => $item) {
159-
// add all acf custom fields
160-
$menu->$field_key = $item;
161-
}
162-
}
163-
}
164-
165-
return $menu;
170+
function wp_api_v2_menus_get_menu_data( $data ) {
171+
// This ensure retro compatibility with versions `<= 0.5` when this endpoint
172+
// was allowing locations id in place of menus id
173+
if ( has_nav_menu( $data['id'] ) ) {
174+
$menu = wp_api_v2_locations_get_menu_data( $data );
175+
} else if ( is_nav_menu( $data['id'] ) ) {
176+
if ( is_int( $data['id'] ) ) {
177+
$id = $data['id'];
178+
} else {
179+
$id = wp_get_nav_menu_object( $data['id'] );
180+
}
181+
$menu = get_term( $id );
182+
$menu->items = wp_api_v2_menus_get_menu_items( $id );
183+
} else {
184+
return new WP_Error( 'not_found', 'No menu has been found with this id or slug: `' . $data['id'] . '`. Please ensure you passed an existing menu ID, menu slug, location ID or location slug.', array( 'status' => 404 ) );
185+
}
186+
187+
// check if there is acf installed
188+
if ( class_exists( 'acf' ) ) {
189+
$fields = get_fields( $menu );
190+
if ( ! empty( $fields ) ) {
191+
foreach ( $fields as $field_key => $item ) {
192+
// add all acf custom fields
193+
$menu->$field_key = $item;
194+
}
195+
}
196+
}
197+
198+
return $menu;
166199
}
167200

168-
add_action('rest_api_init', function () {
169-
register_rest_route('menus/v1', '/menus', array(
170-
'methods' => 'GET',
171-
'callback' => 'wp_api_v2_menus_get_all_menus',
172-
) );
173-
174-
register_rest_route('menus/v1', '/menus/(?P<id>[a-zA-Z0-9_-]+)', array(
175-
'methods' => 'GET',
176-
'callback' => 'wp_api_v2_menus_get_menu_data',
177-
) );
178-
179-
register_rest_route('menus/v1', '/locations/(?P<id>[a-zA-Z0-9_-]+)', array(
180-
'methods' => 'GET',
181-
'callback' => 'wp_api_v2_locations_get_menu_data',
182-
) );
183-
184-
register_rest_route('menus/v1', '/locations', array(
185-
'methods' => 'GET',
186-
'callback' => 'wp_api_v2_menu_get_all_locations',
187-
) );
188-
} );
201+
add_action( 'rest_api_init', function () {
202+
register_rest_route( 'menus/v1', '/menus', array(
203+
'methods' => 'GET',
204+
'callback' => 'wp_api_v2_menus_get_all_menus',
205+
) );
206+
207+
register_rest_route( 'menus/v1', '/menus/(?P<id>[a-zA-Z0-9_-]+)', array(
208+
'methods' => 'GET',
209+
'callback' => 'wp_api_v2_menus_get_menu_data',
210+
) );
211+
212+
register_rest_route( 'menus/v1', '/locations/(?P<id>[a-zA-Z0-9_-]+)', array(
213+
'methods' => 'GET',
214+
'callback' => 'wp_api_v2_locations_get_menu_data',
215+
) );
216+
217+
register_rest_route( 'menus/v1', '/locations', array(
218+
'methods' => 'GET',
219+
'callback' => 'wp_api_v2_menu_get_all_locations',
220+
) );
221+
} );

0 commit comments

Comments
 (0)