AI
1 year ago
AIContent
1 year ago
Assets
1 year ago
BlockTypes
1 year ago
Domain
1 year ago
Images
2 years ago
Integrations
2 years ago
Interactivity
1 year ago
Patterns
1 year ago
Payments
1 year ago
Registry
2 years ago
Shipping
1 year ago
Templates
1 year ago
Utils
1 year ago
Assets.php
2 years ago
AssetsController.php
1 year ago
BlockPatterns.php
1 year ago
BlockTemplatesController.php
1 year ago
BlockTemplatesRegistry.php
1 year ago
BlockTypesController.php
1 year ago
InboxNotifications.php
2 years ago
Installer.php
1 year ago
Library.php
2 years ago
Migration.php
2 years ago
Options.php
2 years ago
Package.php
1 year ago
QueryFilters.php
1 year ago
TemplateOptions.php
1 year ago
BlockTypesController.php
581 lines
| 1 | <?php |
| 2 | declare(strict_types=1); |
| 3 | |
| 4 | namespace Automattic\WooCommerce\Blocks; |
| 5 | |
| 6 | use Automattic\WooCommerce\Admin\Features\Features; |
| 7 | use Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry; |
| 8 | use Automattic\WooCommerce\Blocks\Assets\Api as AssetApi; |
| 9 | use Automattic\WooCommerce\Blocks\Integrations\IntegrationRegistry; |
| 10 | use Automattic\WooCommerce\Blocks\BlockTypes\Cart; |
| 11 | use Automattic\WooCommerce\Blocks\BlockTypes\Checkout; |
| 12 | use Automattic\WooCommerce\Blocks\BlockTypes\MiniCartContents; |
| 13 | |
| 14 | /** |
| 15 | * BlockTypesController class. |
| 16 | * |
| 17 | * @since 5.0.0 |
| 18 | * @internal |
| 19 | */ |
| 20 | final class BlockTypesController { |
| 21 | |
| 22 | /** |
| 23 | * Instance of the asset API. |
| 24 | * |
| 25 | * @var AssetApi |
| 26 | */ |
| 27 | protected $asset_api; |
| 28 | |
| 29 | /** |
| 30 | * Instance of the asset data registry. |
| 31 | * |
| 32 | * @var AssetDataRegistry |
| 33 | */ |
| 34 | protected $asset_data_registry; |
| 35 | |
| 36 | /** |
| 37 | * Holds the registered blocks that have WooCommerce blocks as their parents. |
| 38 | * |
| 39 | * @var array List of registered blocks. |
| 40 | */ |
| 41 | private $registered_blocks_with_woocommerce_parents; |
| 42 | |
| 43 | /** |
| 44 | * Constructor. |
| 45 | * |
| 46 | * @param AssetApi $asset_api Instance of the asset API. |
| 47 | * @param AssetDataRegistry $asset_data_registry Instance of the asset data registry. |
| 48 | */ |
| 49 | public function __construct( AssetApi $asset_api, AssetDataRegistry $asset_data_registry ) { |
| 50 | $this->asset_api = $asset_api; |
| 51 | $this->asset_data_registry = $asset_data_registry; |
| 52 | $this->init(); |
| 53 | } |
| 54 | |
| 55 | /** |
| 56 | * Initialize class features. |
| 57 | */ |
| 58 | protected function init() { // phpcs:ignore WooCommerce.Functions.InternalInjectionMethod.MissingPublic |
| 59 | add_action( 'init', array( $this, 'register_blocks' ) ); |
| 60 | add_action( 'wp_loaded', array( $this, 'register_block_patterns' ) ); |
| 61 | add_filter( 'block_categories_all', array( $this, 'register_block_categories' ), 10, 2 ); |
| 62 | add_filter( 'render_block', array( $this, 'add_data_attributes' ), 10, 2 ); |
| 63 | add_action( 'woocommerce_login_form_end', array( $this, 'redirect_to_field' ) ); |
| 64 | add_filter( 'widget_types_to_hide_from_legacy_widget_block', array( $this, 'hide_legacy_widgets_with_block_equivalent' ) ); |
| 65 | add_action( 'woocommerce_delete_product_transients', array( $this, 'delete_product_transients' ) ); |
| 66 | } |
| 67 | |
| 68 | /** |
| 69 | * Get registered blocks that have WooCommerce blocks as their parents. Adds the value to the |
| 70 | * `registered_blocks_with_woocommerce_parents` cache if `init` has been fired. |
| 71 | * |
| 72 | * @return array Registered blocks with WooCommerce blocks as parents. |
| 73 | */ |
| 74 | public function get_registered_blocks_with_woocommerce_parent() { |
| 75 | // If init has run and the cache is already set, return it. |
| 76 | if ( did_action( 'init' ) && ! empty( $this->registered_blocks_with_woocommerce_parents ) ) { |
| 77 | return $this->registered_blocks_with_woocommerce_parents; |
| 78 | } |
| 79 | |
| 80 | $registered_blocks = \WP_Block_Type_Registry::get_instance()->get_all_registered(); |
| 81 | |
| 82 | if ( ! is_array( $registered_blocks ) ) { |
| 83 | return array(); |
| 84 | } |
| 85 | |
| 86 | $this->registered_blocks_with_woocommerce_parents = array_filter( |
| 87 | $registered_blocks, |
| 88 | function ( $block ) { |
| 89 | if ( empty( $block->parent ) ) { |
| 90 | return false; |
| 91 | } |
| 92 | if ( ! is_array( $block->parent ) ) { |
| 93 | $block->parent = array( $block->parent ); |
| 94 | } |
| 95 | $woocommerce_blocks = array_filter( |
| 96 | $block->parent, |
| 97 | function ( $parent_block_name ) { |
| 98 | return 'woocommerce' === strtok( $parent_block_name, '/' ); |
| 99 | } |
| 100 | ); |
| 101 | return ! empty( $woocommerce_blocks ); |
| 102 | } |
| 103 | ); |
| 104 | return $this->registered_blocks_with_woocommerce_parents; |
| 105 | } |
| 106 | |
| 107 | /** |
| 108 | * Register blocks, hooking up assets and render functions as needed. |
| 109 | */ |
| 110 | public function register_blocks() { |
| 111 | $this->register_block_metadata(); |
| 112 | $block_types = $this->get_block_types(); |
| 113 | |
| 114 | foreach ( $block_types as $block_type ) { |
| 115 | $block_type_class = __NAMESPACE__ . '\\BlockTypes\\' . $block_type; |
| 116 | |
| 117 | new $block_type_class( $this->asset_api, $this->asset_data_registry, new IntegrationRegistry() ); |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | /** |
| 122 | * Register block metadata collections for WooCommerce blocks. |
| 123 | * |
| 124 | * This method handles the registration of block metadata by using WordPress's block metadata |
| 125 | * collection registration system. It includes a temporary workaround for WordPress 6.7's |
| 126 | * strict path validation that might fail for sites using symlinked plugins. |
| 127 | * |
| 128 | * If the registration fails due to path validation, blocks will fall back to regular |
| 129 | * registration without affecting functionality. |
| 130 | */ |
| 131 | public function register_block_metadata() { |
| 132 | $meta_file_path = WC_ABSPATH . 'assets/client/blocks/blocks-json.php'; |
| 133 | if ( function_exists( 'wp_register_block_metadata_collection' ) && file_exists( $meta_file_path ) ) { |
| 134 | add_filter( 'doing_it_wrong_trigger_error', array( __CLASS__, 'bypass_block_metadata_doing_it_wrong' ), 10, 4 ); |
| 135 | wp_register_block_metadata_collection( |
| 136 | WC_ABSPATH . 'assets/client/blocks/', |
| 137 | $meta_file_path |
| 138 | ); |
| 139 | remove_filter( 'doing_it_wrong_trigger_error', array( __CLASS__, 'bypass_block_metadata_doing_it_wrong' ), 10 ); |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | /** |
| 144 | * Temporarily bypasses _doing_it_wrong() notices for block metadata collection registration. |
| 145 | * |
| 146 | * WordPress 6.7 introduced block metadata collections (with strict path validation). |
| 147 | * Any sites using symlinks for plugins will fail the validation which causes the metadata |
| 148 | * collection to not be registered. However, the blocks will still fall back to the regular |
| 149 | * registration and no functionality is affected. |
| 150 | * While this validation is being discussed in WordPress Core (#62140), |
| 151 | * this method allows registration to proceed by temporarily disabling |
| 152 | * the relevant notice. |
| 153 | * |
| 154 | * @param bool $trigger Whether to trigger the error. |
| 155 | * @param string $function The function that was called. |
| 156 | * @param string $message A message explaining what was done incorrectly. |
| 157 | * @param string $version The version of WordPress where the message was added. |
| 158 | * @return bool Whether to trigger the error. |
| 159 | */ |
| 160 | public static function bypass_block_metadata_doing_it_wrong( $trigger, $function, $message, $version ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable,Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed,Universal.NamingConventions.NoReservedKeywordParameterNames.functionFound |
| 161 | if ( 'WP_Block_Metadata_Registry::register_collection' === $function ) { |
| 162 | return false; |
| 163 | } |
| 164 | return $trigger; |
| 165 | } |
| 166 | |
| 167 | /** |
| 168 | * Register block patterns |
| 169 | */ |
| 170 | public function register_block_patterns() { |
| 171 | register_block_pattern( |
| 172 | 'woocommerce/order-confirmation-totals-heading', |
| 173 | array( |
| 174 | 'title' => '', |
| 175 | 'inserter' => false, |
| 176 | 'content' => '<!-- wp:heading {"level":2,"style":{"typography":{"fontSize":"24px"}}} --><h2 class="wp-block-heading" style="font-size:24px">' . esc_html__( 'Order details', 'woocommerce' ) . '</h2><!-- /wp:heading -->', |
| 177 | ) |
| 178 | ); |
| 179 | register_block_pattern( |
| 180 | 'woocommerce/order-confirmation-downloads-heading', |
| 181 | array( |
| 182 | 'title' => '', |
| 183 | 'inserter' => false, |
| 184 | 'content' => '<!-- wp:heading {"level":2,"style":{"typography":{"fontSize":"24px"}}} --><h2 class="wp-block-heading" style="font-size:24px">' . esc_html__( 'Downloads', 'woocommerce' ) . '</h2><!-- /wp:heading -->', |
| 185 | ) |
| 186 | ); |
| 187 | register_block_pattern( |
| 188 | 'woocommerce/order-confirmation-shipping-heading', |
| 189 | array( |
| 190 | 'title' => '', |
| 191 | 'inserter' => false, |
| 192 | 'content' => '<!-- wp:heading {"level":2,"style":{"typography":{"fontSize":"24px"}}} --><h2 class="wp-block-heading" style="font-size:24px">' . esc_html__( 'Shipping address', 'woocommerce' ) . '</h2><!-- /wp:heading -->', |
| 193 | ) |
| 194 | ); |
| 195 | register_block_pattern( |
| 196 | 'woocommerce/order-confirmation-billing-heading', |
| 197 | array( |
| 198 | 'title' => '', |
| 199 | 'inserter' => false, |
| 200 | 'content' => '<!-- wp:heading {"level":2,"style":{"typography":{"fontSize":"24px"}}} --><h2 class="wp-block-heading" style="font-size:24px">' . esc_html__( 'Billing address', 'woocommerce' ) . '</h2><!-- /wp:heading -->', |
| 201 | ) |
| 202 | ); |
| 203 | register_block_pattern( |
| 204 | 'woocommerce/order-confirmation-additional-fields-heading', |
| 205 | array( |
| 206 | 'title' => '', |
| 207 | 'inserter' => false, |
| 208 | 'content' => '<!-- wp:heading {"level":2,"style":{"typography":{"fontSize":"24px"}}} --><h2 class="wp-block-heading" style="font-size:24px">' . esc_html__( 'Additional information', 'woocommerce' ) . '</h2><!-- /wp:heading -->', |
| 209 | ) |
| 210 | ); |
| 211 | } |
| 212 | |
| 213 | /** |
| 214 | * Register block categories |
| 215 | * |
| 216 | * Used in combination with the `block_categories_all` filter, to append |
| 217 | * WooCommerce Blocks related categories to the Gutenberg editor. |
| 218 | * |
| 219 | * @param array $categories The array of already registered categories. |
| 220 | */ |
| 221 | public function register_block_categories( $categories ) { |
| 222 | $woocommerce_block_categories = array( |
| 223 | array( |
| 224 | 'slug' => 'woocommerce', |
| 225 | 'title' => __( 'WooCommerce', 'woocommerce' ), |
| 226 | ), |
| 227 | array( |
| 228 | 'slug' => 'woocommerce-product-elements', |
| 229 | 'title' => __( 'WooCommerce Product Elements', 'woocommerce' ), |
| 230 | ), |
| 231 | ); |
| 232 | |
| 233 | return array_merge( $categories, $woocommerce_block_categories ); |
| 234 | } |
| 235 | |
| 236 | /** |
| 237 | * Check if a block should have data attributes appended on render. If it's in an allowed namespace, or the block |
| 238 | * has explicitly been added to the allowed block list, or if one of the block's parents is in the WooCommerce |
| 239 | * namespace it can have data attributes. |
| 240 | * |
| 241 | * @param string $block_name Name of the block to check. |
| 242 | * |
| 243 | * @return boolean |
| 244 | */ |
| 245 | public function block_should_have_data_attributes( $block_name ) { |
| 246 | $block_namespace = strtok( $block_name ?? '', '/' ); |
| 247 | |
| 248 | /** |
| 249 | * Filters the list of allowed block namespaces. |
| 250 | * |
| 251 | * This hook defines which block namespaces should have block name and attribute `data-` attributes appended on render. |
| 252 | * |
| 253 | * @since 5.9.0 |
| 254 | * |
| 255 | * @param array $allowed_namespaces List of namespaces. |
| 256 | */ |
| 257 | $allowed_namespaces = array_merge( array( 'woocommerce', 'woocommerce-checkout' ), (array) apply_filters( '__experimental_woocommerce_blocks_add_data_attributes_to_namespace', array() ) ); |
| 258 | |
| 259 | /** |
| 260 | * Filters the list of allowed Block Names |
| 261 | * |
| 262 | * This hook defines which block names should have block name and attribute data- attributes appended on render. |
| 263 | * |
| 264 | * @since 5.9.0 |
| 265 | * |
| 266 | * @param array $allowed_namespaces List of namespaces. |
| 267 | */ |
| 268 | $allowed_blocks = (array) apply_filters( '__experimental_woocommerce_blocks_add_data_attributes_to_block', array() ); |
| 269 | |
| 270 | $blocks_with_woo_parents = $this->get_registered_blocks_with_woocommerce_parent(); |
| 271 | $block_has_woo_parent = in_array( $block_name, array_keys( $blocks_with_woo_parents ), true ); |
| 272 | $in_allowed_namespace_list = in_array( $block_namespace, $allowed_namespaces, true ); |
| 273 | $in_allowed_block_list = in_array( $block_name, $allowed_blocks, true ); |
| 274 | |
| 275 | return $block_has_woo_parent || $in_allowed_block_list || $in_allowed_namespace_list; |
| 276 | } |
| 277 | |
| 278 | /** |
| 279 | * Add data- attributes to blocks when rendered if the block is under the woocommerce/ namespace. |
| 280 | * |
| 281 | * @param string $content Block content. |
| 282 | * @param array $block Parsed block data. |
| 283 | * @return string |
| 284 | */ |
| 285 | public function add_data_attributes( $content, $block ) { |
| 286 | |
| 287 | $content = trim( $content ); |
| 288 | |
| 289 | if ( ! $this->block_should_have_data_attributes( $block['blockName'] ) ) { |
| 290 | return $content; |
| 291 | } |
| 292 | |
| 293 | $attributes = (array) $block['attrs']; |
| 294 | $exclude_attributes = array( 'className', 'align' ); |
| 295 | |
| 296 | $processor = new \WP_HTML_Tag_Processor( $content ); |
| 297 | |
| 298 | if ( |
| 299 | false === $processor->next_token() || |
| 300 | 'DIV' !== $processor->get_token_name() || |
| 301 | $processor->is_tag_closer() |
| 302 | ) { |
| 303 | return $content; |
| 304 | } |
| 305 | |
| 306 | foreach ( $attributes as $key => $value ) { |
| 307 | if ( ! is_string( $key ) || in_array( $key, $exclude_attributes, true ) ) { |
| 308 | continue; |
| 309 | } |
| 310 | if ( is_bool( $value ) ) { |
| 311 | $value = $value ? 'true' : 'false'; |
| 312 | } |
| 313 | if ( ! is_scalar( $value ) ) { |
| 314 | $value = wp_json_encode( $value ); |
| 315 | } |
| 316 | |
| 317 | // For output consistency, we convert camelCase to kebab-case and output in lowercase. |
| 318 | $key = strtolower( preg_replace( '/(?<!^|\ )[A-Z]/', '-$0', $key ) ); |
| 319 | |
| 320 | $processor->set_attribute( "data-{$key}", $value ); |
| 321 | } |
| 322 | |
| 323 | // Set this last to prevent user-input from overriding it. |
| 324 | $processor->set_attribute( 'data-block-name', $block['blockName'] ); |
| 325 | return $processor->get_updated_html(); |
| 326 | } |
| 327 | |
| 328 | /** |
| 329 | * Adds a redirect field to the login form so blocks can redirect users after login. |
| 330 | */ |
| 331 | public function redirect_to_field() { |
| 332 | // phpcs:ignore WordPress.Security.NonceVerification |
| 333 | if ( empty( $_GET['redirect_to'] ) ) { |
| 334 | return; |
| 335 | } |
| 336 | echo '<input type="hidden" name="redirect" value="' . esc_attr( esc_url_raw( wp_unslash( $_GET['redirect_to'] ) ) ) . '" />'; // phpcs:ignore WordPress.Security.NonceVerification |
| 337 | } |
| 338 | |
| 339 | /** |
| 340 | * Hide legacy widgets with a feature complete block equivalent in the inserter |
| 341 | * and prevent them from showing as an option in the Legacy Widget block. |
| 342 | * |
| 343 | * @param array $widget_types An array of widgets hidden in core. |
| 344 | * @return array $widget_types An array including the WooCommerce widgets to hide. |
| 345 | */ |
| 346 | public function hide_legacy_widgets_with_block_equivalent( $widget_types ) { |
| 347 | array_push( |
| 348 | $widget_types, |
| 349 | 'woocommerce_product_search', |
| 350 | 'woocommerce_product_categories', |
| 351 | 'woocommerce_recent_reviews', |
| 352 | 'woocommerce_product_tag_cloud', |
| 353 | 'woocommerce_price_filter', |
| 354 | 'woocommerce_layered_nav', |
| 355 | 'woocommerce_layered_nav_filters', |
| 356 | 'woocommerce_rating_filter' |
| 357 | ); |
| 358 | |
| 359 | return $widget_types; |
| 360 | } |
| 361 | |
| 362 | /** |
| 363 | * Delete product transients when a product is deleted. |
| 364 | */ |
| 365 | public function delete_product_transients() { |
| 366 | delete_transient( 'wc_blocks_has_downloadable_product' ); |
| 367 | } |
| 368 | |
| 369 | /** |
| 370 | * Get list of block types allowed in Widget Areas. New blocks won't be |
| 371 | * exposed in the Widget Area unless specifically added here. |
| 372 | * |
| 373 | * @return array Array of block types. |
| 374 | */ |
| 375 | protected function get_widget_area_block_types() { |
| 376 | return array( |
| 377 | 'ActiveFilters', |
| 378 | 'AllReviews', |
| 379 | 'AttributeFilter', |
| 380 | 'Breadcrumbs', |
| 381 | 'CartLink', |
| 382 | 'CatalogSorting', |
| 383 | 'ClassicShortcode', |
| 384 | 'CustomerAccount', |
| 385 | 'FeaturedCategory', |
| 386 | 'FeaturedProduct', |
| 387 | 'FilterWrapper', |
| 388 | 'MiniCart', |
| 389 | 'PriceFilter', |
| 390 | 'ProductCategories', |
| 391 | 'ProductResultsCount', |
| 392 | 'ProductSearch', |
| 393 | 'RatingFilter', |
| 394 | 'ReviewsByCategory', |
| 395 | 'ReviewsByProduct', |
| 396 | 'StockFilter', |
| 397 | // Below product grids are hidden from inserter however they could have been used in widgets. |
| 398 | // Keep them for backward compatibility. |
| 399 | 'HandpickedProducts', |
| 400 | 'ProductBestSellers', |
| 401 | 'ProductNew', |
| 402 | 'ProductOnSale', |
| 403 | 'ProductTopRated', |
| 404 | 'ProductsByAttribute', |
| 405 | 'ProductCategory', |
| 406 | 'ProductTag', |
| 407 | ); |
| 408 | } |
| 409 | |
| 410 | /** |
| 411 | * Get list of block types. |
| 412 | * |
| 413 | * @return array |
| 414 | */ |
| 415 | protected function get_block_types() { |
| 416 | global $pagenow; |
| 417 | |
| 418 | $block_types = array( |
| 419 | 'ActiveFilters', |
| 420 | 'AddToCartForm', |
| 421 | 'AllProducts', |
| 422 | 'AllReviews', |
| 423 | 'AttributeFilter', |
| 424 | 'Breadcrumbs', |
| 425 | 'CartLink', |
| 426 | 'CatalogSorting', |
| 427 | 'ClassicTemplate', |
| 428 | 'ClassicShortcode', |
| 429 | 'ComingSoon', |
| 430 | 'CustomerAccount', |
| 431 | 'FeaturedCategory', |
| 432 | 'FeaturedProduct', |
| 433 | 'FilterWrapper', |
| 434 | 'HandpickedProducts', |
| 435 | 'MiniCart', |
| 436 | 'StoreNotices', |
| 437 | 'PriceFilter', |
| 438 | 'ProductBestSellers', |
| 439 | 'ProductButton', |
| 440 | 'ProductCategories', |
| 441 | 'ProductCategory', |
| 442 | 'ProductCollection\Controller', |
| 443 | 'ProductCollection\NoResults', |
| 444 | 'ProductGallery', |
| 445 | 'ProductGalleryLargeImage', |
| 446 | 'ProductGalleryLargeImageNextPrevious', |
| 447 | 'ProductGalleryPager', |
| 448 | 'ProductGalleryThumbnails', |
| 449 | 'ProductImage', |
| 450 | 'ProductImageGallery', |
| 451 | 'ProductMeta', |
| 452 | 'ProductNew', |
| 453 | 'ProductOnSale', |
| 454 | 'ProductPrice', |
| 455 | 'ProductTemplate', |
| 456 | 'ProductQuery', |
| 457 | 'ProductAverageRating', |
| 458 | 'ProductRating', |
| 459 | 'ProductRatingCounter', |
| 460 | 'ProductRatingStars', |
| 461 | 'ProductResultsCount', |
| 462 | 'ProductReviews', |
| 463 | 'ProductSaleBadge', |
| 464 | 'ProductSearch', |
| 465 | 'ProductSKU', |
| 466 | 'ProductStockIndicator', |
| 467 | 'ProductSummary', |
| 468 | 'ProductTag', |
| 469 | 'ProductTitle', |
| 470 | 'ProductTopRated', |
| 471 | 'ProductsByAttribute', |
| 472 | 'RatingFilter', |
| 473 | 'ReviewsByCategory', |
| 474 | 'ReviewsByProduct', |
| 475 | 'RelatedProducts', |
| 476 | 'ProductDetails', |
| 477 | 'SingleProduct', |
| 478 | 'StockFilter', |
| 479 | 'PageContentWrapper', |
| 480 | 'OrderConfirmation\Status', |
| 481 | 'OrderConfirmation\Summary', |
| 482 | 'OrderConfirmation\Totals', |
| 483 | 'OrderConfirmation\TotalsWrapper', |
| 484 | 'OrderConfirmation\Downloads', |
| 485 | 'OrderConfirmation\DownloadsWrapper', |
| 486 | 'OrderConfirmation\BillingAddress', |
| 487 | 'OrderConfirmation\ShippingAddress', |
| 488 | 'OrderConfirmation\BillingWrapper', |
| 489 | 'OrderConfirmation\ShippingWrapper', |
| 490 | 'OrderConfirmation\AdditionalInformation', |
| 491 | 'OrderConfirmation\AdditionalFieldsWrapper', |
| 492 | 'OrderConfirmation\AdditionalFields', |
| 493 | 'OrderConfirmation\CreateAccount', |
| 494 | ); |
| 495 | |
| 496 | $block_types = array_merge( |
| 497 | $block_types, |
| 498 | Cart::get_cart_block_types(), |
| 499 | Checkout::get_checkout_block_types(), |
| 500 | MiniCartContents::get_mini_cart_block_types() |
| 501 | ); |
| 502 | |
| 503 | // Update plugins/woocommerce-blocks/docs/internal-developers/blocks/feature-flags-and-experimental-interfaces.md |
| 504 | // when modifying this list. |
| 505 | if ( Features::is_enabled( 'experimental-blocks' ) ) { |
| 506 | $block_types[] = 'ProductFilters'; |
| 507 | $block_types[] = 'ProductFilterStatus'; |
| 508 | $block_types[] = 'ProductFilterPrice'; |
| 509 | $block_types[] = 'ProductFilterPriceSlider'; |
| 510 | $block_types[] = 'ProductFilterAttribute'; |
| 511 | $block_types[] = 'ProductFilterRating'; |
| 512 | $block_types[] = 'ProductFilterActive'; |
| 513 | $block_types[] = 'ProductFilterRemovableChips'; |
| 514 | $block_types[] = 'ProductFilterClearButton'; |
| 515 | $block_types[] = 'ProductFilterCheckboxList'; |
| 516 | $block_types[] = 'ProductFilterChips'; |
| 517 | if ( Features::is_enabled( 'blockified-add-to-cart' ) && wc_current_theme_is_fse_theme() ) { |
| 518 | $block_types[] = 'AddToCartWithOptions'; |
| 519 | $block_types[] = 'AddToCartWithOptionsQuantitySelector'; |
| 520 | $block_types[] = 'AddToCartWithOptionsVariationSelector'; |
| 521 | $block_types[] = 'AddToCartWithOptionsGroupedProductSelector'; |
| 522 | $block_types[] = 'AddToCartWithOptionsGroupedProductSelectorItemTemplate'; |
| 523 | } |
| 524 | // Generic blocks that will be pushed upstream. |
| 525 | $block_types[] = 'Accordion\AccordionGroup'; |
| 526 | $block_types[] = 'Accordion\AccordionItem'; |
| 527 | $block_types[] = 'Accordion\AccordionPanel'; |
| 528 | $block_types[] = 'Accordion\AccordionHeader'; |
| 529 | $block_types[] = 'BlockifiedProductDetails'; |
| 530 | } |
| 531 | |
| 532 | /** |
| 533 | * This enables specific blocks in Widget Areas using an opt-in approach. |
| 534 | */ |
| 535 | if ( in_array( $pagenow, array( 'widgets.php', 'themes.php', 'customize.php' ), true ) && ( empty( $_GET['page'] ) || 'gutenberg-edit-site' !== $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification |
| 536 | $block_types = array_intersect( |
| 537 | $block_types, |
| 538 | $this->get_widget_area_block_types() |
| 539 | ); |
| 540 | } |
| 541 | |
| 542 | /** |
| 543 | * This disables specific blocks in Post and Page editor by not registering them. |
| 544 | */ |
| 545 | if ( in_array( $pagenow, array( 'post.php', 'post-new.php' ), true ) ) { |
| 546 | $block_types = array_diff( |
| 547 | $block_types, |
| 548 | array( |
| 549 | 'Breadcrumbs', |
| 550 | 'CatalogSorting', |
| 551 | 'ClassicTemplate', |
| 552 | 'ProductResultsCount', |
| 553 | 'ProductDetails', |
| 554 | 'OrderConfirmation\Status', |
| 555 | 'OrderConfirmation\Summary', |
| 556 | 'OrderConfirmation\Totals', |
| 557 | 'OrderConfirmation\TotalsWrapper', |
| 558 | 'OrderConfirmation\Downloads', |
| 559 | 'OrderConfirmation\DownloadsWrapper', |
| 560 | 'OrderConfirmation\BillingAddress', |
| 561 | 'OrderConfirmation\ShippingAddress', |
| 562 | 'OrderConfirmation\BillingWrapper', |
| 563 | 'OrderConfirmation\ShippingWrapper', |
| 564 | 'OrderConfirmation\AdditionalInformation', |
| 565 | 'OrderConfirmation\AdditionalFieldsWrapper', |
| 566 | 'OrderConfirmation\AdditionalFields', |
| 567 | ) |
| 568 | ); |
| 569 | } |
| 570 | |
| 571 | /** |
| 572 | * Filters the list of allowed block types. |
| 573 | * |
| 574 | * @since 9.0.0 |
| 575 | * |
| 576 | * @param array $block_types List of block types. |
| 577 | */ |
| 578 | return apply_filters( 'woocommerce_get_block_types', $block_types ); |
| 579 | } |
| 580 | } |
| 581 |