Completed
Branch Gutenberg/master (3b2a95)
by
unknown
118:45 queued 105:17
created

BlockRegistrationManager::matchesRoute()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace EventEspresso\core\services\editor;
4
5
use EventEspresso\core\domain\entities\editor\BlockCollection;
6
use EventEspresso\core\domain\entities\editor\BlockInterface;
7
use EventEspresso\core\exceptions\ExceptionStackTraceDisplay;
8
use EventEspresso\core\exceptions\InvalidClassException;
9
use EventEspresso\core\exceptions\InvalidEntityException;
10
use EventEspresso\core\services\assets\BlockAssetManagerCollection;
11
use EventEspresso\core\services\collections\CollectionDetails;
12
use EventEspresso\core\services\collections\CollectionDetailsException;
13
use EventEspresso\core\services\collections\CollectionInterface;
14
use EventEspresso\core\services\collections\CollectionLoader;
15
use EventEspresso\core\services\collections\CollectionLoaderException;
16
use EventEspresso\core\services\request\RequestInterface;
17
use EventEspresso\core\services\route_match\RouteMatchSpecificationManager;
18
use Exception;
19
use WP_Block_Type;
20
21
/**
22
 * Class BlockRegistrationManager
23
 * Loads BlockInterface classes into the injected BlockCollection,
24
 * which can be used in other classes by retrieving it from EE's Loader.
25
 * After loading, the BlockManager gets each Block to register
26
 * its block type and ensures assets are enqueued at the appropriate time
27
 *
28
 * @package EventEspresso\core\domain\services\editor
29
 * @author  Brent Christensen
30
 * @since   $VID:$
31
 */
