configFactory = new ViewerConfig($materials); } public function register(): void { add_shortcode('ds82_3d_print_showcase', [$this, 'shortcode']); add_action('woocommerce_product_thumbnails', fn () => $this->render_for_position('gallery'), 99); add_action('woocommerce_before_single_product_summary', fn () => $this->render_for_position('after_gallery'), 30); add_action('woocommerce_before_add_to_cart_form', fn () => $this->render_for_position('before_cart'), 5); add_action('woocommerce_after_add_to_cart_form', fn () => $this->render_for_position('after_cart'), 20); add_filter('script_loader_tag', [$this, 'module_script_tag'], 10, 3); } public function shortcode(array $attributes = []): string { $attributes = shortcode_atts(['product_id' => 0, 'height' => 0], $attributes, 'ds82_3d_print_showcase'); $productId = absint($attributes['product_id']) ?: get_the_ID(); return $this->html($productId, ['height' => absint($attributes['height'])], true); } public function render_for_position(string $position): void { if (!is_product()) { return; } $productId = get_the_ID(); if ($this->configFactory->position($productId) !== $position) { return; } echo $this->html($productId, [], false); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } public function module_script_tag(string $tag, string $handle, string $src): string { if ('ds82-3dps-viewer' !== $handle || str_contains($tag, 'type=')) { return $tag; } return str_replace('