Content model
Fenómenus models a restaurant as ten public menu post types, each with its own category taxonomy, plus a small number of cross-cutting taxonomies.
Menu post types
| Slug | Menu type |
|---|---|
a_la_carte_menu |
À la carte menu |
terrace_menu |
Terrace menu |
breakfast |
Breakfast |
desserts |
Desserts |
bar_menu |
Bar menu |
wine_list |
Wine list |
cocktails |
Cocktails |
beverages |
Beverages |
tasting_menu |
Tasting menu |
set_menu |
Set menu |
An internal eleventh type, set_menu_dishes, holds the dishes a set menu offers as choices.
Only the types enabled on a site are registered. Check with post_type_exists() rather than assuming.
Category taxonomies
Each menu type has one category taxonomy following the convention <post_type>_category:
a_la_carte_menu_category, terrace_menu_category, breakfast_category, desserts_category, bar_menu_category, wine_list_category, cocktails_category, beverages_category, tasting_menu_category, set_menu_category, set_menu_dishes_category
They are hierarchical and used one level deep by the admin tools.
Term ordering
Category terms carry a stored position in the term meta key tax_position. Every ordered query in the product uses it:
$terms = get_terms( array(
'taxonomy' => 'a_la_carte_menu_category',
'hide_empty' => false,
'orderby' => 'meta_value_num',
'order' => 'ASC',
'meta_key' => 'tax_position',
) );
Reproduce that ordering in custom code, or your output will not match the menu.
Item ordering
Items are ordered by menu_order, ascending. The admin list writes it when rows are dragged, and bulk imports append after the current maximum.
$query = new WP_Query( array(
'post_type' => 'a_la_carte_menu',
'orderby' => 'menu_order',
'order' => 'ASC',
) );
Cross-cutting taxonomies
| Taxonomy | Applies to | Notes |
|---|---|---|
allergen |
The content types enabled for allergens | Terms carry an icon in the term meta key pom_category_thumbnail |
featured |
The menu post types | Non-public; the single term slug is is-featured |
The featured taxonomy is deliberately not publicly queryable. Its public name is editable while the is-featured slug stays fixed.
À la carte and terrace extras
Two additional taxonomies exist for a_la_carte_menu:
a_la_carte_menu_not_suitable_fora_la_carte_menu_options
Both are registered without their own archives.
The independent terrace_menu has the matching terrace_menu_not_suitable_for and terrace_menu_options taxonomies, also without archives.
Wine taxonomies
| Taxonomy | Contents |
|---|---|
wine_list_category |
The wine type tree, seeded on enable |
wine_vintage |
Years, seeded 1930–2030, non-hierarchical |
wine_aging_classification |
Young wine, medium ageing, long ageing |
wine_winery |
Producers |
wine_grape |
Varieties |
wine_region |
Origins, hierarchical |
Supports
The menu post types support title and page-attributes, plus thumbnail where enabled. They do not support revisions, so there is no version history for a menu item.
wine_list does not use the content editor in the same way as the other types; its data lives in wine-specific meta and taxonomies.
The numeric wine-rating contract uses parker_score and penin_score, both constrained to 0–100. An absent rating is stored as an empty value and must not be represented as a zero score.
Statuses
Only publish and draft are used by the admin tools. Status changes made through the list screen are applied to an item and all of its translations.
Reading a menu
$terms = get_terms( array(
'taxonomy' => "{$post_type}_category",
'hide_empty' => false,
'orderby' => 'meta_value_num',
'order' => 'ASC',
'meta_key' => 'tax_position',
) );
foreach ( $terms as $term ) {
$items = new WP_Query( array(
'post_type' => $post_type,
'posts_per_page' => -1,
'orderby' => 'menu_order',
'order' => 'ASC',
'tax_query' => array( array(
'taxonomy' => "{$post_type}_category",
'field' => 'term_id',
'terms' => $term->term_id,
) ),
) );
}
That is the same traversal the PDF generator performs, and it produces the menu in the order guests read it.