Completed
Push — update/sync-users-enqueue-orde... ( d17611...0c48e3 )
by
unknown
29:40
created

Nova_Restaurant::menu_item_loop_header()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 11
nc 2
nop 0
dl 0
loc 12
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
		if ( isset( $GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE] ) ) {
437
			$submenu_item = array_pop( $GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE] );
438
			$GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE][11] = $submenu_item;
439
			ksort( $GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE] );
440
		}
441
442
443
		$this->setup_menu_item_columns();
444
445
		wp_register_script( 'nova-menu-checkboxes', plugins_url( 'js/menu-checkboxes.js', __FILE__ ), array( 'jquery' ), $this->version, true );
446
	}
447
448
449
	/**
450
	 * Custom Nova Icon CSS
451
	 */
452
	function set_custom_font_icon() {
453
	?>
454
	<style type="text/css">
455
	#menu-posts-nova_menu_item .wp-menu-image:before {
456
		font-family: 'nova-font' !important;
457
		content: '\e603' !important;
458
	}
459
	</style>
460
	<?php
461
	}
462
463
	function current_screen_load() {
464
		$screen = get_current_screen();
465
		if ( 'edit-nova_menu_item' !== $screen->id ) {
466
			return;
467
		}
468
469
		$this->edit_menu_items_page_load();
470
		add_filter( 'admin_notices', array( $this, 'admin_notices' ) );
471
	}
472
473
/* Edit Items List */
474
475
	function admin_notices() {
476
		if ( isset( $_GET['nova_reordered'] ) )
477
			/* translators: this is about a food menu */
478
			printf( '<div class="updated"><p>%s</p></div>', __( 'Menu Items re-ordered.', 'jetpack' ) );
479
	}
480
481
	function no_title_sorting( $columns ) {
482
		if ( isset( $columns['title'] ) )
483
			unset( $columns['title'] );
484
		return $columns;
485
	}
486
487
	function setup_menu_item_columns() {
488
		add_filter( sprintf( 'manage_edit-%s_sortable_columns', self::MENU_ITEM_POST_TYPE ), array( $this, 'no_title_sorting' ) );
489
		add_filter( sprintf( 'manage_%s_posts_columns', self::MENU_ITEM_POST_TYPE ), array( $this, 'menu_item_columns' ) );
490
491
		add_action( sprintf( 'manage_%s_posts_custom_column', self::MENU_ITEM_POST_TYPE ), array( $this, 'menu_item_column_callback' ), 10, 2 );
492
	}
493
494
	function menu_item_columns( $columns ) {
495
		unset( $columns['date'], $columns['likes'] );
496
497
		$columns['thumbnail'] = __( 'Thumbnail', 'jetpack' );
498
		$columns['labels']    = __( 'Labels',    'jetpack' );
499
		$columns['price']     = __( 'Price',     'jetpack' );
500
		$columns['order']     = __( 'Order',     'jetpack' );
501
502
		return $columns;
503
	}
504
505
	function menu_item_column_callback( $column, $post_id ) {
506
		$screen = get_current_screen();
507
508
		switch ( $column ) {
509
			case 'thumbnail':
510
				echo get_the_post_thumbnail( $post_id, array( 50, 50 ) );
511
				break;
512
			case 'labels' :
513
				$this->list_admin_labels( $post_id );
514
				break;
515
			case 'price' :
516
				$this->display_price( $post_id );
517
				break;
518
			case 'order' :
519
				$url = admin_url( $screen->parent_file );
520
521
				$up_url = add_query_arg( array(
522
					'action' => 'move-item-up',
523
					'post_id' => (int) $post_id,
524
				), wp_nonce_url( $url, 'nova_move_item_up_' . $post_id ) );
525
526
				$down_url = add_query_arg( array(
527
					'action' => 'move-item-down',
528
					'post_id' => (int) $post_id,
529
				), wp_nonce_url( $url, 'nova_move_item_down_' . $post_id ) );
530
				$menu_item = get_post($post_id);
531
				$this->get_menu_by_post_id( $post_id );
532
				if ( $term_id = $this->get_menu_by_post_id( $post_id ) ) {
533
					$term_id = $term_id->term_id;
534
				}
535
	?>
536
				<input type="hidden" class="menu-order-value" name="nova_order[<?php echo (int) $post_id ?>]" value="<?php echo esc_attr( $menu_item->menu_order ) ?>" />
537
				<input type="hidden" class='nova-menu-term' name="nova_menu_term[<?php echo (int) $post_id ?>]" value="<?php echo esc_attr( $term_id ); ?>">
538
539
				<span class="hide-if-js">
540
				&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>
541
				<br />
542
				&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>
543
				</span>
544
	<?php
545
				break;
546
		}
547
	}
