Completed
Push — master ( ad6d3b...bbc61e )
by Claudio
17s queued 12s
created

wp-rest-api-v2-menus.php (29 issues)

1
<?php
2
/*
3
Plugin Name: WP-REST-API V2 Menus
4
Version: 0.8.1
5
Description: Adding menus endpoints on WP REST API v2
6
Author: Claudio La Barbera
7
Author URI: https://thebatclaud.io
8
*/
9
10
/**
11
 * Get all registered menus
12
 * @return array List of menus with slug and description
13
 */
14
function wp_api_v2_menus_get_all_menus() {
15
	$menus = get_terms( 'nav_menu', array( 'hide_empty' => true ) );
0 ignored issues
show
The function get_terms was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

15
	$menus = /** @scrutinizer ignore-call */ get_terms( 'nav_menu', array( 'hide_empty' => true ) );
Loading history...
16
17
	foreach ( $menus as $key => $menu ) {
18
		// check if there is acf installed
19
		if ( class_exists( 'acf' ) ) {
20
			$fields = get_fields( $menu );
0 ignored issues
show
The function get_fields was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

20
			$fields = /** @scrutinizer ignore-call */ get_fields( $menu );
Loading history...
21
			if ( ! empty( $fields ) ) {
22
				$menu[ $key ]->acf = new stdClass();
23
24
				foreach ( $fields as $field_key => $item ) {
25
					// add all acf custom fields
26
					$menus[ $key ]->acf->$field_key = $item;
27
				}
28
			}
29
		}
30
	}
31
	
32
	return apply_filters('wp_api_v2_menus__menus', $menus);
0 ignored issues
show
The function apply_filters was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

32
	return /** @scrutinizer ignore-call */ apply_filters('wp_api_v2_menus__menus', $menus);
Loading history...
33
}
34
35
/**
36
 * Get all locations
37
 * @return array List of locations
38
 **/
39
40
function wp_api_v2_menu_get_all_locations() {
41
	$nav_menu_locations = get_nav_menu_locations();
0 ignored issues
show
The function get_nav_menu_locations was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

41
	$nav_menu_locations = /** @scrutinizer ignore-call */ get_nav_menu_locations();
Loading history...
42
	$locations          = new stdClass;
43
	foreach ( $nav_menu_locations as $location_slug => $menu_id ) {
44
		if ( get_term( $location_slug ) !== null ) {
0 ignored issues
show
The function get_term was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

44
		if ( /** @scrutinizer ignore-call */ get_term( $location_slug ) !== null ) {
Loading history...
45
			$locations->{$location_slug} = get_term( $location_slug );
46
		} else {
47
			$locations->{$location_slug} = new stdClass;
48
		}
49
		$locations->{$location_slug}->slug = $location_slug;
50
		$locations->{$location_slug}->menu = get_term( $menu_id );
51
	}
52
53
	return apply_filters('wp_api_v2_menus__locations', $locations);
0 ignored issues
show
The function apply_filters was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

53
	return /** @scrutinizer ignore-call */ apply_filters('wp_api_v2_menus__locations', $locations);
Loading history...
54
}
55
56
/**
57
 * Get menu's data from his id
58
 *
59
 * @param array $data WP REST API data variable
60
 *
61
 * @return object Menu's data with his items
62
 */
63
function wp_api_v2_locations_get_menu_data( $data ) {
64
	// Create default empty object
65
	$menu = new stdClass;
0 ignored issues
show
The assignment to $menu is dead and can be removed.
Loading history...
66
67
	// this could be replaced with `if (has_nav_menu($data['id']))`
68
	if ( ( $locations = get_nav_menu_locations() ) && isset( $locations[ $data['id'] ] ) ) {
0 ignored issues
show
The function get_nav_menu_locations was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

68
	if ( ( $locations = /** @scrutinizer ignore-call */ get_nav_menu_locations() ) && isset( $locations[ $data['id'] ] ) ) {
Loading history...
69
		// Replace default empty object with the location object
70
		$menu        = get_term( $locations[ $data['id'] ] );
0 ignored issues
show
The function get_term was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

70
		$menu        = /** @scrutinizer ignore-call */ get_term( $locations[ $data['id'] ] );
Loading history...
71
		$menu->items = wp_api_v2_menus_get_menu_items( $locations[ $data['id'] ] );
72
	} else {
73
		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 ) );
0 ignored issues
show
The type WP_Error was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
74
	}
75
76
	// check if there is acf installed
77
	if ( class_exists( 'acf' ) ) {
78
		$fields = get_fields( $menu );
0 ignored issues
show
The function get_fields was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

78
		$fields = /** @scrutinizer ignore-call */ get_fields( $menu );
Loading history...
79
		if ( ! empty( $fields ) ) {
80
			$menu->acf = new stdClass();
81
82
			foreach ( $fields as $field_key => $item ) {
83
				// add all acf custom fields
84
				$menu->acf->$field_key = $item;
85
			}
86
		}
87
	}
88
89
	return apply_filters('wp_api_v2_menus__menu', $menu);
0 ignored issues
show
The function apply_filters was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

89
	return /** @scrutinizer ignore-call */ apply_filters('wp_api_v2_menus__menu', $menu);
Loading history...
90
}
91
92
/**
93
 * Check if a menu item is child of one of the menu's element passed as reference
94
 *
95
 * @param $parents Menu's items
0 ignored issues
show
Documentation Bug introduced by
The doc comment Menu's at position 0 could not be parsed: Unknown type name 'Menu's' at position 0 in Menu's.
Loading history...
96
 * @param $child Menu's item to check
97
 *
98
 * @return bool True if the parent is found, false otherwise
99
 */
