Completed
Push — jetpack-fusion-mock-files ( e51750...3b1561 )
by
unknown
13:31
created

Nova_Restaurant::edit_menu_items_page_load()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 18
nc 2
nop 0
dl 0
loc 26
rs 8.8571
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(
446
			'nova-menu-checkboxes',
447
			Jetpack::get_file_url_for_environment(
448
				'_inc/build/custom-post-types/js/menu-checkboxes.min.js',
449
				'modules/custom-post-types/js/menu-checkboxes.js'
450
			),
451
			array( 'jquery' ),
452
			$this->version,
453
			true
454
		);
455
	}
456
457
458
	/**
459
	 * Custom Nova Icon CSS
460
	 */
461
	function set_custom_font_icon() {
462
	?>
463
	<style type="text/css">
464
	#menu-posts-nova_menu_item .wp-menu-image:before {
465
		font-family: 'nova-font' !important;
466
		content: '\e603' !important;
467
	}
468
	</style>
469
	<?php
470
	}
471
472
	function current_screen_load() {
473
		$screen = get_current_screen();
474
		if ( 'edit-nova_menu_item' !== $screen->id ) {
475
			return;
476
		}
477
478
		$this->edit_menu_items_page_load();
479
		add_filter( 'admin_notices', array( $this, 'admin_notices' ) );
480
	}
481
482
/* Edit Items List */
483
484
	function admin_notices() {
485
		if ( isset( $_GET['nova_reordered'] ) )
486
			/* translators: this is about a food menu */
487
			printf( '<div class="updated"><p>%s</p></div>', __( 'Menu Items re-ordered.', 'jetpack' ) );
488
	}
489
490
	function no_title_sorting( $columns ) {
491
		if ( isset( $columns['title'] ) )
492
			unset( $columns['title'] );
493
		return $columns;
494
	}
495
496
	function setup_menu_item_columns() {
497
		add_filter( sprintf( 'manage_edit-%s_sortable_columns', self::MENU_ITEM_POST_TYPE ), array( $this, 'no_title_sorting' ) );
498
		add_filter( sprintf( 'manage_%s_posts_columns', self::MENU_ITEM_POST_TYPE ), array( $this, 'menu_item_columns' ) );
499
500
		add_action( sprintf( 'manage_%s_posts_custom_column', self::MENU_ITEM_POST_TYPE ), array( $this, 'menu_item_column_callback' ), 10, 2 );
501
	}
502
503
	function menu_item_columns( $columns ) {
504
		unset( $columns['date'], $columns['likes'] );
505
506
		$columns['thumbnail'] = __( 'Thumbnail', 'jetpack' );
507
		$columns['labels']    = __( 'Labels',    'jetpack' );
508
		$columns['price']     = __( 'Price',     'jetpack' );
509
		$columns['order']     = __( 'Order',     'jetpack' );
510
511
		return $columns;
512
	}
513
514
	function menu_item_column_callback( $column, $post_id ) {
515
		$screen = get_current_screen();
516
517
		switch ( $column ) {
518
			case 'thumbnail':
519
				echo get_the_post_thumbnail( $post_id, array( 50, 50 ) );
520
				break;
521
			case 'labels' :
522
				$this->list_admin_labels( $post_id );
523
				break;
524
			case 'price' :
525
				$this->display_price( $post_id );
526
				break;
527
			case 'order' :
528
				$url = admin_url( $screen->parent_file );
529
530
				$up_url = add_query_arg( array(
531
					'action' => 'move-item-up',
532
					'post_id' => (int) $post_id,
533
				), wp_nonce_url( $url, 'nova_move_item_up_' . $post_id ) );
534
535
				$down_url = add_query_arg( array(
536
					'action' => 'move-item-down',
537
					'post_id' => (int) $post_id,
538
				), wp_nonce_url( $url, 'nova_move_item_down_' . $post_id ) );
539
				$menu_item = get_post($post_id);
540
				$this->get_menu_by_post_id( $post_id );
541
				if ( $term_id = $this->get_menu_by_post_id( $post_id ) ) {
542
					$term_id = $term_id->term_id;
543
				}
544
	?>
545
				<input type="hidden" class="menu-order-value" name="nova_order[<?php echo (int) $post_id ?>]" value="<?php echo esc_attr( $menu_item->menu_order ) ?>" />
546
				<input type="hidden" class='nova-menu-term' name="nova_menu_term[<?php echo (int) $post_id ?>]" value="<?php echo esc_attr( $term_id ); ?>">
547
548
				<span class="hide-if-js">
549
				&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>
550
				<br />
551
				&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>
552
				</span>
553
	<?php
554
				break;
555
		}
556
	}