548
549
	function get_menu_by_post_id( $post_id = null ) {
550
		if ( ! $post_id )
551
			return false;
552
553
		$terms = get_the_terms( $post_id, self::MENU_TAX );
554
555
		if ( ! is_array( $terms ) )
556
			return false;
557
558
		return array_pop( $terms );
559
	}
560
561
	/**
562
	 * Fires on a menu edit page. We might have drag-n-drop reordered
563
	 */
564
	function maybe_reorder_menu_items() {
565
		// make sure we clicked our button
566
		if ( ! ( isset( $_REQUEST['menu_reorder_submit'] ) && $_REQUEST['menu_reorder_submit'] === __( 'Save New Order', 'jetpack' ) ) )
567
			return;
568
		;
569
570
		// make sure we have the nonce
571
		if ( ! ( isset( $_REQUEST['drag-drop-reorder'] ) && wp_verify_nonce( $_REQUEST['drag-drop-reorder'], 'drag-drop-reorder' ) ) )
572
			return;
573
574
		$term_pairs = array_map( 'absint', $_REQUEST['nova_menu_term'] );
575
		$order_pairs = array_map( 'absint', $_REQUEST['nova_order'] );
576
577
		foreach( $order_pairs as $ID => $menu_order ) {
578
			$ID = absint( $ID );
579
			unset( $order_pairs[$ID] );
580
			if ( $ID < 0 )
581
				continue;
582
583
			$post = get_post( $ID );
584
			if ( ! $post )
585
				continue;
586
587
			// save a write if the order hasn't changed
588
			if ( $menu_order != $post->menu_order )
589
				wp_update_post( compact( 'ID', 'menu_order' ) );
590
591
			// save a write if the term hasn't changed
592
			if ( $term_pairs[$ID] != $this->get_menu_by_post_id( $ID )->term_id )
593
				wp_set_object_terms( $ID, $term_pairs[$ID], self::MENU_TAX );
594
595
		}
596
597
		$redirect = add_query_arg( array(
598
			'post_type' => self::MENU_ITEM_POST_TYPE,
599
			'nova_reordered' => '1'
600
		), admin_url( 'edit.php' ) );
601
		wp_safe_redirect( $redirect );
602
		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...
603
604
	}
605
606
	function edit_menu_items_page_load() {
607
		if ( isset( $_GET['action'] ) ) {
608
			$this->handle_menu_item_actions();
609
		}
610
611
		$this->maybe_reorder_menu_items();
612
613
		wp_enqueue_script( 'nova-drag-drop', plugins_url( 'js/nova-drag-drop.js', __FILE__ ), array( 'jquery-ui-sortable' ), $this->version, true );
614
		wp_localize_script( 'nova-drag-drop', '_novaDragDrop', array(
615
			'nonce'       => wp_create_nonce( 'drag-drop-reorder' ),
616
			'nonceName'   => 'drag-drop-reorder',
617
			'reorder'     => __( 'Save New Order', 'jetpack' ),
618
			'reorderName' => 'menu_reorder_submit'
619
		) );
620
		add_action( 'the_post', array( $this, 'show_menu_titles_in_menu_item_list' ) );
621
	}
