Advanced Restaurant for WooCommerce
One-page online ordering for WooCommerce restaurants: a menu with a status bar, dish popups with add-ons and notes, a basket drawer, delivery or pickup, opening hours with lead time and time slots at checkout, in the classic checkout and the Checkout block.
Version 2.0.0 WooCommerce plugin Paid plugin Requires WordPress 6.3 Requires PHP 7.4 WooCommerce 8.0 – 11.1
1. Overview
Advanced Restaurant for WooCommerce turns your WooCommerce products into a one-page online ordering menu, the way food-delivery apps work. Put the shortcode [wxp_restaurant] on a page: every product category that has published dishes becomes a section, customers see whether you are open, choose delivery or pickup, search and filter, add dishes with one tap or through a popup for sizes, add-ons and a note, and check out from a basket drawer without leaving the page. At checkout they pick a day and a time slot built from your opening hours.
How it works
- Dishes are products. Name, photo, price, short description, stock, variations and categories come from WooCommerce. The plugin adds a Restaurant tab to the product editor (spice level, labels, allergens, calories) and the Is Non-Vegetarian tick box.
- Sections are categories. Each product category with published dishes is a section, in the order of Products → Categories; child categories follow their parent.
- The basket is WooCommerce's cart. Adding, changing and removing lines goes through WooCommerce, so stock limits, "Sold individually", coupons, taxes, shipping and payment methods work as they do today. Add-on prices and notes are stored on the cart line and copied to the order.
- Opening hours decide the rest. They drive the Open now / Closed status, the next-opening message, whether orders are accepted right now, and the time slots offered at checkout (after your preparation time).
- Orders carry the restaurant data. The order type (delivery or pickup), the day and the time are saved as order meta and shown on the thank-you page, in the e-mails, on the order screen and in a Restaurant column of the orders list.
At a glance
| Area | What you get |
|---|---|
| Menu page | Status bar (open / closed / next opening, hours popup, call button), Delivery / Pickup switch, header message, search, Veg / Non-veg / Vegan / Gluten-free chips, sticky category navigation, list or card layout. |
| Dishes | Photo, price, description, spice level, labels (Popular, New, Chef's special, Vegan, Gluten-free, Dairy-free), allergens, calories, Sold out / Unavailable badges. |
| Popup | Variation pills, PPOM add-ons with prices and limits, a special-instructions note, quantity stepper, live total. |
| Basket | Lines with steppers, options and notes, Delivery / Pickup switch with a note, minimum-order progress bar, free-delivery hint, Checkout and View cart. |
| Ordering rules | Delivery and/or pickup, opening hours with two periods per day, closed dates, lead time, order-ahead window, pre-orders or no orders while closed, temporarily-closed switch, minimum order. |
| Checkout | Order type and day / time slot fields on the classic checkout and in the Checkout block; pickup orders see Local pickup rates only. |
| Admin | WooCommerce → Restaurant with an overview strip and six tabs; a Restaurant column in the orders list; the Restaurant tab on products. |
What it does not do
- It is not a point-of-sale, kitchen display, table-ordering or QR-ordering system, and it does not print tickets. Orders are normal WooCommerce orders.
- It does not deliver or calculate delivery fees by distance. Delivery fees are your WooCommerce shipping methods; the plugin only filters them by delivery or pickup and shows your free-delivery hint.
- It does not manage reservations or table bookings.
- It does not replace the cart and checkout pages; customers can still use them. The basket drawer is a shortcut to the same cart.
- Add-ons need the free PPOM for WooCommerce plugin; without it, dish options are the product's variations.
- One opening-hours set for the whole site; no hours per order type or per location.
How it relates to Restaurant for WooCommerce (free)
The free plugin on WordPress.org has the one-page menu, the dish popup for variations, the basket drawer and the Veg filter in the same design. This plugin adds everything about opening hours, delivery or pickup, time slots, add-ons, notes, dish labels, the minimum order, the settings screen and the orders-list column. When both are active only this plugin runs and a notice on the Plugins screen says the free plugin is not used; deactivate and delete it. The shortcode and the Is Non-Vegetarian flag are the same, and the CSS custom properties and template folder names differ (your-theme/advanced-restaurant-for-woocommerce/), so template copies made for the free plugin have to be redone.
2. Requirements
| Requirement | Version |
|---|---|
| WordPress | 6.3 or later (tested up to 7.1) |
| WooCommerce | 8.0 or later, active (tested up to 11.1). WordPress 6.5+ shows the dependency on the Plugins screen; the plugin does nothing without WooCommerce. |
| PHP | 7.4 or later (checked on 8.2, 8.3, 8.4 and 8.5) |
| Optional | PPOM for WooCommerce (free, WordPress.org) for add-ons on simple products. |
| Browsers | Any current browser. The popup, the basket and the hours popup are native <dialog> elements; the menu layout uses container queries (Chrome 105, Safari 16, Firefox 110 and later). Older browsers get the chip bar instead of the side column. |
| Theme | Any theme; the menu adapts to the width of its container. Tested with Storefront and Twenty Twenty-Five. |
3. Installation
- Make sure WooCommerce is active.
- Open Plugins → Add Plugin → Upload Plugin, choose
advanced-restaurant-for-woocommerce-2.0.0.zip, install and activate. - If the free Restaurant for WooCommerce plugin is installed, deactivate and delete it (a notice reminds you).
- Open Plugins → WpExperts Hub Licences, paste your licence key and click Activate licence.
- Add
[wxp_restaurant]to a page and open WooCommerce → Restaurant.
The licence and updates
The licence is used for updates only: every feature works without it. Your key is in the purchase e-mail and in My Account → Downloads on wpexpertshub.com. After activation, new versions appear on Dashboard → Updates and in the plugin row like any other plugin. The plugin checks for updates at most once every 12 hours. Email me my key on the licence screen sends the key to the address you type. Deactivate the licence before moving the plugin to another live site.
Updating from version 1.x
- Update through Dashboard → Updates (with an active licence) or upload the 2.0.0 zip over the old folder. The plugin folder and licence slug stayed
advanced-restaurant-for-woocommerce, so nothing has to be re-activated. - Your opening hours, messages and checkout settings are kept. A site that already had settings saved stays delivery only until you choose "Delivery and pickup" under Ordering; new installs offer both.
- The twelve colour settings of 1.x are not carried over. The Design tab has nine colour tokens with sensible defaults; set your accent colour there.
- The menu markup changed completely (no jQuery, fancybox or icon font). Theme overrides of
templates/menu.phpand custom CSS written for 1.x must be redone; see Templates and CSS. - Delivery times are stored as 24-hour values on new orders (
18:30orASAP); orders placed with 1.x keep displaying.
Deactivating and deleting
Deactivating stops the menu, the checkout fields and the orders-list column; the shortcode is then printed as text until you remove it from the page. Deleting the plugin removes its files only: the settings option, the licence options, the product meta and the order meta stay in the database (so a reinstall finds everything). "Deactivate licence" on the licence screen removes the two licence options.
Multisite
Activate the plugin per site, or network-wide: WooCommerce is detected either way (the plugin boots on plugins_loaded). Settings, hours and licence are per site.
4. Quick start
- Categories: in Products → Categories create Starters, Mains, Drinks… and drag them into the order you want. A category description is shown under the section title.
- Dishes: add simple products with a price, a photo and a short description (that is the text on the menu). Use variable products for sizes or crusts. Tick Is Non-Vegetarian for meat and fish dishes and fill the Restaurant tab (spice level, labels, allergens, calories).
- Hours: in WooCommerce → Restaurant → Restaurant switch each day on, type the hours (
11:00–14:30, add a second period for dinner), add closed dates and your phone number. Save. - Ordering: on the Ordering tab choose delivery and/or pickup, the preparation time (30 minutes by default), how many days ahead customers can order, what happens while you are closed, and a minimum order if you want one.
- Checkout: on the Checkout tab switch on "Ask for a day" and "Ask for a time slot" and set the slot length. The slot preview shows what customers will see.
- Shipping: in WooCommerce → Settings → Shipping add a "Local pickup" method next to your delivery method, so pickup orders carry no delivery fee.
- The page: add a Shortcode block with
[wxp_restaurant]and publish. Open it, add a dish, open the basket, switch to pickup and go to the checkout: the Order type and the day and time fields are there.
5. The menu page
The shortcode and which dishes it lists
| Shortcode | Result |
|---|---|
[wxp_restaurant] | Every product category that has at least one listable dish, in the order of Products → Categories; a child category follows its parent and is indented in the navigation. |
[wxp_restaurant categories="starters,mains,drinks"] | Only these category slugs, in this order (slugs, not names; unknown slugs are ignored). |
[wxp_restaurant layout="grid"] | The card layout on this page, whatever the Menu setting says. layout="list" forces the list. |
- Only published products that are not hidden from the catalog are listed, in the order of Products → All Products → Sorting, then by title. A dish in a child category is listed in the child's section only.
- With Hide out of stock items from the catalog on (WooCommerce → Settings → Products → Inventory), out-of-stock dishes are not listed; with it off they stay on the menu as Sold out. A dish that is in stock but cannot be bought (no price) shows Unavailable.
- Simple and variable products are ordered from the menu. External, grouped and other product types show a button that opens their own page.
- Use the shortcode once per page. A second menu on the same page works, but both share one basket drawer.
The status bar
The first thing on the menu is the status card:
- Open now · Closes at 10:00 pm while the current time is inside one of today's periods.
- Closed · Opens today at 6:00 pm (between lunch and dinner), Opens tomorrow at 10:00 am or Opens Tuesday at 10:00 am otherwise, followed by Pre-order for later when pre-orders are accepted.
- Closed · Temporarily not taking orders while the Temporarily closed switch is on; your closed message is shown underneath in red.
- An Opening hours button that opens a popup with the weekly hours (every period on its own line, today highlighted, closed days in red) and the next closed dates with their labels.
- A call button with your phone number (a
tel:link). - The Delivery / Pickup switch when both types are offered.
- Your header message (offers, delivery news) in a soft box below the card.
Delivery or pickup
With "Delivery and pickup" chosen under Ordering, the customer picks one in the status bar or at the bottom of the basket. The choice is stored in the WooCommerce session (for guests too), repeated as the default at checkout, saved on the order and used to pick the shipping rates (see Shipping rates). The basket shows your delivery note or pickup note (for example the collection address) under the switch. With "Delivery only" or "Pickup only" the switch is not shown and every order gets that type.
Navigation, search and filters
- Navigation: where the menu is at least 760 px wide the categories are a sticky list on the left; narrower menus get a sticky, swipeable bar of chips. The current section is highlighted while scrolling, and each entry shows how many dishes are visible.
- Search: filters as you type on the dish name and short description, ignoring case and accents. Escape or the × clears it.
- Veg only / Non-veg only: one or the other (ticking one unticks the other), based on the Is Non-Vegetarian flag.
- Vegan / Gluten-free: chips that keep only dishes carrying that label; both can be on at once. They are shown when dish labels are enabled.
- When nothing matches: "No dishes match your search." and a Show the whole menu button.
- You can hide the search box and the Veg filter on the Menu tab.
Dish cards, labels, spice and allergens
In the list layout each dish is a row with the diet mark, spice chillies and labels, the name (click it or the photo to open the popup), the short description, "Contains: …" and the kcal value, the price (sale prices with the old price struck through) and the Add button; the photo sits on the right. In the card layout the photo is on top and several cards share a row. Dishes with options or add-ons carry the word Customizable under their button.
- Diet mark: green square for vegetarian, red triangle for non-vegetarian.
- Spice level: one to three chillies (Mild, Medium, Hot), none for "Not spicy".
- Labels: Popular (shown as a ribbon on the photo), New, Chef's special, Vegan, Gluten-free, Dairy-free. Developers can add labels with the
wxp_restaurant_dish_labelsfilter. - Allergens and calories: a "Contains: Gluten, Dairy" line and "640 kcal" under the description; switch them off on the Menu tab.
Adding dishes and the popup
- Simple dish without add-ons: Add puts one in the basket and turns into a stepper (−, quantity, +). At a quantity of 1 the minus button becomes a bin. Plus is disabled for products sold individually or at the maximum quantity.
- Dish with variations or add-ons: Add opens the popup. The popup shows the photo, name, diet mark, labels, price, description, allergens, the option groups, the note box, a quantity stepper and an Add to basket button with the live total (price plus add-ons, times the quantity).
- Same dish twice: if two versions of one dish are in the basket (two sizes), the minus button on the menu opens the basket instead of guessing which line to reduce.
- Every change shows a short toast ("Added to your basket." with a View basket button) and refreshes the floating basket button and your theme's mini cart.
Variable products
Each attribute becomes a row of option pills. The product's default attributes are preselected, combinations that are out of stock or have no price are shown crossed out and cannot be chosen, and the price and photo follow the chosen variation. "Any …" attributes take the customer's choice as usual. Variable products cannot carry PPOM add-ons.
PPOM for WooCommerce add-ons
Install the free PPOM for WooCommerce plugin and attach a field group to a simple product (directly or through its categories). The popup shows these field types:
| PPOM field | In the popup |
|---|---|
| Radio | A row of pills; one choice. "Required" shows a Required tag and must be chosen. |
| Checkbox | Pills; several choices. PPOM's minimum and maximum checked counts are shown as a hint ("You can choose up to 3.") and enforced. |
| Select | A drop-down; the first entry is "Choose…". |
| Text, Textarea | A text box; a price on the field is added when something is typed. |
Option prices are shown next to each option ("+$2.00"). A percentage price ("15%") is a percentage of the dish price. Prices and limits always come from the field definitions on the server: a changed request cannot lower a price. Other PPOM field types (file, date, image…) are ignored. In the basket, the order and the e-mails each group is listed as "Extras: Paneer (+$2.00), Garlic naan (+$2.50)" and the add-on total is added to the line price.
Special instructions
With "Let customers add a note to each dish" on (Menu tab, on by default), the popup has a Special instructions box (300 characters). The note is shown under the line in the basket, saved as the line meta "Note" on the order, and printed in the order e-mails and on the order screen. Two identical dishes with different notes are two basket lines. Dishes without options still open the popup through their name or photo, so the note is available for every dish.
The basket drawer
A floating button shows the item count and subtotal; on phones it becomes a full-width bar once the basket holds something. It opens a drawer with:
- Every line with its thumbnail, name, options, note, unit price, a quantity stepper (minus becomes a bin at 1; plus is disabled at the stock or sold-individually limit) and the line total.
- The Delivery / Pickup switch and your delivery or pickup note.
- The subtotal, the minimum-order bar and the free-delivery hint (next section), or "We are closed right now. Opens …" while ordering is refused.
- Checkout (disabled while the minimum is not reached or ordering is closed) and View cart.
Requests are sent one after another, so quick repeated taps on a stepper work from the latest basket; a failed request shows the WooCommerce message (stock, sold individually, other plugins' checks) as a toast. Hide the floating basket on the Menu tab to use your theme's cart instead.
Minimum order and the free-delivery hint
A Minimum order amount (Ordering tab) is compared with the basket subtotal (before shipping and discounts; including tax when your store shows prices including tax). Below it the drawer shows a progress bar and "Add $4.50 more to reach the minimum order of $15.00", the Checkout button is disabled, and the classic checkout and the Checkout block refuse the order with the same message. "Minimum order reached." appears once it is met. The Free delivery message from amount only shows "Add $12.00 more for free delivery." or "You qualify for free delivery." for delivery orders; set up the free-shipping rule itself in WooCommerce → Settings → Shipping.
6. Opening hours, closed dates and lead time
Open, closed and the next opening
- Each week day has an Open switch and up to two periods, typed as 24-hour times (
11:00,14:30;24:00means midnight;10and10.30are accepted and normalised). A period must end after it starts and within the same day; hours that cross midnight are not supported, so use24:00as the closing time. - Closed dates (holidays, private events) are a list of
YYYY-MM-DDlines with an optional label after a|. On those dates the restaurant counts as closed all day and no slot is offered; the next six upcoming ones are listed in the hours popup. - The status is computed in the site timezone (Settings → General). "Open now" means the current time is inside a period of today and today is not a closed date; "Closes at" is the end of that period. "Opens …" is the start of the next period within the next 14 days.
- The Temporarily closed switch overrides everything: the status says Closed, your closed message is shown, ordering is refused and the delivery fields disappear from the checkout, until you switch it off.
- The Time format setting (12-hour "10:00 am" or 24-hour "10:00") applies to the status bar, the hours popup, the slots and the order details.
Ordering while closed
| Setting (Ordering → While the restaurant is closed) | Outside opening hours |
|---|---|
| Accept orders for the next opening (pre-orders) – the default | Status "Closed · Opens Tuesday at 10:00 am · Pre-order for later". Dishes can be added and the checkout offers the slots of the next opening. |
| Do not accept orders while closed | Status "Closed · Opens …". The Add buttons are greyed out and answer "We are closed right now. Opens …"; quantities can still be lowered; the basket says the same and its Checkout button is disabled; the classic checkout and the Checkout block refuse to place the order. The menu stays browsable. |
How the time slots are built
- For today and the next days of the Order ahead window (1 – 14 days, 5 by default), the periods of each day are taken; closed days and closed dates are skipped.
- The earliest time is now plus the Preparation / lead time (0 – 720 minutes, 30 by default).
- While you are open and the earliest time is still before the end of the current period, the first slot is ASAP (about 30 min).
- Timed slots start at the earliest time rounded up to the next Slot length boundary (5 – 240 minutes, 15 by default) and run every slot length until the end of the period, including the closing time. A period that would end before the earliest time offers nothing.
- A day without any slot is left out. Days are labelled Today, Tomorrow, then "Wed Oct 14th". Slot values are stored as 24-hour times; the labels follow the Time format setting.
The Checkout tab shows a preview of the next three days' slots, so you can see the effect of the lead time and the slot length. The slots are rebuilt on every page load and checked again when the order is placed: a slot that has passed in the meantime is refused with "Please choose an available delivery time."
7. Checkout and orders
Classic checkout
Under "Additional information" the classic checkout gets an Order type row of pills (Delivery / Pickup, preselected with the customer's choice) when both types are offered, and – with "Ask for a day" on – a Delivery day / Pickup day select and, with "Ask for a time slot" on, a Delivery time / Pickup time select whose options follow the chosen day. The labels follow the chosen order type. Switching the type reloads the shipping rates. All three fields are required.
The Checkout block
The Checkout block gets two drop-downs under "Additional order information", registered through WooCommerce's Additional Checkout Fields API: Order type (when both types are offered) and Delivery / pickup time, one list that combines day and slot ("Today – ASAP (about 30 min)", "Tomorrow – 12:00 pm"), or Delivery / pickup day when no time slot is asked for. The values are mirrored into the same order meta as the classic checkout, and the plugin hides WooCommerce's raw copy of the fields from the confirmation and from the order editor (their options are the slots of the moment, so an admin save must not overwrite the customer's choice).
Shipping rates for pickup and delivery
When both order types are offered, the plugin filters the shipping rates of the current package by the chosen type: pickup keeps the rates of the methods local_pickup and pickup_location (WooCommerce's Local pickup, including the block checkout's pickup locations), delivery keeps all other rates. If a type would be left without any rate (for example no Local pickup method in the zone), the rates are left untouched so the checkout never gets stuck. Disable this with the wxp_restaurant_filter_shipping_rates filter.
Where the order type and slot go
| Where | What is shown |
|---|---|
| Thank-you page | "Order type: Pickup", "Pickup day: October 14, 2026", "Pickup time: 12:00 pm" in the order overview list. |
| Order e-mails (HTML and plain text) | The same three lines above the order details, in every WooCommerce e-mail that prints order meta. |
| Order screen | The same lines under the shipping address. |
| Orders list | A Restaurant column after Status: a Delivery or Pickup badge and the day and time. HPOS and legacy storage. |
| Order line meta | Each add-on group ("Extras: Paneer (+$2.00)") and the "Note". |
What is checked on the server
- Every add-to-cart request is checked by WooCommerce (product published, purchasable, stock, sold individually, other plugins'
woocommerce_add_to_cart_validation) and by the plugin: ordering open, a variation for variable products, required add-ons, minimum and maximum counts, prices from the field definitions. - At checkout the plugin checks that ordering is open, the minimum order is reached, the order type is one you offer, and the day and time are slots that are available right now; the Checkout block gets the same checks through the Store API.
- Nothing a customer can edit in the browser (a price, a slot value, an add-on id) is trusted.
Security token and page caching
Every menu request carries a WordPress nonce (action wooexperts-menu). A page served from a full-page cache can carry an expired one; the server then answers with a fresh token and the script retries once, invisibly. If the retry fails too, the customer sees "Your session has expired. Please reload the page and try again." Keep the menu page's cache lifetime at 12 hours or less, and exclude it from caching for visitors with a basket if your cache does not already do that (the basket state is printed into the page).
Compatibility
- High-Performance Order Storage (HPOS) and the Cart and Checkout blocks (compatibility declared).
- Block themes: the assets are registered when the shortcode renders, so the menu works in templates that render before
wp_enqueue_scripts. - Right-to-left sites: the basket opens from the left and the layout mirrors.
- Reduced motion: animations are switched off when the visitor asks for it.
- Fixed footer bars (Storefront's handheld bar is handled): add
body { --wxp-basket-lift: 60px; }to raise the floating basket.
8. Settings
WooCommerce → Restaurant (capability manage_woocommerce) starts with an overview strip – open or closed right now with the closing or next-opening time, orders today, dishes and categories on the menu, pages that contain the shortcode – and has six tabs. One Save changes button saves all tabs; the tab you were on is remembered.
Restaurant
| Setting | Meaning | Default |
|---|---|---|
| Temporarily closed | Shows the menu as closed, refuses orders and hides the delivery fields until switched off. | off |
| Message while closed | Shown in red under the status bar while Temporarily closed is on (basic HTML). | empty |
| Show a message at the top of the menu + Message | A soft info box under the status bar (basic HTML). | off |
| Phone number | The call button in the status bar; empty hides it. | empty |
| Opening hours | Per day: Open switch, first period, optional second period, "Copy to all". | all days closed |
| Time format | 12-hour or 24-hour everywhere. | 12-hour |
| Show an "Opening hours" button on the menu | The hours popup. | on |
| Closed dates | One YYYY-MM-DD | label per line. | empty |
Menu
| Setting | Meaning | Default |
|---|---|---|
| Dish layout | List, or cards with the photo on top. | List |
| Show dish photos | Product images on the menu and in the popup. | on |
| Show dish labels | Badges plus the Vegan / Gluten-free chips. | on |
| Show allergens and calories | The "Contains: …" line and the kcal value. | on |
| Let customers add a note to each dish | The Special instructions box. | on |
| Hide the search box / the Veg filter / the floating basket | Tools on the menu page. | off |
Ordering
| Setting | Meaning | Default |
|---|---|---|
| Order types | Delivery and pickup (the customer chooses), Delivery only, Pickup only. | both (delivery only on sites updated from 1.x) |
| Delivery note / Pickup note | One line shown in the basket under the switch. | empty |
| Preparation / lead time | Minutes added to "now" before the first slot; also the ASAP estimate. | 30 |
| Order ahead | Days, including today, for which slots are offered (1 – 14). | 5 |
| While the restaurant is closed | Accept pre-orders, or do not accept orders. | pre-orders |
| Minimum order amount | Basket subtotal needed to check out; empty = none. | empty |
| Free delivery message from | Threshold for the hint in the basket (informational). | empty |
Checkout
| Setting | Meaning | Default |
|---|---|---|
| Ask for a day | The required day field at checkout. | off |
| Ask for a time slot | The required slot field (needs "Ask for a day"). | off |
| Slot length | Minutes between slots (1 – 240). | 15 |
Below the fields the tab previews the slots of the next three days.
Design
Nine colour tokens (Accent, Text on accent, Text, Muted text, Surface, Surface soft, Borders, Vegetarian mark, Non-vegetarian mark) with a colour picker each and a Reset colours to defaults button, a Corner radius slider (0 – 32 px) and a Custom CSS box. The values become CSS custom properties on .wxp-root and are printed with the menu stylesheet; the hover colour and the soft accent are derived from the accent. Your theme's font is used throughout.
The Restaurant tab of a product
The product editor (simple and variable products) gets a Restaurant tab in the Product data box: Spice level (Not spicy, Mild, Medium, Hot), Dish labels (Popular, New, Chef's special, Vegan, Gluten-free, Dairy-free), Allergens (comma-separated) and Calories (kcal). Is Non-Vegetarian stays in the row of tick boxes next to the product type. The fields are saved from the product editor only; Quick Edit, imports and the REST API leave them as they are.
9. Developer reference
Shortcode
| Attribute | Default | Meaning |
|---|---|---|
categories | empty | Comma-separated product category slugs. Order is kept. |
layout | the Menu setting | list or grid. |
menu | lunch | Passed to wxp_restaurant_menu_category_args only. |
Filters and actions the plugin fires
| Hook | Parameters | When |
|---|---|---|
Filter wxp_restaurant_settings | $settings | After the saved settings are merged with the defaults, once per request. |
Filter wxp_restaurant_status | $status (open, manual, until, next, today), $settings | Whenever the opening status is computed. |
Filter wxp_restaurant_ordering_open | $open (bool), $settings | Decides whether dishes can be added and orders placed right now. |
Filter wxp_restaurant_order_types | $types (key => label), $settings | The order types offered. |
Filter wxp_restaurant_filter_shipping_rates | $enabled, $rates, $package | Return false to leave the shipping rates alone. |
Filter wxp_restaurant_delivery_days | $days (the Order ahead setting), $settings | The number of calendar days checked for slots. |
Filter wxp_restaurant_delivery_slots | $slots, $settings | After the slots are built: Y-m-d => array( 'label' => 'Today', 'times' => array( 'ASAP' => 'ASAP (about 30 min)', '12:30' => '12:30 pm', … ) ). Used for the checkout fields and for validation. |
Filter wxp_restaurant_now | null | Return a DateTimeImmutable to pin "now" (tests, previews). |
Filter wxp_restaurant_dish_labels | $labels (key => label) | The labels offered on the Restaurant tab and shown on the menu (CSS class wxp-tag-<key>). |
Filter wxp_restaurant_dish_details | $details (spice, labels, allergens, calories), $product | Per dish, before rendering. |
Filter wxp_restaurant_menu_item_data | $data, $product | Everything the template knows about one dish, including the JSON given to the script. |
Filter wxp_restaurant_ppom_fields | $fields, $product_id | The PPOM fields used for a product (also a way to supply add-ons without PPOM). |
Filter wxp_restaurant_menu_product_args | $args, $slug, $atts | Before the products of one section are queried with wc_get_products(). |
Filter wxp_restaurant_menu_category_args | $args, $menu, $atts | Before the categories are fetched with get_terms(). |
Filter wxp_restaurant_order_details | $details (label => value), $order | The lines shown on the thank-you page, in e-mails and on the order screen. |
Action wxp_menu_header | $settings | At the top of the menu; the plugin's callback (priority 10) renders templates/header.php. |
Action wxp_save_restaurant_settings | $settings | After the settings screen is saved. |
Close the kitchen 30 minutes before the end of the hours, and add a label:
add_filter( 'wxp_restaurant_delivery_slots', function ( $slots, $settings ) {
foreach ( $slots as $date => &$slot ) {
array_pop( $slot['times'] ); // the last slot of every day is the closing time
}
return $slots;
}, 10, 2 );
add_filter( 'wxp_restaurant_dish_labels', function ( $labels ) {
$labels['halal'] = 'Halal';
return $labels;
} );
AJAX endpoints
Requests go to WooCommerce's endpoint ?wc-ajax=wxp_<action> as POST, for logged-out visitors too. Each handler verifies the nonce (action wooexperts-menu, POST parameter check) and, on an invalid one, answers code: "nonce" with a fresh nonce so the script can retry once.
| Endpoint | POST parameters | What it does |
|---|---|---|
wxp_add_to_cart | data: URL-encoded product, quantity, variation (0 for none), opts[attribute_pa_size]=value for "Any" attributes, opts[i][data_name]=value (an array for checkboxes) for PPOM fields, note | Adds a line. Refused while ordering is closed (code: "closed"), for a missing variation, a missing required add-on, a count outside min/max, or anything WooCommerce refuses. |
wxp_update_item | key (cart item key), qty (0 removes) | Changes a line's quantity with the cart page's checks (stock, sold individually, woocommerce_update_cart_validation). Increasing is refused while ordering is closed. |
wxp_remove_item | id (cart item key) | Removes a line. |
wxp_set_order_type | type (delivery or pickup) | Stores the choice in the WooCommerce session (creates the session cookie for a guest) and clears the cached shipping rates. |
Every answer has res (bool), message, fragments (div.wxp-drawer-content and button.wxp-basket-btn, replaced in the page) and cart (count, subtotal, subtotal_raw, products as id => qty and keys, order_type). The legacy endpoint ?wxperts-ajax=<action> still works for pages cached with a 1.x script.
JavaScript configuration
assets/js/menu.js (handle restaurant-script, deferred, no dependencies) receives the global wxpmenu: ajax_url, ajax_prefix (wxp_), nonce, cart_url, checkout_url, price (symbol, format, decimals, separators, so the popup total is formatted like wc_price()), settings (order_types, order_type, item_notes, ordering, closed_message, min_order, free_over) and i18n. On the checkout page assets/js/wxp-check.js (handle restaurant-check, needs jQuery) fills the time select from the day select's data-wxp JSON and renames the labels when the order type changes.
Templates and CSS
templates/menu.php,templates/header.phpandtemplates/basket.phpare loaded withwc_get_template(); copy them toyour-theme/advanced-restaurant-for-woocommerce/to override.menu.phpreceives$items,$cats,$instance,$cart,$settings,$status,$layoutand$ordering; the basket is printed once inwp_footer.- Colours and sizes are CSS custom properties on
.wxp-root(--wxp-accent,--wxp-accent-hover,--wxp-accent-contrast,--wxp-accent-soft,--wxp-text,--wxp-muted,--wxp-surface,--wxp-surface-2,--wxp-border,--wxp-veg,--wxp-nonveg,--wxp-radius…). The Design tab writes them; your own CSS can override them.body { --wxp-basket-lift: 60px; }lifts the floating basket above a fixed footer bar. - Icons are inline SVG from
RFWCP_Wexperts_AJAX::icon(); there is no icon font.
PHP classes and functions
wxp_restaurant_pro()returns the main object (WooExperts_Restaurant_Pro):get_settings(),get_settings_fields( $data = null )(sanitiser; defaults without arguments),reset_settings_cache(),get_color_defaults(),get_setting_choices(),get_dish_labels(),get_spice_levels(),get_dish_details( $product ),get_options( $product ),get_ppom_fields( $product_id ).WpExpertshub_Restaurant(classes/class-wpexpertshub-restaurant.php): the shortcode and menu data (get_menu_categories(),get_menu_items(),get_item_data()), the hours engine (now(),get_day_ranges(),get_date_ranges(),is_closed_date(),get_status(),is_open(),next_opening(),next_opening_text(),ordering_open(),closed_message(),get_weekly_hours(),get_delivery_slots()), order types (get_order_types(),get_order_type(),set_order_type()), the checkout fields,min_order_error(),get_order_delivery_details()and the orders-list column.RFWCP_Wexperts_AJAX(classes/ajax.php): the AJAX handlers,get_cart_state(), the basket, basket-button and order-type-switch HTML,stepper_html(),icon().WPXH_Licence_Client_V2(licence/class-wpxh-licence-client.php): the licence and update client.- Constants
WXP_RESTAURANT_PRO_FILE,WXP_RESTAURANT_PRO_VER(2.0.0); block field idswxp-restaurant/order-type,wxp-restaurant/delivery-day,wxp-restaurant/delivery-slot; session keywxp_order_type.
Options, meta and stored data
| Item | Where | Content |
|---|---|---|
_wxp_restaurant_opts | Option (autoload off) | All settings: notice, g-notice, is-closed, close-notice, days (day => from, to, from2, to2; 0 = closed), closed-dates (date => label), phone, show-hours, hours-style, when-closed, layout, show-badges, show-allergens, show-images, item-notes, disable-sidebar, disable-veg-filter, disable-searchbar, order-types, lead-time, days-ahead, min-order, free-delivery-over, delivery-note, pickup-note, date, time, time-int, the nine colour keys, radius, custom-css. |
_advanced-restaurant-for-woocommerce_licence_key, …_key_status | Options (autoload off) | The licence key and its status (the 1.x keys under the old slug are copied once). |
wpxh_licence_check_v2 | Site transient | Cached update information, 12 hours. |
_is_nonveg, _wxp_spice, _wxp_labels, _wxp_allergens, _wxp_calories | Product meta | Diet flag (yes/no), spice level 0 – 3, label keys (array), comma-separated allergens, calories. |
_wxp_order_type, _delivery_date, _delivery_time | Order meta | delivery or pickup; Y-m-d; H:i or ASAP (1.x orders hold the formatted label). |
_wc_other/wxp-restaurant/… | Order meta (written by WooCommerce) | The raw Checkout block values. |
| Add-on groups, "Note" | Order line meta | "Extras: Paneer (+$2.00), …" per group; the special instructions. |
wxp-menu, wxp-price, wxp-note | Cart item data (session) | The chosen add-ons with server-side prices, the price when added, the note. |
wxp_order_type | WooCommerce session | The chosen order type. |
The plugin has no custom tables, cron events, roles, capabilities or REST routes.
File layout
advanced-restaurant-for-woocommerce.php: bootstrap, settings schema and sanitiser, the Restaurant product tab, PPOM field reader, licence registration.classes/class-wpexpertshub-restaurant.php: menu, hours engine, order types, slots, checkout, order display, orders-list column.classes/ajax.php: AJAX handlers, basket and switch HTML, icons.templates/menu.php,header.php,basket.php,dashboard.php.assets/js/menu.js,wxp-check.js,admin.js;assets/css/front.css,checkout.css,admin.css.licence/class-wpxh-licence-client.php,languages/advanced-restaurant-for-woocommerce.pot,readme.txt.
10. Privacy
| Topic | What the plugin does |
|---|---|
| Data stored by the plugin | Your settings, the dish details on products, the order type, day and time on orders, and the add-on choices and notes on order lines. Text a customer types into a note or a PPOM text field is stored with the order like any order note. |
| Cookies | The plugin sets none of its own. When a customer adds an item or chooses delivery or pickup, WooCommerce's session cookie (wp_woocommerce_session_*) and cart cookies are set by WooCommerce. The script uses localStorage only on the settings screen (the last tab). |
| Data sent from the menu, the checkout and the admin screens | Nothing leaves your site. Requests go to your own server; no external font, script or image is loaded. |
| Data sent to wpexpertshub.com | Only by the licence and update client, over HTTPS (https://wpexpertshub.com/wp-json/wphub-licence/v1/). See below. |
| Retention | The plugin deletes nothing by itself; order data stays with the order. The update cache expires after 12 hours. |
| Deactivation and deletion | Neither removes settings, product meta or order meta. "Deactivate licence" removes the two licence options. |
| Privacy policy text, exporter, eraser | None of its own; WooCommerce's export and erase tools cover the order data. |
What the licence client sends
| When | Request | Data sent |
|---|---|---|
| You click Activate licence | activate | The plugin slug (advanced-restaurant-for-woocommerce), the licence key you entered and your site URL. |
| You click Deactivate licence | deactivate | Slug, the stored key and the site URL. |
| You click Email me my key | send-key | Slug and the e-mail address you typed. |
| WordPress checks for updates (at most every 12 hours), or "View details" is opened | check | The site URL and, for every plugin that uses this client: slug, stored key (empty if none) and installed version. |
11. Troubleshooting
| Problem | Likely cause and fix |
|---|---|
| The menu says "Closed" although the restaurant is open. | Today's Open switch is off, the hours are empty or invalid (the To time must be later than the From time, within the same day), today is a closed date, the Temporarily closed switch is on, or the site timezone (Settings → General) is wrong. The overview strip on the settings screen says what the plugin thinks right now. |
| Customers cannot add anything: "We are closed right now." | "Do not accept orders while closed" is on and you are outside opening hours, or Temporarily closed is on. Choose "Accept orders for the next opening" to allow pre-orders. |
| "The minimum order is $15.00 (your basket is $9.50)." | Working as set under Ordering → Minimum order amount. Empty the field for no minimum. |
| "Please choose an available delivery day / time." | No slot is offered: no hours, every day in the order-ahead window closed, or the chosen slot passed between page load and submit. Check the slot preview on the Checkout tab, widen the hours or the window, or lower the lead time. |
| No "ASAP" today. | ASAP is offered only while you are open and now plus the lead time is still before the end of the current period. |
| The delivery fields are missing at checkout. | "Ask for a day" is off, Temporarily closed is on, or (classic checkout) the theme's checkout template does not call woocommerce_after_order_notes. In the Checkout block the fields are under "Additional order information". |
| The Order type field is missing at checkout. | Only one order type is offered under Ordering; every order then gets that type. |
| Pickup orders are still charged delivery. | Add a "Local pickup" method to the shipping zone. The plugin only removes delivery rates when a local pickup rate exists for that address. |
| Add-ons do not appear in the popup. | PPOM for WooCommerce is not active, the product has no field group, the product is variable (not supported), or the fields are of an unsupported type. |
| "Size is a required field." / "You can choose up to 2." | The server enforces PPOM's required flag and min/max counts even if the browser skipped them. Choose accordingly. |
| "Your session has expired. Please reload the page and try again." | A cached page carried an expired token and the automatic retry failed too. Reload; keep the page cache at 12 hours or less. |
| The basket shows an old state after a reload. | The basket state is printed into the page; exclude the menu page from page caching for visitors with a basket. |
| A dish shows the wrong diet mark, spice or labels. | Those fields are saved from the product editor only; open the product and update it. |
| Labels, allergens or the note box are missing. | Switched off on the Menu tab. |
| The floating basket covers the theme's footer bar on phones. | Add body { --wxp-basket-lift: 60px; } (Storefront's handheld bar is handled automatically). |
| The category list is not sticky. | A theme wrapper with overflow: hidden breaks sticky positioning; the script switches such wrappers to overflow: clip, but a wrapper added after load is missed. Check the theme's container styles. |
| Colours did not change. | Save the Design tab; a page or CSS cache may serve the old page. The values are printed inline with the menu stylesheet. |
| After updating from 1.x the menu looks different / my CSS no longer applies. | The markup changed in 2.0.0; see Updating from version 1.x and Templates and CSS. |
| No update appears. | The licence is not active, or the plugin's cached answer is still fresh (up to 12 hours). WordPress's "Check again" link does not clear that cache. |
| A notice says the free plugin is not used. | Both plugins are active. Deactivate and delete the free plugin. |
12. FAQ
Which plugin do I get with this product?
One plugin, the one documented on this page. See How it relates to Restaurant for WooCommerce (free).
Can customers choose between delivery and pickup?
Yes, when "Delivery and pickup" is chosen under Ordering: on the menu, in the basket and at checkout. The choice is saved on the order and decides which shipping rates are offered.
Does it stop orders when the restaurant is closed?
Your choice: accept pre-orders for the next opening (the default) or refuse orders while closed. The Temporarily closed switch refuses orders at any time.
How are the time slots calculated?
From the opening hours of each day, skipping closed dates, starting after the lead time and rounded to the slot length; "ASAP" while open. See How the time slots are built.
Can I have different hours for lunch and dinner?
Yes, every day has up to two periods. The status bar shows "Closed · Opens today at 6:00 pm" between them.
How do I close for a holiday?
Add the date under Closed dates (2026-12-25 | Christmas Day). For a short unplanned closure use the Temporarily closed switch.
How do add-ons work?
Sizes and similar choices are WooCommerce variations. Extras come from PPOM for WooCommerce fields on simple products; see PPOM for WooCommerce add-ons.
Can customers add a note to a dish?
Yes, the Special instructions box in the popup (on by default). The note is on the basket line, the order and the e-mails.
Does it work with the WooCommerce Checkout block?
Yes: Order type and Delivery / pickup time drop-downs under Additional order information, saved to the same order fields as the classic checkout. HPOS is supported.
Can I set a minimum order?
Yes, under Ordering. The basket shows a progress bar, and the checkout refuses orders below it.
Can I show only some categories, or use cards?
[wxp_restaurant categories="starters,mains"] and [wxp_restaurant layout="grid"].
Can I change the colours and the layout?
Colours, corner radius and custom CSS on the Design tab; the layout by copying the templates to your theme. See Templates and CSS.
What happens when I update from 1.x?
Settings are kept, the site stays delivery-only until you enable pickup, the old colours are not carried over, and template overrides must be redone. See Updating from version 1.x.
How do I activate my licence and get updates?
Plugins → WpExperts Hub Licences, paste the key, Activate licence. Updates then appear on Dashboard → Updates. See The licence and updates.
Does the plugin work without a licence?
Yes. The licence is only needed for updates.
How do I get support?
Email support@wpexpertshub.com with your order ID.
13. Changelog
2.0.0 - 14/10/2026
- New - Menu redesigned: status bar (Open now / Closed with the next opening), opening-hours popup, call button, sticky category navigation, search and filter chips, dish cards with photo, spice level, labels, allergens and calories, list or card layout.
- New - Dish popup rebuilt as a native dialog: variations as pills, PPOM add-ons (select, radio, checkbox with min/max, text, textarea) with a live total, per-dish "Special instructions" note shown on the order.
- New - Basket drawer with quantity steppers, delivery/pickup switch, minimum-order progress bar, free-delivery hint and a disabled checkout while the minimum is not reached.
- New - Delivery or pickup: customers choose on the menu and at checkout (classic and block); the order type is saved on the order, shown in e-mails, on the order screen and in a new "Restaurant" column of the orders list; pickup orders only see "Local pickup" shipping rates.
- New - Opening hours with two periods per day (lunch and dinner), closed dates (holidays), preparation/lead time, order-ahead window, "pre-orders while closed" or "no orders while closed", temporarily-closed switch with its own message, 12/24-hour format.
- New - Time slots start after the lead time, "ASAP (about N min)" while open; a slot preview on the settings screen.
- New - "Restaurant" tab in the product editor: spice level, dish labels (Popular, New, Chef's special, Vegan, Gluten-free, Dairy-free), allergens, calories.
- New - Settings screen rebuilt with the WpExperts Hub look: overview strip (status, orders today, dishes, menu page), pill tabs, cards, switches, opening-hours editor with "Copy to all", design tab with colour tokens, corner radius and custom CSS.
- New - Template overrides in your-theme/advanced-restaurant-for-woocommerce/, filters wxp_restaurant_settings, wxp_restaurant_status, wxp_restaurant_ordering_open, wxp_restaurant_order_types, wxp_restaurant_dish_labels, wxp_restaurant_menu_item_data, wxp_restaurant_now.
- Tweak - Fancybox, the icon font and the loader image were removed (vanilla JavaScript, inline SVG icons, native dialogs). The 12 colour settings became 9 colour tokens (previous colour values are not carried over).
- Tweak - Delivery times are stored as 24-hour values (older orders keep displaying); translations load from /languages.
- Fix - Expired nonces on cached pages are refreshed and the request retried; add-on prices are always taken from the field definitions, never from the request.
1.5.1 - 08/10/2026
- Tweak - Renamed from "Restaurant for WooCommerce Pro" to "Advanced Restaurant for WooCommerce". The plugin folder, main file and text domain are now advanced-restaurant-for-woocommerce. Your settings and licence carry over.
- Tweak - An existing licence key is moved to the new plugin name automatically.
- Fix - If the older "restaurant-for-woocommerce-pro" folder is still active next to this one, a notice explains it instead of causing a fatal error.
1.5 - 27/09/2026
- Security - New licence client: licence data is exchanged as JSON only and a failed server request can no longer cause a fatal error.
- Enhancement - One "Plugins → WpExperts Hub Licences" screen manages the licences of all WpExperts Hub plugins; updates are delivered through the standard WordPress update screen; "Email me my key" added.
- Fix - Fatal error on an invalid product ID; the Non-Vegetarian flag reset on programmatic saves; settings saved without a capability check; closed days offered for delivery; empty delivery time accepted; localised delivery dates that could not be read back; interval 0 division by zero; PPOM fields through groups/categories, percentage prices and required fields; variable products with multi-word or global attributes; add-to-cart failures leaving the menu blocked; BlockUI dependency; generated stylesheet in uploads; PHP 8.2 deprecations; mobile basket overflow.
- New - Delivery day/time field for the Checkout block; shortcode attribute categories; "Sold out" for out-of-stock items; header mini cart refresh.
- Tweak - WooCommerce AJAX endpoint; WordPress colour picker; correct compatibility declarations; boot on plugins_loaded; text domain renamed.
1.4 - 20/02/2024
- Minor tweaks.
1.3 - 08/02/2024
- Menu scroll fixed.
1.2 - 24/01/2024
- Compatibility Check.
1.1 - 18/02/2023
- Compatibility Check.
1.0 - 04/05/2021
- Initial release.
14. Support
Email support@wpexpertshub.com. Include:
- Your order ID.
- The plugin version (2.0.0 or the version you run), your WordPress, PHP and WooCommerce versions and your theme.
- The address of the menu page, and whether you use the classic checkout or the Checkout block.
- What you expected, what happened, and what you already tried. A screenshot of the settings and of any message helps.