Completed
Pull Request — master (#27)
by
unknown
02:12
created

WP_JSON_Menus::get_menus()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 28
Code Lines 20

Duplication

Lines 17
Ratio 60.71 %

Importance

Changes 7
Bugs 0 Features 1
Metric Value
cc 2
eloc 20
c 7
b 0
f 1
nc 2
nop 0
dl 17
loc 28
rs 8.8571
1
<?php
2
/**
3
 * WP JSON API Menu routes
4
 *
5
 * @package WP_API_Menus
6
 */
7
8
if ( ! defined( 'ABSPATH' ) ) {
9
	exit; // Exit if accessed directly
10
}
11
12
if ( ! class_exists( 'WP_JSON_Menus' ) ) :
13
14
15
	/**
16
	 * WP JSON Menus class.
17
	 *
18
	 * WP API Menus support for WP API v1.
19
	 *
20
	 * @package WP_API_Menus
21
	 * @since 1.0.0
22
	 */
23
	class WP_JSON_Menus {
24
25
26
		/**
27
		 * Register menu routes for WP API.
28
		 *
29
		 * @since 1.0.0
30
		 * @param  array $routes Existing routes
31
		 * @return array Modified routes
32
		 */
33
		public function register_routes( $routes ) {
34
35
			// all registered menus
36
			$routes['/menus'] = array(
37
				array( array( $this, 'get_menus' ), WP_JSON_Server::READABLE ),
38
			);
39
			// a specific menu
40
			$routes['/menus/(?P<id>\d+)'] = array(
41
				array( array( $this, 'get_menu' ), WP_JSON_Server::READABLE ),
42
			);
43
			// a specific menu rendered in html
44
			$routes['/menu-html/(?P<id>[a-zA-Z0-9_-]+)'] = array(
45
				array( array( $this, 'get_menu_html' ), WP_JSON_Server::READABLE ),
46
			);
47
			// all registered menu locations
48
			$routes['/menu-locations'] = array(
49
				array( array( $this, 'get_menu_locations' ), WP_JSON_Server::READABLE ),
50
			);
51
			// menu for given location
52
			$routes['/menu-locations/(?P<location>[a-zA-Z0-9_-]+)'] = array(
53
				array( array( $this, 'get_menu_location' ), WP_JSON_Server::READABLE ),
54
			);
55
56
			return $routes;
57
		}
58
59
60
		/**
61
		 * Get menus.
62
		 *
63
		 * @since  1.0.0
64
		 * @return array All registered menus
65
		 */
66
		public static function get_menus() {
67
68
			$json_url = get_json_url() . '/menus/';
69
			$json_url_base = get_json_url();
70
			$wp_menus = wp_get_nav_menus();
71
72
			$i = 0;
73
			$json_menus = array();
74 View Code Duplication
			foreach ( $wp_menus as $wp_menu ) :
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
75
76
				$menu = (array) $wp_menu;
77
78
				$json_menus[ $i ]                 = $menu;
79
				$json_menus[ $i ]['ID']           = $menu['term_id'];
80
				$json_menus[ $i ]['name']         = $menu['name'];
81
				$json_menus[ $i ]['slug']         = $menu['slug'];
82
				$json_menus[ $i ]['description']  = $menu['description'];
83
				$json_menus[ $i ]['count']        = $menu['count'];
84
85
				$json_menus[ $i ]['meta']['links']['collection'] = $json_url;
86
				$json_menus[ $i ]['meta']['links']['self']       = $json_url . $menu['term_id'];
87
				$json_menus[ $i ]['meta']['links']['self']       = $json_url_base . '/menu-html/' . $menu['term_id'];
88
89
				$i ++;
90
			endforeach;
91
92
			return $json_menus;
93
		}
94
95
96
		/**
97
		 * Get a menu.
98
		 *
99
		 * @since  1.0.0
100
		 * @param  int   $id ID of the menu
101
		 * @return array Menu data
102
		 */
103
		public function get_menu( $id ) {
104
105
			$json_url       = get_json_url() . '/menus/';
106
			$wp_menu_object = $id ? wp_get_nav_menu_object( $id ) : array();
107
			$wp_menu_items  = $id ? wp_get_nav_menu_items( $id ) : array();
108
109
			$json_menu = array();
110
111 View Code Duplication
			if ( $wp_menu_object ) :
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
112
113
				$menu = (array) $wp_menu_object;
114
				$json_menu['ID']            = abs( $menu['term_id'] );
115
				$json_menu['name']          = $menu['name'];
116
				$json_menu['slug']          = $menu['slug'];
117
				$json_menu['description']   = $menu['description'];
118
				$json_menu['count']         = abs( $menu['count'] );
119
120
				$json_menu_items = array();
121
				foreach ( $wp_menu_items as $item_object ) {
122
					$json_menu_items[] = $this->format_menu_item( $item_object );
123
				}
124
125
				$json_menu['items']                       = $json_menu_items;
126
				$json_menu['meta']['links']['collection'] = $json_url;
127
				$json_menu['meta']['links']['self']       = $json_url . $id;
128
129
			endif;
130
131
			return $json_menu;
132
		}
133
134
135
		/**
136
		 * Get a menu rendered in html.
137
		 *
138
		 * @since  1.0.0
139
		 * @param  int   $id ID of the menu
0 ignored issues
show
Bug introduced by
There is no parameter named $id. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
140
		 * @return array Menu data
141
		 */
142
		public function get_menu_html( $menu_id ) {
143
144
			$json_url_base  = get_json_url();
145
			$wp_menu_object = $menu_id ? wp_get_nav_menu_object( $menu_id ) : array();
146
			$wp_menu_items  = $menu_id ? wp_get_nav_menu_items( $menu_id ) : array();
0 ignored issues
show
Unused Code introduced by
$wp_menu_items is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
147
148
			$json_menu = array();
149
150 View Code Duplication
			if ( $wp_menu_object ) :
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
151
152
				$menu = (array) $wp_menu_object;
153
				$json_menu['ID']            = abs( $menu['term_id'] );
154
				$json_menu['name']          = $menu['name'];
155
				$json_menu['slug']          = $menu['slug'];
156
				$json_menu['description']   = $menu['description'];
157
				$json_menu['count']         = abs( $menu['count'] );
158
159
				ob_start();
160
           			wp_nav_menu( array( 'menu' => $menu_id ) );
161
           		$json_menu['render_html']=ob_get_clean();
162
163
           		$json_menu['meta']['links']['collection'] = $json_url_base . '/menus/';
164
				$json_menu['meta']['links']['self']       = $json_url_base . '/menu-html/' . $menu_id;
165
166
			endif;
167
168
			return $json_menu;
169
		}
170
171
172
		/**
173
		 * Get menu locations.
174
		 *
175
		 * @since  1.0.0
176
		 * @return array All registered menus locations
177
		 */
178 View Code Duplication
		public static function get_menu_locations() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
179
180
			$locations        = get_nav_menu_locations();
181
			$registered_menus = get_registered_nav_menus();
182
			$json_url         = get_json_url() . '/menu-locations/';
183
			$json_menus       = array();
184
185
			if ( $locations && $registered_menus ) :
186
187
				foreach ( $registered_menus as $slug => $label ) :
188
189
					// Sanity check
190
					if ( ! isset( $locations[ $slug ] ) ) {
191
						continue;
192
					}
193
194
					$json_menus[ $slug ]['ID']                          = $locations[ $slug ];
195
					$json_menus[ $slug ]['label']                       = $label;
196
					$json_menus[ $slug ]['meta']['links']['collection'] = $json_url;
197
					$json_menus[ $slug ]['meta']['links']['self']       = $json_url . $slug;
198
199
				endforeach;
200
201
			endif;
202
203
			return $json_menus;
204
		}
205
206
207
		/**
208
		 * Get menu for location.
209
		 *
210
		 * @since  1.0.0
211
		 * @param  string $location The theme location menu name
212
		 * @return array The menu for the corresponding location
213
		 */
214
		public function get_menu_location( $location ) {
215
216
			$locations = get_nav_menu_locations();
217
			if ( ! isset( $locations[ $location ] ) ) {
218
				return array();
219
			}
220
221
			$wp_menu = wp_get_nav_menu_object( $locations[ $location ] );
222
			$menu_items = wp_get_nav_menu_items( $wp_menu->term_id );
223
224
			$sorted_menu_items = $top_level_menu_items = $menu_items_with_children = array();
225
226
			foreach ( (array) $menu_items as $menu_item ) {
227
				$sorted_menu_items[ $menu_item->menu_order ] = $menu_item;
228
			}
229
			foreach ( $sorted_menu_items as $menu_item ) {
230
				if ( (int) $menu_item->menu_item_parent !== 0 ) {
231
					$menu_items_with_children[ $menu_item->menu_item_parent ] = true;
232
				} else {
233
					$top_level_menu_items[] = $menu_item;
234
				}
235
			}
236
237
			$menu = array();
238
			while ( $sorted_menu_items ) :
0 ignored issues
show
Bug Best Practice introduced by
The expression $sorted_menu_items of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
239
240
				$i = 0;
241
				foreach ( $top_level_menu_items as $top_item ) :
242
243
					$menu[ $i ] = $this->format_menu_item( $top_item, false );
244
					if ( isset( $menu_items_with_children[ $top_item->ID ] ) ) {
245
						$menu[ $i ]['children'] = $this->get_nav_menu_item_children( $top_item->ID, $menu_items, false );
246
					} else {
247
						$menu[ $i ]['children'] = array();
248
					}
249
250
					$i++;
251
				endforeach;
252
253
				break;
254
255
			endwhile;
256
257
			return $menu;
258
		}
259
260
261
		/**
262
		 * Returns all child nav_menu_items under a specific parent.
263
		 *
264
		 * @since  1.1.0
265
		 * @param  int     $parent_id      the parent nav_menu_item ID
266
		 * @param  array   $nav_menu_items navigation menu items
267
		 * @param  bool    $depth          gives all children or direct children only
268
		 * @return array   returns filtered array of nav_menu_items
269
		 */
270 View Code Duplication
		public function get_nav_menu_item_children( $parent_id, $nav_menu_items, $depth = true ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
271
272
			$nav_menu_item_list = array();
273
274
			foreach ( (array) $nav_menu_items as $nav_menu_item ) :
275
276
				if ( $nav_menu_item->menu_item_parent == $parent_id ) :
277
278
					$nav_menu_item_list[] = $this->format_menu_item( $nav_menu_item, true, $nav_menu_items );
279
280
					if ( $depth ) {
281
						if ( $children = $this->get_nav_menu_item_children( $nav_menu_item->ID, $nav_menu_items ) ) {
282
							$nav_menu_item_list = array_merge( $nav_menu_item_list, $children );
283
						}
284
					}
285
286
				endif;
287
288
			endforeach;
289
290
			return $nav_menu_item_list;
291
		}
292
293
294
		/**
295
		 * Format a menu item for JSON API consumption.
296
		 *
297
		 * @since   1.1.0
298
		 * @param   object|array    $menu_item  the menu item
299
		 * @param   bool            $children   get menu item children (default false)
300
		 * @param   array           $menu       the menu the item belongs to (used when $children is set to true)
301
		 * @return  array   a formatted menu item for JSON
302
		 */
303 View Code Duplication
		public function format_menu_item( $menu_item, $children = false, $menu = array() ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
304
305
			$item = (array) $menu_item;
306
307
			$menu_item = array(
308
				'ID'          => abs( $item['ID'] ),
309
				'order'       => (int) $item['menu_order'],
310
				'parent'      => abs( $item['menu_item_parent'] ),
311
				'title'       => $item['title'],
312
				'url'         => $item['url'],
313
				'attr'        => $item['attr_title'],
314
				'target'      => $item['target'],
315
				'classes'     => implode( ' ', $item['classes'] ),
316
				'xfn'         => $item['xfn'],
317
				'description' => $item['description'],
318
				'object_id'   => abs( $item['object_id'] ),
319
				'object'      => $item['object'],
320
				'type'        => $item['type'],
321
				'type_label'  => $item['type_label'],
322
			);
323
324
			if ( $children === true && ! empty( $menu ) ) {
325
				$menu_item['children'] = $this->get_nav_menu_item_children( $item['ID'], $menu );
326
			}
327
328
			return apply_filters( 'json_menus_format_menu_item', $menu_item );
329
		}
330
331
332
	}
333
334
335
endif;
336