622
623
	function handle_menu_item_actions() {
624
		$action = (string) $_GET['action'];
625
626
		switch ( $action ) {
627
		case 'move-item-up' :
628
		case 'move-item-down' :
629
			$reorder = false;
630
631
			$post_id = (int) $_GET['post_id'];
632
633
			$term = $this->get_menu_item_menu_leaf( $post_id );
634
635
			// Get all posts in that term
636
			$query = new WP_Query( array(
637
				'taxonomy' => self::MENU_TAX,
638
				'term'     => $term->slug,
639
			) );
640
641
			$order = array();
642
			foreach ( $query->posts as $post ) {
643
				$order[] = $post->ID;
644
			}
645
646
			if ( 'move-item-up' == $action ) {
647
				check_admin_referer( 'nova_move_item_up_' . $post_id );
648
649
				$first_post_id = $order[0];
650
				if ( $post_id == $first_post_id ) {
651
					break;
652
				}
653
654
				foreach ( $order as $menu_order => $order_post_id ) {
655
					if ( $post_id != $order_post_id ) {
656
						continue;
657
					}
658
659
					$swap_post_id = $order[$menu_order - 1];
660
					$order[$menu_order - 1] = $post_id;
661
					$order[$menu_order] = $swap_post_id;
662
663
					$reorder = true;
664
					break;
665
				}
666 View Code Duplication
			} else {
667
				check_admin_referer( 'nova_move_item_down_' . $post_id );
668
669
				$last_post_id = end( $order );
670
				if ( $post_id == $last_post_id ) {
671
					break;
672
				}
673
674
				foreach ( $order as $menu_order => $order_post_id ) {
675
					if ( $post_id != $order_post_id ) {
676
						continue;
677
					}
678
679
					$swap_post_id = $order[$menu_order + 1];
680
					$order[$menu_order + 1] = $post_id;
681
					$order[$menu_order] = $swap_post_id;
682
683
					$reorder = true;
684
				}
685
			}
686
687
			if ( $reorder ) {
688
				foreach ( $order as $menu_order => $ID ) {
689
					wp_update_post( compact( 'ID', 'menu_order' ) );
690
				}
691
			}
692
693
			break;
694
		case 'move-menu-up' :
695
		case 'move-menu-down' :
696
			$reorder = false;
697
698
			$term_id = (int) $_GET['term_id'];
699
700
			$terms = $this->get_menus();
701
702
			$order = array();
703
			foreach ( $terms as $term ) {
704
				$order[] = $term->term_id;
705
			}
706
707
			if ( 'move-menu-up' == $action ) {
708
				check_admin_referer( 'nova_move_menu_up_' . $term_id );
709
710
				$first_term_id = $order[0];
711
				if ( $term_id == $first_term_id ) {
712
					break;
713
				}
714
715
				foreach ( $order as $menu_order => $order_term_id ) {
716
					if ( $term_id != $order_term_id ) {
717
						continue;
718
					}
719
720
					$swap_term_id = $order[$menu_order - 1];
721
					$order[$menu_order - 1] = $term_id;
722
					$order[$menu_order] = $swap_term_id;
723
724
					$reorder = true;
725
					break;
726
				}
727 View Code Duplication
			} else {
728
				check_admin_referer( 'nova_move_menu_down_' . $term_id );
729
730
				$last_term_id = end( $order );
731
				if ( $term_id == $last_term_id ) {
732
					break;
733
				}
734
735
				foreach ( $order as $menu_order => $order_term_id ) {
736
					if ( $term_id != $order_term_id ) {
737
						continue;
738
					}
739
740
					$swap_term_id = $order[$menu_order + 1];
741
					$order[$menu_order + 1] = $term_id;
742
					$order[$menu_order] = $swap_term_id;
743
744
					$reorder = true;
745
				}
746
			}
747
748
			if ( $reorder ) {
749
				update_option( 'nova_menu_order', $order );
750
			}
751
752
			break;
753
		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...
754
			return;
755
		}
756
757
		$redirect = add_query_arg( array(
758
			'post_type' => self::MENU_ITEM_POST_TYPE,
759
			'nova_reordered' => '1'
760
		), admin_url( 'edit.php' ) );
761
		wp_safe_redirect( $redirect );
762
		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...
763
	}
764
765
	/*
766
	 * Add menu title rows to the list table
767
	 */
