$template_area}_after_add_block_{$block_id}", [ $this, 'hook_block_template' ] ); } /** * Action hanlder for the 'init' hook. */ public function hook_init(): void { $build_path = "{$this->get_root_dir()}/js/build"; $uri = 'js/build/blocks'; $this->register_custom_blocks( BlockRegistry::get_instance(), $build_path, $uri, self::CUSTOM_BLOCKS ); } /** * Action hanlder for the "woocommerce_block_template_area_{$template_area}_after_add_block_{$block_id}" hook. * * @param BlockInterface $block The block just added to get its root template to add this extension's group and blocks. */ public function hook_block_template( BlockInterface $block ): void { /** @var Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates\ProductFormTemplateInterface */ $template = $block->get_root_template(); $is_variation_template = $this->is_variation_template( $block ); // Please note that the simple, variable, grouped, and external product types // use the same product block template 'simple-product'. Their dynamic hidden // conditions are added below. if ( 'simple-product' !== $template->get_id() && ! $is_variation_template ) { return; } /** @var Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates\GroupInterface */ $group = $template->add_group( [ 'id' => 'google-listings-and-ads-group', 'order' => 100, 'attributes' => [ 'title' => __( 'Google Listings & Ads', 'google-listings-and-ads' ), ], ] ); $visible_product_types = ProductSyncer::get_supported_product_types(); if ( $is_variation_template ) { // The property of `editedProduct.type` doesn't exist in the variation product. // The condition returned from `get_hide_condition` won't work, so it uses 'true' directly. if ( ! in_array( 'variation', $visible_product_types, true ) ) { $group->add_hide_condition( 'true' ); } } else { $group->add_hide_condition( $this->get_hide_condition( $visible_product_types ) ); } if ( ! $this->merchant_center->is_setup_complete() ) { $group->add_block( [ 'id' => 'google-listings-and-ads-product-onboarding-prompt', 'blockName' => 'google-listings-and-ads/product-onboarding-prompt', 'attributes' => [ 'startUrl' => $this->get_start_url(), ], ] ); return; } /** @var SectionInterface */ $channel_visibility_section = $group->add_section( [ 'id' => 'google-listings-and-ads-channel-visibility-section', 'order' => 1, 'attributes' => [ 'title' => __( 'Channel visibility', 'google-listings-and-ads' ), ], ] ); if ( ! $is_variation_template ) { $this->add_channel_visibility_block( $channel_visibility_section ); } // Add the hidden condition to the channel visibility section because it only has one block. $visible_product_types = $this->channel_visibility_block->get_visible_product_types(); $channel_visibility_section->add_hide_condition( $this->get_hide_condition( $visible_product_types ) ); /** @var SectionInterface */ $product_attributes_section = $group->add_section( [ 'id' => 'google-listings-and-ads-product-attributes-section', 'order' => 2, 'attributes' => [ 'title' => __( 'Product attributes', 'google-listings-and-ads' ), ], ] ); $this->add_product_attribute_blocks( $product_attributes_section ); } /** * Register the custom blocks and their assets. * * @param BlockRegistry $block_registry BlockRegistry instance getting from Woo Core for registering custom blocks. * @param string $build_path The absolute path to the build directory of the assets. * @param string $uri The script URI of the custom blocks. * @param string[] $custom_blocks The directory names of each custom block under the build path. */ public function register_custom_blocks( BlockRegistry $block_registry, string $build_path, string $uri, array $custom_blocks ): void { foreach ( $custom_blocks as $custom_block ) { $block_json_file = "{$build_path}/{$custom_block}/block.json"; if ( ! file_exists( $block_json_file ) ) { continue; } $block_registry->register_block_type_from_metadata( $block_json_file ); } $assets[] = new AdminScriptWithBuiltDependenciesAsset( 'google-listings-and-ads-product-blocks', $uri, "{$build_path}/blocks.asset.php", new BuiltScriptDependencyArray( [ 'dependencies' => [], 'version' => (string) filemtime( "{$build_path}/blocks.js" ), ] ) ); $assets[] = new AdminStyleAsset( 'google-listings-and-ads-product-blocks-css', $uri, [], (string) filemtime( "{$build_path}/blocks.css" ) ); $this->assets_handler->register_many( $assets ); $this->assets_handler->enqueue_many( $assets ); } /** * Add the channel visibility block to the given section block. * * @param SectionInterface $section The section block to add the channel visibility block */ private function add_channel_visibility_block( SectionInterface $section ): void { $section->add_block( $this->channel_visibility_block->get_block_config() ); } /** * Add product attribute blocks to the given section block. * * @param SectionInterface $section The section block to add product attribute blocks */ private function add_product_attribute_blocks( SectionInterface $section ): void { $is_variation_template = $this->is_variation_template( $section ); $product_types = $is_variation_template ? [ 'variation' ] : $this->get_applicable_product_types(); $attribute_types = $this->attribute_manager->get_attribute_types_for_product_types( $product_types ); foreach ( $attribute_types as $attribute_type ) { $input_type = call_user_func( [ $attribute_type, 'get_input_type' ] ); $input = AttributesForm::init_input( new $input_type(), new $attribute_type() ); if ( $is_variation_template ) { // When editing a variation, its product type on the frontend side won't be changed dynamically. // In addition, the property of `editedProduct.type` doesn't exist in the variation product. // Therefore, instead of using the ProductTemplates API `add_hide_condition` to conditionally // hide attributes, it doesn't add invisible attribute blocks from the beginning. if ( $this->is_visible_for_variation( $attribute_type ) ) { $section->add_block( $input->get_block_config() ); } } else { $visible_product_types = AttributesForm::get_attribute_product_types( $attribute_type )['visible']; // When editing a simple, variable, grouped, or external product, its product type on the // frontend side can be changed dynamically. So, it needs to use the ProductTemplates API // `add_hide_condition` to conditionally hide attributes. /** @var BlockInterface */ $block = $section->add_block( $input->get_block_config() ); $block->add_hide_condition( $this->get_hide_condition( $visible_product_types ) ); } } } /** * Determine if the product block template of the given block is the variation template. * * @param BlockInterface $block The block to be checked * * @return boolean */ private function is_variation_template( BlockInterface $block ): bool { return 'product-variation' === $block->get_root_template()->get_id(); } /** * Determine if the given attribute is visible for variation product after applying related filters. * * @param string $attribute_type An attribute class extending AttributeInterface * * @return bool */ private function is_visible_for_variation( string $attribute_type ): bool { $attribute_product_types = AttributesForm::get_attribute_product_types( $attribute_type ); return in_array( 'variation', $attribute_product_types['visible'], true ); } /** * Get the expression of the hide condition to a block based on the visible product types. * e.g. "editedProduct.type !== 'simple' && ! editedProduct.parent_id > 0" * * The hide condition is a JavaScript-like expression that will be evaluated on the client to determine if the block should be hidden. * See [@woocommerce/expression-evaluation](https://github.com/woocommerce/woocommerce/blob/trunk/packages/js/expression-evaluation/README.md) for more details. * * @param array $visible_product_types The visible product types to be converted to a hidden condition * * @return string */ public function get_hide_condition( array $visible_product_types ): string { $conditions = array_map( function ( $type ) { return "editedProduct.type !== '{$type}'"; }, $visible_product_types ); return implode( ' && ', $conditions ) ?: 'true'; } }
Warning: class_implements(): Class Automattic\WooCommerce\GoogleListingsAndAds\Admin\ProductBlocksService does not exist and could not be loaded in /htdocs/wp-content/plugins/google-listings-and-ads/src/Internal/DependencyManagement/AbstractServiceProvider.php on line 119

