* * Other settable fields include: * * - Description * - Viewport Width * - Categories (comma-separated values) * - Keywords (comma-separated values) * - Block Types (comma-separated values) * - Inserter (yes/no) * * @internal */ class BlockPatterns { const CATEGORIES_PREFIXES = [ '_woo_', '_dotcom_imported_' ]; /** * Path to the patterns' directory. * * @var string $patterns_path */ private string $patterns_path; /** * PatternRegistry instance. * * @var PatternRegistry $pattern_registry */ private PatternRegistry $pattern_registry; /** * Patterns dictionary * * @var array|WP_Error */ private $dictionary; /** * PTKPatternsStore instance. * * @var PTKPatternsStore $ptk_patterns_store */ private PTKPatternsStore $ptk_patterns_store; /** * Constructor for class * * @param Package $package An instance of Package. * @param PatternRegistry $pattern_registry An instance of PatternRegistry. * @param PTKPatternsStore $ptk_patterns_store An instance of PTKPatternsStore. */ public function __construct( Package $package, PatternRegistry $pattern_registry, PTKPatternsStore $ptk_patterns_store ) { $this->patterns_path = $package->get_path( 'patterns' ); $this->pattern_registry = $pattern_registry; $this->ptk_patterns_store = $ptk_patterns_store; add_action( 'init', array( $this, 'register_block_patterns' ) ); if ( Features::is_enabled( 'pattern-toolkit-full-composability' ) ) { add_action( 'init', array( $this, 'register_ptk_patterns' ) ); } } /** * Returns the Patterns dictionary. * * @return array|WP_Error */ private function get_patterns_dictionary() { if ( null === $this->dictionary ) { $this->dictionary = PatternsHelper::get_patterns_dictionary(); } return $this->dictionary; } /** * Register block patterns from core. * * @return void */ public function register_block_patterns() { if ( ! class_exists( 'WP_Block_Patterns_Registry' ) ) { return; } $default_headers = array( 'title' => 'Title', 'slug' => 'Slug', 'description' => 'Description', 'viewportWidth' => 'Viewport Width', 'categories' => 'Categories', 'keywords' => 'Keywords', 'blockTypes' => 'Block Types', 'inserter' => 'Inserter', 'featureFlag' => 'Feature Flag', ); if ( ! file_exists( $this->patterns_path ) ) { return; } $files = glob( $this->patterns_path . '/*.php' ); if ( ! $files ) { return; } foreach ( $files as $file ) { $pattern_data = get_file_data( $file, $default_headers ); $this->pattern_registry->register_block_pattern( $file, $pattern_data, $this->get_patterns_dictionary() ); } } /** * Register patterns from the Patterns Toolkit. * * @return void */ public function register_ptk_patterns() { // Only if the user has allowed tracking, we register the patterns from the PTK. $allow_tracking = 'yes' === get_option( 'woocommerce_allow_tracking' ); if ( ! $allow_tracking ) { return; } // The most efficient way to check for an existing action is to use `as_has_scheduled_action`, but in unusual // cases where another plugin has loaded a very old version of Action Scheduler, it may not be available to us. $has_scheduled_action = function_exists( 'as_has_scheduled_action' ) ? 'as_has_scheduled_action' : 'as_next_scheduled_action'; $patterns = $this->ptk_patterns_store->get_patterns(); if ( empty( $patterns ) ) { // By only logging when patterns are empty and no fetch is scheduled, // we ensure that warnings are only generated in genuinely problematic situations, // such as when the pattern fetching mechanism has failed entirely. if ( ! call_user_func( $has_scheduled_action, 'fetch_patterns' ) ) { wc_get_logger()->warning( __( 'Empty patterns received from the PTK Pattern Store', 'woocommerce' ), ); } return; } $patterns = $this->parse_categories( $patterns ); foreach ( $patterns as $pattern ) { $pattern['slug'] = $pattern['name']; $pattern['content'] = $pattern['html']; $this->pattern_registry->register_block_pattern( $pattern['ID'], $pattern, $this->get_patterns_dictionary() ); } } /** * Parse prefixed categories from the PTK patterns into the actual WooCommerce categories. * * @param array $patterns The patterns to parse. * @return array The parsed patterns. */ private function parse_categories( array $patterns ) { return array_map( function ( $pattern ) { $pattern['categories'] = array_map( function ( $category ) { foreach ( self::CATEGORIES_PREFIXES as $prefix ) { if ( strpos( $category['title'], $prefix ) !== false ) { $parsed_category = str_replace( $prefix, '', $category['title'] ); $parsed_category = str_replace( '_', ' ', $parsed_category ); $category['title'] = ucfirst( $parsed_category ); } } return $category; }, $pattern['categories'] ); return $pattern; }, $patterns ); } }