768
	function show_menu_titles_in_menu_item_list( $post ) {
769
		global $wp_list_table;
770
771
		static $last_term_id = false;
772
773
		$term = $this->get_menu_item_menu_leaf( $post->ID );
774
775
		$term_id = $term instanceof WP_Term ? $term->term_id : null;
0 ignored issues
show
Bug introduced by
The class WP_Term does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
776
777
		if ( false !== $last_term_id && $last_term_id === $term_id ) {
778
			return;
779
		}
780
781
		if ( is_null( $term_id ) ) {
782
			$last_term_id = null;
783
			$term_name = '';
784
			$parent_count = 0;
785
		} else {
786
			$last_term_id = $term->term_id;
787
			$term_name = $term->name;
788
			$parent_count = 0;
789
			$current_term = $term;
790
			while ( $current_term->parent ) {
791
				$parent_count++;
792
				$current_term = get_term( $current_term->parent, self::MENU_TAX );
793
			}
794
		}
795
796
		$non_order_column_count = $wp_list_table->get_column_count() - 1;
797
798
		$screen = get_current_screen();
799
800
		$url = admin_url( $screen->parent_file );
801
802
		$up_url = add_query_arg( array(
803
			'action'  => 'move-menu-up',
804
			'term_id' => (int) $term_id,
805
		), wp_nonce_url( $url, 'nova_move_menu_up_' . $term_id ) );
806
807
		$down_url = add_query_arg( array(
808
			'action'  => 'move-menu-down',
809
			'term_id' => (int) $term_id,
810
		), wp_nonce_url( $url, 'nova_move_menu_down_' . $term_id ) );
811
812
?>
813
		<tr class="no-items menu-label-row" data-term_id="<?php echo esc_attr( $term_id ) ?>">
814
			<td class="colspanchange" colspan="<?php echo (int) $non_order_column_count; ?>">
815
				<h3><?php
816
					echo str_repeat( ' &mdash; ', (int) $parent_count );
817
818
					if ( $term instanceof WP_Term ) {
0 ignored issues
show
Bug introduced by
The class WP_Term does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
819
						echo esc_html( sanitize_term_field( 'name', $term_name, $term_id, self::MENU_TAX, 'display' ) );
820
						edit_term_link( __( 'edit', 'jetpack' ), '<span class="edit-nova-section"><span class="dashicon dashicon-edit"></span>', '</span>', $term );
821
822
					} else {
823
						_e( 'Uncategorized' , 'jetpack' );
824
					}
825
				?></h3>
826
			</td>
827
			<td>
828
				<?php if ( $term instanceof WP_Term ) { ?>
0 ignored issues
show
Bug introduced by
The class WP_Term does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
829
				<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>
830
				<br />
831
				<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>
832
				<?php } ?>
833
			</td>
834
		</tr>
835
<?php
836
	}
837
838
/* Edit Many Items */
839
840
	function add_many_new_items_page_load() {
841
		if ( 'POST' === strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
842
			$this->process_form_request();
843
			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...
844
		}
845
846
		$this->enqueue_many_items_scripts();
847
	}
848
849
	function enqueue_many_items_scripts() {
850
		wp_enqueue_script( 'nova-many-items', plugins_url( 'js/many-items.js', __FILE__ ), array( 'jquery' ), $this->version, true );
851
	}