557
558
	function get_menu_by_post_id( $post_id = null ) {
559
		if ( ! $post_id )
560
			return false;
561
562
		$terms = get_the_terms( $post_id, self::MENU_TAX );
563
564
		if ( ! is_array( $terms ) )
565
			return false;
566
567
		return array_pop( $terms );
568
	}
569
570
	/**
571
	 * Fires on a menu edit page. We might have drag-n-drop reordered
572
	 */
573
	function maybe_reorder_menu_items() {
574
		// make sure we clicked our button
575
		if ( ! ( isset( $_REQUEST['menu_reorder_submit'] ) && $_REQUEST['menu_reorder_submit'] === __( 'Save New Order', 'jetpack' ) ) )
576
			return;
577
		;
578
579
		// make sure we have the nonce
580
		if ( ! ( isset( $_REQUEST['drag-drop-reorder'] ) && wp_verify_nonce( $_REQUEST['drag-drop-reorder'], 'drag-drop-reorder' ) ) )
581
			return;
582
583
		$term_pairs = array_map( 'absint', $_REQUEST['nova_menu_term'] );
584
		$order_pairs = array_map( 'absint', $_REQUEST['nova_order'] );
585
586
		foreach( $order_pairs as $ID => $menu_order ) {
587
			$ID = absint( $ID );
588
			unset( $order_pairs[$ID] );
589
			if ( $ID < 0 )
590
				continue;
591
592
			$post = get_post( $ID );
593
			if ( ! $post )
594
				continue;
595
596
			// save a write if the order hasn't changed
597
			if ( $menu_order != $post->menu_order )
598
				wp_update_post( compact( 'ID', 'menu_order' ) );
599
600
			// save a write if the term hasn't changed
601
			if ( $term_pairs[$ID] != $this->get_menu_by_post_id( $ID )->term_id )
602
				wp_set_object_terms( $ID, $term_pairs[$ID], self::MENU_TAX );
603
604
		}
605
606
		$redirect = add_query_arg( array(
607
			'post_type' => self::MENU_ITEM_POST_TYPE,
608
			'nova_reordered' => '1'
609
		), admin_url( 'edit.php' ) );
610
		wp_safe_redirect( $redirect );
611
		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...
612
613
	}
614
615
	function edit_menu_items_page_load() {
616
		if ( isset( $_GET['action'] ) ) {
617
			$this->handle_menu_item_actions();
618
		}
619
620
		$this->maybe_reorder_menu_items();
621
622
		wp_enqueue_script(
623
			'nova-drag-drop',
624
			Jetpack::get_file_url_for_environment(
625
				'_inc/build/custom-post-types/js/nova-drag-drop.min.js',
626
				'modules/custom-post-types/js/nova-drag-drop.js'
627
			),
628
			array( 'jquery-ui-sortable' ),
629
			$this->version,
630
			true
631
		);
632
633
		wp_localize_script( 'nova-drag-drop', '_novaDragDrop', array(
634
			'nonce'       => wp_create_nonce( 'drag-drop-reorder' ),
635
			'nonceName'   => 'drag-drop-reorder',
636
			'reorder'     => __( 'Save New Order', 'jetpack' ),
637
			'reorderName' => 'menu_reorder_submit'
638
		) );
639
		add_action( 'the_post', array( $this, 'show_menu_titles_in_menu_item_list' ) );
640
	}
