Passed
Push — master ( c9d24a...67ad85 )
by Claudio
02:00 queued 10s
created

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

1
<?php
2
/*
3
Plugin Name: WP-REST-API V2 Menus
4
Version: 0.7.7
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
				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 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

30
	return /** @scrutinizer ignore-call */ apply_filters('wp_api_v2_menus__menus', $menus);
Loading history...
31
}
32
33
/**
34
 * Get all locations
35
 * @return array List of locations
36
 **/
37
38
function wp_api_v2_menu_get_all_locations() {
39
	$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

39
	$nav_menu_locations = /** @scrutinizer ignore-call */ get_nav_menu_locations();
Loading history...
40
	$locations          = new stdClass;
41
	foreach ( $nav_menu_locations as $location_slug => $menu_id ) {
42
		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

42
		if ( /** @scrutinizer ignore-call */ get_term( $location_slug ) !== null ) {
Loading history...
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 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

51
	return /** @scrutinizer ignore-call */ apply_filters('wp_api_v2_menus__locations', $locations);
Loading history...
52
}
53
54
/**
55
 * Get menu's data from his id
56
 *
57
 * @param array $data WP REST API data variable
58
 *
59
 * @return object Menu's data with his items
60
 */
61
function wp_api_v2_locations_get_menu_data( $data ) {
62
	// Create default empty object
63
	$menu = new stdClass;
0 ignored issues
show
The assignment to $menu is dead and can be removed.
Loading history...
64
65
	// this could be replaced with `if (has_nav_menu($data['id']))`
66
	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

66
	if ( ( $locations = /** @scrutinizer ignore-call */ get_nav_menu_locations() ) && isset( $locations[ $data['id'] ] ) ) {
Loading history...
67
		// Replace default empty object with the location object
68
		$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

68
		$menu        = /** @scrutinizer ignore-call */ get_term( $locations[ $data['id'] ] );
Loading history...
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 ) );
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...
72
	}
73
74
	// check if there is acf installed
75
	if ( class_exists( 'acf' ) ) {
76
		$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

76
		$fields = /** @scrutinizer ignore-call */ get_fields( $menu );
Loading history...
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 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

85
	return /** @scrutinizer ignore-call */ apply_filters('wp_api_v2_menus__menu', $menu);
Loading history...
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
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...
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;
114
}
115
116
/**
117
 * Search object in an array by ID
118
 */
119
function wp_api_v2_find_object_by_id( $array, $id ) {
120
	foreach ( $array as $element ) {
121
		if ( $id == $element->ID ) {
122
				return $element;
123
		}
124
	}
125
126
	return false;
127
}
128
129
/**
130
 * Retrieve items for a specific menu
131
 *
132
 * @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...
133
 *
134
 * @return array List of menu items
135
 */
136
function wp_api_v2_menus_get_menu_items( $id ) {
137
	$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

137
	$menu_items = /** @scrutinizer ignore-call */ wp_get_nav_menu_items( $id );
Loading history...
138
	$all_menu_items = $menu_items;
139
140
	// check if there is acf installed
141
	if ( class_exists( 'acf' ) ) {
142
		foreach ( $menu_items as $menu_key => $menu_item ) {
143
			$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

143
			$fields = /** @scrutinizer ignore-call */ get_fields( $menu_item->ID );
Loading history...
144
			if ( ! empty( $fields ) ) {
145
				foreach ( $fields as $field_key => $item ) {
146
					// add all acf custom fields
147
					$menu_items[ $menu_key ]->$field_key = $item;
148
				}
149
			}
150
		}
151
	}
152
153
	// wordpress does not group child menu items with parent menu items
154
	$child_items = [];
155
	// pull all child menu items into separate object
156
	foreach ( $menu_items as $key => $item ) {
157
158
		if($item->type == 'post_type') {
159
			// add slug to menu items
160
			$slug = basename( get_permalink($item->object_id) );
0 ignored issues
show
The function get_permalink 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

160
			$slug = basename( /** @scrutinizer ignore-call */ get_permalink($item->object_id) );
Loading history...
161
			$item->slug = $slug;
162
		} else if($item->type == 'taxonomy') {
163
			$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

163
			$cat = /** @scrutinizer ignore-call */ get_term($item->object_id);
Loading history...
164
			$item->slug = $cat->slug;
165
		} else if($item->type == 'post_type_archive') {
166
			$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

166
			$post_type_data = /** @scrutinizer ignore-call */ get_post_type_object($item->object);
Loading history...
167
168
			if ($post_type_data->has_archive) {
169
				$item->slug = $post_type_data->rewrite['slug'];
170
			}
171
		}
172
173
		if (isset($item->thumbnail_id) && $item->thumbnail_id) {
174
			$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

174
			$item->thumbnail_src = /** @scrutinizer ignore-call */ wp_get_attachment_image_url(intval($item->thumbnail_id), 'post-thumbnail');
Loading history...
175
		}
176
		if (isset($item->thumbnail_hover_id) && $item->thumbnail_hover_id) {
177
			$item->thumbnail_hover_src = wp_get_attachment_image_url(intval($item->thumbnail_hover_id), 'post-thumbnail');
178
		}
179
180
		if ( $item->menu_item_parent ) {
181
			array_push( $child_items, $item );
182
			unset( $menu_items[ $key ] );
183
		}
184
185
	}
186
187
	// push child items into their parent item in the original object
188
	do {
189
		foreach($child_items as $key => $child_item) {
190
			$parent = wp_api_v2_find_object_by_id( $all_menu_items, $child_item->menu_item_parent );
191
192
			if ( empty( $parent ) ) {
193
				unset($child_items[$key]);
194
			}
195
196
			else if (wp_api_v2_menus_dna_test($menu_items, $child_item)) {
197
				unset($child_items[$key]);
198
			}
199
		}
200
	} while(count($child_items));
201
202
	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

202
	return /** @scrutinizer ignore-call */ apply_filters('wp_api_v2_menus__menu_items', array_values($menu_items));
Loading history...
203
}
204
205
/**
206
 * Get menu's data from his id.
207
 *    It ensures compatibility for previous versions when this endpoint
208
 *    was allowing locations id in place of menus id)
209
 *
210
 * @param array $data WP REST API data variable
211
 *
212
 * @return object Menu's data with his items
213
 */
214
function wp_api_v2_menus_get_menu_data( $data ) {
215
	// This ensure retro compatibility with versions `<= 0.5` when this endpoint
216
	//   was allowing locations id in place of menus id
217
	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

217
	if ( /** @scrutinizer ignore-call */ has_nav_menu( $data['id'] ) ) {
Loading history...
218
		$menu = wp_api_v2_locations_get_menu_data( $data );
219
	} 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

219
	} else if ( /** @scrutinizer ignore-call */ is_nav_menu( $data['id'] ) ) {
Loading history...
220
		if ( is_int( $data['id'] ) ) {
221
			$id = $data['id'];
222
		} else {
223
			$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

223
			$id = /** @scrutinizer ignore-call */ wp_get_nav_menu_object( $data['id'] );
Loading history...
224
		}
225
		$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

225
		$menu        = /** @scrutinizer ignore-call */ get_term( $id );
Loading history...
226
		$menu->items = wp_api_v2_menus_get_menu_items( $id );
227
	} else {
228
		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 ) );