852
853
	function process_form_request() {
854
		if ( !isset( $_POST['nova_title'] ) || !is_array( $_POST['nova_title'] ) ) {
855
			return;
856
		}
857
858
		$is_ajax = !empty( $_POST['ajax'] );
859
860
		if ( $is_ajax ) {
861
			check_ajax_referer( 'nova_many_items' );
862
		} else {
863
			check_admin_referer( 'nova_many_items' );
864
		}
865
866
		foreach ( array_keys( $_POST['nova_title'] ) as $key ) :
867
			// $_POST is already slashed
868
			$post_details = array(
869
				'post_status'  => 'publish',
870
				'post_type'    => self::MENU_ITEM_POST_TYPE,
871
				'post_content' => $_POST['nova_content'][$key],
872
				'post_title'   => $_POST['nova_title'][$key],
873
				'tax_input'    => array(
874
					self::MENU_ITEM_LABEL_TAX => $_POST['nova_labels'][$key],
875
					self::MENU_TAX            => isset( $_POST['nova_menu_tax'] ) ? $_POST['nova_menu_tax'] : null,
876
				),
877
			);
878
879
			$post_id = wp_insert_post( $post_details );
880
			if ( !$post_id || is_wp_error( $post_id ) ) {
881
				continue;
882
			}
883
884
			$this->set_price( $post_id, isset( $_POST['nova_price'][$key] ) ? stripslashes( $_POST['nova_price'][$key] ) : '' );
885
886
			if ( $is_ajax ) :
887
				$post = get_post( $post_id );
888
				$GLOBALS['post'] = $post;
889
				setup_postdata( $post );
890
891
?>
892
			<td><?php the_title(); ?></td>
893
			<td class="nova-price"><?php $this->display_price(); ?></td>
894
			<td><?php $this->list_labels( $post_id ); ?></td>
895
			<td><?php the_content(); ?></td>
896
<?php
897
			endif;
898
899
		endforeach;
900
901
		if ( $is_ajax ) {
902
			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...
903
		}
904
905
		wp_safe_redirect( admin_url( 'edit.php?post_type=' . self::MENU_ITEM_POST_TYPE ) );
906
		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...
907
	}
908
909
	function add_many_new_items_page() {
910
?>
911
	<div class="wrap">
912
		<h2><?php esc_html_e( 'Add Many Items', 'jetpack' ); ?></h2>
913
914
		<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>
915
916
		<form method="post" action="" enctype="multipart/form-data">
917
			<p><h3><?php esc_html_e( 'Add to section:', 'jetpack' ); ?> <?php wp_dropdown_categories( array(
918
				'id'           => 'nova-menu-tax',
919
				'name'         => 'nova_menu_tax',
920
				'taxonomy'     => self::MENU_TAX,
921
				'hide_empty'   => false,
922
				'hierarchical' => true,
923
			) ); ?></h3></p>
924
925
			<table class="many-items-table wp-list-table widefat">
926
				<thead>
927
					<tr>
928
						<th scope="col"><?php esc_html_e( 'Name', 'jetpack' ); ?></th>
929
						<th scope="col" class="nova-price"><?php esc_html_e( 'Price', 'jetpack' ); ?></th>
930
						<th scope="col"><?php _e( 'Labels: <small>spicy, favorite, etc. <em>Separate Labels with commas</em></small>', 'jetpack' ); ?></th>
931
						<th scope="col"><?php esc_html_e( 'Description', 'jetpack' ); ?></th>
932
					</tr>
933
				</thead>
934
				<tbody>
935
					<tr>
936
						<td><input type="text" name="nova_title[]" aria-required="true" /></td>
937
						<td class="nova-price"><input type="text" name="nova_price[]" /></td>
938
						<td><input type="text" name="nova_labels[]" /></td>
939
						<td><textarea name="nova_content[]" cols="20" rows="1"></textarea>
940
					</tr>
941
				</tbody>
942
				<tbody>
943
					<tr>
944
						<td><input type="text" name="nova_title[]" aria-required="true" /></td>
945
						<td class="nova-price"><input type="text" name="nova_price[]" /></td>
946
						<td><input type="text" name="nova_labels[]" /></td>
947
						<td><textarea name="nova_content[]" cols="20" rows="1"></textarea>
948
					</tr>
949
				</tbody>
950
				<tfoot>
951
					<tr>
952
						<th><a class="button button-secondary nova-new-row"><span class="dashicon dashicon-plus"></span> <?php esc_html_e( 'New Row' , 'jetpack' ); ?></a></th>
953
						<th class="nova-price"></th>
954
						<th></th>
955
						<th></th>
956
					</tr>
957
				</tfoot>
958
			</table>
959
960
			<p class="submit">
961
				<input type="submit" class="button-primary" value="<?php esc_attr_e( 'Add These New Menu Items', 'jetpack' ); ?>" />
962
				<?php wp_nonce_field( 'nova_many_items' ); ?>
963
			</p>
964
		</form>
965
	</div>
966
<?php
967
	}