100
function wp_api_v2_menus_dna_test( &$parents, $child ) {
101
	foreach ( $parents as $key => $item ) {
102
		if ( $child->menu_item_parent == $item->ID ) {
103
			if ( ! $item->child_items ) {
104
				$item->child_items = [];
105
			}
106
			array_push( $item->child_items, $child );
107
			return true;
108
		}
109
110
		if($item->child_items) {
111
			if(wp_api_v2_menus_dna_test($item->child_items, $child)) {
112
				return true;
113
			}
114
		}
115
	}
116
117
	return false;
118
}
119
120
/**
121
 * Search object in an array by ID
122
 */
123
function wp_api_v2_find_object_by_id( $array, $id ) {
124
	foreach ( $array as $element ) {
125
		if ( $id == $element->ID ) {
126
				return $element;
127
		}
128
	}
129
130
	return false;
131
}
132
133
/**
134
 * Retrieve items for a specific menu
135
 *
136
 * @param $id Menu id
0 ignored issues
show
The type Menu was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
137
 *
138
 * @return array List of menu items
139
 */
140
function wp_api_v2_menus_get_menu_items( $id ) {
141
	$menu_items = wp_get_nav_menu_items( $id );
0 ignored issues
show
The function wp_get_nav_menu_items was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

141
	$menu_items = /** @scrutinizer ignore-call */ wp_get_nav_menu_items( $id );
Loading history...
142
	$all_menu_items = $menu_items;
143
144
	// check if there is acf installed
145
	if ( class_exists( 'acf' ) ) {
146
		foreach ( $menu_items as $menu_key => $menu_item ) {
147
			$fields = get_fields( $menu_item->ID );
0 ignored issues
show
The function get_fields was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

147
			$fields = /** @scrutinizer ignore-call */ get_fields( $menu_item->ID );
Loading history...
148
			if ( ! empty( $fields ) ) {
149
				$menu_items[$menu_key]->acf = new stdClass();
150
151
				foreach ( $fields as $field_key => $item ) {
152
					// add all acf custom fields
153
					$menu_items[ $menu_key ]->acf->$field_key = $item;
154
				}
155
			}
156
		}
157
	}
158
159
	// wordpress does not group child menu items with parent menu items
160
	$child_items = [];
161
	// pull all child menu items into separate object
162
	foreach ( $menu_items as $key => $item ) {
163
164
		if($item->type == 'post_type') {
165
			// add slug to menu items
166
			$slug = get_post_field( 'post_name', $item->object_id );
0 ignored issues
show
The function get_post_field was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

166
			$slug = /** @scrutinizer ignore-call */ get_post_field( 'post_name', $item->object_id );
Loading history...
167
			$item->slug = $slug;
168
		} else if($item->type == 'taxonomy') {
169
			$cat = get_term($item->object_id);
0 ignored issues
show
The function get_term was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

169
			$cat = /** @scrutinizer ignore-call */ get_term($item->object_id);
Loading history...
170
			$item->slug = $cat->slug;
171
		} else if($item->type == 'post_type_archive') {
172
			$post_type_data = get_post_type_object($item->object);
0 ignored issues
show
The function get_post_type_object was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

172
			$post_type_data = /** @scrutinizer ignore-call */ get_post_type_object($item->object);
Loading history...
173
174
			if ($post_type_data->has_archive) {
175
				$item->slug = $post_type_data->rewrite['slug'];
176
			}
177
		}
178
179
		if (isset($item->thumbnail_id) && $item->thumbnail_id) {
180
			$item->thumbnail_src = wp_get_attachment_image_url(intval($item->thumbnail_id), 'post-thumbnail');
0 ignored issues
show
The function wp_get_attachment_image_url was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

180
			$item->thumbnail_src = /** @scrutinizer ignore-call */ wp_get_attachment_image_url(intval($item->thumbnail_id), 'post-thumbnail');
Loading history...
181
		}
182
		if (isset($item->thumbnail_hover_id) && $item->thumbnail_hover_id) {
183
			$item->thumbnail_hover_src = wp_get_attachment_image_url(intval($item->thumbnail_hover_id), 'post-thumbnail');
184
		}
185
186
		if ( $item->menu_item_parent ) {
187
			array_push( $child_items, $item );
188
			unset( $menu_items[ $key ] );
189
		}
190
191
	}
192
193
	// push child items into their parent item in the original object
194
	do {
195
		foreach($child_items as $key => $child_item) {
196
			$parent = wp_api_v2_find_object_by_id( $all_menu_items, $child_item->menu_item_parent );
197
198
			if ( empty( $parent ) ) {
199
				unset($child_items[$key]);
200
			}
201
202
			else if (wp_api_v2_menus_dna_test($menu_items, $child_item)) {
203
				unset($child_items[$key]);
204
			}
205
		}
206
	} while(count($child_items));
207
208
	return apply_filters('wp_api_v2_menus__menu_items', array_values($menu_items));
0 ignored issues
show
The function apply_filters was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

208
	return /** @scrutinizer ignore-call */ apply_filters('wp_api_v2_menus__menu_items', array_values($menu_items));
Loading history...
209
}
210
211
/**
212
 * Get menu's data from his id.
213
 *    It ensures compatibility for previous versions when this endpoint
214
 *    was allowing locations id in place of menus id)
215
 *
216
 * @param array $data WP REST API data variable
217
 *
218
 * @return object Menu's data with his items
219
 */