641
642
	function handle_menu_item_actions() {
643
		$action = (string) $_GET['action'];
644
645
		switch ( $action ) {
646
		case 'move-item-up' :
647
		case 'move-item-down' :
648
			$reorder = false;
649
650
			$post_id = (int) $_GET['post_id'];
651
652
			$term = $this->get_menu_item_menu_leaf( $post_id );
653
654
			// Get all posts in that term
655
			$query = new WP_Query( array(
656
				'taxonomy' => self::MENU_TAX,
657
				'term'     => $term->slug,
658
			) );
659
660
			$order = array();
661
			foreach ( $query->posts as $post ) {
662
				$order[] = $post->ID;
663
			}
664
665
			if ( 'move-item-up' == $action ) {
666
				check_admin_referer( 'nova_move_item_up_' . $post_id );
667
668
				$first_post_id = $order[0];
669
				if ( $post_id == $first_post_id ) {
670
					break;
671
				}
672
673
				foreach ( $order as $menu_order => $order_post_id ) {
674
					if ( $post_id != $order_post_id ) {
675
						continue;
676
					}
677
678
					$swap_post_id = $order[$menu_order - 1];
679
					$order[$menu_order - 1] = $post_id;
680
					$order[$menu_order] = $swap_post_id;
681
682
					$reorder = true;
683
					break;
684
				}
685 View Code Duplication
			} else {
686
				check_admin_referer( 'nova_move_item_down_' . $post_id );
687
688
				$last_post_id = end( $order );
689
				if ( $post_id == $last_post_id ) {
690
					break;
691
				}
692
693
				foreach ( $order as $menu_order => $order_post_id ) {
694
					if ( $post_id != $order_post_id ) {
695
						continue;
696
					}
697
698
					$swap_post_id = $order[$menu_order + 1];
699
					$order[$menu_order + 1] = $post_id;
700
					$order[$menu_order] = $swap_post_id;
701
702
					$reorder = true;
703
				}
704
			}
705
706
			if ( $reorder ) {
707
				foreach ( $order as $menu_order => $ID ) {
708
					wp_update_post( compact( 'ID', 'menu_order' ) );
709
				}
710
			}
711
712
			break;
713
		case 'move-menu-up' :
714
		case 'move-menu-down' :
715
			$reorder = false;
716
717
			$term_id = (int) $_GET['term_id'];
718
719
			$terms = $this->get_menus();
720
721
			$order = array();
722
			foreach ( $terms as $term ) {
723
				$order[] = $term->term_id;
724
			}
725
726
			if ( 'move-menu-up' == $action ) {
727
				check_admin_referer( 'nova_move_menu_up_' . $term_id );
728
729
				$first_term_id = $order[0];
730
				if ( $term_id == $first_term_id ) {
731
					break;
732
				}
733
734
				foreach ( $order as $menu_order => $order_term_id ) {
735
					if ( $term_id != $order_term_id ) {
736
						continue;
737
					}
738
739
					$swap_term_id = $order[$menu_order - 1];
740
					$order[$menu_order - 1] = $term_id;
741
					$order[$menu_order] = $swap_term_id;
742
743
					$reorder = true;
744
					break;
745
				}
746 View Code Duplication
			} else {
747
				check_admin_referer( 'nova_move_menu_down_' . $term_id );
748
749
				$last_term_id = end( $order );
750
				if ( $term_id == $last_term_id ) {
751
					break;
752
				}
753
754
				foreach ( $order as $menu_order => $order_term_id ) {
755
					if ( $term_id != $order_term_id ) {
756
						continue;
757
					}
758
759
					$swap_term_id = $order[$menu_order + 1];
760
					$order[$menu_order + 1] = $term_id;
761
					$order[$menu_order] = $swap_term_id;
762
763
					$reorder = true;
764
				}
765
			}
766
767
			if ( $reorder ) {
768
				update_option( 'nova_menu_order', $order );
769
			}
770
771
			break;
772
		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...
773
			return;
774
		}
775
776
		$redirect = add_query_arg( array(
777
			'post_type' => self::MENU_ITEM_POST_TYPE,
778
			'nova_reordered' => '1'
779
		), admin_url( 'edit.php' ) );
780
		wp_safe_redirect( $redirect );
781
		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...
782
	}