968
969
/* Edit One Item */
970
971
	function register_menu_item_meta_boxes() {
972
		wp_enqueue_script( 'nova-menu-checkboxes' );
973
974
		add_meta_box( 'menu_item_price', __( 'Price', 'jetpack' ), array( $this, 'menu_item_price_meta_box' ), null, 'side', 'high' );
975
	}
976
977
	function menu_item_price_meta_box( $post, $meta_box ) {
978
		$price = $this->get_price( $post->ID );
979
?>
980
	<label for="nova-price-<?php echo (int) $post->ID; ?>" class="screen-reader-text"><?php esc_html_e( 'Price', 'jetpack' ); ?></label>
981
	<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 ); ?>" />
982
<?php
983
	}
984
985
	function add_post_meta( $post_id ) {
986
		if ( !isset( $_POST['nova_price'][$post_id] ) ) {
987
			return;
988
		}
989
990
		$this->set_price( $post_id, stripslashes( $_POST['nova_price'][$post_id] ) );
991
	}
992
993
/* Data */
994
995
	function get_menus( $args = array() ) {
996
		$args = wp_parse_args( $args, array(
997
			'hide_empty' => false,
998
		) );
999
1000
		$terms = get_terms( self::MENU_TAX, $args );
1001
		if ( !$terms || is_wp_error( $terms ) ) {
1002
			return array();
1003
		}
1004
1005
		$terms_by_id = array();
1006
		foreach ( $terms as $term ) {
1007
			$terms_by_id["{$term->term_id}"] = $term;
1008
		}
1009
1010
		$term_order = get_option( 'nova_menu_order', array() );
1011
1012
		$return = array();
1013 View Code Duplication
		foreach ( $term_order as $term_id ) {
1014
			if ( isset( $terms_by_id["$term_id"] ) ) {
1015
				$return[] = $terms_by_id["$term_id"];
1016
				unset( $terms_by_id["$term_id"] );
1017
			}
1018
		}
1019
1020
		foreach ( $terms_by_id as $term_id => $term ) {
1021
			$return[] = $term;
1022
		}
1023
1024
		return $return;
1025
	}
1026
1027
	function get_menu_item_menu_leaf( $post_id ) {
1028
		// Get first menu taxonomy "leaf"
1029
		$term_ids = wp_get_object_terms( $post_id, self::MENU_TAX, array( 'fields' => 'ids' ) );
1030
1031
		foreach ( $term_ids as $term_id ) {
1032
			$children = get_term_children( $term_id, self::MENU_TAX );
1033
			if ( ! $children ) {
1034
				break;
1035
			}
1036
		}
1037
1038
		if ( ! isset( $term_id ) ) {
1039
			return false;
1040
		}
1041
1042
		return get_term( $term_id, self::MENU_TAX );
1043
1044
	}
1045
1046
	function list_labels( $post_id = 0 ) {
1047
		$post = get_post( $post_id );
1048
		echo get_the_term_list( $post->ID, self::MENU_ITEM_LABEL_TAX, '', _x( ', ', 'Nova label separator', 'jetpack' ), '' );
1049
	}
1050
1051
	function list_admin_labels( $post_id = 0 ) {
1052
		$post = get_post( $post_id );
1053
		$labels = get_the_terms( $post->ID, self::MENU_ITEM_LABEL_TAX );
1054
		if ( !empty( $labels ) ) {
1055
			$out = array();
1056
			foreach ( $labels as $label ) {
1057
				$out[] = sprintf( '<a href="%s">%s</a>',
1058
					esc_url( add_query_arg( array(
1059
						'post_type' => self::MENU_ITEM_POST_TYPE,
1060
						'taxonomy'  => self::MENU_ITEM_LABEL_TAX,
1061
						'term'      => $label->slug
1062
					), 'edit.php' ) ),
1063
					esc_html( sanitize_term_field( 'name', $label->name, $label->term_id, self::MENU_ITEM_LABEL_TAX, 'display' ) )
1064
				);
1065
			}
1066
1067
			echo join( _x( ', ', 'Nova label separator', 'jetpack' ), $out );
1068
		} else {
1069
			esc_html_e( 'No Labels', 'jetpack' );
1070
		}
1071
	}