220
function wp_api_v2_menus_get_menu_data( $data ) {
221
	// This ensure retro compatibility with versions `<= 0.5` when this endpoint
222
	//   was allowing locations id in place of menus id
223
	if ( has_nav_menu( $data['id'] ) ) {
0 ignored issues
show
The function has_nav_menu was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

223
	if ( /** @scrutinizer ignore-call */ has_nav_menu( $data['id'] ) ) {
Loading history...
224
		$menu = wp_api_v2_locations_get_menu_data( $data );
225
	} else if ( is_nav_menu( $data['id'] ) ) {
0 ignored issues
show
The function is_nav_menu was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

225
	} else if ( /** @scrutinizer ignore-call */ is_nav_menu( $data['id'] ) ) {
Loading history...
226
		if ( is_int( $data['id'] ) ) {
227
			$id = $data['id'];
228
		} else {
229
			$id = wp_get_nav_menu_object( $data['id'] );
0 ignored issues
show
The function wp_get_nav_menu_object was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

229
			$id = /** @scrutinizer ignore-call */ wp_get_nav_menu_object( $data['id'] );
Loading history...
230
		}
231
		$menu        = get_term( $id );
0 ignored issues
show
The function get_term was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

231
		$menu        = /** @scrutinizer ignore-call */ get_term( $id );
Loading history...
232
		$menu->items = wp_api_v2_menus_get_menu_items( $id );
233
	} else {
234
		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 ) );
235
	}
236
237
	// check if there is acf installed
238
	if ( class_exists( 'acf' ) ) {
239
		$fields = get_fields( $menu );
0 ignored issues
show
The function get_fields was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

239
		$fields = /** @scrutinizer ignore-call */ get_fields( $menu );
Loading history...
240
		if ( ! empty( $fields ) ) {
241
			$menu->acf = new stdClass();
242
243
			foreach ( $fields as $field_key => $item ) {
244
				// add all acf custom fields
245
				$menu->acf->$field_key = $item;
246
			}
247
		}
248
	}
249
250
	return apply_filters('wp_api_v2_menus__menu', $menu);
0 ignored issues
show
The function apply_filters was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

250
	return /** @scrutinizer ignore-call */ apply_filters('wp_api_v2_menus__menu', $menu);
Loading history...
251
}
252
253
add_action( 'rest_api_init', function () {
0 ignored issues
show
The function add_action was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

253
/** @scrutinizer ignore-call */ 
254
add_action( 'rest_api_init', function () {
Loading history...
254
	register_rest_route( 'menus/v1', '/menus', array(
0 ignored issues
show
The function register_rest_route was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

254
	/** @scrutinizer ignore-call */ 
255
 register_rest_route( 'menus/v1', '/menus', array(
Loading history...
255
		'methods'  => 'GET',
256
		'callback' => 'wp_api_v2_menus_get_all_menus',
257
		'permission_callback' => '__return_true'
258
	) );
259
260
	register_rest_route( 'menus/v1', '/menus/(?P<id>[a-zA-Z0-9_-]+)', array(
261
		'methods'  => 'GET',
262
		'callback' => 'wp_api_v2_menus_get_menu_data',
263
		'permission_callback' => '__return_true'
264
	) );
265
266
	register_rest_route( 'menus/v1', '/locations/(?P<id>[a-zA-Z0-9_-]+)', array(
267
		'methods'  => 'GET',
268
		'callback' => 'wp_api_v2_locations_get_menu_data',
269
		'permission_callback' => '__return_true'
270
	) );
271
272
	register_rest_route( 'menus/v1', '/locations', array(
273
		'methods'  => 'GET',
274
		'callback' => 'wp_api_v2_menu_get_all_locations',
275
		'permission_callback' => '__return_true'
276
	) );
277
} );
278