783
784
	/*
785
	 * Add menu title rows to the list table
786
	 */
787
	function show_menu_titles_in_menu_item_list( $post ) {
788
		global $wp_list_table;
789
790
		static $last_term_id = false;
791
792
		$term = $this->get_menu_item_menu_leaf( $post->ID );
793
794
		$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...
795
796
		if ( false !== $last_term_id && $last_term_id === $term_id ) {
797
			return;
798
		}
799
800
		if ( is_null( $term_id ) ) {
801
			$last_term_id = null;
802
			$term_name = '';
803
			$parent_count = 0;
804
		} else {
805
			$last_term_id = $term->term_id;
806
			$term_name = $term->name;
807
			$parent_count = 0;
808
			$current_term = $term;
809
			while ( $current_term->parent ) {
810
				$parent_count++;
811
				$current_term = get_term( $current_term->parent, self::MENU_TAX );
812
			}
813
		}
814
815
		$non_order_column_count = $wp_list_table->get_column_count() - 1;
816
817
		$screen = get_current_screen();
818
819
		$url = admin_url( $screen->parent_file );
820
821
		$up_url = add_query_arg( array(
822
			'action'  => 'move-menu-up',
823
			'term_id' => (int) $term_id,
824
		), wp_nonce_url( $url, 'nova_move_menu_up_' . $term_id ) );
825
826
		$down_url = add_query_arg( array(
827
			'action'  => 'move-menu-down',
828
			'term_id' => (int) $term_id,
829
		), wp_nonce_url( $url, 'nova_move_menu_down_' . $term_id ) );
830
831
?>
832
		<tr class="no-items menu-label-row" data-term_id="<?php echo esc_attr( $term_id ) ?>">
833
			<td class="colspanchange" colspan="<?php echo (int) $non_order_column_count; ?>">
834
				<h3><?php
835
					echo str_repeat( ' &mdash; ', (int) $parent_count );
836
837
					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...
838
						echo esc_html( sanitize_term_field( 'name', $term_name, $term_id, self::MENU_TAX, 'display' ) );
839
						edit_term_link( __( 'edit', 'jetpack' ), '<span class="edit-nova-section"><span class="dashicon dashicon-edit"></span>', '</span>', $term );
840
841
					} else {
842
						_e( 'Uncategorized' , 'jetpack' );
843
					}
844
				?></h3>
845
			</td>
846
			<td>
847
				<?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...
848
				<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>
849
				<br />
850
				<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>
851
				<?php } ?>
852
			</td>
853
		</tr>
854
<?php
855
	}
856
857
/* Edit Many Items */
858
859
	function add_many_new_items_page_load() {
860
		if ( 'POST' === strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
861
			$this->process_form_request();
862
			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...
863
		}
864
865
		$this->enqueue_many_items_scripts();
866
	}
867
868
	function enqueue_many_items_scripts() {
869
		wp_enqueue_script(
870
			'nova-many-items',
871
			Jetpack::get_file_url_for_environment(
872
				'_inc/build/custom-post-types/js/many-items.min.js',
873
				'modules/custom-post-types/js/many-items.js'
874
			),
875
			array( 'jquery' ),
876
			$this->version,
877
			true
878
		);
879
	}
