context()->post_id : (function_exists('get_the_ID') ? (int) get_the_ID() : 0); $found = self::get($context_id); if ($found) { return $found; } $global = $GLOBALS['product'] ?? null; if (self::is_product($global)) { return $global; } if ($context_id > 0 && TemplatePost::is_template($context_id)) { $found = self::get(TemplatePost::preview_post($context_id)); if ($found) { return $found; } } return self::previewing() ? self::latest() : null; } /** @return \WC_Product|null */ public static function get(int $id): ?object { if ($id <= 0 || !function_exists('wc_get_product')) { return null; } $product = wc_get_product($id); return self::is_product($product) ? $product : null; } public static function is_product($value): bool { return is_object($value) && method_exists($value, 'get_id') && method_exists($value, 'get_type'); } /** Editor requests: REST previews (POST /render) and the canvas page. */ public static function previewing(): bool { return (defined('REST_REQUEST') && REST_REQUEST) || \Zadex\Editor\EditorLoader::mode() !== ''; } /** @return \WC_Product|null */ public static function latest(): ?object { if (!function_exists('get_posts')) { return null; } $ids = get_posts(['post_type' => 'product', 'post_status' => 'publish', 'numberposts' => 1, 'orderby' => 'date', 'order' => 'DESC', 'fields' => 'ids']); return $ids ? self::get((int) $ids[0]) : null; } /** * Runs $fn with $product as the global product / post and returns its output (echo or return value). * * @param \WC_Product $product */ public static function with(object $product, callable $fn): string { $prev_product = $GLOBALS['product'] ?? null; $prev_product_id = self::is_product($prev_product) ? (int) $prev_product->get_id() : 0; $target = function_exists('get_post') ? get_post($product->get_id()) : null; // The product's post becomes the current post (PostData) and WooCommerce sets its global product itself. $returned = null; $echoed = (string) PostData::with($target, static function () use ($product, $target, $fn, &$returned): string { if ($target && function_exists('wc_setup_product_data')) { wc_setup_product_data($target); } ob_start(); try { $returned = $fn($product); } finally { $echoed = (string) ob_get_clean(); } return $echoed; }); // Back to the product that was current before (or none): WooCommerce's own setup again. if (function_exists('wc_setup_product_data')) { wc_setup_product_data($prev_product_id > 0 ? $prev_product_id : 0); } return $echoed . (is_string($returned) ? $returned : ''); } /** Editor-only placeholder shown when no product can be found. */ public static function placeholder(string $attrs): string { if (!self::previewing()) { return ''; } return '
' . esc_html__('No product to preview. Publish a product or choose one in "Preview with".', 'zadex') . '