html_output */ public static function capture_hooks($context, $args = []) { $captured = []; // Filter hooks based on context $context_hooks = self::get_context_hooks($context); foreach ($context_hooks as $hook) { // Start output buffering ob_start(); // Setup context (e.g., global $product for product hooks) self::setup_context($context, $args); // Execute the hook do_action($hook); // Capture output $output = ob_get_clean(); // Only include hooks that have output if (!empty(trim($output))) { $captured[$hook] = $output; } // Cleanup context self::cleanup_context($context); } return $captured; } /** * Get hooks for a specific context */ private static function get_context_hooks($context) { $context_map = [ 'product' => [ 'woocommerce_before_single_product', 'woocommerce_before_single_product_summary', 'woocommerce_single_product_summary', 'woocommerce_before_add_to_cart_form', 'woocommerce_before_add_to_cart_button', 'woocommerce_after_add_to_cart_button', 'woocommerce_after_add_to_cart_form', 'woocommerce_product_meta_start', 'woocommerce_product_meta_end', 'woocommerce_after_single_product_summary', 'woocommerce_after_single_product', ], 'shop' => [ 'woocommerce_before_shop_loop', 'woocommerce_after_shop_loop', 'woocommerce_before_shop_loop_item', 'woocommerce_after_shop_loop_item', ], 'cart' => [ 'woocommerce_before_cart', 'woocommerce_before_cart_table', 'woocommerce_cart_collaterals', 'woocommerce_after_cart', ], 'checkout' => [ 'woocommerce_before_checkout_form', 'woocommerce_checkout_before_customer_details', 'woocommerce_checkout_after_customer_details', 'woocommerce_after_checkout_form', ], ]; return $context_map[$context] ?? []; } /** * Setup context for hook execution */ private static function setup_context($context, $args) { global $product, $post; switch ($context) { case 'product': if (isset($args['product_id'])) { $product = wc_get_product($args['product_id']); $post = get_post($args['product_id']); setup_postdata($post); } break; case 'shop': // Setup shop context if needed break; case 'cart': // Ensure cart is loaded if (!WC()->cart) { WC()->cart = new \WC_Cart(); } break; case 'checkout': // Ensure checkout is loaded if (!WC()->checkout()) { WC()->checkout = new \WC_Checkout(); } break; } } /** * Cleanup context after hook execution */ private static function cleanup_context($context) { global $product, $post; switch ($context) { case 'product': wp_reset_postdata(); $product = null; break; } } /** * Register REST API endpoint for hook capture */ public static function register_routes() { register_rest_route('woonoow/v1', '/hooks/(?P[a-z]+)', [ 'methods' => 'GET', 'callback' => [__CLASS__, 'get_hooks'], 'permission_callback' => '__return_true', 'args' => [ 'context' => [ 'required' => true, 'type' => 'string', 'enum' => ['product', 'shop', 'cart', 'checkout'], ], 'product_id' => [ 'type' => 'integer', ], ], ]); } /** * REST API callback to get hooks */ public static function get_hooks($request) { $context = $request->get_param('context'); $args = []; // Get context-specific args if ($context === 'product') { $args['product_id'] = $request->get_param('product_id'); } $hooks = self::capture_hooks($context, $args); return rest_ensure_response([ 'success' => true, 'context' => $context, 'hooks' => $hooks, ]); } }