Twig functions and filters
KahunaCart registers Twig functions and filters that any theme can call, whether or not it uses the shipped templates. This page is the signature reference; worked examples and template override rules are on Storefront.
These are a theme's tool. To put a product grid or a buy button into an ordinary page's content, use the shortcodes instead — they render through these same functions and the same partials, and need neither security.twig_content nor a theme change.
Before you begin
- KahunaCart installed and enabled.
- A theme or a page template to call them from.
Everything here works in any storefront Twig template, including your own theme's. Nothing needs enabling.
Reference
text|kahunacart_markdownfilterMerchant-written Markdown as HTML, with raw markup escaped and executable link targets defused
message|kahunacart_messagefilterA storefront sentence as HTML: everything in it escaped, then its links and bold drawn
message|kahunacart_message_textfilterThe same storefront sentence as plain text, with its links and bold taken out, for an attribute, a title, or anywhere a link cannot go
minor|kahunacart_price(currency = null, with = null)filterFormats minor units as money, localized to the active language, in the currency you pass or else the visitor's
kahunacart_account_profile_url()functionThe credentials page, whose slug is configurable — a theme that hardcodes "/account/profile" breaks on any store that changed it
kahunacart_account_url()functionThe customer account route, {base}/account, honouring your configured base
kahunacart_addons(product = null)functionA product's add-on options, priced, in the order the merchant put them
kahunacart_address_lines(address)functionAn address as printable lines, laid out for its own country: postcode before the city in Germany, largest unit first in Japan, and the layout the partial always used everywhere else, with the country's name rather than its code on the last line
kahunacart_attribute(product, slug)functionOne attribute's display string, or null when the product does not answer it, for the theme that wants a single fact in the hero rather than the whole table
kahunacart_attribute_url(product, slug)functionWhere one attribute value's link goes: the shop narrowed to every product answering the same thing
kahunacart_attributes(product)functionA product's attributes, as the plugin's own product page has them: a list of {slug, label, type, value, display, unit, group, options, filter_url, values} in definition order, holding only the ones marked to show on the product and only where the product has an answer
kahunacart_avatar(size = 64)functionThe signed-in customer's picture as a URL, at the pixel size you ask for
kahunacart_badges(product = null, labels = [])functionThe badges over a product's picture, in the order they are drawn: sold out, pre-order, the sale, the merchant's own badge, download
kahunacart_base_route()functionThe configured base route, normalized with a leading slash and no trailing one
kahunacart_buy_button_fields(product = null, variants = null)functionThe form fields other plugins want inside this product's add-to-cart form, already rendered
kahunacart_buy_now(product = null)functionHow a product's buy button behaves: {on, label}
kahunacart_cart_count()functionTotal units in the current session's cart, or 0
kahunacart_cart_line_notes(order = null, items = null)functionWhat other plugins need the customer to read beside a cart or receipt line, keyed by line item id
kahunacart_cart_word()functionThe storefront's word for the cart, cart, bag or basket (storefront.cart_word), for a theme that picks an icon or a class by it
kahunacart_categories()functionThe whole category tree, nested
kahunacart_category_image(category = null, width = 160, height = null)functionA category's picture at the size you ask for, as {url, alt, width, height}, or null when the category has none
kahunacart_countries()functionEvery ISO 3166-1 alpha-2 code with its English name, ordered by name, and the code checkout.default_country names (or '')
kahunacart_coupon_notice()functionThe "you are holding a discount code" banner, rendered
kahunacart_currencies()functionThe currencies a shopper can pick, for the switcher or a theme's own menu
kahunacart_currency_link(url)functionKeeps an explicit ?currency= choice on an existing site-navigation URL
kahunacart_currency_notice()functionWhat to tell a shopper whose cart is in one currency and who followed a link to another
kahunacart_current_currency()functionThe currency this request is in, and the store's base currency, for the "Not available in EUR" partial or a theme's own line
kahunacart_custom_fields(entity, entityId)functionThe custom field values on one row — a product, a variant, an order, an order line, a customer, an address — as a CustomFieldValues object
kahunacart_customer()functionThe customer record the current visitor is, as an array, or null
kahunacart_date(at = null, form = StoreDate::LONG)functionA date the way the store's language writes one, in the store's timezone: "November 19, 2026" on a US English store, "19 November 2026" on a British one, "19
kahunacart_default_country()functionThe country code checkout.default_country names, for preselecting an address form
kahunacart_downloads(limit = 0)functionThe signed-in customer's downloads, newest first, for a theme's own library
kahunacart_express_buttons(zone = ExpressButtonRegistry::ZONE_CART)functionThe express-pay region for the cart page ('cart.express', the default) or the checkout page ('checkout.express'): the wallet buttons every eligible provider registered on onKahunaCartRegisterExpressButtons, each drawn to the merchant's express.* style so they sit in one row at one height
kahunacart_image(image, width = 600, height = null)functionOne image at a size of your choosing, as {url, alt, width, height}
kahunacart_kit_items(product = null)functionWhat a grouped product or a kit contains
kahunacart_lightbox()functionThe lightbox's <dialog>, the first time a page asks for it, and nothing after that, so every template that draws an opener can call it
kahunacart_line_fixed_qty(item = null)functionWhether a cart line's quantity is the add-on's rather than the customer's
kahunacart_login_url()functionThe Login plugin's own sign-in route, and its logout task on the current page with the nonce that task expects — built exactly the way its own login-status partial builds it
kahunacart_logout_url()functionThe Login plugin's own sign-in route, and its logout task on the current page with the nonce that task expects — built exactly the way its own login-status partial builds it
kahunacart_notices(notices, filters = [])functionNarrows a list of order notices to the ones a template is about to draw
kahunacart_order_fields(order)functionWhat the customer answered on one order's checkout fields, in the order the form asked them
kahunacart_order_reference(order)functionWhat an order is called: the reference the order_reference object template stamped on it at completion, or #<number> for an order placed before references existed
kahunacart_order_status_axes(order)functionWhich of an order's statuses the customer is shown, as a list of axis names in the order the account draws them
kahunacart_pay_what_you_want(product = null, variants = null)functionWhat a shopper may pay for a pay-what-you-want product, ready for the price box, or null for a product sold at its price
kahunacart_paywall(page)functionWhat this visitor gets of a page, for a theme or a listing template that wants to decide for itself
kahunacart_preorder(product = null)functionWhether a product is a pre-order, and how to say when it comes out
kahunacart_price(minor, currency = null, with = null)functionFormats minor units as money, localized to the active language, in the currency you pass or else the visitor's
kahunacart_price_set(vars = [], units = null)functionEvery amount a cart or order summary prints, as one list for the with of kahunacart_price(), so the summary is printed alike: if any amount in it has cents all of them keep them, and if every one is whole none show cents
kahunacart_product(slug)functionOne published product, or null
kahunacart_product_images(product)functionEvery picture on a product, in gallery order — gallery images and nothing else, which is what this function has always returned and what a theme drawing an <img> with it wants
kahunacart_product_labels(product)functionA product's labels as the storefront draws them, in order: its EU energy labels and its label images
kahunacart_product_media(product, role = null, kind = null)functionEverything attached to a product, gallery first and then the samples
kahunacart_product_safety(product)functionThe Product safety block for a product, as the product route hands it to partials/kahunacart-product-safety.html.twig: {manufacturer, responsible_person, safety_info}, or null when the product has no manufacturer (its own or the store default) and no safety information
kahunacart_product_type(product = null)function—
kahunacart_products(limit = 50, offset = 0)functionPublished products in the store's listing order
kahunacart_quantity_limits(product = null, variant = null)functionHow many of one thing this shopper may put in the box, ready for the box: {min, max, step, sold_individually, hint}
kahunacart_quick_add(product = null)functionThe variant a product card's Add button can post, or null when the card should link to the product instead
kahunacart_related(product, kind = RelationKind::RELATED)functionOne product's curated block, for a theme rendering it somewhere the shipped partials do not
kahunacart_releases(product = null, limit = ReleaseFeed::DEFAULT_LIMIT)functionA product's releases, newest first, or the latest across the store: a changelog, a "what's new" strip or a ticker of what shipped lately
kahunacart_sale(variant, product = null)functionThe sale covering one variant, or null at the ordinary price
kahunacart_search_url(query = null)functionThe search route, {base}/search
kahunacart_sections()functionThe store's sectioned listing, resolved: the blocks catalog.sections declares, each already holding its products, for a theme that wants to draw them its own way rather than through the shipped partials
kahunacart_set_price(product = null)functionWhat a grouped product or a kit costs, in the visitor's currency
kahunacart_sign_in_url(returnTo = null)functionA sign-in link that brings the shopper back to a storefront page afterwards: this page when no page is named, or the one you name as a path under the shop ('/product/' ~ product.slug, '/cart') or as a whole kahunacart_url()
kahunacart_status_label(status, axis = StatusAxis::STATUS)functionWhat a customer is told a status is
kahunacart_stock(product = null, variant = null)functionA product's stock, as a card, a stock line or a buy button draws it: {tracked, qty, sold_out, backorder, low, preorder, in_stock, digital, reason, label}
kahunacart_store_status()functionWhether the store is open, and whether this visitor may buy: the one thing a theme asks instead of reading the configuration
kahunacart_subdivision(country, value)functionA stored region as the option value to preselect
kahunacart_subdivisions(country)functionOne country's states or provinces, code => English name, for a <select>
kahunacart_subdivisions_json()functionEvery subdivision list as JSON, once per response
kahunacart_tags()functionEvery tag in the store, each with its label, its slug, how many published products wear it, and the listing URL that filters on it
kahunacart_tax_note(product = null, variant = null)functionThe small line under a price that says whether it includes tax ("incl. VAT", "excl. VAT"), or empty when the store is not asked to say so or charges no tax
kahunacart_url(path = '', currency = null)functionA storefront URL, ready for an href or a form action
kahunacart_whole_amounts()functionWhether the store prints whole amounts without their cents (storefront.whole_amounts)
kahunacart_zone(zone, context = [])functionA storefront extension zone, rendered: every widget an add-on mounted there, in the merchant's order, inside one element naming the zone
A filter takes the value on its left as its first argument, so each filter card shows it there. text|kahunacart_markdown is a line you can paste:
{{ product.description|kahunacart_markdown }}
kahunacart_price is registered twice, as a function and as a filter, so both of these work:
{{ kahunacart_price(item.total_minor) }}
{{ item.total_minor|kahunacart_price }}
The kit items function
kahunacart_kit_items(product) lists the parts of a grouped product or a kit, in the order you set them, for a theme that draws its own buy form. Each row has id, child_product_id, child_title, child_slug, child_status, required_quantity, resolved_variant_id and shopper_picks.
A part the shopper picks also carries the variants to choose from:
| Key | What it holds |
|---|---|
choices |
One entry per variant of the part: id, label, available, sold_out, backorder, note (the sold-out or backorder wording, or the "not sold in this currency" note) and price_minor in the visitor's currency, or null when the variant has no price there |
choice_prices_differ |
True when the choices don't all cost the same |
Draw a <select name="parts[<row id>]" required> with one <option value="<choice id>"> per choice and a first empty option, and disable the choices that aren't available. Leave out a part with fewer than two choices, because there is nothing to pick and the cart uses its one variant. partials/kahunacart-kit.html.twig does all of this, and shows the price beside each choice only when the set isn't sold as a set and choice_prices_differ is true. See Which variant a part sells.
The set price function
kahunacart_set_price(product) answers what a grouped product or a kit costs in the visitor's currency, for a theme that draws its own price line. It returns {parts_minor, price_minor, saving_minor, sells_as_set}, or null for any other product.
| Key | What it holds |
|---|---|
parts_minor |
One set of the parts at their own prices, or null when a part has no price in the visitor's currency |
price_minor |
The bundle price when the product is sold as a set, else null |
saving_minor |
What the set saves, 0 when it saves nothing |
sells_as_set |
Whether Sell as a set is on |
A grouped product never shows its own price, so print price_minor with parts_minor struck through when saving_minor is above 0, and parts_minor alone when it isn't, both through kahunacart_price. Or include partials/kahunacart-set-price.html.twig, which does that and draws nothing when there is nothing to show. See Storefront for the partial's variables.
The newsletter signup function
The Newsletters add-on registers one function of its own, for drawing a signup form anywhere in a theme. See Subscribers, lists and tags for its arguments.
kahunacart_newsletter_form(list = null, options = [])functionThe signup form for a list, as HTML a theme can print anywhere
The booking functions
The Bookings add-on's functions draw a booking picker, a customer's own booking page and a class list. See Developers.
kahunacart_booking(product = null, options = null)functionThe booking picker for a product, by its slug, anywhere in a template. with pins it to one bookable
kahunacart_booking_manage()functionThe page a customer's booking link opens, where they can see, move or cancel their own booking. The token is read from the address, never written into the page
kahunacart_bookings_board(options = null)functionWhich products are free on which days, for a week-at-a-glance board
kahunacart_bookings_counts(options = null)functionOpenings left today, resources free right now and a class's places
kahunacart_bookings_day(options = null)functionOne day, lane by lane: each person and each tub with what is booked on it, what is free and what is shut
kahunacart_bookings_lengths(product = null)functionThe lengths a product is sold in, each with its price and start times
kahunacart_bookings_next_free(product = null)functionThe next day from tomorrow with something free, or null
kahunacart_bookings_services(options = null)functionThe appointments a shopper can book, flat or grouped by category
kahunacart_bookings_sizes(product = null, options = null)functionThe sizes of a product and how many of each are free on a day
kahunacart_bookings_staff(options = null)functionThe people who do the work, each with a link that books them
kahunacart_sessions_data(days = 60, category = '')functionThe same list as data
The availability function
The Rentals add-on's function answers a property's calendar. See Developers.
kahunacart_availability(product = null, options = null)functionA property's availability calendar, by its product slug. months is how many it draws, 1 to 12
kahunacart_rentals_house(product = null)functionThe house rules and the next night to arrive on, or null on anything wrong
kahunacart_rentals_rates(product = null)functionThe rate bands still to come, in date order
Rules that apply to all of them
Money is minor units. Every *_minor field is an integer in the store's smallest unit. Pass it to kahunacart_price rather than dividing it yourself. See Money conventions.
URLs honour the base route. kahunacart_url, kahunacart_account_url, kahunacart_search_url and the rest build on the configured storefront base and the active language prefix. Do not hardcode /shop/cart; it breaks on a store that changed the base.
A failure is contained. If one of these throws, the call returns an empty value and logs instead of breaking the page.
Nothing here is cached. A listing call runs a query each time. Assign it to a variable when you need it twice in one template.