Skip to content

Developer reference

Integrate VAT pairs, catalogue prices and public offers

Use current server-calculated amounts and distinguish built-in theme integration from an optional adapter.

PressFlow 1.25.3 · 3 min read

PressFlow 1.25.3 naming

The VAT setting is a localStorage preference, not a VAT cookie. Only pressflow-vat is read and written in 1.25.3; an older-key preference is not migrated. Use window.PFWVat.setMode(‘incl’) or setMode(‘excl’) after the plugin VAT script has loaded, or emit the shared pressflow:vat-change event from your theme. A saved preference takes precedence over optional window.pressflowVat.mode, then the WooCommerce default.

Live PressFlow job amounts follow WooCommerce's current prices-entered-with-tax basis, captured in job snapshots. The server uses the product's tax status/class and WooCommerce's customer-aware tax APIs. Historic staff quote amounts have an explicit exclusive basis and must not be passed to the live-product formatter as if they shared its input basis.

Current built-in price presentation

PFW_Price_Display::amounts(WC_Product $product, float $job_price) returns ['excl' => float, 'incl' => float] using wc_get_price_excluding_tax() / wc_get_price_including_tax() with explicit price and quantity 1. The input is the complete job, not a single printed copy.

PFW_Price_Display::job($product, $price, $copies) previews the eligible mapped native promotion, calculates both tax amounts and returns price_html, unit_html, display_amounts and promotion. The unit pair divides those job amounts by copies. A unit amount that rounds to zero can be omitted.

When pressflow_vat_price_markup() exists, markup passes formatted exclusive/inclusive prices with its third argument false. The starting-price renderer already supplies “From”. The theme owns the visible suffix; do not append another VAT label.

Without a theme formatter, PressFlow 1.25.3 still supplies paired markup. Its VAT script controls the visible branch and updates newly inserted prices. WooCommerce remains responsible for the tax amounts.

Browser contract

  • Theme paired spans use data-pressflow-vat="excl" and data-pressflow-vat="incl".
  • window.pressflowVat.mode is read-only (excl or incl).
  • The document event pressflow:vat-change carries event.detail.mode.
  • The theme applies its saved pressflow-vat preference and processes newly inserted paired HTML.
  • PressFlow's .pfw-vat-price carries plain accessible amounts in data-pfw-price-excl / data-pfw-price-incl and refreshes price-bearing matrix labels with the preference.

Preserve the configurator's request sequencing/abort logic. Apply VAT presentation after current AJAX output is inserted. Do not vary selected values, native cart prices, coupon eligibility or tax calculation because this event fired. Custom price buttons must update their accessible amount as well as the visible span.

Optional pressflow_catalogue_price adapter

The theme accepts a two-argument filter starting with null and a WC_Product. PressFlow 1.25.3 does not register this filter itself. Its default catalogue/price-block renderers already show starting-price markup. Use an adapter only when your custom theme slot expects that contract, and avoid rendering a second automatic slot.

<?php
defined('ABSPATH') || exit;

add_filter('pressflow_catalogue_price', static function ($incoming, $product) {
    if (!class_exists('PFW_Config') || !class_exists('PFW_From_Price')
        || !class_exists('PFW_Price_Display') || !PFW_Config::active($product)) {
        return $incoming;
    }
    if (PFW_Config::get($product->get_id())['mode'] === 'quote') {
        return null;
    }
    $reference = PFW_From_Price::reference($product);
    if (!$reference || $reference['price'] <= 0) {
        return null;
    }
    $copies = (int) $reference['values']['copies'];
    $display = PFW_Price_Display::job($product, (float) $reference['price'], $copies);
    $detail = '<small>' . esc_html($copies . ' copies · per print job') . '</small>';
    return [
        'excl_html' => wc_price($display['display_amounts']['excl']) . $detail,
        'incl_html' => wc_price($display['display_amounts']['incl']) . $detail,
        'from' => true,
    ];
}, 20, 2);

// Use only if the theme's own catalogue slot replaces the automatic one.
add_filter('pfw_from_price_hooks', static function (array $places): array {
    $places['catalog'] = false;
    return $places;
});

This is an extension example, not code already active in the release. Both amounts describe the same validated reference job. Extend the detail for custom dimensions and preserve the starting-specification tooltip in a custom slot if replacing the normal wrapper. No safe reference means no fabricated amount. A custom starting configuration is preferable for arbitrary dimensions/quantities; do not enumerate every configuration during archive rendering.

Do not duplicate the normal [pressflow_from_price] output and this slot. The hook placement filter does not turn off separate WooCommerce price-HTML/block integration; design the template around one price component.

Public offers

PressFlow registers pressflow_product_offer at priority 20 with two arguments. For eligible managed products it supplies a verified mapped public coupon offer: percent, up_to => false, code => '', because that offer is automatically applied rather than requiring entry. Quote-only, unavailable or ineligible managed offers return null; unmanaged products preserve the incoming offer.

It also registers pressflow_native_sale_badge at priority 20 with two arguments and returns false for managed placeholder prices. Do not manufacture a PressFlow offer from a nominal regular/sale comparison.

A theme can support a separate coupon-required presentation contract or pressflow_native_price_display opt-out; those are theme-owned surfaces. Neither is a generic PressFlow pricing filter. Native coupon calculation remains responsible for the actual basket discount.

Related: VAT setup, Discounts, Starting prices, Testing.

Example files

Reference examples for adapting to your shop. PHP examples are not plugin installers; review the guide and replace sample IDs before using them.

Need a hand?

Contact the PressFlow team with details of what you are trying to do.