PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / trunk
Pods – Custom Content Types and Fields vtrunk
trunk 1.14.8 2.7.31.3 2.8.23.3 2.9.19.3 3.0.10.3 3.1.4.1 3.2.0 3.2.1 3.2.1.1 3.2.2 3.2.4 3.2.5 3.2.6 3.2.7 3.2.7.1 3.2.8 3.2.8.1 3.2.8.2 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9
pods / src / Pods / Blocks / API.php
pods / src / Pods / Blocks Last commit date
Collections 4 months ago Types 4 months ago API.php 4 months ago Blocks_Abstract.php 4 months ago Blocks_Interface.php 4 months ago Service_Provider.php 4 months ago
API.php
414 lines
1 <?php
2
3 namespace Pods\Blocks;
4
5 // Don't load directly.
6 if ( ! defined( 'ABSPATH' ) ) {
7 die( '-1' );
8 }
9
10 use Pods;
11 use Pods\Pod_Manager;
12 use Pods\Whatsit\Block;
13
14 /**
15 * Blocks functionality class.
16 *
17 * @since 2.8.0
18 */
19 class API {
20
21 /**
22 * Register blocks for the Pods Blocks API.
23 *
24 * @since 2.8.0
25 */
26 public function register_blocks() {
27 static $registered = false;
28
29 if ( $registered ) {
30 return;
31 }
32
33 // The 'block_categories' filter has been deprecated in WordPress 5.8+ and replaced by 'block_categories_all'.
34 if ( pods_version_check( 'wp', '5.8-beta0' ) ) {
35 add_filter( 'block_categories_all', [ $this, 'register_block_collections' ] );
36 } else {
37 add_filter( 'block_categories', [ $this, 'register_block_collections' ] );
38 }
39
40 $blocks = $this->get_blocks();
41
42 foreach ( $blocks as $block ) {
43 $block_name = $block['blockName'];
44
45 unset( $block['blockName'], $block['fields'] );
46
47 register_block_type( $block_name, $block );
48 }
49
50 add_action( 'admin_enqueue_scripts', [ $this, 'register_assets' ], 15 );
51
52 $registered = true;
53 }
54
55 /**
56 * @return void
57 */
58 public function register_assets() {
59 $js_blocks = $this->get_js_blocks();
60
61 // The Pods Blocks JS API.
62 $pods_blocks_options_file = file_get_contents( PODS_DIR . 'ui/js/blocks/pods-blocks-api.min.asset.json' );
63
64 $pods_blocks_options = null;
65
66 if ( $pods_blocks_options_file ) {
67 $pods_blocks_options = json_decode( $pods_blocks_options_file, true );
68 }
69
70 if ( ! is_array( $pods_blocks_options ) ) {
71 $pods_blocks_options = [
72 'dependencies' => [],
73 'version' => false,
74 ];
75 }
76
77 wp_register_script( 'pods-blocks-api', PODS_URL . 'ui/js/blocks/pods-blocks-api.min.js', $pods_blocks_options['dependencies'], $pods_blocks_options['version'], true );
78
79 wp_set_script_translations( 'pods-blocks-api', 'pods' );
80
81 $blocks_config = [
82 'blocks' => $js_blocks,
83 'commands' => [],
84 'panelsToDisable' => [],
85 // No custom collections to register directly with JS right now.
86 'collections' => [],
87 ];
88
89 $is_admin = is_admin();
90 $screen = ( $is_admin && function_exists( 'get_current_screen' ) ) ? get_current_screen() : null;
91
92 if ( $screen && 'post' === $screen->base && $screen->post_type ) {
93 // Check if this is a Pod or not.
94 $api = pods_api();
95
96 $pod = false;
97
98 try {
99 $pod = $api->load_pod( [
100 'name' => $screen->post_type,
101 'auto_setup' => false,
102 ] );
103
104 // Check if this was auto-setup before and isn't a full pod.
105 if ( $pod && true === $pod->get_arg( 'adhoc' ) ) {
106 $pod = false;
107 }
108 } catch ( \Exception $exception ) {
109 // Nothing to do here.
110 }
111
112 if ( $pod instanceof Pods\Whatsit\Pod ) {
113 // Check if we need to disable any specific taxonomies.
114 $taxonomy_sync_fields = $pod->get_fields( [
115 'type' => 'pick',
116 'args' => [
117 'pick_object' => 'taxonomy',
118 'pick_sync_taxonomy' => 1,
119 'pick_sync_taxonomy_hide_taxonomy_ui' => 1,
120 ],
121 ] );
122
123 foreach ( $taxonomy_sync_fields as $taxonomy_sync_field ) {
124 $taxonomy_name = $taxonomy_sync_field->get_related_object_name();
125
126 if ( $taxonomy_name ) {
127 $blocks_config['panelsToDisable'][] = 'taxonomy-panel-' . $taxonomy_name;
128 }
129 }
130
131 // Maybe add commands if the person has the right access.
132 if ( pods_is_admin( 'pods' ) ) {
133 $blocks_config['commands'][] = [
134 'name' => 'pods/edit',
135 'label' => __( 'Edit this Pod configuration', 'pods' ),
136 'searchLabel' => __( 'Edit this Pod configuration > Manage Field Groups, Custom Fields, and other Custom Post Type settings in the Pods Admin', 'pods' ),
137 'icon' => 'pods',
138 'callbackUrl' => admin_url(
139 sprintf(
140 'admin.php?page=pods&action=edit&id=%d',
141 $pod->get_id()
142 )
143 ),
144 ];
145 } else {
146 $nonce = wp_create_nonce( 'pods_extend_post_type_' . $screen->post_type );
147
148 $blocks_config['commands'][] = [
149 'name' => 'pods/extend',
150 'label' => __( 'Extend this Post Type with Pods to add custom fields', 'pods' ),
151 'icon' => 'pods',
152 'callbackUrl' => admin_url(
153 sprintf(
154 'admin.php?page=pods-add-new&pods_extend_post_type=%1$s&pods_extend_post_type_nonce=%2$s',
155 $screen->post_type,
156 $nonce
157 )
158 ),
159 ];
160 }
161 }
162 }
163
164 /**
165 * Allow filtering the blocks API config data.
166 *
167 * @since 3.0.0
168 *
169 * @param array $blocks_config The blocks API config data.
170 */
171 $blocks_config = (array) apply_filters( 'pods_blocks_api_config', $blocks_config );
172
173 // Sanitize callbackUrl for security.
174 foreach ( $blocks_config['commands'] as $key => $command ) {
175 $blocks_config['commands'][ $key ]['callbackUrl'] = pods_enforce_safe_url( (string) $command['callbackUrl'] );
176 }
177
178 wp_localize_script( 'pods-blocks-api', 'podsBlocksConfig', $blocks_config );
179
180 wp_enqueue_style( 'pods-styles' );
181 }
182
183 /**
184 * Setup core blocks.
185 *
186 * @since 2.8.0
187 */
188 public function setup_core_blocks() {
189 static $setup = false;
190
191 if ( $setup ) {
192 return;
193 }
194
195 /**
196 * Allow any integrations to be set up before core blocks and collections are called.
197 *
198 * @since 2.8.0
199 */
200 do_action( 'pods_blocks_api_pre_init' );
201
202 pods_container( 'pods.blocks.collection.pods' );
203
204 // Check if the feature is enabled.
205 if ( pods_can_use_dynamic_feature( 'display' ) ) {
206 pods_container( 'pods.blocks.field' );
207 pods_container( 'pods.blocks.list' );
208 pods_container( 'pods.blocks.related-list' );
209 pods_container( 'pods.blocks.single' );
210 pods_container( 'pods.blocks.single-list-fields' );
211 }
212
213 // Check if the feature is enabled.
214 if ( pods_can_use_dynamic_feature( 'form' ) ) {
215 pods_container( 'pods.blocks.form' );
216 }
217
218 // Check if the feature is enabled.
219 if ( pods_can_use_dynamic_feature( 'view' ) ) {
220 pods_container( 'pods.blocks.view' );
221 }
222
223 /**
224 * Allow custom blocks to be registered with Pods.
225 *
226 * @since 2.8.0
227 */
228 do_action( 'pods_blocks_api_init' );
229
230 $setup = true;
231 }
232
233 /**
234 * Get list of registered blocks for the Pods Blocks API.
235 *
236 * @since 2.8.0
237 *
238 * @return array List of registered blocks.
239 */
240 public function get_blocks() {
241 $blocks = pods_static_cache_get( __FUNCTION__, __CLASS__ );
242
243 if ( ! empty( $blocks ) && is_array( $blocks ) ) {
244 return $blocks;
245 }
246
247 $this->setup_core_blocks();
248
249 $api = pods_api();
250
251 /**
252 * Allow filtering whether to bypass the post type find queries for blocks.
253 *
254 * @since 2.9.14
255 *
256 * @param bool $bypass_post_type_find Whether to bypass the post type find queries for blocks.
257 */
258 $bypass_post_type_find = apply_filters( 'pods_blocks_api_get_blocks_bypass_post_type_find', true );
259
260 /** @var Block[] $blocks */
261 $blocks = $api->_load_objects( [
262 'object_type' => 'block',
263 'bypass_cache' => true,
264 // Disable DB queries for now.
265 'bypass_post_type_find' => $bypass_post_type_find,
266 ] );
267
268 // Ensure the response is an array.
269 $blocks = array_values( $blocks );
270
271 $blocks = array_map( static function ( $block ) {
272 return $block->get_block_args();
273 }, $blocks );
274
275 pods_static_cache_set( __FUNCTION__, $blocks, __CLASS__ );
276
277 return $blocks;
278 }
279
280 /**
281 * Get list of registered blocks for the Pods Blocks API and prepare them for JavaScript registerBlockType().
282 *
283 * @since 2.8.0
284 *
285 * @return array List of registered blocks prepared for JavaScript registerBlockType().
286 */
287 public function get_js_blocks() {
288 static $js_blocks = [];
289
290 if ( ! empty( $js_blocks ) ) {
291 return $js_blocks;
292 }
293
294 $cached = pods_transient_get( 'pods_blocks_js' );
295
296 if ( is_array( $cached ) ) {
297 return $cached;
298 }
299
300 $blocks = $this->get_blocks();
301
302 foreach ( $blocks as $block_key => $block ) {
303 $js_block = [];
304
305 // Remove render options.
306 unset( $block['render_callback'], $block['render_custom_callback'], $block['render_template'], $block['render_template_path'] );
307
308 // Remove assets options.
309 unset( $block['enqueue_assets'], $block['enqueue_script'], $block['enqueue_style'] );
310
311 foreach ( $block as $key => $value ) {
312 // Prepare the keys as camelCase.
313 $key = pods_js_camelcase_name( $key );
314
315 // Skip if the value is null.
316 if ( null === $value ) {
317 continue;
318 }
319
320 $js_block[ $key ] = $value;
321 }
322
323 if ( ! isset( $js_block['usesContext'] ) ) {
324 $js_block['usesContext'] = [];
325 }
326
327 $js_blocks[ $block_key ] = $js_block;
328 }
329
330 pods_transient_set( 'pods_blocks_js', $js_blocks, DAY_IN_SECONDS * 7 );
331
332 return $js_blocks;
333 }
334
335 /**
336 * Get list of registered block collections for the Pods Blocks API.
337 *
338 * @since 2.8.0
339 *
340 * @return array List of registered block collections.
341 */
342 public function get_block_collections() {
343 static $collections = [];
344
345 if ( ! empty( $collections ) ) {
346 return $collections;
347 }
348
349 $this->setup_core_blocks();
350
351 $api = pods_api();
352
353 /** @var Block_Collection[] $block_collections */
354 $block_collections = $api->_load_objects( [
355 'object_type' => 'block-collection',
356 ] );
357
358 // Ensure the response is an array.
359 $block_collections = array_values( $block_collections );
360
361 $block_collections = array_map( static function ( $block_collection ) {
362 return $block_collection->get_block_collection_args();
363 }, $block_collections );
364
365 return $block_collections;
366 }
367
368 /**
369 * Register block collections by adding them to the list of 'categories'.
370 *
371 * @since 2.8.0
372 *
373 * @param array $collections List of block 'categories' from WordPress.
374 *
375 * @return array List of block 'categories' with custom block collections added.
376 */
377 public function register_block_collections( array $collections ) {
378 $block_collections = $this->get_block_collections();
379
380 if ( empty( $block_collections ) ) {
381 return $collections;
382 }
383
384 foreach ( $block_collections as $collection ) {
385 $collections[] = [
386 'slug' => $collection['namespace'],
387 'title' => $collection['title'],
388 'icon' => $collection['icon'],
389 ];
390 }
391
392 return $collections;
393 }
394
395 /**
396 * Remove our legacy Pods widgets from the Legacy Widget block.
397 *
398 * @since 2.8.0
399 *
400 * @param array $widgets An array of excluded widget-type IDs.
401 *
402 * @return array An array of excluded widget-type IDs.
403 */
404 public function remove_from_legacy_widgets( $widgets ) {
405 $widgets[] = 'pods_widget_field';
406 $widgets[] = 'pods_widget_form';
407 $widgets[] = 'pods_widget_list';
408 $widgets[] = 'pods_widget_single';
409 $widgets[] = 'pods_widget_view';
410
411 return $widgets;
412 }
413 }
414