229
	}
230
231
	// check if there is acf installed
232
	if ( class_exists( 'acf' ) ) {
233
		$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

233
		$fields = /** @scrutinizer ignore-call */ get_fields( $menu );
Loading history...
234
		if ( ! empty( $fields ) ) {
235
			foreach ( $fields as $field_key => $item ) {
236
				// add all acf custom fields
237
				$menu->$field_key = $item;
238
			}
239
		}
240
	}
241
242
	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

242
	return /** @scrutinizer ignore-call */ apply_filters('wp_api_v2_menus__menu', $menu);
Loading history...
243
}
244
245
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

245
/** @scrutinizer ignore-call */ 
246
add_action( 'rest_api_init', function () {
Loading history...
246
	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

246
	/** @scrutinizer ignore-call */ 
247
 register_rest_route( 'menus/v1', '/menus', array(
Loading history...
247
		'methods'  => 'GET',
248
		'callback' => 'wp_api_v2_menus_get_all_menus',
249
		'permission_callback' => '__return_true'
250
	) );
251
252
	register_rest_route( 'menus/v1', '/menus/(?P<id>[a-zA-Z0-9_-]+)', array(
253
		'methods'  => 'GET',
254
		'callback' => 'wp_api_v2_menus_get_menu_data',
255
		'permission_callback' => '__return_true'
256
	) );
257
258
	register_rest_route( 'menus/v1', '/locations/(?P<id>[a-zA-Z0-9_-]+)', array(
259
		'methods'  => 'GET',
260
		'callback' => 'wp_api_v2_locations_get_menu_data',
261
		'permission_callback' => '__return_true'
262
	) );
263
264
	register_rest_route( 'menus/v1', '/locations', array(
265
		'methods'  => 'GET',
266
		'callback' => 'wp_api_v2_menu_get_all_locations',
267
		'permission_callback' => '__return_true'
268
	) );
269
} );
270