880
881
	function process_form_request() {
882
		if ( !isset( $_POST['nova_title'] ) || !is_array( $_POST['nova_title'] ) ) {
883
			return;
884
		}
885
886
		$is_ajax = !empty( $_POST['ajax'] );
887
888
		if ( $is_ajax ) {
889
			check_ajax_referer( 'nova_many_items' );
890
		} else {
891
			check_admin_referer( 'nova_many_items' );
892
		}
893
894
		foreach ( array_keys( $_POST['nova_title'] ) as $key ) :
895
			// $_POST is already slashed
896
			$post_details = array(
897
				'post_status'  => 'publish',
898
				'post_type'    => self::MENU_ITEM_POST_TYPE,
899
				'post_content' => $_POST['nova_content'][$key],
900
				'post_title'   => $_POST['nova_title'][$key],
901
				'tax_input'    => array(
902
					self::MENU_ITEM_LABEL_TAX => $_POST['nova_labels'][$key],
903
					self::MENU_TAX            => isset( $_POST['nova_menu_tax'] ) ? $_POST['nova_menu_tax'] : null,
904
				),
905
			);
906
907
			$post_id = wp_insert_post( $post_details );
908
			if ( !$post_id || is_wp_error( $post_id ) ) {
909
				continue;
910
			}
911
912
			$this->set_price( $post_id, isset( $_POST['nova_price'][$key] ) ? stripslashes( $_POST['nova_price'][$key] ) : '' );
913
914
			if ( $is_ajax ) :
915
				$post = get_post( $post_id );
916
				$GLOBALS['post'] = $post;
917
				setup_postdata( $post );
918
919
?>
920
			<td><?php the_title(); ?></td>
921
			<td class="nova-price"><?php $this->display_price(); ?></td>
922
			<td><?php $this->list_labels( $post_id ); ?></td>
923
			<td><?php the_content(); ?></td>
924
<?php
925
			endif;
926
927
		endforeach;
928
929
		if ( $is_ajax ) {
930
			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...
931
		}
932
933
		wp_safe_redirect( admin_url( 'edit.php?post_type=' . self::MENU_ITEM_POST_TYPE ) );
934
		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...
935
	}
936
937
	function add_many_new_items_page() {
938
?>
939
	<div class="wrap">
940
		<h2><?php esc_html_e( 'Add Many Items', 'jetpack' ); ?></h2>
941
942
		<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>
943
944
		<form method="post" action="" enctype="multipart/form-data">
945
			<p><h3><?php esc_html_e( 'Add to section:', 'jetpack' ); ?> <?php wp_dropdown_categories( array(
946
				'id'           => 'nova-menu-tax',
947
				'name'         => 'nova_menu_tax',
948
				'taxonomy'     => self::MENU_TAX,
949
				'hide_empty'   => false,
950
				'hierarchical' => true,
951
			) ); ?></h3></p>
952
953
			<table class="many-items-table wp-list-table widefat">
954
				<thead>
955
					<tr>
956
						<th scope="col"><?php esc_html_e( 'Name', 'jetpack' ); ?></th>
957
						<th scope="col" class="nova-price"><?php esc_html_e( 'Price', 'jetpack' ); ?></th>
958
						<th scope="col"><?php _e( 'Labels: <small>spicy, favorite, etc. <em>Separate Labels with commas</em></small>', 'jetpack' ); ?></th>
959
						<th scope="col"><?php esc_html_e( 'Description', 'jetpack' ); ?></th>
960
					</tr>
961
				</thead>
962
				<tbody>
963
					<tr>
964
						<td><input type="text" name="nova_title[]" aria-required="true" /></td>
965
						<td class="nova-price"><input type="text" name="nova_price[]" /></td>
966
						<td><input type="text" name="nova_labels[]" /></td>
967
						<td><textarea name="nova_content[]" cols="20" rows="1"></textarea>
968
					</tr>
969
				</tbody>
970
				<tbody>
971
					<tr>
972
						<td><input type="text" name="nova_title[]" aria-required="true" /></td>
973
						<td class="nova-price"><input type="text" name="nova_price[]" /></td>
974
						<td><input type="text" name="nova_labels[]" /></td>
975
						<td><textarea name="nova_content[]" cols="20" rows="1"></textarea>
976
					</tr>
977
				</tbody>
978
				<tfoot>
979
					<tr>
980
						<th><a class="button button-secondary nova-new-row"><span class="dashicon dashicon-plus"></span> <?php esc_html_e( 'New Row' , 'jetpack' ); ?></a></th>
981
						<th class="nova-price"></th>
982
						<th></th>
983
						<th></th>
984
					</tr>
985
				</tfoot>
986
			</table>
987
988
			<p class="submit">
989
				<input type="submit" class="button-primary" value="<?php esc_attr_e( 'Add These New Menu Items', 'jetpack' ); ?>" />
990
				<?php wp_nonce_field( 'nova_many_items' ); ?>
991
			</p>
992
		</form>
993
	</div>
994
<?php
995
	}