Fatal error: Uncaught TypeError: array_key_exists(): Argument #2 ($array) must be of type array, bool given in /htdocs/wp-content/plugins/google-listings-and-ads/src/Internal/DependencyManagement/AbstractServiceProvider.php:120 Stack trace: #0 /htdocs/wp-content/plugins/google-listings-and-ads/src/Internal/DependencyManagement/AbstractServiceProvider.php(120): array_key_exists('Automattic\\WooC...', false) #1 /htdocs/wp-content/plugins/google-listings-and-ads/src/Internal/DependencyManagement/CoreServiceProvider.php(329): Automattic\WooCommerce\GoogleListingsAndAds\Internal\DependencyManagement\AbstractServiceProvider->conditionally_share_with_tags('Automattic\\WooC...', 'Automattic\\WooC...', 'Automattic\\WooC...', 'Automattic\\WooC...', 'Automattic\\WooC...') #2 /htdocs/wp-content/plugins/google-listings-and-ads/vendor/league/container/src/ServiceProvider/ServiceProviderAggregate.php(102): Automattic\WooCommerce\GoogleListingsAndAds\Internal\DependencyManagement\CoreServiceProvider->register() #3 /htdocs/wp-content/plugins/google-listings-and-ads/vendor/league/container/src/Container.php(172): Automattic\WooCommerce\GoogleListingsAndAds\Vendor\League\Container\ServiceProvider\ServiceProviderAggregate->register('Automattic\\WooC...') #4 /htdocs/wp-content/plugins/google-listings-and-ads/src/Container.php(90): Automattic\WooCommerce\GoogleListingsAndAds\Vendor\League\Container\Container->get('Automattic\\WooC...') #5 /htdocs/wp-content/plugins/google-listings-and-ads/src/Infrastructure/GoogleListingsAndAdsPlugin.php(130): Automattic\WooCommerce\GoogleListingsAndAds\Container->get('Automattic\\WooC...') #6 /htdocs/wp-content/plugins/google-listings-and-ads/src/Infrastructure/GoogleListingsAndAdsPlugin.php(91): Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\GoogleListingsAndAdsPlugin->maybe_register_services() #7 /htdocs/wp-includes/class-wp-hook.php(324): Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\GoogleListingsAndAdsPlugin->Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\{closure}('') #8 /htdocs/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters(NULL, Array) #9 /htdocs/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #10 /htdocs/wp-settings.php(559): do_action('plugins_loaded') #11 /htdocs/wp-config.php(85): require_once('/htdocs/wp-sett...') #12 /htdocs/wp-load.php(50): require_once('/htdocs/wp-conf...') #13 /htdocs/wp-blog-header.php(13): require_once('/htdocs/wp-load...') #14 /htdocs/index.php(17): require('/htdocs/wp-blog...') #15 {main} thrown in /htdocs/wp-content/plugins/google-listings-and-ads/src/Internal/DependencyManagement/AbstractServiceProvider.php on line 120