1072
1073
	function set_price( $post_id = 0, $price = '' ) {
1074
		$post = get_post( $post_id );
1075
1076
		return update_post_meta( $post->ID, 'nova_price', $price );
1077
	}
1078
1079
	function get_price( $post_id = 0 ) {
1080
		$post = get_post( $post_id );
1081
1082
		return get_post_meta( $post->ID, 'nova_price', true );
1083
	}
1084
1085
	function display_price( $post_id = 0 ) {
1086
		echo esc_html( $this->get_price( $post_id ) );
1087
	}
1088
1089
/* Menu Item Loop Markup */
1090
1091
	/* Does not support nested loops */
1092
1093
	function get_menu_item_loop_markup( $field = null ) {
1094
		return $this->menu_item_loop_markup;
1095
	}
1096
1097
	/**
1098
	 * Sets up the loop markup.
1099
	 * Attached to the 'template_include' *filter*,
1100
	 * which fires only during a real blog view (not in admin, feeds, etc.)
1101
	 *
1102
	 * @param string Template File
1103
	 * @return string Template File.  VERY Important.
1104
	 */
1105
	function setup_menu_item_loop_markup__in_filter( $template ) {
1106
		add_action( 'loop_start', array( $this, 'start_menu_item_loop' ) );
1107
1108
		return $template;
1109
	}
1110
1111
	/**
1112
	 * If the Query is a Menu Item Query, start outputing the Menu Item Loop Marku
1113
	 * Attached to the 'loop_start' action.
1114
	 *
1115
	 * @param WP_Query
1116
	 */
1117
	function start_menu_item_loop( $query ) {
1118
		if ( !$this->is_menu_item_query( $query ) ) {
1119
			return;
1120
		}
1121
1122
		$this->menu_item_loop_last_term_id = false;
1123
		$this->menu_item_loop_current_term = false;
1124
1125
		add_action( 'the_post', array( $this, 'menu_item_loop_each_post' ) );
1126
		add_action( 'loop_end', array( $this, 'stop_menu_item_loop' ) );
1127
	}
1128
1129
	/**
1130
	 * Outputs the Menu Item Loop Marku
1131
	 * Attached to the 'the_post' action.
1132
	 *
1133
	 * @param WP_Post
1134
	 */
1135
	function menu_item_loop_each_post( $post ) {
1136
		$this->menu_item_loop_current_term = $this->get_menu_item_menu_leaf( $post->ID );
1137
1138
		if ( false === $this->menu_item_loop_last_term_id ) {
1139
			// We're at the very beginning of the loop
1140
1141
			$this->menu_item_loop_open_element( 'menu' ); // Start a new menu section
1142
			$this->menu_item_loop_header(); // Output the menu's header
1143
		} elseif ( $this->menu_item_loop_last_term_id != $this->menu_item_loop_current_term->term_id ) {
1144
			// We're not at the very beginning but still need to start a new menu section.  End the previous menu section first.
1145
1146
			$this->menu_item_loop_close_element( 'menu' ); // End the previous menu section
1147
			$this->menu_item_loop_open_element( 'menu' ); // Start a new menu section
1148
			$this->menu_item_loop_header(); // Output the menu's header
1149
		}
1150
1151
		$this->menu_item_loop_last_term_id = $this->menu_item_loop_current_term->term_id;
1152
	}
1153
1154
	/**
1155
	 * If the Query is a Menu Item Query, stop outputing the Menu Item Loop Marku
1156
	 * Attached to the 'loop_end' action.
1157
	 *
1158
	 * @param WP_Query
1159
	 */
1160
	function stop_menu_item_loop( $query ) {
1161
		if ( !$this->is_menu_item_query( $query ) ) {
1162
			return;
1163
		}
1164
1165
		remove_action( 'the_post', array( $this, 'menu_item_loop_each_post' ) );
1166
		remove_action( 'loop_start', array( $this, 'start_menu_item_loop' ) );
1167
		remove_action( 'loop_end', array( $this, 'stop_menu_item_loop' ) );
1168
1169
		$this->menu_item_loop_close_element( 'menu' ); // End the last menu section
1170
	}