996
997
/* Edit One Item */
998
999
	function register_menu_item_meta_boxes() {
1000
		wp_enqueue_script( 'nova-menu-checkboxes' );
1001
1002
		add_meta_box( 'menu_item_price', __( 'Price', 'jetpack' ), array( $this, 'menu_item_price_meta_box' ), null, 'side', 'high' );
1003
	}
1004
1005
	function menu_item_price_meta_box( $post, $meta_box ) {
1006
		$price = $this->get_price( $post->ID );
1007
?>
1008
	<label for="nova-price-<?php echo (int) $post->ID; ?>" class="screen-reader-text"><?php esc_html_e( 'Price', 'jetpack' ); ?></label>
1009
	<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 ); ?>" />
1010
<?php
1011
	}
1012
1013
	function add_post_meta( $post_id ) {
1014
		if ( !isset( $_POST['nova_price'][$post_id] ) ) {
1015
			return;
1016
		}
1017
1018
		$this->set_price( $post_id, stripslashes( $_POST['nova_price'][$post_id] ) );
1019
	}
1020
1021
/* Data */
1022
1023
	function get_menus( $args = array() ) {
1024
		$args = wp_parse_args( $args, array(
1025
			'hide_empty' => false,
1026
		) );
1027
1028
		$terms = get_terms( self::MENU_TAX, $args );
1029
		if ( !$terms || is_wp_error( $terms ) ) {
1030
			return array();
1031
		}
1032
1033
		$terms_by_id = array();
1034
		foreach ( $terms as $term ) {
1035
			$terms_by_id["{$term->term_id}"] = $term;
1036
		}
1037
1038
		$term_order = get_option( 'nova_menu_order', array() );
1039
1040
		$return = array();
1041 View Code Duplication
		foreach ( $term_order as $term_id ) {
1042
			if ( isset( $terms_by_id["$term_id"] ) ) {
1043
				$return[] = $terms_by_id["$term_id"];
1044
				unset( $terms_by_id["$term_id"] );
1045
			}
1046
		}
1047
1048
		foreach ( $terms_by_id as $term_id => $term ) {
1049
			$return[] = $term;
1050
		}
1051
1052
		return $return;
1053
	}
1054
1055
	function get_menu_item_menu_leaf( $post_id ) {
1056
		// Get first menu taxonomy "leaf"
1057
		$term_ids = wp_get_object_terms( $post_id, self::MENU_TAX, array( 'fields' => 'ids' ) );
1058
1059
		foreach ( $term_ids as $term_id ) {
1060
			$children = get_term_children( $term_id, self::MENU_TAX );
1061
			if ( ! $children ) {
1062
				break;
1063
			}
1064
		}
1065
1066
		if ( ! isset( $term_id ) ) {
1067
			return false;
1068
		}
1069
1070
		return get_term( $term_id, self::MENU_TAX );
1071
1072
	}
1073
1074
	function list_labels( $post_id = 0 ) {
1075
		$post = get_post( $post_id );
1076
		echo get_the_term_list( $post->ID, self::MENU_ITEM_LABEL_TAX, '', _x( ', ', 'Nova label separator', 'jetpack' ), '' );
1077
	}
1078
1079
	function list_admin_labels( $post_id = 0 ) {
1080
		$post = get_post( $post_id );
1081
		$labels = get_the_terms( $post->ID, self::MENU_ITEM_LABEL_TAX );
1082
		if ( !empty( $labels ) ) {
1083
			$out = array();
1084
			foreach ( $labels as $label ) {
1085
				$out[] = sprintf( '<a href="%s">%s</a>',
1086
					esc_url( add_query_arg( array(
1087
						'post_type' => self::MENU_ITEM_POST_TYPE,
1088
						'taxonomy'  => self::MENU_ITEM_LABEL_TAX,
1089
						'term'      => $label->slug
1090
					), 'edit.php' ) ),
1091
					esc_html( sanitize_term_field( 'name', $label->name, $label->term_id, self::MENU_ITEM_LABEL_TAX, 'display' ) )
1092
				);
1093
			}
1094
1095
			echo join( _x( ', ', 'Nova label separator', 'jetpack' ), $out );
1096
		} else {
1097
			esc_html_e( 'No Labels', 'jetpack' );
1098
		}
1099
	}
