ount'] ) ? $cart_payload['items_count'] : null, null ); } /** * Temporary remove the this filter so $wp_scripts->print_translations * calls won't accident print the translations scripts for the block * when inserted as a widget. * * $wp_scripts->print_translations() calls load_script_textdomain() * which calls load_script_translations() containing the below filter. * * In Customzier, woocommerce_blocks_get_i18n_data_json doesn't exist * at the time of this filter call. So we need checking for its * existence to prevent fatal error. */ if ( function_exists( 'woocommerce_blocks_get_i18n_data_json' ) ) { remove_filter( 'pre_load_script_translations', 'woocommerce_blocks_get_i18n_data_json', 10, 4 ); } $script_data = $this->asset_api->get_script_data( 'build/mini-cart-component-frontend.js' ); $num_dependencies = count( $script_data['dependencies'] ); $wp_scripts = wp_scripts(); for ( $i = 0; $i < $num_dependencies; $i++ ) { $dependency = $script_data['dependencies'][ $i ]; foreach ( $wp_scripts->registered as $script ) { if ( $script->handle === $dependency ) { $this->append_script_and_deps_src( $script ); break; } } } $payment_method_registry = Package::container()->get( PaymentMethodRegistry::class ); $payment_methods = $payment_method_registry->get_all_active_payment_method_script_dependencies(); foreach ( $payment_methods as $payment_method ) { $payment_method_script = $this->get_script_from_handle( $payment_method ); if ( ! is_null( $payment_method_script ) ) { $this->append_script_and_deps_src( $payment_method_script ); } } $this->scripts_to_lazy_load['wc-block-mini-cart-component-frontend'] = array( 'src' => $script_data['src'], 'version' => $script_data['version'], 'translations' => $this->get_inner_blocks_translations(), ); // Re-add the filter. if ( function_exists( 'woocommerce_blocks_get_i18n_data_json' ) ) { add_filter( 'pre_load_script_translations', 'woocommerce_blocks_get_i18n_data_json', 10, 4 ); } $this->asset_data_registry->add( 'mini_cart_block_frontend_dependencies', $this->scripts_to_lazy_load, true ); $this->asset_data_registry->add( 'displayCartPricesIncludingTax', $this->display_cart_prices_including_tax, true ); $template_part_edit_uri = ''; if ( current_user_can( 'edit_theme_options' ) && function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() ) { $theme_slug = BlockTemplateUtils::theme_has_template_part( 'mini-cart' ) ? wp_get_theme()->get_stylesheet() : BlockTemplateUtils::PLUGIN_SLUG; $site_editor_uri = admin_url( 'site-editor.php' ); if ( version_compare( get_bloginfo( 'version' ), '5.9', '<' ) ) { $site_editor_uri = add_query_arg( array( 'page' => 'gutenberg-edit-site' ), admin_url( 'themes.php' ) ); } $template_part_edit_uri = add_query_arg( array( 'postId' => sprintf( '%s//%s', $theme_slug, 'mini-cart' ), 'postType' => 'wp_template_part', ), $site_editor_uri ); } $this->asset_data_registry->add( 'templatePartEditUri', $template_part_edit_uri, '' ); /** * Fires after cart block data is registered. */ do_action( 'woocommerce_blocks_cart_enqueue_data' ); } /** * Returns the script data given its handle. * * @param string $handle Handle of the script. * * @return \_WP_Dependency|null Object containing the script data if found, or null. */ protected function get_script_from_handle( $handle ) { $wp_scripts = wp_scripts(); foreach ( $wp_scripts->registered as $script ) { if ( $script->handle === $handle ) { return $script; } } return null; } /** * Recursively appends a scripts and its dependencies into the scripts_to_lazy_load array. * * @param \_WP_Dependency $script Object containing script data. */ protected function append_script_and_deps_src( $script ) { $wp_scripts = wp_scripts(); // This script and its dependencies have already been appended. if ( ! $script || array_key_exists( $script->handle, $this->scripts_to_lazy_load ) ) { return; } if ( count( $script->deps ) ) { foreach ( $script->deps as $dep ) { if ( ! array_key_exists( $dep, $this->scripts_to_lazy_load ) ) { $dep_script = $this->get_script_from_handle( $dep ); if ( ! is_null( $dep_script ) ) { $this->append_script_and_deps_src( $dep_script ); } } } } if ( ! $script->src ) { return; } $this->scripts_to_lazy_load[ $script->handle ] = array( 'src' => $script->src, 'version' => $script->ver, 'before' => $wp_scripts->print_inline_script( $script->handle, 'before', false ), 'after' => $wp_scripts->print_inline_script( $script->handle, 'after', false ), 'translations' => $wp_scripts->print_translations( $script->handle, false ), ); } /** * Returns the markup for render the tax label. * * @return string */ protected function get_include_tax_label_markup() { $cart_controller = $this->get_cart_controller(); $cart = $cart_controller->get_cart_instance(); $cart_contents_total = $cart->get_subtotal(); return ( ! empty( $this->tax_label ) && 0 !== $cart_contents_total ) ? ( "" . esc_html( $this->tax_label ) . '' ) : ''; } /** * Append frontend scripts when rendering the Mini Cart block. * * @param array $attributes Block attributes. * @param string $content Block content. * * @return string Rendered block type output. */ protected function render( $attributes, $content ) { return $content . $this->get_markup( $attributes ); } /** * Render the markup for the Mini Cart block. * * @param array $attributes Block attributes. * * @return string The HTML markup. */ protected function get_markup( $attributes ) { if ( is_admin() || WC()->is_rest_api_request() ) { // In the editor we will display the placeholder, so no need to load // real cart data and to print the markup. return ''; } $cart_controller = $this->get_cart_controller(); $cart = $cart_controller->get_cart_instance(); $cart_contents_count = $cart->get_cart_contents_count(); $cart_contents = $cart->get_cart(); $cart_contents_total = $cart->get_subtotal(); if ( $cart->display_prices_including_tax() ) { $cart_contents_total += $cart->get_subtotal_tax(); } $classes_styles = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes, array( 'text_color', 'background_color' ) ); $wrapper_classes = sprintf( 'wc-block-mini-cart wp-block-woocommerce-mini-cart %s', $classes_styles['classes'] ); $wrapper_styles = $classes_styles['styles']; $aria_label = sprintf( /* translators: %1$d is the number of products in the cart. %2$s is the cart total */ _n( '%1$d item in cart, total price of %2$s', '%1$d items in cart, total price of %2$s', $cart_contents_count, 'woocommerce' ), $cart_contents_count, wp_strip_all_tags( wc_price( $cart_contents_total ) ) ); $icon = ' '; $button_html = '' . esc_html( wp_strip_all_tags( wc_price( $cart_contents_total ) ) ) . ' ' . $this->get_include_tax_label_markup() . ' ' . $icon . ' ' . $cart_contents_count . ' '; if ( is_cart() || is_checkout() ) { // It is not necessary to load the Mini Cart Block on Cart and Checkout page. return ''; } $template_part_contents = ''; // Determine if we need to load the template part from the theme, or WooCommerce in that order. $theme_has_mini_cart = BlockTemplateUtils::theme_has_template_part( 'mini-cart' ); $template_slug_to_load = $theme_has_mini_cart ? get_stylesheet() : BlockTemplateUtils::PLUGIN_SLUG; $template_part = BlockTemplateUtils::get_block_template( $template_slug_to_load . '//mini-cart', 'wp_template_part' ); if ( $template_part && ! empty( $template_part->content ) ) { $template_part_contents = do_blocks( $template_part->content ); } if ( '' === $template_part_contents ) { $template_part_contents = do_blocks( // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents file_get_contents( Package::get_path() . 'templates/' . BlockTemplateUtils::DIRECTORY_NAMES['TEMPLATE_PARTS'] . '/mini-cart.html' ) ); } return '
'; } /** * Return an instace of the CartController class. * * @return CartController CartController class instance. */ protected function get_cart_controller() { return new CartController(); } /** * Get array with data for handle the tax label. * the entire logic of this function is was taken from: * https://github.com/woocommerce/woocommerce/blob/e730f7463c25b50258e97bf56e31e9d7d3bc7ae7/includes/class-wc-cart.php#L1582 * * @return array; */ protected function get_tax_label() { $cart = WC()->cart; if ( $cart->display_prices_including_tax() ) { if ( ! wc_prices_include_tax() ) { $tax_label = WC()->countries->inc_tax_or_vat(); $display_cart_prices_including_tax = true; return array( 'tax_label' => $tax_label, 'display_cart_prices_including_tax' => $display_cart_prices_including_tax, ); } return array( 'label_including_tax' => '', 'display_cart_prices_including_tax' => true, ); } if ( wc_prices_include_tax() ) { $tax_label = WC()->countries->ex_tax_or_vat(); return array( 'tax_label' => $tax_label, 'display_cart_prices_including_tax' => false, ); }; return array( 'tax_label' => '', 'display_cart_prices_including_tax' => false, ); } /** * Get Cart Payload. * * @return object; */ protected function get_cart_payload() { return WC()->api->get_endpoint_data( '/wc/store/cart' ); } /** * Prepare translations for inner blocks and dependencies. */ protected function get_inner_blocks_translations() { $wp_scripts = wp_scripts(); $translations = array(); $blocks = [ 'mini-cart-contents-block/filled-cart', 'mini-cart-contents-block/empty-cart', 'mini-cart-contents-block/title', 'mini-cart-contents-block/items', 'mini-cart-contents-block/products-table', 'mini-cart-contents-block/footer', 'mini-cart-contents-block/shopping-button', ]; $chunks = preg_filter( '/$/', '-frontend', $blocks ); foreach ( $chunks as $chunk ) { $handle = 'wc-blocks-' . $chunk . '-chunk'; $this->asset_api->register_script( $handle, $this->asset_api->get_block_asset_build_path( $chunk ), [], true ); $translations[] = $wp_scripts->print_translations( $handle, false ); wp_deregister_script( $handle ); } $translations = array_filter( $translations ); return implode( '', $translations ); } /** * Register block pattern for Empty Cart Message to make it translatable. */ public function register_empty_cart_message_block_pattern() { register_block_pattern( 'woocommerce/mini-cart-empty-cart-message', array( 'title' => __( 'Mini Cart Empty Cart Message', 'woocommerce' ), 'inserter' => false, 'content' => '

' . __( 'Your cart is currently empty!', 'woocommerce' ) . '

', ) ); } }