32
class BlockRegistrationManager extends BlockManager
33
{
34
35
    /**
36
     * @var BlockAssetManagerCollection $block_asset_manager_collection
37
     */
38
    protected $block_asset_manager_collection;
39
40
    /**
41
     * @var RouteMatchSpecificationManager $route_manager
42
     */
43
    protected $route_manager;
44
45
    /**
46
     * array for tracking asset managers required by blocks for the current route
47
     *
48
     * @var array $block_asset_managers
49
     */
50
    protected $block_asset_managers = array();
51
52
53
    /**
54
     * BlockRegistrationManager constructor.
55
     *
56
     * @param BlockAssetManagerCollection    $block_asset_manager_collection
57
     * @param BlockCollection                $blocks
58
     * @param RouteMatchSpecificationManager $route_manager
59
     * @param RequestInterface               $request
60
     */
61
    public function __construct(
62
        BlockAssetManagerCollection $block_asset_manager_collection,
63
        BlockCollection $blocks,
64
        RouteMatchSpecificationManager $route_manager,
65
        RequestInterface $request
66
    ) {
67
        $this->block_asset_manager_collection = $block_asset_manager_collection;
68
        $this->route_manager = $route_manager;
69
        parent::__construct($blocks, $request);
70
    }
71
72
73
    /**
74
     *  Returns the name of a hookpoint to be used to call initialize()
75
     *
76
     * @return string
77
     */
78
    public function initHook()
79
    {
80
        return 'AHEE__EE_System__initialize';
81
    }
82
83
84
    /**
85
     * Perform any early setup required for block editors to functions
86
     *
87
     * @return void
88
     * @throws Exception
89
     */
90
    public function initialize()
91
    {
92
        $this->initializeBlocks();
93
        add_action('AHEE__EE_System__initialize_last', array($this, 'registerBlocks'));
94
        add_action('wp_loaded', array($this, 'unloadAssets'));
95
    }
96
97
98
    /**
99
     * @return CollectionInterface|BlockInterface[]
100
     * @throws CollectionLoaderException
101
     * @throws CollectionDetailsException
102
     */
103
    protected function populateBlockCollection()
104
    {
105
        $loader = new CollectionLoader(
106
            new CollectionDetails(
107
                // collection name
108
                'editor_blocks',
109
                // collection interface
110
                'EventEspresso\core\domain\entities\editor\BlockInterface',
111
                // FQCNs for classes to add (all classes within each namespace will be loaded)
112
                apply_filters(
113
                    'FHEE__EventEspresso_core_services_editor_BlockManager__populateBlockCollection__collection_FQCNs',
114
                    array(
115
                        // 'EventEspresso\core\domain\entities\editor\blocks\common',
116
                        // 'EventEspresso\core\domain\entities\editor\blocks\editor',
117
                        // 'EventEspresso\core\domain\entities\editor\blocks\widgets',
118
                    )
119
                ),
120
                // filepaths to classes to add
121
                array(),
122
                // file mask to use if parsing folder for files to add
123
                '',
124
                // what to use as identifier for collection entities
125
                // using CLASS NAME prevents duplicates (works like a singleton)
126
                CollectionDetails::ID_CLASS_NAME
127
            ),
128
            $this->blocks
129
        );
130
        return $loader->getCollection();
131
    }
132
133
134
    /**
135
     * populates the BlockCollection and calls initialize() on all installed blocks
136
     *
137
     * @return void
138
     * @throws Exception
139
     */
140
    public function initializeBlocks()
141
    {
142
        try {
143
            $this->populateBlockCollection();
144
            // cycle thru block loaders and initialize each loader
145
            foreach ($this->blocks as $block) {
146
                $block->initialize();
147
                $this->trackAssetManagersForBlocks($block);
148
                if (! $this->block_asset_manager_collection->has($block->assetManager())) {
149
                    $this->block_asset_manager_collection->add($block->assetManager());
150
                    $block->assetManager()->setAssetHandles();
151
                }
152
            }
153
        } catch (Exception $exception) {
154
            new ExceptionStackTraceDisplay($exception);
155
        }
156
    }
157
158
159
    /**
160
     * track blocks with routes that match the current request
161
     *
162
     * @param BlockInterface $block
163
     * @throws InvalidClassException
164
     */
165
    private function trackAssetManagersForBlocks(BlockInterface $block)
166
    {
167
        $supported_routes = $block->supportedRoutes();
168
        foreach ($supported_routes as $supported_route) {
169
            if ($this->route_manager->routeMatchesCurrentRequest($supported_route)) {
170
                $this->block_asset_managers[ $block->blockType() ] = $block->assetManager()->assetNamespace();
171
            }
172
        }
173
    }
174
175
176
    /**
177
     * returns true if the block should be registered for the current request
178
     * else removes block from block_routes array and returns false
179
     *
180
     * @param BlockInterface $block
181
     * @return boolean
182
     * @throws InvalidClassException
183
     */
184
    public function matchesRoute(BlockInterface $block)
185
    {
186
        if (isset($this->block_asset_managers[ $block->blockType() ])) {
187
            return true;
188
        }
189
        unset($this->block_asset_managers[ $block->blockType() ]);
190
        return false;
191
    }
192
193
194
    /**
195
     * calls registerBlock() and load assets for all installed blocks
196
     *
197
     * @return void
198
     * @throws Exception
199
     */
200
    public function registerBlocks()
201
    {
202
        try {
203
            // cycle thru block loader folders
204
            foreach ($this->blocks as $block) {
205
                if (! $this->matchesRoute($block)) {
206
                    continue;
207
                }
208
                // perform any setup required for the block
209
                $block_type = $block->registerBlock();
210
                if (! $block_type instanceof WP_Block_Type) {
0 ignored issues
show
Bug introduced by
The class WP_Block_Type does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
211
                    throw new InvalidEntityException($block_type, 'WP_Block_Type');
212
                }
213
                do_action(
214
                    'FHEE__EventEspresso_core_services_editor_BlockManager__registerBlocks__block_type_registered',
215
                    $block,
216
                    $block_type
217
                );
218
            }
219
        } catch (Exception $exception) {
220
            new ExceptionStackTraceDisplay($exception);
221
        }
222
    }
223
224
    public function unloadAssets()
225
    {
226
        $assets = array_flip($this->block_asset_managers);
227
        foreach ($this->block_asset_manager_collection as $asset_manager) {
228
            // if there are no longer any blocks that require these assets,
229
            if (! isset($assets[ $asset_manager->assetNamespace() ])) {
230
                // then unset asset enqueueing and bail
231
                remove_action('wp_enqueue_scripts', array($asset_manager, 'addManifestFile'), 0);
232
                remove_action('admin_enqueue_scripts', array($asset_manager, 'addManifestFile'), 0);
233
                remove_action('wp_enqueue_scripts', array($asset_manager, 'addAssets'), 2);
234
                remove_action('admin_enqueue_scripts', array($asset_manager, 'addAssets'), 2);
235
            }
236
        }
237
    }
238
}
239