1100
1101
	function set_price( $post_id = 0, $price = '' ) {
1102
		$post = get_post( $post_id );
1103
1104
		return update_post_meta( $post->ID, 'nova_price', $price );
1105
	}
1106
1107
	function get_price( $post_id = 0 ) {
1108
		$post = get_post( $post_id );
1109
1110
		return get_post_meta( $post->ID, 'nova_price', true );
1111
	}
1112
1113
	function display_price( $post_id = 0 ) {
1114
		echo esc_html( $this->get_price( $post_id ) );
1115
	}
1116
1117
/* Menu Item Loop Markup */
1118
1119
	/* Does not support nested loops */
1120
1121
	function get_menu_item_loop_markup( $field = null ) {
1122
		return $this->menu_item_loop_markup;
1123
	}
1124
1125
	/**
1126
	 * Sets up the loop markup.
1127
	 * Attached to the 'template_include' *filter*,
1128
	 * which fires only during a real blog view (not in admin, feeds, etc.)
1129
	 *
1130
	 * @param string Template File
1131
	 * @return string Template File.  VERY Important.
1132
	 */
1133
	function setup_menu_item_loop_markup__in_filter( $template ) {
1134
		add_action( 'loop_start', array( $this, 'start_menu_item_loop' ) );
1135
1136
		return $template;
1137
	}
1138
1139
	/**
1140
	 * If the Query is a Menu Item Query, start outputing the Menu Item Loop Marku
1141
	 * Attached to the 'loop_start' action.
1142
	 *
1143
	 * @param WP_Query
1144
	 */
1145
	function start_menu_item_loop( $query ) {
1146
		if ( !$this->is_menu_item_query( $query ) ) {
1147
			return;
1148
		}
1149
1150
		$this->menu_item_loop_last_term_id = false;
1151
		$this->menu_item_loop_current_term = false;
1152
1153
		add_action( 'the_post', array( $this, 'menu_item_loop_each_post' ) );
1154
		add_action( 'loop_end', array( $this, 'stop_menu_item_loop' ) );
1155
	}
1156
1157
	/**
1158
	 * Outputs the Menu Item Loop Marku
1159
	 * Attached to the 'the_post' action.
1160
	 *
1161
	 * @param WP_Post
1162
	 */
1163
	function menu_item_loop_each_post( $post ) {
1164
		$this->menu_item_loop_current_term = $this->get_menu_item_menu_leaf( $post->ID );
1165
1166
		if ( false === $this->menu_item_loop_last_term_id ) {
1167
			// We're at the very beginning of the loop
1168
1169
			$this->menu_item_loop_open_element( 'menu' ); // Start a new menu section
1170
			$this->menu_item_loop_header(); // Output the menu's header
1171
		} elseif ( $this->menu_item_loop_last_term_id != $this->menu_item_loop_current_term->term_id ) {
1172
			// We're not at the very beginning but still need to start a new menu section.  End the previous menu section first.
1173
1174
			$this->menu_item_loop_close_element( 'menu' ); // End the previous menu section
1175
			$this->menu_item_loop_open_element( 'menu' ); // Start a new menu section
1176
			$this->menu_item_loop_header(); // Output the menu's header
1177
		}
1178
1179
		$this->menu_item_loop_last_term_id = $this->menu_item_loop_current_term->term_id;
1180
	}
1181
1182
	/**
1183
	 * If the Query is a Menu Item Query, stop outputing the Menu Item Loop Marku
1184
	 * Attached to the 'loop_end' action.
1185
	 *
1186
	 * @param WP_Query
1187
	 */
1188
	function stop_menu_item_loop( $query ) {
1189
		if ( !$this->is_menu_item_query( $query ) ) {
1190
			return;
1191
		}
1192
1193
		remove_action( 'the_post', array( $this, 'menu_item_loop_each_post' ) );
1194
		remove_action( 'loop_start', array( $this, 'start_menu_item_loop' ) );
1195
		remove_action( 'loop_end', array( $this, 'stop_menu_item_loop' ) );
1196
1197
		$this->menu_item_loop_close_element( 'menu' ); // End the last menu section
1198
	}
