Completed
Push — branch-4.0 ( fc0d6f...bf547c )
by
unknown
08:22
created

Nova_Restaurant::menu_item_price_meta_box()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 2
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * Put the following code in your theme's Food Menu Page Template to customize the markup of the menu.
5
6
if ( class_exists( 'Nova_Restaurant' ) ) {
7
	Nova_Restaurant::init( array(
8
		'menu_tag'               => 'section',
9
		'menu_class'             => 'menu-items',
10
		'menu_header_tag'        => 'header',
11
		'menu_header_class'      => 'menu-group-header',
12
		'menu_title_tag'         => 'h1',
13
		'menu_title_class'       => 'menu-group-title',
14
		'menu_description_tag'   => 'div',
15
		'menu_description_class' => 'menu-group-description',
16
	) );
17
}
18
19
*/
20
21
/* @todo
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
22
23
Bulk/Quick edit response of Menu Item rows is broken.
24
25
Drag and Drop reordering.
26
*/
27
28
class Nova_Restaurant {
29
	const MENU_ITEM_POST_TYPE = 'nova_menu_item';
30
	const MENU_ITEM_LABEL_TAX = 'nova_menu_item_label';
31
	const MENU_TAX = 'nova_menu';
32
33
	public $version = '0.1';
34
35
	protected $default_menu_item_loop_markup = array(
36
		'menu_tag'               => 'section',
37
		'menu_class'             => 'menu-items',
38
		'menu_header_tag'        => 'header',
39
		'menu_header_class'      => 'menu-group-header',
40
		'menu_title_tag'         => 'h1',
41
		'menu_title_class'       => 'menu-group-title',
42
		'menu_description_tag'   => 'div',
43
		'menu_description_class' => 'menu-group-description',
44
	);
45
46
	protected $menu_item_loop_markup = array();
47
	protected $menu_item_loop_last_term_id = false;
48
	protected $menu_item_loop_current_term = false;
49
50
	static function init( $menu_item_loop_markup = array() ) {
51
		static $instance = false;
52
53
		if ( !$instance ) {
54
			$instance = new Nova_Restaurant;
55
		}
56
57
		if ( $menu_item_loop_markup ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $menu_item_loop_markup 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...
58
			$instance->menu_item_loop_markup = wp_parse_args( $menu_item_loop_markup, $instance->default_menu_item_loop_markup );
59
		}
60
61
		return $instance;
62
	}
63
64
	function __construct() {
65
		if ( ! $this->site_supports_nova() )
66
			return;
67
68
		$this->register_taxonomies();
69
		$this->register_post_types();
70
		add_action( 'admin_menu',            array( $this, 'add_admin_menus'      ) );
71
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_nova_styles'  ) );
72
		add_action( 'admin_head',            array( $this, 'set_custom_font_icon' ) );
73
74
		// Enable Omnisearch for Menu Items.
75
		if ( class_exists( 'Jetpack_Omnisearch_Posts' ) )
76
			new Jetpack_Omnisearch_Posts( self::MENU_ITEM_POST_TYPE );
77
78
		// Always sort menu items correctly
79
		add_action( 'parse_query',   array( $this, 'sort_menu_item_queries_by_menu_order'    ) );
80
		add_filter( 'posts_results', array( $this, 'sort_menu_item_queries_by_menu_taxonomy' ), 10, 2 );
81
82
		add_action( 'wp_insert_post', array( $this, 'add_post_meta' ) );
83
84
		$this->menu_item_loop_markup = $this->default_menu_item_loop_markup;
85
86
		// Only output our Menu Item Loop Markup on a real blog view.  Not feeds, XML-RPC, admin, etc.
87
		add_filter( 'template_include', array( $this, 'setup_menu_item_loop_markup__in_filter' ) );
88
89
		add_filter( 'enter_title_here',       array( $this, 'change_default_title' ) );
90
		add_filter( 'post_updated_messages',  array( $this, 'updated_messages'     ) );
91
		add_filter( 'dashboard_glance_items', array( $this, 'add_to_dashboard'     ) );
92
	}
93
94
	/**
95
	* Should this Custom Post Type be made available?
96
	*/
97
	function site_supports_nova() {
98
		// If we're on WordPress.com, and it has the menu site vertical.
99
		if ( function_exists( 'site_vertical' ) && 'nova_menu' == site_vertical() )
100
			return true;
101
102
		// Else, if the current theme requests it.
103
		if ( current_theme_supports( self::MENU_ITEM_POST_TYPE ) )
104
			return true;
105
106
		// Otherwise, say no unless something wants to filter us to say yes.
107
		/**
108
		 * Allow something else to hook in and enable this CPT.
109
		 *
110
		 * @module custom-content-types
111
		 *
112
		 * @since 2.6.0
113
		 *
114
		 * @param bool false Whether or not to enable this CPT.
115
		 * @param string $var The slug for this CPT.
116
		 */
117
		return (bool) apply_filters( 'jetpack_enable_cpt', false, self::MENU_ITEM_POST_TYPE );
118
	}
119
120
/* Setup */
121
122
	/**
123
	 * Register Taxonomies and Post Type
124
	 */
125
	function register_taxonomies() {
126
		if ( ! taxonomy_exists( self::MENU_ITEM_LABEL_TAX ) ) {
127
			register_taxonomy( self::MENU_ITEM_LABEL_TAX, self::MENU_ITEM_POST_TYPE, array(
128
				'labels' => array(
129
					/* translators: this is about a food menu */
130
					'name'                       => __( 'Menu Item Labels', 'jetpack' ),
131
					/* translators: this is about a food menu */
132
					'singular_name'              => __( 'Menu Item Label', 'jetpack' ),
133
					/* translators: this is about a food menu */
134
					'search_items'               => __( 'Search Menu Item Labels', 'jetpack' ),
135
					'popular_items'              => __( 'Popular Labels', 'jetpack' ),
136
					/* translators: this is about a food menu */
137
					'all_items'                  => __( 'All Menu Item Labels', 'jetpack' ),
138
					/* translators: this is about a food menu */
139
					'edit_item'                  => __( 'Edit Menu Item Label', 'jetpack' ),
140
					/* translators: this is about a food menu */
141
					'view_item'                  => __( 'View Menu Item Label', 'jetpack' ),
142
					/* translators: this is about a food menu */
143
					'update_item'                => __( 'Update Menu Item Label', 'jetpack' ),
144
					/* translators: this is about a food menu */
145
					'add_new_item'               => __( 'Add New Menu Item Label', 'jetpack' ),
146
					/* translators: this is about a food menu */
147
					'new_item_name'              => __( 'New Menu Item Label Name', 'jetpack' ),
148
					'separate_items_with_commas' => __( 'For example, spicy, favorite, etc. <br /> Separate Labels with commas', 'jetpack' ),
149
					'add_or_remove_items'        => __( 'Add or remove Labels', 'jetpack' ),
150
					'choose_from_most_used'      => __( 'Choose from the most used Labels', 'jetpack' ),
151
					'items_list_navigation'      => __( 'Menu item label list navigation',   'jetpack' ),
152
					'items_list'                 => __( 'Menu item labels list',              'jetpack' ),
153
				),
154
				'no_tagcloud' => __( 'No Labels found', 'jetpack' ),
155
				'hierarchical'  => false,
156
			) );
157
		}
158
159
		if ( ! taxonomy_exists( self::MENU_TAX ) ) {
160
			register_taxonomy( self::MENU_TAX, self::MENU_ITEM_POST_TYPE, array(
161
				'labels' => array(
162
					/* translators: this is about a food menu */
163
					'name'               => __( 'Menu Sections', 'jetpack' ),
164
					/* translators: this is about a food menu */
165
					'singular_name'      => __( 'Menu Section', 'jetpack' ),
166
					/* translators: this is about a food menu */
167
					'search_items'       => __( 'Search Menu Sections', 'jetpack' ),
168
					/* translators: this is about a food menu */
169
					'all_items'          => __( 'All Menu Sections', 'jetpack' ),
170
					/* translators: this is about a food menu */
171
					'parent_item'        => __( 'Parent Menu Section', 'jetpack' ),
172
					/* translators: this is about a food menu */
173
					'parent_item_colon'  => __( 'Parent Menu Section:', 'jetpack' ),
174
					/* translators: this is about a food menu */
175
					'edit_item'          => __( 'Edit Menu Section', 'jetpack' ),
176
					/* translators: this is about a food menu */
177
					'view_item'          => __( 'View Menu Section', 'jetpack' ),
178
					/* translators: this is about a food menu */
179
					'update_item'        => __( 'Update Menu Section', 'jetpack' ),
180
					/* translators: this is about a food menu */
181
					'add_new_item'       => __( 'Add New Menu Section', 'jetpack' ),
182
					/* translators: this is about a food menu */
183
					'new_item_name'      => __( 'New Menu Sections Name', 'jetpack' ),
184
					'items_list_navigation' => __( 'Menu section list navigation',  'jetpack' ),
185
					'items_list'            => __( 'Menu section list',             'jetpack' ),
186
				),
187
				'rewrite' => array(
188
					'slug'         => 'menu',
189
					'with_front'   => false,
190
					'hierarchical' => true,
191
				),
192
				'hierarchical'  => true,
193
				'show_tagcloud' => false,
194
				'query_var'     => 'menu',
195
			) );
196
		}
197
	}
198
199 View Code Duplication
	function register_post_types() {
200
		if ( post_type_exists( self::MENU_ITEM_POST_TYPE ) ) {
201
			return;
202
		}
203
204
		register_post_type( self::MENU_ITEM_POST_TYPE, array(
205
			'description' => __( "Items on your restaurant's menu", 'jetpack' ),
206
207
			'labels' => array(
208
				/* translators: this is about a food menu */
209
				'name'               => __( 'Menu Items', 'jetpack' ),
210
				/* translators: this is about a food menu */
211
				'singular_name'      => __( 'Menu Item', 'jetpack' ),
212
				/* translators: this is about a food menu */
213
				'menu_name'          => __( 'Food Menus', 'jetpack' ),
214
				/* translators: this is about a food menu */
215
				'all_items'          => __( 'Menu Items', 'jetpack' ),
216
				/* translators: this is about a food menu */
217
				'add_new'            => __( 'Add One Item', 'jetpack' ),
218
				/* translators: this is about a food menu */
219
				'add_new_item'       => __( 'Add Menu Item', 'jetpack' ),
220
				/* translators: this is about a food menu */
221
				'edit_item'          => __( 'Edit Menu Item', 'jetpack' ),
222
				/* translators: this is about a food menu */
223
				'new_item'           => __( 'New Menu Item', 'jetpack' ),
224
				/* translators: this is about a food menu */
225
				'view_item'          => __( 'View Menu Item', 'jetpack' ),
226
				/* translators: this is about a food menu */
227
				'search_items'       => __( 'Search Menu Items', 'jetpack' ),
228
				/* translators: this is about a food menu */
229
				'not_found'          => __( 'No Menu Items found', 'jetpack' ),
230
				/* translators: this is about a food menu */
231
				'not_found_in_trash' => __( 'No Menu Items found in Trash', 'jetpack' ),
232
				'filter_items_list'     => __( 'Filter menu items list',       'jetpack' ),
233
				'items_list_navigation' => __( 'Menu item list navigation',    'jetpack' ),
234
				'items_list'            => __( 'Menu items list',              'jetpack' ),
235
			),
236
			'supports' => array(
237
				'title',
238
				'editor',
239
				'thumbnail',
240
				'excerpt',
241
			),
242
			'rewrite' => array(
243
				'slug'       => 'item',
244
				'with_front' => false,
245
				'feeds'      => false,
246
				'pages'      => false,
247
			),
248
			'register_meta_box_cb' => array( $this, 'register_menu_item_meta_boxes' ),
249
250
			'public'          => true,
251
			'show_ui'         => true, // set to false to replace with custom UI
252
			'menu_position'   => 20, // below Pages
253
			'capability_type' => 'page',
254
			'map_meta_cap'    => true,
255
			'has_archive'     => false,
256
			'query_var'       => 'item',
257
		) );
258
	}
259
260
261
	/**
262
	 * Update messages for the Menu Item admin.
263
	 */
264 View Code Duplication
	function updated_messages( $messages ) {
265
		global $post;
266
267
		$messages[self::MENU_ITEM_POST_TYPE] = array(
268
			0  => '', // Unused. Messages start at index 1.
269
				/* translators: this is about a food menu */
270
			1  => sprintf( __( 'Menu item updated. <a href="%s">View item</a>', 'jetpack' ), esc_url( get_permalink( $post->ID ) ) ),
271
			2  => esc_html__( 'Custom field updated.', 'jetpack' ),
272
			3  => esc_html__( 'Custom field deleted.', 'jetpack' ),
273
			/* translators: this is about a food menu */
274
			4  => esc_html__( 'Menu item updated.', 'jetpack' ),
275
			/* translators: %s: date and time of the revision */
276
			5  => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Menu item restored to revision from %s', 'jetpack' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
277
			/* translators: this is about a food menu */
278
			6  => sprintf( __( 'Menu item published. <a href="%s">View item</a>', 'jetpack' ), esc_url( get_permalink( $post->ID ) ) ),
279
			/* translators: this is about a food menu */
280
			7  => esc_html__( 'Menu item saved.', 'jetpack' ),
281
			/* translators: this is about a food menu */
282
			8  => sprintf( __( 'Menu item submitted. <a target="_blank" href="%s">Preview item</a>', 'jetpack' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
283
			/* translators: this is about a food menu */
284
			9  => sprintf( __( 'Menu item scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview item</a>', 'jetpack' ),
285
			// translators: Publish box date format, see http://php.net/date
286
			date_i18n( __( 'M j, Y @ G:i', 'jetpack' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post->ID) ) ),
287
			/* translators: this is about a food menu */
288
			10 => sprintf( __( 'Menu item draft updated. <a target="_blank" href="%s">Preview item</a>', 'jetpack' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
289
		);
290
291
		return $messages;
292
	}
293
294
295
	/**
296
	 * Nova Styles and Scripts
297
	 */
298
	function enqueue_nova_styles( $hook ) {
299
		global $post_type;
300
		$pages = array( 'edit.php', 'post.php', 'post-new.php' );
301
302
		if ( in_array( $hook, $pages ) && $post_type == self::MENU_ITEM_POST_TYPE ) {
303
			wp_enqueue_style( 'nova-style', plugins_url( 'css/nova.css', __FILE__ ),      array(), $this->version );
304
		}
305
306
		wp_enqueue_style( 'nova-font',  plugins_url( 'css/nova-font.css', __FILE__ ), array(), $this->version );
307
	}
308
309
310
	/**
311
	 * Change ‘Enter Title Here’ text for the Menu Item.
312
	 */
313 View Code Duplication
	function change_default_title( $title ) {
314
		$screen = get_current_screen();
315
316
		if ( self::MENU_ITEM_POST_TYPE == $screen->post_type )
317
			/* translators: this is about a food menu */
318
			$title = esc_html__( "Enter the menu item's name here", 'jetpack' );
319
320
		return $title;
321
	}
322
323
324
	/**
325
	 * Add to Dashboard At A Glance
326
	 */
327
	function add_to_dashboard() {
328
		$number_menu_items = wp_count_posts( self::MENU_ITEM_POST_TYPE );
329
330
		if ( current_user_can( 'administrator' ) ) {
331
			$number_menu_items_published = sprintf( '<a href="%1$s">%2$s</a>',
332
				esc_url( get_admin_url( get_current_blog_id(), 'edit.php?post_type=' . self::MENU_ITEM_POST_TYPE ) ),
333
				sprintf( _n( '%1$d Food Menu Item', '%1$d Food Menu Items', intval( $number_menu_items->publish ), 'jetpack' ), number_format_i18n( $number_menu_items->publish ) )
334
			);
335
		}
336
		else {
337
			$number_menu_items_published = sprintf( '<span>%1$s</span>',
338
				sprintf( _n( '%1$d Food Menu Item', '%1$d Food Menu Items', intval( $number_menu_items->publish ), 'jetpack' ), number_format_i18n( $number_menu_items->publish ) )
339
			);
340
		}
341
342
		echo '<li class="nova-menu-count">' . $number_menu_items_published . '</li>';
343
	}
344
345
346
	/**
347
	 * Query
348
	 */
349
	function is_menu_item_query( $query ) {
350
		if (
351
			( isset( $query->query_vars['taxonomy'] ) && self::MENU_TAX == $query->query_vars['taxonomy'] )
352
		||
353
			( isset( $query->query_vars['post_type'] ) && self::MENU_ITEM_POST_TYPE == $query->query_vars['post_type'] )
354
		) {
355
			return true;
356
		}
357
358
		return false;
359
	}
360
361
	function sort_menu_item_queries_by_menu_order( $query ) {
362
		if ( ! $this->is_menu_item_query( $query ) ) {
363
			return;
364
		}
365
366
		$query->query_vars['orderby'] = 'menu_order';
367
		$query->query_vars['order'] = 'ASC';
368
369
		// For now, just turn off paging so we can sort by taxonmy later
370
		// If we want paging in the future, we'll need to add the taxonomy sort here (or at least before the DB query is made)
371
		$query->query_vars['posts_per_page'] = -1;
372
	}
373
374
	function sort_menu_item_queries_by_menu_taxonomy( $posts, $query ) {
375
		if ( !$posts ) {
376
			return $posts;
377
		}
378
379
		if ( !$this->is_menu_item_query( $query ) ) {
380
			return $posts;
381
		}
382
383
		$grouped_by_term = array();
384
385
		foreach ( $posts as $post ) {
386
			$term = $this->get_menu_item_menu_leaf( $post->ID );
387
			if ( !$term || is_wp_error( $term ) ) {
388
				$term_id = 0;
389
			} else {
390
				$term_id = $term->term_id;
391
			}
392
393
			if ( !isset( $grouped_by_term["$term_id"] ) ) {
394
				$grouped_by_term["$term_id"] = array();
395
			}
396
397
			$grouped_by_term["$term_id"][] = $post;
398
		}
399
400
		$term_order = get_option( 'nova_menu_order', array() );
401
402
		$return = array();
403 View Code Duplication
		foreach ( $term_order as $term_id ) {
404
			if ( isset( $grouped_by_term["$term_id"] ) ) {
405
				$return = array_merge( $return, $grouped_by_term["$term_id"] );
406
				unset( $grouped_by_term["$term_id"] );
407
			}
408
		}
409
410
		foreach ( $grouped_by_term as $term_id => $posts ) {
411
			$return = array_merge( $return, $posts );
412
		}
413
414
		return $return;
415
	}
416
417
418
	/**
419
	 * Add Many Items
420
	 */
421
	function add_admin_menus() {
422
		$hook = add_submenu_page(
423
			'edit.php?post_type=' . self::MENU_ITEM_POST_TYPE,
424
			__( 'Add Many Items', 'jetpack' ),
425
			__( 'Add Many Items', 'jetpack' ),
426
			'edit_pages',
427
			'add_many_nova_items',
428
			array( $this, 'add_many_new_items_page' )
429
		);
430
431
		add_action( "load-$hook",     array( $this, 'add_many_new_items_page_load' ) );
432
433
		add_action( 'current_screen', array( $this, 'current_screen_load' ) );
434
435
		//Adjust 'Add Many Items' submenu position
436
		$submenu_item = array_pop( $GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE] );
437
		$GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE][11] = $submenu_item;
438
		ksort( $GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE] );
439
440
		$this->setup_menu_item_columns();
441
442
		wp_register_script( 'nova-menu-checkboxes', plugins_url( 'js/menu-checkboxes.js', __FILE__ ), array( 'jquery' ), $this->version, true );
443
	}
444
445
446
	/**
447
	 * Custom Nova Icon CSS
448
	 */
449
	function set_custom_font_icon() {
450
	?>
451
	<style type="text/css">
452
	#menu-posts-nova_menu_item .wp-menu-image:before {
453
		font-family: 'nova-font' !important;
454
		content: '\e603' !important;
455
	}
456
	</style>
457
	<?php
458
	}
459
460
	function current_screen_load() {
461
		$screen = get_current_screen();
462
		if ( 'edit-nova_menu_item' !== $screen->id ) {
463
			return;
464
		}
465
466
		$this->edit_menu_items_page_load();
467
		add_filter( 'admin_notices', array( $this, 'admin_notices' ) );
468
	}
469
470
/* Edit Items List */
471
472
	function admin_notices() {
473
		if ( isset( $_GET['nova_reordered'] ) )
474
			/* translators: this is about a food menu */
475
			printf( '<div class="updated"><p>%s</p></div>', __( 'Menu Items re-ordered.', 'jetpack' ) );
476
	}
477
478
	function no_title_sorting( $columns ) {
479
		if ( isset( $columns['title'] ) )
480
			unset( $columns['title'] );
481
		return $columns;
482
	}
483
484
	function setup_menu_item_columns() {
485
		add_filter( sprintf( 'manage_edit-%s_sortable_columns', self::MENU_ITEM_POST_TYPE ), array( $this, 'no_title_sorting' ) );
486
		add_filter( sprintf( 'manage_%s_posts_columns', self::MENU_ITEM_POST_TYPE ), array( $this, 'menu_item_columns' ) );
487
488
		add_action( sprintf( 'manage_%s_posts_custom_column', self::MENU_ITEM_POST_TYPE ), array( $this, 'menu_item_column_callback' ), 10, 2 );
489
	}
490
491
	function menu_item_columns( $columns ) {
492
		unset( $columns['date'], $columns['likes'] );
493
494
		$columns['thumbnail'] = __( 'Thumbnail', 'jetpack' );
495
		$columns['labels']    = __( 'Labels',    'jetpack' );
496
		$columns['price']     = __( 'Price',     'jetpack' );
497
		$columns['order']     = __( 'Order',     'jetpack' );
498
499
		return $columns;
500
	}
501
502
	function menu_item_column_callback( $column, $post_id ) {
503
		$screen = get_current_screen();
504
505
		switch ( $column ) {
506
			case 'thumbnail':
507
				echo get_the_post_thumbnail( $post_id, array( 50, 50 ) );
508
				break;
509
			case 'labels' :
510
				$this->list_admin_labels( $post_id );
511
				break;
512
			case 'price' :
513
				$this->display_price( $post_id );
514
				break;
515
			case 'order' :
516
				$url = admin_url( $screen->parent_file );
517
518
				$up_url = add_query_arg( array(
519
					'action' => 'move-item-up',
520
					'post_id' => (int) $post_id,
521
				), wp_nonce_url( $url, 'nova_move_item_up_' . $post_id ) );
522
523
				$down_url = add_query_arg( array(
524
					'action' => 'move-item-down',
525
					'post_id' => (int) $post_id,
526
				), wp_nonce_url( $url, 'nova_move_item_down_' . $post_id ) );
527
				$menu_item = get_post($post_id);
528
				$this->get_menu_by_post_id( $post_id );
529
	?>
530
				<input type="hidden" class="menu-order-value" name="nova_order[<?php echo (int) $post_id ?>]" value="<?php echo esc_attr( $menu_item->menu_order ) ?>" />
531
				<input type="hidden" class='nova-menu-term' name="nova_menu_term[<?php echo (int) $post_id ?>]" value="<?php echo esc_attr( $this->get_menu_by_post_id( $post_id )->term_id ); ?>">
532
533
				<span class="hide-if-js">
534
				&nbsp; &nbsp; &mdash; <a class="nova-move-item-up" data-post-id="<?php echo (int) $post_id; ?>" href="<?php echo esc_url( $up_url ); ?>">up</a>
535
				<br />
536
				&nbsp; &nbsp; &mdash; <a class="nova-move-item-down" data-post-id="<?php echo (int) $post_id; ?>" href="<?php echo esc_url( $down_url ); ?>">down</a>
537
				</span>
538
	<?php
539
				break;
540
		}
541
	}
542
543
	function get_menu_by_post_id( $post_id = null ) {
544
		if ( ! $post_id )
545
			return false;
546
547
		$terms = get_the_terms( $post_id, self::MENU_TAX );
548
549
		if ( ! is_array( $terms ) )
550
			return false;
551
552
		return array_pop( $terms );
553
	}
554
555
	/**
556
	 * Fires on a menu edit page. We might have drag-n-drop reordered
557
	 */
558
	function maybe_reorder_menu_items() {
559
		// make sure we clicked our button
560
		if ( ! ( isset( $_REQUEST['menu_reorder_submit'] ) && $_REQUEST['menu_reorder_submit'] === __( 'Save New Order', 'jetpack' ) ) )
561
			return;
562
		;
563
564
		// make sure we have the nonce
565
		if ( ! ( isset( $_REQUEST['drag-drop-reorder'] ) && wp_verify_nonce( $_REQUEST['drag-drop-reorder'], 'drag-drop-reorder' ) ) )
566
			return;
567
568
		$term_pairs = array_map( 'absint', $_REQUEST['nova_menu_term'] );
569
		$order_pairs = array_map( 'absint', $_REQUEST['nova_order'] );
570
571
		foreach( $order_pairs as $ID => $menu_order ) {
572
			$ID = absint( $ID );
573
			unset( $order_pairs[$ID] );
574
			if ( $ID < 0 )
575
				continue;
576
577
			$post = get_post( $ID );
578
			if ( ! $post )
579
				continue;
580
581
			// save a write if the order hasn't changed
582
			if ( $menu_order != $post->menu_order )
583
				wp_update_post( compact( 'ID', 'menu_order' ) );
584
585
			// save a write if the term hasn't changed
586
			if ( $term_pairs[$ID] != $this->get_menu_by_post_id( $ID )->term_id )
587
				wp_set_object_terms( $ID, $term_pairs[$ID], self::MENU_TAX );
588
589
		}
590
591
		$redirect = add_query_arg( array(
592
			'post_type' => self::MENU_ITEM_POST_TYPE,
593
			'nova_reordered' => '1'
594
		), admin_url( 'edit.php' ) );
595
		wp_safe_redirect( $redirect );
596
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method maybe_reorder_menu_items() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
597
598
	}
599
600
	function edit_menu_items_page_load() {
601
		if ( isset( $_GET['action'] ) ) {
602
			$this->handle_menu_item_actions();
603
		}
604
605
		$this->maybe_reorder_menu_items();
606
607
		wp_enqueue_script( 'nova-drag-drop', plugins_url( 'js/nova-drag-drop.js', __FILE__ ), array( 'jquery-ui-sortable' ), $this->version, true );
608
		wp_localize_script( 'nova-drag-drop', '_novaDragDrop', array(
609
			'nonce'       => wp_create_nonce( 'drag-drop-reorder' ),
610
			'nonceName'   => 'drag-drop-reorder',
611
			'reorder'     => __( 'Save New Order', 'jetpack' ),
612
			'reorderName' => 'menu_reorder_submit'
613
		) );
614
		add_action( 'the_post', array( $this, 'show_menu_titles_in_menu_item_list' ) );
615
	}
616
617
	function handle_menu_item_actions() {
618
		$action = (string) $_GET['action'];
619
620
		switch ( $action ) {
621
		case 'move-item-up' :
622
		case 'move-item-down' :
623
			$reorder = false;
624
625
			$post_id = (int) $_GET['post_id'];
626
627
			$term = $this->get_menu_item_menu_leaf( $post_id );
628
629
			// Get all posts in that term
630
			$query = new WP_Query( array(
631
				'taxonomy' => self::MENU_TAX,
632
				'term'     => $term->slug,
633
			) );
634
635
			$order = array();
636
			foreach ( $query->posts as $post ) {
637
				$order[] = $post->ID;
638
			}
639
640
			if ( 'move-item-up' == $action ) {
641
				check_admin_referer( 'nova_move_item_up_' . $post_id );
642
643
				$first_post_id = $order[0];
644
				if ( $post_id == $first_post_id ) {
645
					break;
646
				}
647
648
				foreach ( $order as $menu_order => $order_post_id ) {
649
					if ( $post_id != $order_post_id ) {
650
						continue;
651
					}
652
653
					$swap_post_id = $order[$menu_order - 1];
654
					$order[$menu_order - 1] = $post_id;
655
					$order[$menu_order] = $swap_post_id;
656
657
					$reorder = true;
658
					break;
659
				}
660 View Code Duplication
			} else {
661
				check_admin_referer( 'nova_move_item_down_' . $post_id );
662
663
				$last_post_id = end( $order );
664
				if ( $post_id == $last_post_id ) {
665
					break;
666
				}
667
668
				foreach ( $order as $menu_order => $order_post_id ) {
669
					if ( $post_id != $order_post_id ) {
670
						continue;
671
					}
672
673
					$swap_post_id = $order[$menu_order + 1];
674
					$order[$menu_order + 1] = $post_id;
675
					$order[$menu_order] = $swap_post_id;
676
677
					$reorder = true;
678
				}
679
			}
680
681
			if ( $reorder ) {
682
				foreach ( $order as $menu_order => $ID ) {
683
					wp_update_post( compact( 'ID', 'menu_order' ) );
684
				}
685
			}
686
687
			break;
688
		case 'move-menu-up' :
689
		case 'move-menu-down' :
690
			$reorder = false;
691
692
			$term_id = (int) $_GET['term_id'];
693
694
			$terms = $this->get_menus();
695
696
			$order = array();
697
			foreach ( $terms as $term ) {
698
				$order[] = $term->term_id;
699
			}
700
701
			if ( 'move-menu-up' == $action ) {
702
				check_admin_referer( 'nova_move_menu_up_' . $term_id );
703
704
				$first_term_id = $order[0];
705
				if ( $term_id == $first_term_id ) {
706
					break;
707
				}
708
709
				foreach ( $order as $menu_order => $order_term_id ) {
710
					if ( $term_id != $order_term_id ) {
711
						continue;
712
					}
713
714
					$swap_term_id = $order[$menu_order - 1];
715
					$order[$menu_order - 1] = $term_id;
716
					$order[$menu_order] = $swap_term_id;
717
718
					$reorder = true;
719
					break;
720
				}
721 View Code Duplication
			} else {
722
				check_admin_referer( 'nova_move_menu_down_' . $term_id );
723
724
				$last_term_id = end( $order );
725
				if ( $term_id == $last_term_id ) {
726
					break;
727
				}
728
729
				foreach ( $order as $menu_order => $order_term_id ) {
730
					if ( $term_id != $order_term_id ) {
731
						continue;
732
					}
733
734
					$swap_term_id = $order[$menu_order + 1];
735
					$order[$menu_order + 1] = $term_id;
736
					$order[$menu_order] = $swap_term_id;
737
738
					$reorder = true;
739
				}
740
			}
741
742
			if ( $reorder ) {
743
				update_option( 'nova_menu_order', $order );
744
			}
745
746
			break;
747
		default :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a DEFAULT statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in the default statement.

switch ($expr) {
    default : //wrong
        doSomething();
        break;
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
748
			return;
749
		}
750
751
		$redirect = add_query_arg( array(
752
			'post_type' => self::MENU_ITEM_POST_TYPE,
753
			'nova_reordered' => '1'
754
		), admin_url( 'edit.php' ) );
755
		wp_safe_redirect( $redirect );
756
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method handle_menu_item_actions() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
757
	}
758
759
	/*
760
	 * Add menu title rows to the list table
761
	 */
762
	function show_menu_titles_in_menu_item_list( $post ) {
763
		global $wp_list_table;
764
765
		static $last_term_id = false;
766
767
		$term = $this->get_menu_item_menu_leaf( $post->ID );
768
769
		if ( false !== $last_term_id && $last_term_id === $term->term_id )
770
			return;
771
772
		$last_term_id = $term->term_id;
773
774
		$parent_count = 0;
775
		$current_term = $term;
776
		while ( $current_term->parent ) {
777
			$parent_count++;
778
			$current_term = get_term( $current_term->parent, self::MENU_TAX );
779
		}
780
781
		$non_order_column_count = $wp_list_table->get_column_count() - 1;
782
783
		$screen = get_current_screen();
784
785
		$url = admin_url( $screen->parent_file );
786
787
		$up_url = add_query_arg( array(
788
			'action'  => 'move-menu-up',
789
			'term_id' => (int) $term->term_id,
790
		), wp_nonce_url( $url, 'nova_move_menu_up_' . $term->term_id ) );
791
792
		$down_url = add_query_arg( array(
793
			'action'  => 'move-menu-down',
794
			'term_id' => (int) $term->term_id,
795
		), wp_nonce_url( $url, 'nova_move_menu_down_' . $term->term_id ) );
796
797
?>
798
		<tr class="no-items menu-label-row" data-term_id="<?php echo esc_attr( $term->term_id ) ?>">
799
			<td class="colspanchange" colspan="<?php echo (int) $non_order_column_count; ?>">
800
				<h3><?php
801
					echo str_repeat( ' &mdash; ', (int) $parent_count );
802
803
					if ( ! is_wp_error( $term ) ) {
804
						echo esc_html( sanitize_term_field( 'name', $term->name, $term->term_id, self::MENU_TAX, 'display' ) );
805
						edit_term_link( __( 'edit', 'jetpack' ), '<span class="edit-nova-section"><span class="dashicon dashicon-edit"></span>', '</span>', $term );
806
807
					} else {
808
						_e( 'Uncategorized' , 'jetpack' );
809
					}
810
				?></h3>
811
			</td>
812
			<td>
813
				<?php if ( ! is_wp_error( $term ) ) { ?>
814
				<a class="nova-move-menu-up" title="<?php esc_attr_e( 'Move menu section up', 'jetpack' ); ?>" href="<?php echo esc_url( $up_url ); ?>"><?php esc_html_e( 'UP', 'jetpack' ); ?></a>
815
				<br />
816
				<a class="nova-move-menu-down" title="<?php esc_attr_e( 'Move menu section down', 'jetpack' ); ?>" href="<?php echo esc_url( $down_url ); ?>"><?php esc_html_e( 'DOWN', 'jetpack' ); ?></a>
817
				<?php } ?>
818
			</td>
819
		</tr>
820
<?php
821
	}
822
823
/* Edit Many Items */
824
825
	function add_many_new_items_page_load() {
826
		if ( 'POST' === strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
827
			$this->process_form_request();
828
			exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method add_many_new_items_page_load() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
829
		}
830
831
		$this->enqueue_many_items_scripts();
832
	}
833
834
	function enqueue_many_items_scripts() {
835
		wp_enqueue_script( 'nova-many-items', plugins_url( 'js/many-items.js', __FILE__ ), array( 'jquery' ), $this->version, true );
836
	}
837
838
	function process_form_request() {
839
		if ( !isset( $_POST['nova_title'] ) || !is_array( $_POST['nova_title'] ) ) {
840
			return;
841
		}
842
843
		$is_ajax = !empty( $_POST['ajax'] );
844
845
		if ( $is_ajax ) {
846
			check_ajax_referer( 'nova_many_items' );
847
		} else {
848
			check_admin_referer( 'nova_many_items' );
849
		}
850
851
		foreach ( array_keys( $_POST['nova_title'] ) as $key ) :
852
			// $_POST is already slashed
853
			$post_details = array(
854
				'post_status'  => 'publish',
855
				'post_type'    => self::MENU_ITEM_POST_TYPE,
856
				'post_content' => $_POST['nova_content'][$key],
857
				'post_title'   => $_POST['nova_title'][$key],
858
				'tax_input'    => array(
859
					self::MENU_ITEM_LABEL_TAX => $_POST['nova_labels'][$key],
860
					self::MENU_TAX            => $_POST['nova_menu_tax'],
861
				),
862
			);
863
864
			$post_id = wp_insert_post( $post_details );
865
			if ( !$post_id || is_wp_error( $post_id ) ) {
866
				continue;
867
			}
868
869
			$this->set_price( $post_id, isset( $_POST['nova_price'][$key] ) ? stripslashes( $_POST['nova_price'][$key] ) : '' );
870
871
			if ( $is_ajax ) :
872
				$post = get_post( $post_id );
873
				$GLOBALS['post'] = $post;
874
				setup_postdata( $post );
875
876
?>
877
			<td><?php the_title(); ?></td>
878
			<td class="nova-price"><?php $this->display_price(); ?></td>
879
			<td><?php $this->list_labels( $post_id ); ?></td>
880
			<td><?php the_content(); ?></td>
881
<?php
882
			endif;
883
884
		endforeach;
885
886
		if ( $is_ajax ) {
887
			exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method process_form_request() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
888
		}
889
890
		wp_safe_redirect( admin_url( 'edit.php?post_type=' . self::MENU_ITEM_POST_TYPE ) );
891
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method process_form_request() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
892
	}
893
894
	function add_many_new_items_page() {
895
?>
896
	<div class="wrap">
897
		<h2><?php esc_html_e( 'Add Many Items', 'jetpack' ); ?></h2>
898
899
		<p><?php _e( 'Use the <kbd>TAB</kbd> key on your keyboard to move between colums and the <kbd>ENTER</kbd> or <kbd>RETURN</kbd> key to save each row and move on to the next.', 'jetpack' ); ?></p>
900
901
		<form method="post" action="" enctype="multipart/form-data">
902
			<p><h3><?php esc_html_e( 'Add to section:', 'jetpack' ); ?> <?php wp_dropdown_categories( array(
903
				'id'           => 'nova-menu-tax',
904
				'name'         => 'nova_menu_tax',
905
				'taxonomy'     => self::MENU_TAX,
906
				'hide_empty'   => false,
907
				'hierarchical' => true,
908
			) ); ?></h3></p>
909
910
			<table class="many-items-table wp-list-table widefat">
911
				<thead>
912
					<tr>
913
						<th scope="col"><?php esc_html_e( 'Name', 'jetpack' ); ?></th>
914
						<th scope="col" class="nova-price"><?php esc_html_e( 'Price', 'jetpack' ); ?></th>
915
						<th scope="col"><?php _e( 'Labels: <small>spicy, favorite, etc. <em>Separate Labels with commas</em></small>', 'jetpack' ); ?></th>
916
						<th scope="col"><?php esc_html_e( 'Description', 'jetpack' ); ?></th>
917
					</tr>
918
				</thead>
919
				<tbody>
920
					<tr>
921
						<td><input type="text" name="nova_title[]" aria-required="true" /></td>
922
						<td class="nova-price"><input type="text" name="nova_price[]" /></td>
923
						<td><input type="text" name="nova_labels[]" /></td>
924
						<td><textarea name="nova_content[]" cols="20" rows="1"></textarea>
925
					</tr>
926
				</tbody>
927
				<tbody>
928
					<tr>
929
						<td><input type="text" name="nova_title[]" aria-required="true" /></td>
930
						<td class="nova-price"><input type="text" name="nova_price[]" /></td>
931
						<td><input type="text" name="nova_labels[]" /></td>
932
						<td><textarea name="nova_content[]" cols="20" rows="1"></textarea>
933
					</tr>
934
				</tbody>
935
				<tfoot>
936
					<tr>
937
						<th><a class="button button-secondary nova-new-row"><span class="dashicon dashicon-plus"></span> <?php esc_html_e( 'New Row' , 'jetpack' ); ?></a></th>
938
						<th class="nova-price"></th>
939
						<th></th>
940
						<th></th>
941
					</tr>
942
				</tfoot>
943
			</table>
944
945
			<p class="submit">
946
				<input type="submit" class="button-primary" value="<?php esc_attr_e( 'Add These New Menu Items', 'jetpack' ); ?>" />
947
				<?php wp_nonce_field( 'nova_many_items' ); ?>
948
			</p>
949
		</form>
950
	</div>
951
<?php
952
	}
953
954
/* Edit One Item */
955
956
	function register_menu_item_meta_boxes() {
957
		wp_enqueue_script( 'nova-menu-checkboxes' );
958
959
		add_meta_box( 'menu_item_price', __( 'Price', 'jetpack' ), array( $this, 'menu_item_price_meta_box' ), null, 'side', 'high' );
960
	}
961
962
	function menu_item_price_meta_box( $post, $meta_box ) {
0 ignored issues
show
Unused Code introduced by
The parameter $meta_box is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
963
		$price = $this->get_price( $post->ID );
964
?>
965
	<label for="nova-price-<?php echo (int) $post->ID; ?>" class="screen-reader-text"><?php esc_html_e( 'Price', 'jetpack' ); ?></label>
966
	<input type="text" id="nova-price-<?php echo (int) $post->ID; ?>" class="widefat" name="nova_price[<?php echo (int) $post->ID; ?>]" value="<?php echo esc_attr( $price ); ?>" />
967
<?php
968
	}
969
970
	function add_post_meta( $post_id ) {
971
		if ( !isset( $_POST['nova_price'][$post_id] ) ) {
972
			return;
973
		}
974
975
		$this->set_price( $post_id, stripslashes( $_POST['nova_price'][$post_id] ) );
976
	}
977
978
/* Data */
979
980
	function get_menus( $args = array() ) {
981
		$args = wp_parse_args( $args, array(
982
			'hide_empty' => false,
983
		) );
984
985
		$terms = get_terms( self::MENU_TAX, $args );
986
		if ( !$terms || is_wp_error( $terms ) ) {
987
			return array();
988
		}
989
990
		$terms_by_id = array();
991
		foreach ( $terms as $term ) {
992
			$terms_by_id["{$term->term_id}"] = $term;
993
		}
994
995
		$term_order = get_option( 'nova_menu_order', array() );
996
997
		$return = array();
998 View Code Duplication
		foreach ( $term_order as $term_id ) {
999
			if ( isset( $terms_by_id["$term_id"] ) ) {
1000
				$return[] = $terms_by_id["$term_id"];
1001
				unset( $terms_by_id["$term_id"] );
1002
			}
1003
		}
1004
1005
		foreach ( $terms_by_id as $term_id => $term ) {
1006
			$return[] = $term;
1007
		}
1008
1009
		return $return;
1010
	}
1011
1012
	function get_menu_item_menu_leaf( $post_id ) {
1013
		// Get first menu taxonomy "leaf"
1014
		$term_ids = wp_get_object_terms( $post_id, self::MENU_TAX, array( 'fields' => 'ids' ) );
1015
1016
		foreach ( $term_ids as $term_id ) {
1017
			$children = get_term_children( $term_id, self::MENU_TAX );
1018
			if ( ! $children ) {
1019
				break;
1020
			}
1021
		}
1022
1023
		if ( ! isset( $term_id ) ) {
1024
			return false;
1025
		}
1026
1027
		return get_term( $term_id, self::MENU_TAX );
1028
1029
	}
1030
1031
	function list_labels( $post_id = 0 ) {
1032
		$post = get_post( $post_id );
1033
		echo get_the_term_list( $post->ID, self::MENU_ITEM_LABEL_TAX, '', _x( ', ', 'Nova label separator', 'jetpack' ), '' );
1034
	}
1035
1036
	function list_admin_labels( $post_id = 0 ) {
1037
		$post = get_post( $post_id );
1038
		$labels = get_the_terms( $post->ID, self::MENU_ITEM_LABEL_TAX );
1039
		if ( !empty( $labels ) ) {
1040
			$out = array();
1041
			foreach ( $labels as $label ) {
1042
				$out[] = sprintf( '<a href="%s">%s</a>',
1043
					esc_url( add_query_arg( array(
1044
						'post_type' => self::MENU_ITEM_POST_TYPE,
1045
						'taxonomy'  => self::MENU_ITEM_LABEL_TAX,
1046
						'term'      => $label->slug
1047
					), 'edit.php' ) ),
1048
					esc_html( sanitize_term_field( 'name', $label->name, $label->term_id, self::MENU_ITEM_LABEL_TAX, 'display' ) )
1049
				);
1050
			}
1051
1052
			echo join( _x( ', ', 'Nova label separator', 'jetpack' ), $out );
1053
		} else {
1054
			esc_html_e( 'No Labels', 'jetpack' );
1055
		}
1056
	}
1057
1058
	function set_price( $post_id = 0, $price = '' ) {
1059
		$post = get_post( $post_id );
1060
1061
		return update_post_meta( $post->ID, 'nova_price', $price );
1062
	}
1063
1064
	function get_price( $post_id = 0 ) {
1065
		$post = get_post( $post_id );
1066
1067
		return get_post_meta( $post->ID, 'nova_price', true );
1068
	}
1069
1070
	function display_price( $post_id = 0 ) {
1071
		echo esc_html( $this->get_price( $post_id ) );
1072
	}
1073
1074
/* Menu Item Loop Markup */
1075
1076
	/* Does not support nested loops */
1077
1078
	function get_menu_item_loop_markup( $field = null ) {
0 ignored issues
show
Unused Code introduced by
The parameter $field is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1079
		return $this->menu_item_loop_markup;
1080
	}
1081
1082
	/**
1083
	 * Sets up the loop markup.
1084
	 * Attached to the 'template_include' *filter*,
1085
	 * which fires only during a real blog view (not in admin, feeds, etc.)
1086
	 *
1087
	 * @param string Template File
1088
	 * @return string Template File.  VERY Important.
1089
	 */
1090
	function setup_menu_item_loop_markup__in_filter( $template ) {
1091
		add_action( 'loop_start', array( $this, 'start_menu_item_loop' ) );
1092
1093
		return $template;
1094
	}
1095
1096
	/**
1097
	 * If the Query is a Menu Item Query, start outputing the Menu Item Loop Marku
1098
	 * Attached to the 'loop_start' action.
1099
	 *
1100
	 * @param WP_Query
1101
	 */
1102
	function start_menu_item_loop( $query ) {
1103
		if ( !$this->is_menu_item_query( $query ) ) {
1104
			return;
1105
		}
1106
1107
		$this->menu_item_loop_last_term_id = false;
1108
		$this->menu_item_loop_current_term = false;
1109
1110
		add_action( 'the_post', array( $this, 'menu_item_loop_each_post' ) );
1111
		add_action( 'loop_end', array( $this, 'stop_menu_item_loop' ) );
1112
	}
1113
1114
	/**
1115
	 * Outputs the Menu Item Loop Marku
1116
	 * Attached to the 'the_post' action.
1117
	 *
1118
	 * @param WP_Post
1119
	 */
1120
	function menu_item_loop_each_post( $post ) {
1121
		$this->menu_item_loop_current_term = $this->get_menu_item_menu_leaf( $post->ID );
1122
1123
		if ( false === $this->menu_item_loop_last_term_id ) {
1124
			// We're at the very beginning of the loop
1125
1126
			$this->menu_item_loop_open_element( 'menu' ); // Start a new menu section
1127
			$this->menu_item_loop_header(); // Output the menu's header
1128
		} elseif ( $this->menu_item_loop_last_term_id != $this->menu_item_loop_current_term->term_id ) {
1129
			// We're not at the very beginning but still need to start a new menu section.  End the previous menu section first.
1130
1131
			$this->menu_item_loop_close_element( 'menu' ); // End the previous menu section
1132
			$this->menu_item_loop_open_element( 'menu' ); // Start a new menu section
1133
			$this->menu_item_loop_header(); // Output the menu's header
1134
		}
1135
1136
		$this->menu_item_loop_last_term_id = $this->menu_item_loop_current_term->term_id;
1137
	}
1138
1139
	/**
1140
	 * If the Query is a Menu Item Query, stop outputing the Menu Item Loop Marku
1141
	 * Attached to the 'loop_end' action.
1142
	 *
1143
	 * @param WP_Query
1144
	 */
1145
	function stop_menu_item_loop( $query ) {
1146
		if ( !$this->is_menu_item_query( $query ) ) {
1147
			return;
1148
		}
1149
1150
		remove_action( 'the_post', array( $this, 'menu_item_loop_each_post' ) );
1151
		remove_action( 'loop_start', array( $this, 'start_menu_item_loop' ) );
1152
		remove_action( 'loop_end', array( $this, 'stop_menu_item_loop' ) );
1153
1154
		$this->menu_item_loop_close_element( 'menu' ); // End the last menu section
1155
	}
1156
1157
	/**
1158
	 * Outputs the Menu Group Header
1159
	 */
1160
	function menu_item_loop_header() {
1161
		$this->menu_item_loop_open_element( 'menu_header' );
1162
			$this->menu_item_loop_open_element( 'menu_title' );
1163
				echo esc_html( $this->menu_item_loop_current_term->name ); // @todo tax filter
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
1164
			$this->menu_item_loop_close_element( 'menu_title' );
1165
		if ( $this->menu_item_loop_current_term->description ) :
1166
			$this->menu_item_loop_open_element( 'menu_description' );
1167
				echo esc_html( $this->menu_item_loop_current_term->description ); // @todo kses, tax filter
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
1168
			$this->menu_item_loop_close_element( 'menu_description' );
1169
		endif;
1170
		$this->menu_item_loop_close_element( 'menu_header' );
1171
	}
1172
1173
	/**
1174
	 * Outputs a Menu Item Markup element opening tag
1175
	 *
1176
	 * @param string $field - Menu Item Markup settings field
1177
	 */
1178
	function menu_item_loop_open_element( $field ) {
1179
		$markup = $this->get_menu_item_loop_markup();
1180
		echo '<' . tag_escape( $markup["{$field}_tag"] ) .  $this->menu_item_loop_class( $markup["{$field}_class"] ) . ">\n";
1181
	}
1182
1183
	/**
1184
	 * Outputs a Menu Item Markup element closing tag
1185
	 *
1186
	 * @param string $field - Menu Item Markup settings field
1187
	 */
1188
	function menu_item_loop_close_element( $field ) {
1189
		$markup = $this->get_menu_item_loop_markup();
1190
		echo '</' . tag_escape( $markup["{$field}_tag"] ) . ">\n";
1191
	}
1192
1193
	/**
1194
	 * Returns a Menu Item Markup element's class attribute
1195
	 *
1196
	 * @param string $class
1197
	 * @return string HTML class attribute with leading whitespace
1198
	 */
1199
	function menu_item_loop_class( $class ) {
1200
		if ( !$class ) {
1201
			return '';
1202
		}
1203
1204
		return ' class="' . esc_attr( $class ) . '"';
1205
	}
1206
}
1207
1208
add_action( 'init', array( 'Nova_Restaurant', 'init' ) );
1209