2026-02-28 11:15:59 +01:00
|
|
|
<?php
|
|
|
|
|
/**
|
|
|
|
|
* WooCommerce Twig Extension.
|
|
|
|
|
*
|
|
|
|
|
* Registers all WooCommerce and WordPress functions/filters needed
|
|
|
|
|
* by the child theme's Twig templates.
|
|
|
|
|
*
|
|
|
|
|
* @package WcBootstrap
|
|
|
|
|
* @since 0.1.0
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
namespace WcBootstrap\Twig;
|
|
|
|
|
|
|
|
|
|
use Twig\Extension\AbstractExtension;
|
|
|
|
|
use Twig\TwigFunction;
|
|
|
|
|
use Twig\TwigFilter;
|
|
|
|
|
|
|
|
|
|
class WooCommerceExtension extends AbstractExtension {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* {@inheritdoc}
|
|
|
|
|
*/
|
|
|
|
|
public function getFunctions(): array {
|
|
|
|
|
return array_merge(
|
|
|
|
|
$this->getWordPressFunctions(),
|
|
|
|
|
$this->getWooCommerceFunctions()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* {@inheritdoc}
|
|
|
|
|
*/
|
|
|
|
|
public function getFilters(): array {
|
|
|
|
|
return [
|
|
|
|
|
// Escaping filters (parent registers as functions only, templates use as |filter).
|
|
|
|
|
new TwigFilter( 'esc_html', 'esc_html', [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFilter( 'esc_attr', 'esc_attr', [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFilter( 'esc_url', 'esc_url', [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
|
Fix 10 known bugs: catalog, single product, and account pages (v0.1.5)
Catalog: page title via woocommerce_page_title(), breadcrumbs, category
template rename (underscore), 3-column grid, single chevron on sort.
Single product: variable form data attributes + disabled CSS class fix
(WC JS only toggles CSS classes, not HTML disabled attribute), dark mode
select specificity (0,5,1) to beat WC's (0,4,3) background shorthand,
gallery main image in thumbnail strip with empty URL guard, related/
upsells setup_postdata for correct global $product, grouped product
loop logic rewrite.
Account: downloads via wc_get_customer_available_downloads().
New: product-gallery.js, sanitize_title filter, wc_setup_product_data()
and wp_reset_postdata() Twig functions, product-thumbnails.html.twig
suppressor. Removed obsolete PLAN.md and SETUP.md.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:33:31 +01:00
|
|
|
// Slug/sanitize filters.
|
|
|
|
|
new TwigFilter( 'sanitize_title', 'sanitize_title' ),
|
|
|
|
|
|
2026-02-28 11:15:59 +01:00
|
|
|
// Text processing filters.
|
|
|
|
|
new TwigFilter( 'wpautop', 'wpautop', [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFilter( 'wp_kses_post', 'wp_kses_post', [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFilter( 'wptexturize', 'wptexturize' ),
|
|
|
|
|
new TwigFilter( 'do_shortcode', 'do_shortcode', [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* WordPress core functions not registered by the parent theme's TwigService.
|
|
|
|
|
*
|
|
|
|
|
* @return TwigFunction[]
|
|
|
|
|
*/
|
|
|
|
|
private function getWordPressFunctions(): array {
|
|
|
|
|
return [
|
|
|
|
|
// Hook system.
|
|
|
|
|
new TwigFunction( 'do_action', [ $this, 'doAction' ], [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'apply_filters', [ $this, 'applyFilters' ] ),
|
|
|
|
|
|
|
|
|
|
// Security.
|
|
|
|
|
new TwigFunction( 'wp_nonce_field', function ( string $action = '-1', string $name = '_wpnonce', bool $referer = true ): string {
|
|
|
|
|
return wp_nonce_field( $action, $name, $referer, false );
|
|
|
|
|
}, [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
|
|
|
|
|
// Options and settings.
|
|
|
|
|
new TwigFunction( 'get_option', 'get_option' ),
|
|
|
|
|
|
|
|
|
|
// User functions.
|
|
|
|
|
new TwigFunction( 'get_current_user_id', 'get_current_user_id' ),
|
|
|
|
|
new TwigFunction( 'is_user_logged_in', 'is_user_logged_in' ),
|
|
|
|
|
|
|
|
|
|
// URL helpers.
|
|
|
|
|
new TwigFunction( 'wp_lostpassword_url', 'wp_lostpassword_url' ),
|
|
|
|
|
new TwigFunction( 'get_permalink', 'get_permalink' ),
|
|
|
|
|
new TwigFunction( 'get_term_link', 'get_term_link' ),
|
|
|
|
|
new TwigFunction( 'wp_get_attachment_url', 'wp_get_attachment_url' ),
|
|
|
|
|
|
|
|
|
|
// Content rendering (echo-based, wrapped in ob_start).
|
|
|
|
|
new TwigFunction( 'get_avatar', 'get_avatar', [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'the_title', function (): string {
|
|
|
|
|
ob_start();
|
|
|
|
|
the_title();
|
|
|
|
|
return ob_get_clean();
|
|
|
|
|
}, [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'the_content', function (): string {
|
|
|
|
|
ob_start();
|
|
|
|
|
the_content();
|
|
|
|
|
return ob_get_clean();
|
|
|
|
|
}, [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
|
|
|
|
|
// Taxonomy.
|
|
|
|
|
new TwigFunction( 'term_description', 'term_description', [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'single_term_title', function ( string $prefix = '' ): string {
|
|
|
|
|
return single_term_title( $prefix, false );
|
|
|
|
|
} ),
|
|
|
|
|
|
|
|
|
|
// Date/time.
|
|
|
|
|
new TwigFunction( 'date_i18n', 'date_i18n' ),
|
|
|
|
|
|
|
|
|
|
// Text processing (as functions).
|
|
|
|
|
new TwigFunction( 'wpautop', 'wpautop', [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'wptexturize', 'wptexturize' ),
|
|
|
|
|
new TwigFunction( 'wp_parse_url', 'wp_parse_url' ),
|
|
|
|
|
|
|
|
|
|
// Formatting.
|
|
|
|
|
new TwigFunction( 'sprintf', 'sprintf' ),
|
|
|
|
|
|
|
|
|
|
// Dynamic function calls.
|
|
|
|
|
new TwigFunction( 'call_user_func', [ $this, 'callUserFunc' ], [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'fn', [ $this, 'callFunction' ] ),
|
Fix 10 known bugs: catalog, single product, and account pages (v0.1.5)
Catalog: page title via woocommerce_page_title(), breadcrumbs, category
template rename (underscore), 3-column grid, single chevron on sort.
Single product: variable form data attributes + disabled CSS class fix
(WC JS only toggles CSS classes, not HTML disabled attribute), dark mode
select specificity (0,5,1) to beat WC's (0,4,3) background shorthand,
gallery main image in thumbnail strip with empty URL guard, related/
upsells setup_postdata for correct global $product, grouped product
loop logic rewrite.
Account: downloads via wc_get_customer_available_downloads().
New: product-gallery.js, sanitize_title filter, wc_setup_product_data()
and wp_reset_postdata() Twig functions, product-thumbnails.html.twig
suppressor. Removed obsolete PLAN.md and SETUP.md.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:33:31 +01:00
|
|
|
|
|
|
|
|
// Product loop helpers (set global $product for WC hooks in Twig loops).
|
|
|
|
|
new TwigFunction( 'wc_setup_product_data', [ $this, 'setupProductData' ] ),
|
|
|
|
|
new TwigFunction( 'wp_reset_postdata', 'wp_reset_postdata' ),
|
2026-02-28 11:15:59 +01:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* WooCommerce-specific functions.
|
|
|
|
|
*
|
|
|
|
|
* @return TwigFunction[]
|
|
|
|
|
*/
|
|
|
|
|
private function getWooCommerceFunctions(): array {
|
|
|
|
|
return [
|
|
|
|
|
// URL functions.
|
|
|
|
|
new TwigFunction( 'wc_get_cart_url', 'wc_get_cart_url' ),
|
|
|
|
|
new TwigFunction( 'wc_get_checkout_url', 'wc_get_checkout_url' ),
|
|
|
|
|
new TwigFunction( 'wc_get_page_permalink', 'wc_get_page_permalink' ),
|
|
|
|
|
new TwigFunction( 'wc_get_endpoint_url', 'wc_get_endpoint_url' ),
|
|
|
|
|
new TwigFunction( 'wc_get_account_endpoint_url', 'wc_get_account_endpoint_url' ),
|
|
|
|
|
new TwigFunction( 'wc_logout_url', 'wc_logout_url' ),
|
|
|
|
|
|
|
|
|
|
// Boolean helpers.
|
|
|
|
|
new TwigFunction( 'wc_coupons_enabled', 'wc_coupons_enabled' ),
|
|
|
|
|
new TwigFunction( 'wc_shipping_enabled', 'wc_shipping_enabled' ),
|
|
|
|
|
new TwigFunction( 'wc_ship_to_billing_address_only', 'wc_ship_to_billing_address_only' ),
|
|
|
|
|
new TwigFunction( 'wc_terms_and_conditions_checkbox_enabled', 'wc_terms_and_conditions_checkbox_enabled' ),
|
|
|
|
|
|
|
|
|
|
// Order functions.
|
|
|
|
|
new TwigFunction( 'wc_get_order', 'wc_get_order' ),
|
|
|
|
|
new TwigFunction( 'wc_get_order_status_name', 'wc_get_order_status_name' ),
|
|
|
|
|
new TwigFunction( 'wc_format_datetime', 'wc_format_datetime' ),
|
|
|
|
|
new TwigFunction( 'wc_date_format', 'wc_date_format' ),
|
|
|
|
|
|
|
|
|
|
// Product functions.
|
|
|
|
|
new TwigFunction( 'wc_attribute_label', 'wc_attribute_label' ),
|
|
|
|
|
new TwigFunction( 'wc_placeholder_img_src', 'wc_placeholder_img_src' ),
|
|
|
|
|
new TwigFunction( 'wc_get_image_size', 'wc_get_image_size' ),
|
|
|
|
|
|
|
|
|
|
// Account functions.
|
|
|
|
|
new TwigFunction( 'wc_get_account_menu_items', 'wc_get_account_menu_items' ),
|
|
|
|
|
new TwigFunction( 'wc_get_account_menu_item_classes', 'wc_get_account_menu_item_classes' ),
|
|
|
|
|
new TwigFunction( 'wc_get_account_orders_columns', 'wc_get_account_orders_columns' ),
|
|
|
|
|
new TwigFunction( 'wc_get_account_orders_actions', 'wc_get_account_orders_actions' ),
|
|
|
|
|
new TwigFunction( 'wc_get_account_payment_methods_columns', 'wc_get_account_payment_methods_columns' ),
|
|
|
|
|
new TwigFunction( 'wc_get_account_formatted_address', 'wc_get_account_formatted_address', [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'wc_get_customer_saved_methods_list', 'wc_get_customer_saved_methods_list' ),
|
|
|
|
|
new TwigFunction( 'wc_get_credit_card_type_label', 'wc_get_credit_card_type_label' ),
|
|
|
|
|
|
|
|
|
|
// Content/form functions (echo-based, need output capture).
|
|
|
|
|
new TwigFunction( 'wc_print_notices', [ $this, 'wcPrintNotices' ], [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'wc_display_item_meta', [ $this, 'wcDisplayItemMeta' ], [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'wc_query_string_form_fields', [ $this, 'wcQueryStringFormFields' ], [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'woocommerce_form_field', [ $this, 'woocommerceFormField' ], [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'woocommerce_breadcrumb', function ( array $args = [] ): string {
|
|
|
|
|
ob_start();
|
|
|
|
|
woocommerce_breadcrumb( $args );
|
|
|
|
|
return ob_get_clean();
|
|
|
|
|
}, [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'woocommerce_quantity_input', function ( array $args = [], $product = null ): string {
|
|
|
|
|
ob_start();
|
|
|
|
|
woocommerce_quantity_input( $args, $product, true );
|
|
|
|
|
return ob_get_clean();
|
|
|
|
|
}, [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'woocommerce_product_loop_start', function (): string {
|
|
|
|
|
return woocommerce_product_loop_start( false );
|
|
|
|
|
}, [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'woocommerce_product_loop_end', function (): string {
|
|
|
|
|
return woocommerce_product_loop_end( false );
|
|
|
|
|
}, [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
|
|
|
|
|
// Text/policy functions.
|
|
|
|
|
new TwigFunction( 'wc_terms_and_conditions_checkbox_text', 'wc_terms_and_conditions_checkbox_text', [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'wc_replace_policy_page_link_placeholders', 'wc_replace_policy_page_link_placeholders', [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
new TwigFunction( 'wc_get_privacy_policy_text', 'wc_get_privacy_policy_text', [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
|
|
|
|
|
// Data helpers.
|
|
|
|
|
new TwigFunction( 'wc_get_post_data_by_key', 'wc_get_post_data_by_key' ),
|
|
|
|
|
new TwigFunction( 'wc_get_page_id', 'wc_get_page_id' ),
|
|
|
|
|
|
|
|
|
|
// Template recursion (renders a WC template and returns HTML).
|
|
|
|
|
new TwigFunction( 'wc_get_template', [ $this, 'wcGetTemplate' ], [ 'is_safe' => [ 'html' ] ] ),
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
// Method implementations for functions that need special handling.
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Execute a WordPress action hook and capture its output.
|
|
|
|
|
*
|
|
|
|
|
* Actions may echo HTML (e.g., rendering sub-templates). Output buffering
|
|
|
|
|
* captures this so it can be returned as a Twig-safe string.
|
|
|
|
|
*
|
|
|
|
|
* @param string $tag Action hook name.
|
|
|
|
|
* @param mixed ...$args Arguments to pass to the hook.
|
|
|
|
|
* @return string Captured HTML output.
|
|
|
|
|
*/
|
|
|
|
|
public function doAction( string $tag, ...$args ): string {
|
|
|
|
|
ob_start();
|
|
|
|
|
do_action( $tag, ...$args );
|
|
|
|
|
return ob_get_clean();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Apply WordPress filters.
|
|
|
|
|
*
|
|
|
|
|
* @param string $tag Filter hook name.
|
|
|
|
|
* @param mixed ...$args Arguments (first is the value to filter).
|
|
|
|
|
* @return mixed Filtered value.
|
|
|
|
|
*/
|
|
|
|
|
public function applyFilters( string $tag, ...$args ): mixed {
|
|
|
|
|
return apply_filters( $tag, ...$args );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Call a user function and capture its output.
|
|
|
|
|
*
|
|
|
|
|
* Used for tab callbacks that echo content.
|
|
|
|
|
*
|
|
|
|
|
* @param callable $callback Function to call.
|
|
|
|
|
* @param mixed ...$args Arguments.
|
|
|
|
|
* @return string Captured output.
|
|
|
|
|
*/
|
|
|
|
|
public function callUserFunc( callable $callback, ...$args ): string {
|
|
|
|
|
ob_start();
|
|
|
|
|
call_user_func( $callback, ...$args );
|
|
|
|
|
return ob_get_clean();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2026-03-01 01:02:43 +01:00
|
|
|
* Allowlist of PHP functions that can be called via fn() in Twig templates.
|
|
|
|
|
*
|
|
|
|
|
* Prevents arbitrary function execution (e.g., exec, system) if template
|
|
|
|
|
* context were ever compromised. Only functions actually used in templates
|
|
|
|
|
* are permitted.
|
|
|
|
|
*/
|
|
|
|
|
private const ALLOWED_FUNCTIONS = [
|
|
|
|
|
'WC',
|
|
|
|
|
'_n',
|
|
|
|
|
'get_pagenum_link',
|
|
|
|
|
'wc_review_ratings_enabled',
|
|
|
|
|
'wc_get_product_category_list',
|
|
|
|
|
'wc_get_product_tag_list',
|
Fix 10 known bugs: catalog, single product, and account pages (v0.1.5)
Catalog: page title via woocommerce_page_title(), breadcrumbs, category
template rename (underscore), 3-column grid, single chevron on sort.
Single product: variable form data attributes + disabled CSS class fix
(WC JS only toggles CSS classes, not HTML disabled attribute), dark mode
select specificity (0,5,1) to beat WC's (0,4,3) background shorthand,
gallery main image in thumbnail strip with empty URL guard, related/
upsells setup_postdata for correct global $product, grouped product
loop logic rewrite.
Account: downloads via wc_get_customer_available_downloads().
New: product-gallery.js, sanitize_title filter, wc_setup_product_data()
and wp_reset_postdata() Twig functions, product-thumbnails.html.twig
suppressor. Removed obsolete PLAN.md and SETUP.md.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:33:31 +01:00
|
|
|
'woocommerce_page_title',
|
|
|
|
|
'wc_get_customer_available_downloads',
|
2026-03-01 01:02:43 +01:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Call a whitelisted PHP function by name and return its result.
|
2026-02-28 11:15:59 +01:00
|
|
|
*
|
|
|
|
|
* Enables `fn('WC')` in templates to access the WooCommerce singleton
|
|
|
|
|
* and chain method calls via Twig's property accessor.
|
|
|
|
|
*
|
2026-03-01 01:02:43 +01:00
|
|
|
* Only functions in the ALLOWED_FUNCTIONS list can be called. This prevents
|
|
|
|
|
* arbitrary code execution if template context were ever compromised.
|
|
|
|
|
*
|
2026-02-28 11:15:59 +01:00
|
|
|
* @param string $name Function name.
|
|
|
|
|
* @param mixed ...$args Arguments.
|
|
|
|
|
* @return mixed Function return value.
|
|
|
|
|
*
|
2026-03-01 01:02:43 +01:00
|
|
|
* @throws \RuntimeException If function is not allowed or does not exist.
|
2026-02-28 11:15:59 +01:00
|
|
|
*/
|
|
|
|
|
public function callFunction( string $name, ...$args ): mixed {
|
2026-03-01 01:02:43 +01:00
|
|
|
if ( ! in_array( $name, self::ALLOWED_FUNCTIONS, true ) ) {
|
|
|
|
|
throw new \RuntimeException( "Function {$name} is not allowed. Add it to ALLOWED_FUNCTIONS." );
|
|
|
|
|
}
|
2026-02-28 11:15:59 +01:00
|
|
|
if ( ! function_exists( $name ) ) {
|
|
|
|
|
throw new \RuntimeException( "Function {$name} does not exist." );
|
|
|
|
|
}
|
|
|
|
|
return $name( ...$args );
|
|
|
|
|
}
|
|
|
|
|
|
Fix 10 known bugs: catalog, single product, and account pages (v0.1.5)
Catalog: page title via woocommerce_page_title(), breadcrumbs, category
template rename (underscore), 3-column grid, single chevron on sort.
Single product: variable form data attributes + disabled CSS class fix
(WC JS only toggles CSS classes, not HTML disabled attribute), dark mode
select specificity (0,5,1) to beat WC's (0,4,3) background shorthand,
gallery main image in thumbnail strip with empty URL guard, related/
upsells setup_postdata for correct global $product, grouped product
loop logic rewrite.
Account: downloads via wc_get_customer_available_downloads().
New: product-gallery.js, sanitize_title filter, wc_setup_product_data()
and wp_reset_postdata() Twig functions, product-thumbnails.html.twig
suppressor. Removed obsolete PLAN.md and SETUP.md.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:33:31 +01:00
|
|
|
/**
|
|
|
|
|
* Set up global product data for WC hook-based rendering in Twig loops.
|
|
|
|
|
*
|
|
|
|
|
* WooCommerce hooks (woocommerce_before_shop_loop_item, etc.) read from
|
|
|
|
|
* the global $product. When iterating products in Twig (related, upsells),
|
|
|
|
|
* the global must be updated before rendering each product card.
|
|
|
|
|
*
|
|
|
|
|
* @param \WC_Product $product Product object.
|
|
|
|
|
* @return string Empty string (Twig requires a return value).
|
|
|
|
|
*/
|
|
|
|
|
public function setupProductData( \WC_Product $product ): string {
|
|
|
|
|
$GLOBALS['product'] = $product;
|
|
|
|
|
$post = get_post( $product->get_id() );
|
|
|
|
|
if ( $post ) {
|
|
|
|
|
setup_postdata( $GLOBALS['post'] = $post );
|
|
|
|
|
}
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-28 11:15:59 +01:00
|
|
|
/**
|
|
|
|
|
* Capture wc_print_notices() output.
|
|
|
|
|
*
|
|
|
|
|
* @return string Rendered notices HTML.
|
|
|
|
|
*/
|
|
|
|
|
public function wcPrintNotices(): string {
|
|
|
|
|
ob_start();
|
|
|
|
|
wc_print_notices();
|
|
|
|
|
return ob_get_clean();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Render item meta without echoing.
|
|
|
|
|
*
|
|
|
|
|
* @param mixed $item WC_Order_Item object.
|
|
|
|
|
* @param array $args Display arguments.
|
|
|
|
|
* @return string Rendered meta HTML.
|
|
|
|
|
*/
|
|
|
|
|
public function wcDisplayItemMeta( $item, array $args = [] ): string {
|
|
|
|
|
$args['echo'] = false;
|
|
|
|
|
return wc_display_item_meta( $item, $args );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Render query string form fields and return HTML.
|
|
|
|
|
*
|
|
|
|
|
* @param mixed $values Values array or null.
|
|
|
|
|
* @param array $exclude Keys to exclude.
|
|
|
|
|
* @param string $currentKey Current key prefix.
|
|
|
|
|
* @return string Hidden input fields HTML.
|
|
|
|
|
*/
|
|
|
|
|
public function wcQueryStringFormFields( $values = null, array $exclude = [], string $currentKey = '' ): string {
|
|
|
|
|
return wc_query_string_form_fields( $values, $exclude, $currentKey, true );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Render a WooCommerce form field and return HTML.
|
|
|
|
|
*
|
|
|
|
|
* @param string $key Field key.
|
|
|
|
|
* @param array $args Field arguments.
|
|
|
|
|
* @param mixed $value Field value.
|
|
|
|
|
* @return string Rendered field HTML.
|
|
|
|
|
*/
|
|
|
|
|
public function woocommerceFormField( string $key, array $args, $value = null ): string {
|
|
|
|
|
$args['return'] = true;
|
|
|
|
|
return woocommerce_form_field( $key, $args, $value );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Render a WooCommerce template and return its HTML.
|
|
|
|
|
*
|
|
|
|
|
* Enables recursive template calls from within Twig templates.
|
|
|
|
|
* The rendered template goes through the same interception pipeline,
|
|
|
|
|
* so it will use the Twig version if one exists.
|
|
|
|
|
*
|
|
|
|
|
* @param string $templateName Template name (e.g., 'order/order-downloads.php').
|
|
|
|
|
* @param array $args Template context variables.
|
|
|
|
|
* @return string Rendered HTML.
|
|
|
|
|
*/
|
|
|
|
|
public function wcGetTemplate( string $templateName, array $args = [] ): string {
|
|
|
|
|
ob_start();
|
|
|
|
|
wc_get_template( $templateName, $args );
|
|
|
|
|
return ob_get_clean();
|
|
|
|
|
}
|
|
|
|
|
}
|