/var/www/html_us/wp-content/plugins/woocommerce/src/Blocks/Utils/BlockHooksTrait.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php
namespace Automattic\WooCommerce\Blocks\Utils;

/**
 * BlockHooksTrait
 *
 * Shared functionality for using the Block Hooks API with WooCommerce Blocks.
 */
trait BlockHooksTrait {
    
/**
     * Callback for `hooked_block_types` to auto-inject the mini-cart block into headers after navigation.
     *
     * @param array                             $hooked_blocks An array of block slugs hooked into a given context.
     * @param string                            $position      Position of the block insertion point.
     * @param string                            $anchor_block  The block acting as the anchor for the inserted block.
     * @param array|\WP_Post|\WP_Block_Template $context       Where the block is embedded.
     * @since 8.5.0
     * @return array An array of block slugs hooked into a given context.
     */
    
public function register_hooked_block$hooked_blocks$position$anchor_block$context ) {
        
// If the block has no hook placements, return early.
        
if ( ! isset( $this->hooked_block_placements ) || empty( $this->hooked_block_placements ) ) {
            return 
$hooked_blocks;
        }

        
// Cache the block hooks version.
        
static $block_hooks_version null;
        if ( 
defined'WP_RUN_CORE_TESTS' ) || is_null$block_hooks_version ) ) {
            
$block_hooks_version get_option'woocommerce_hooked_blocks_version' );
        }

        
// If block hooks are disabled or the version is not set, return early.
        
if ( 'no' === $block_hooks_version || false === $block_hooks_version ) {
            return 
$hooked_blocks;
        }

        
// Valid placements are those that have no version specified,
        // or have a version that is less than or equal to version specified in the woocommerce_hooked_blocks_version option.
        
$valid_placements array_filter(
            
$this->hooked_block_placements,
            function ( 
$placement ) use ( $block_hooks_version ) {
                
$placement_version = isset( $placement['version'] ) ? $placement['version'] : null;
                return 
is_null$placement_version ) || ! is_null$placement_version ) && version_compare$block_hooks_version$placement_version'>=' );
            }
        );

        if ( 
$context && ! empty( $valid_placements ) ) {
            foreach ( 
$valid_placements as $placement ) {

                if ( 
$placement['position'] === $position && $placement['anchor'] === $anchor_block ) {
                    
// If an area has been specified for this placement.
                    
if (
                        isset( 
$placement['area'] ) &&
                        ! 
$this->has_block_in_content$context )
                        && 
$this->is_target_area$context$placement['area'] )
                    ) {
                        
$hooked_blocks[] = $this->namespace '/' $this->block_name;
                    }

                    
// If no area has been specified for this placement just insert the block.
                    // This is likely to be the case when we're inserting into the navigation block
                    // where we don't have a specific area to target.
                    
if ( ! isset( $placement['area'] ) ) {
                        
$hooked_blocks[] = $this->namespace '/' $this->block_name;
                    }

                    
// If a callback has been specified for this placement, call it. This allows for custom block-specific logic to be run.
                    
$callback = isset( $placement['callback'] ) && is_callable( array( $this$placement['callback'] ) ) ? array( $this$placement['callback'] ) : null;
                    if ( 
null !== $callback ) {
                        
$modified_hooked_blocks $callback$hooked_blocks$position$anchor_block$context );
                        if ( 
is_array$modified_hooked_blocks ) ) {
                            
$hooked_blocks $modified_hooked_blocks;
                        }
                    }
                }
            }
        }

        return 
$hooked_blocks;
    }

    
/**
     * Checks if the provided context contains a the block already.
     *
     * @param array|\WP_Block_Template $context Where the block is embedded.
     * @return boolean
     */
    
protected function has_block_in_content$context ) {
        
$content $this->get_context_content$context );
        return 
strpos$content'wp:' $this->namespace '/' $this->block_name ) !== false;
    }

    
/**
     * Given a provided context, returns the content of the context.
     *
     * @param array|\WP_Post|\WP_Block_Template $context Where the block is embedded.
     * @since 8.5.0
     * @return string
     */
    
protected function get_context_content$context ) {
        
$content is_array$context ) && isset( $context['content'] ) ? $context['content'] : '';
        
$content '' === $content && $context instanceof \WP_Block_Template $context->content $content;
        
$content '' === $content && $context instanceof \WP_Post $context->post_content $content;
        return 
$content;
    }

    
/**
     * Given a provided context, returns whether the context refers to header content.
     *
     * @param array|\WP_Post|\WP_Block_Template $context Where the block is embedded.
     * @param string                            $area The area to check against before inserting.
     * @since 8.5.0
     * @return boolean
     */
    
protected function is_template_part_or_pattern$context$area ) {
        
$is_pattern       is_array$context ) &&
        (
            ( isset( 
$context['blockTypes'] ) && in_array'core/template-part/' $area$context['blockTypes'], true ) ) ||
            ( isset( 
$context['categories'] ) && in_array$area$context['categories'], true ) )
        );
        
$is_template_part $context instanceof \WP_Block_Template && $area === $context->area;
        return ( 
$is_pattern || $is_template_part );
    }

    
/**
     * Given a provided context, returns whether the context refers to the target area and isn't marked as excluded.
     *
     * @param array|\WP_Post|\WP_Block_Template $context the context to check.
     * @param string                            $area The area to check against before inserting.
     * @since 8.5.0
     * @return boolean
     */
    
protected function is_target_area$context$area ) {
        if ( 
$this->is_template_part_or_pattern$context$area ) && ! $this->pattern_is_excluded$context ) ) {
            return 
true;
        }

        return 
false;
    }

    
/**
     * Returns whether the pattern is excluded or not
     *
     * @since 8.5.0
     *
     * @param array|\WP_Block_Template $context Where the block is embedded.
     * @return boolean
     */
    
protected function pattern_is_excluded$context ) {
        
/**
         * A list of pattern slugs to exclude from auto-insert (useful when there are patterns that have a very specific location for the block)
         * Note: The patterns that are currently excluded are the ones that don't work well with the mini-cart block or customer-account block.
         *
         * @since 8.5.0
         */
        
$pattern_exclude_list apply_filters(
            
'woocommerce_hooked_blocks_pattern_exclude_list',
            
array_uniquearray_merge( isset( $this->hooked_block_excluded_patterns ) ? $this->hooked_block_excluded_patterns : array(), array( 'twentytwentytwo/header-centered-logo''twentytwentytwo/header-stacked' ) ) )
        );

        
$pattern_slug is_array$context ) && isset( $context['slug'] ) ? $context['slug'] : '';
        if ( ! 
$pattern_slug ) {
            
/**
             * Woo patterns have a slug property in $context, but core/theme patterns dont.
             * In that case, we fallback to the name property, as they're the same.
             */
            
$pattern_slug is_array$context ) && isset( $context['name'] ) ? $context['name'] : '';
        }
        return 
in_array$pattern_slug$pattern_exclude_listtrue );
    }
}