1171
1172
	/**
1173
	 * Outputs the Menu Group Header
1174
	 */
1175
	function menu_item_loop_header() {
1176
		$this->menu_item_loop_open_element( 'menu_header' );
1177
			$this->menu_item_loop_open_element( 'menu_title' );
1178
				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...
1179
			$this->menu_item_loop_close_element( 'menu_title' );
1180
		if ( $this->menu_item_loop_current_term->description ) :
1181
			$this->menu_item_loop_open_element( 'menu_description' );
1182
				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...
1183
			$this->menu_item_loop_close_element( 'menu_description' );
1184
		endif;
1185
		$this->menu_item_loop_close_element( 'menu_header' );
1186
	}
1187
1188
	/**
1189
	 * Outputs a Menu Item Markup element opening tag
1190
	 *
1191
	 * @param string $field - Menu Item Markup settings field.
1192
	 */
1193 View Code Duplication
	function menu_item_loop_open_element( $field ) {
1194
		$markup = $this->get_menu_item_loop_markup();
1195
		/**
1196
		 * Filter a menu item's element opening tag.
1197
		 *
1198
		 * @module custom-content-types
1199
		 *
1200
		 * @since 4.4.0
1201
		 *
1202
		 * @param string       $tag    Menu item's element opening tag.
1203
		 * @param string       $field  Menu Item Markup settings field.
1204
		 * @param array        $markup Array of markup elements for the menu item.
1205
		 * @param false|object $term   Taxonomy term for current menu item.
1206
		 */
1207
		echo apply_filters(
1208
			'jetpack_nova_menu_item_loop_open_element',
1209
			'<' . tag_escape( $markup["{$field}_tag"] ) . $this->menu_item_loop_class( $markup["{$field}_class"] ) . ">\n",
1210
			$field,
1211
			$markup,
1212
			$this->menu_item_loop_current_term
1213
		);
1214
	}
1215
1216
	/**
1217
	 * Outputs a Menu Item Markup element closing tag
1218
	 *
1219
	 * @param string $field - Menu Item Markup settings field
1220
	 */
1221 View Code Duplication
	function menu_item_loop_close_element( $field ) {
1222
		$markup = $this->get_menu_item_loop_markup();
1223
		/**
1224
		 * Filter a menu item's element closing tag.
1225
		 *
1226
		 * @module custom-content-types
1227
		 *
1228
		 * @since 4.4.0
1229
		 *
1230
		 * @param string       $tag    Menu item's element closing tag.
1231
		 * @param string       $field  Menu Item Markup settings field.
1232
		 * @param array        $markup Array of markup elements for the menu item.
1233
		 * @param false|object $term   Taxonomy term for current menu item.
1234
		 */
1235
		echo apply_filters(
1236
			'jetpack_nova_menu_item_loop_close_element',
1237
			'</' . tag_escape( $markup["{$field}_tag"] ) . ">\n",
1238
			$field,
1239
			$markup,
1240
			$this->menu_item_loop_current_term
1241
		);
1242
	}
1243
1244
	/**
1245
	 * Returns a Menu Item Markup element's class attribute.
1246
	 *
1247
	 * @param  string $class Class name.
1248
	 * @return string HTML   class attribute with leading whitespace.
1249
	 */
1250
	function menu_item_loop_class( $class ) {
1251
		if ( ! $class ) {
1252
			return '';
1253
		}
1254
1255
		/**
1256
		 * Filter a menu Item Markup element's class attribute.
1257
		 *
1258
		 * @module custom-content-types
1259
		 *
1260
		 * @since 4.4.0
1261
		 *
1262
		 * @param string       $tag    Menu Item Markup element's class attribute.
1263
		 * @param string       $class  Menu Item Class name.
1264
		 * @param false|object $term   Taxonomy term for current menu item.
1265
		 */
1266
		return apply_filters(
1267
			'jetpack_nova_menu_item_loop_class',
1268
			' class="' . esc_attr( $class ) . '"',
1269
			$class,
1270
			$this->menu_item_loop_current_term
1271
		);
1272
	}
1273
}
1274
1275
add_action( 'init', array( 'Nova_Restaurant', 'init' ) );
1276