1199
1200
	/**
1201
	 * Outputs the Menu Group Header
1202
	 */
1203
	function menu_item_loop_header() {
1204
		$this->menu_item_loop_open_element( 'menu_header' );
1205
			$this->menu_item_loop_open_element( 'menu_title' );
1206
				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...
1207
			$this->menu_item_loop_close_element( 'menu_title' );
1208
		if ( $this->menu_item_loop_current_term->description ) :
1209
			$this->menu_item_loop_open_element( 'menu_description' );
1210
				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...
1211
			$this->menu_item_loop_close_element( 'menu_description' );
1212
		endif;
1213
		$this->menu_item_loop_close_element( 'menu_header' );
1214
	}
1215
1216
	/**
1217
	 * Outputs a Menu Item Markup element opening tag
1218
	 *
1219
	 * @param string $field - Menu Item Markup settings field.
1220
	 */
1221 View Code Duplication
	function menu_item_loop_open_element( $field ) {
1222
		$markup = $this->get_menu_item_loop_markup();
1223
		/**
1224
		 * Filter a menu item's element opening tag.
1225
		 *
1226
		 * @module custom-content-types
1227
		 *
1228
		 * @since 4.4.0
1229
		 *
1230
		 * @param string       $tag    Menu item's element opening 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_open_element',
1237
			'<' . tag_escape( $markup["{$field}_tag"] ) . $this->menu_item_loop_class( $markup["{$field}_class"] ) . ">\n",
1238
			$field,
1239
			$markup,
1240
			$this->menu_item_loop_current_term
1241
		);
1242
	}
1243
1244
	/**
1245
	 * Outputs a Menu Item Markup element closing tag
1246
	 *
1247
	 * @param string $field - Menu Item Markup settings field
1248
	 */
1249 View Code Duplication
	function menu_item_loop_close_element( $field ) {
1250
		$markup = $this->get_menu_item_loop_markup();
1251
		/**
1252
		 * Filter a menu item's element closing tag.
1253
		 *
1254
		 * @module custom-content-types
1255
		 *
1256
		 * @since 4.4.0
1257
		 *
1258
		 * @param string       $tag    Menu item's element closing tag.
1259
		 * @param string       $field  Menu Item Markup settings field.
1260
		 * @param array        $markup Array of markup elements for the menu item.
1261
		 * @param false|object $term   Taxonomy term for current menu item.
1262
		 */
1263
		echo apply_filters(
1264
			'jetpack_nova_menu_item_loop_close_element',
1265
			'</' . tag_escape( $markup["{$field}_tag"] ) . ">\n",
1266
			$field,
1267
			$markup,
1268
			$this->menu_item_loop_current_term
1269
		);
1270
	}
1271
1272
	/**
1273
	 * Returns a Menu Item Markup element's class attribute.
1274
	 *
1275
	 * @param  string $class Class name.
1276
	 * @return string HTML   class attribute with leading whitespace.
1277
	 */
1278
	function menu_item_loop_class( $class ) {
1279
		if ( ! $class ) {
1280
			return '';
1281
		}
1282
1283
		/**
1284
		 * Filter a menu Item Markup element's class attribute.
1285
		 *
1286
		 * @module custom-content-types
1287
		 *
1288
		 * @since 4.4.0
1289
		 *
1290
		 * @param string       $tag    Menu Item Markup element's class attribute.
1291
		 * @param string       $class  Menu Item Class name.
1292
		 * @param false|object $term   Taxonomy term for current menu item.
1293
		 */
1294
		return apply_filters(
1295
			'jetpack_nova_menu_item_loop_class',
1296
			' class="' . esc_attr( $class ) . '"',
1297
			$class,
1298
			$this->menu_item_loop_current_term
1299
		);
1300
	}
1301
}
1302
1303
add_action( 'init', array( 'Nova_Restaurant', 'init' ) );
1304