PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / 8.0.1
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI v8.0.1
8.0.1 8.0.2 8.0.0 7.9.9.7 7.9.9.6 7.9.9.5 7.9.9.4 7.9.9.3 7.9.9.2 7.9.9.1 7.9.9 7.9.8 7.9.7 7.9.6 7.9.5 7.9.4 7.9.3 7.9.2 7.9.1 7.9.0 7.8.9 7.8.8 7.8.7 7.8.6 7.8.5 All 44 releases
gamipress / includes / blocks.php

blocks.php in GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI 8.0.1, at includes/blocks.php

495 lines 16.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Blocks
4 *
5 * @package GamiPress\Blocks
6 * @author GamiPress <contact@gamipress.com>, Ruben Garcia <rubengcdev@gmail.com>
7 * @since 1.6.0
8 */
9 // Exit if accessed directly
10 if( !defined( 'ABSPATH' ) ) exit;
11
12 /**
13 * Select the right "block_categories" filter according to WP version
14 *
15 * @since 2.1.9
16 */
17 function gamipress_init_block_category() {
18
19 global $wp_version;
20
21 if( version_compare( $wp_version, '5.8', '<' ) ) {
22 // WP version is less than 5.8
23 add_filter( 'block_categories', 'gamipress_register_block_categories', 10, 2 );
24 } else {
25 // WP version is 5.8 or higher
26 add_filter( 'block_categories_all', 'gamipress_register_block_categories', 10, 2 );
27 }
28
29 }
30 add_action( 'gamipress_init', 'gamipress_init_block_category' );
31
32 /**
33 * Register GamiPress as block category
34 *
35 * @since 1.6.0
36 */
37 function gamipress_register_block_categories( $categories, $post ) {
38
39 // Register GamiPress as block category
40 $categories[] = array(
41 'title' => 'GamiPress',
42 'slug' => 'gamipress',
43 'icon' => 'gamipress',
44 );
45
46 return $categories;
47
48 }
49
50 /**
51 * GamiPress block icons
52 *
53 * @since 1.6.1
54 */
55 function gamipress_get_block_icons() {
56
57 $icons = array(
58 'gamipress' =>
59 '<svg width="24" height="24" viewBox="0 0 167.548 167.548" xmlns="http://www.w3.org/2000/svg" >
60 <path d="M 131.973,136.242 H 35.596 L 8.108,57.111 42.507,82.363 c -0.172,0.873 -0.264,1.727 -0.264,2.584 0,7.815 6.359,14.175 14.175,14.175 7.812,0 14.175,-6.359 14.175,-14.175 0,-6.091 -3.797,-11.274 -9.273,-13.255 l 22.465,-47.363 22.396,47.239 c -5.627,1.898 -9.629,7.193 -9.629,13.384 0,7.815 6.359,14.175 14.175,14.175 7.81,0 14.175,-6.359 14.175,-14.175 0,-1.036 -0.121,-2.077 -0.364,-3.103 l 34.984,-24.922 z"/>
61 </svg>',
62 'rank' =>
63 '<svg width="24" height="24" viewBox="0 0 92.275001 92.275002" xmlns="http://www.w3.org/2000/svg" >
64 <polygon points="50.1,96.2 76.2,81.3 76.2,66.5 50.1,81.3 24.1,66.5 24.1,81.3" transform="translate(-4.1,-3.9250045)"/>
65 <polygon points="50.1,74.5 76.2,59.7 76.2,44.8 50.1,59.7 24.1,44.8 24.1,59.7" transform="translate(-4.1,-3.9250045)"/>
66 <path d="M 47,0.67499541 52.6,11.974994 c 0.2,0.3 0.5,0.5 0.8,0.6 l 12.5,1.8 c 0.9,0.1 1.3,1.2 0.6,1.9 l -9,8.8 c -0.3,0.3 -0.4,0.6 -0.3,1 l 2.1,12.5 c 0.2,0.9 -0.8,1.6 -1.6,1.2 l -11.2,-5.9 c -0.3,-0.2 -0.7,-0.2 -1,0 l -11.2,5.9 c -0.8,0.4 -1.7,-0.3 -1.6,-1.2 l 2.2,-12.5 c 0.1,-0.4 -0.1,-0.7 -0.3,-1 l -9.1,-8.8 c -0.7,-0.6 -0.3,-1.7 0.6,-1.9 l 12.5,-1.8 c 0.4,-0.1 0.7,-0.3 0.8,-0.6 L 45,0.67499541 c 0.5,-0.9 1.6,-0.9 2,0 z"/>
67 </svg>',
68 );
69
70 /**
71 * Filter to register custom GamiPress block icons
72 *
73 * @since 1.6.1
74 *
75 * @param array $icons Icons already registered
76 *
77 * @return array
78 */
79 return apply_filters( 'gamipress_block_icons', $icons );
80
81 }
82
83 /**
84 * Register GamiPress blocks
85 *
86 * Important: Priority is set to 20 to let every add-on register their shortcodes first
87 *
88 * @since 1.6.0
89 */
90 function gamipress_register_block_types() {
91
92 // Bail if Gutenberg is not enabled
93 if( ! function_exists( 'register_block_type' ) ) {
94 return;
95 }
96
97 foreach( GamiPress()->shortcodes as $shortcode ) {
98
99 // Block name requires to be a prefix/block-slug
100 // So let's turn gamipress_points_types to gamipress/points-types
101 $block_name = str_replace( '_', '-', str_replace( 'gamipress_', 'gamipress/', $shortcode->slug ) );
102
103 // Register block and attributes
104 register_block_type( $block_name, array(
105 'attributes' => gamipress_get_block_attributes( $shortcode ),
106 'render_callback' => $shortcode->output_callback,
107 ) );
108
109 // Filter to remove null attributes passed by Gutenberg
110 add_filter( "shortcode_atts_{$shortcode->slug}", 'gamipress_remove_null_block_attributes', 10, 4 );
111
112 }
113
114 }
115 add_action( 'init', 'gamipress_register_block_types', 20 );
116
117 /**
118 * Setup block fields from give shortcode object
119 *
120 * @since 1.6.0
121 *
122 * @param GamiPress_Shortcode $shortcode
123 *
124 * @return array
125 */
126 function gamipress_get_block_fields( $shortcode ) {
127
128 $fields = array();
129
130 foreach( $shortcode->fields as $field_id => $field ) {
131
132 // Parse options callbacks
133 if( isset( $field['options_cb'] ) ) {
134 $field['options'] = gamipress_blocks_parse_options_cb( $field );
135 }
136
137 // Move tooltip to desc
138 if( isset( $field['tooltip'] ) ) {
139
140 if( ! isset( $field['desc'] ) ) {
141 $field['desc'] = '';
142 }
143
144 if( ! is_array( $field['tooltip'] ) ) {
145 // tooltip => description
146 $field['desc'] .= $field['tooltip'];
147 } else {
148 // tooltip => array()
149 $field['desc'] .= ( isset( $field['tooltip']['desc'] ) ? $field['tooltip']['desc'] : '' );
150 }
151
152 }
153
154 // Set the definitive object field
155 $fields[$field_id] = $field;
156 }
157
158 /**
159 * Filter to override specific block fields
160 *
161 * @since 1.6.0
162 *
163 * @param array $fields
164 * @param GamiPress_Shortcode $shortcode
165 *
166 * @return array
167 */
168 $fields = apply_filters( "gamipress_get_{$shortcode->slug}_block_fields", $fields, $shortcode );
169
170 /**
171 * Filter to override block fields
172 *
173 * @since 1.6.0
174 *
175 * @param array $fields
176 * @param GamiPress_Shortcode $shortcode
177 *
178 * @return array
179 */
180 return apply_filters( 'gamipress_get_block_fields', $fields, $shortcode );
181
182 }
183
184 /**
185 * Turn select2 fields into 'post' or 'user' field types
186 *
187 * @since 1.6.0
188 *
189 * @param array $fields
190 * @param GamiPress_Shortcode $shortcode
191 *
192 * @return array
193 */
194 function gamipress_blocks_selector_fields( $fields, $shortcode ) {
195
196 switch ( $shortcode->slug ) {
197 case 'gamipress_achievement':
198 case 'gamipress_inline_achievement':
199 // Achievement ID
200 $fields['id']['type'] = 'post';
201 $fields['id']['post_type'] = gamipress_get_achievement_types_slugs();
202 break;
203 case 'gamipress_achievements':
204 // Include
205 $fields['include']['type'] = 'post';
206 $fields['include']['post_type'] = gamipress_get_achievement_types_slugs();
207 // Exclude
208 $fields['exclude']['type'] = 'post';
209 $fields['exclude']['post_type'] = gamipress_get_achievement_types_slugs();
210 break;
211 case 'gamipress_rank':
212 case 'gamipress_inline_rank':
213 // Rank ID
214 $fields['id']['type'] = 'post';
215 $fields['id']['post_type'] = gamipress_get_rank_types_slugs();
216 break;
217 case 'gamipress_ranks':
218 // Include
219 $fields['include']['type'] = 'post';
220 $fields['include']['post_type'] = gamipress_get_rank_types_slugs();
221 // Exclude
222 $fields['exclude']['type'] = 'post';
223 $fields['exclude']['post_type'] = gamipress_get_rank_types_slugs();
224 break;
225 case 'gamipress_points':
226 case 'gamipress_user_points':
227 case 'gamipress_site_points':
228 // Period start and end visibility
229 $fields['period_start']['conditions'] = array( 'period' => 'custom' );
230 $fields['period_end']['conditions'] = array( 'period' => 'custom' );
231 // Inline conditions
232 $inline_condition = array(
233 'field_id' => 'inline',
234 'value' => true,
235 'compare' => '!=',
236 );
237 $fields['columns']['conditions'] = array( $inline_condition );
238 $fields['columns_small']['conditions'] = array( $inline_condition );
239 $fields['layout']['conditions'] = array( $inline_condition );
240 $fields['align']['conditions'] = array( $inline_condition );
241 break;
242 case 'gamipress_points_types':
243 // Points Types attributes
244 $fields['toggle']['conditions'] = array( 'awards' => true, 'deducts' => true, 'relation' => 'OR' );
245 $fields['heading']['conditions'] = array( 'awards' => true, 'deducts' => true, 'relation' => 'OR' );
246 $fields['heading_size']['conditions'] = array( 'heading' => true );
247 break;
248 }
249
250 // Common attributes
251 switch ( $shortcode->slug ) {
252 case 'gamipress_achievement':
253 case 'gamipress_achievements':
254 case 'gamipress_last_achievements_earned':
255 // Achievement common attributes
256 $fields['title_size']['conditions'] = array( 'title' => true );
257 $fields['thumbnail_size']['conditions'] = array( 'thumbnail' => true );
258 $fields['points_awarded_thumbnail']['conditions'] = array( 'points_awarded' => true );
259 $fields['toggle']['conditions'] = array( 'steps' => true );
260 $fields['heading']['conditions'] = array( 'steps' => true );
261 $fields['heading_size']['conditions'] = array( 'steps' => true, 'heading' => true );
262 $fields['earners_limit']['conditions'] = array( 'earners' => true );
263 break;
264 case 'gamipress_inline_achievement':
265 case 'gamipress_inline_last_achievements_earned':
266 // Inline achievement common attributes
267 $fields['thumbnail_size']['conditions'] = array( 'thumbnail' => true );
268 break;
269 case 'gamipress_rank':
270 case 'gamipress_ranks':
271 case 'gamipress_user_rank':
272 // Rank common attributes
273 $fields['title_size']['conditions'] = array( 'title' => true );
274 $fields['thumbnail_size']['conditions'] = array( 'thumbnail' => true );
275 $fields['toggle']['conditions'] = array( 'requirements' => true );
276 $fields['heading']['conditions'] = array( 'requirements' => true );
277 $fields['heading_size']['conditions'] = array( 'requirements' => true, 'heading' => true );
278 $fields['earners_limit']['conditions'] = array( 'earners' => true );
279 break;
280 case 'gamipress_inline_rank':
281 case 'gamipress_inline_user_rank':
282 // Inline rank common attributes
283 $fields['thumbnail_size']['conditions'] = array( 'thumbnail' => true );
284 break;
285 case 'gamipress_points':
286 case 'gamipress_user_points':
287 case 'gamipress_site_points':
288 case 'gamipress_points_types':
289 // Points common attributes
290 $fields['thumbnail_size']['conditions'] = array( 'thumbnail' => true );
291 break;
292 }
293
294 // Common fields to all shortcodes
295
296 // User ID
297 if( isset( $fields['user_id'] ) ) {
298 // User ID
299 $fields['user_id']['type'] = 'user';
300 }
301
302 // User ID visibility when current user field is in form
303 if( isset( $fields['user_id'] ) && isset( $fields['current_user'] ) ) {
304 // Setup as display condition that current_user needs to be false (unchecked)
305 $fields['user_id']['conditions'] = array(
306 'current_user' => false,
307 );
308 }
309
310 return $fields;
311 }
312 add_filter( 'gamipress_get_block_fields', 'gamipress_blocks_selector_fields', 10, 2 );
313
314 /**
315 * Setup block attributes from give shortcode object
316 *
317 * @since 1.6.0
318 *
319 * @param GamiPress_Shortcode $shortcode
320 *
321 * @return array
322 */
323 function gamipress_get_block_attributes( $shortcode ) {
324
325 $attributes = array();
326
327 // Turn fields into attributes
328 foreach( $shortcode->fields as $field_id => $field ) {
329
330 if( $field['type'] === 'checkbox' ) {
331 // Checkboxes as boolean
332 $attributes[$field_id] = array(
333 'type' => 'boolean',
334 );
335 } else {
336 // String is the default type
337 $attributes[$field_id] = array(
338 'type' => 'string',
339 );
340 }
341
342 }
343
344 /**
345 * Filter to override specific block attributes
346 *
347 * @since 1.6.0
348 *
349 * @param array $attributes
350 * @param GamiPress_Shortcode $shortcode
351 *
352 * @return array
353 */
354 $attributes = apply_filters( "gamipress_gutenberg_blocks_get_{$shortcode->slug}_block_attributes", $attributes, $shortcode );
355
356 /**
357 * Filter to override block attributes
358 *
359 * @since 1.6.0
360 *
361 * @param array $attributes
362 * @param GamiPress_Shortcode $shortcode
363 *
364 * @return array
365 */
366 return apply_filters( 'gamipress_gutenberg_blocks_get_block_attributes', $attributes, $shortcode );
367
368 }
369
370 /**
371 * Removes null attributes passed by Gutenberg
372 *
373 * @since 1.6.0
374 *
375 * @param array $out The output array of shortcode attributes
376 * @param array $pairs The supported attributes and their defaults
377 * @param array $atts The user defined shortcode attributes
378 * @param string $shortcode The shortcode name
379 *
380 * @return array
381 */
382 function gamipress_remove_null_block_attributes( $out, $pairs, $atts, $shortcode ) {
383
384 // Bail if shortcode is not registered
385 if( ! isset( GamiPress()->shortcodes[$shortcode] ) )
386 return $out;
387
388 // Setup the shortcode object
389 $shortcode_obj = GamiPress()->shortcodes[$shortcode];
390
391 foreach( $out as $name => $value ) {
392
393 // Gutenberg pass default values and empty as null
394 // So let's force default value instead of null
395 if( $value === null ) {
396 $out[$name] = $pairs[$name];
397 }
398
399 if( isset( $shortcode_obj->fields[$name] ) ) {
400 $field = $shortcode_obj->fields[$name];
401
402 if( $field['type'] === 'checkbox' && is_bool( $out[$name] ) ) {
403 // Turn booleans into yes|no
404 $out[$name] = ( $out[$name] === true ? 'yes' : 'no' );
405 }
406 }
407 }
408
409 return $out;
410
411 }
412
413 /**
414 * Filter block per-rendering to setup the renderer for error messages
415 *
416 * @since 1.7.6
417 *
418 * @param string $pre_render The pre-rendered content. Default null.
419 * @param array $block The block being rendered.
420 *
421 * @return string
422 */
423 function gamipress_pre_render_block( $pre_render, $block ) {
424
425 global $gamipress_renderer;
426
427 // Setup renderer
428 $gamipress_renderer = 'block';
429
430 return $pre_render;
431 }
432 add_filter( 'pre_render_block', 'gamipress_pre_render_block', 10, 2 );
433
434 /**
435 * Filter block rendering to reset the renderer for error messages
436 *
437 * @since 1.7.6
438 *
439 * @param string $block_content The block content about to be appended.
440 * @param array $block The full block, including name and attributes.
441 *
442 * @return string
443 */
444 function gamipress_render_block( $block_content, $block ) {
445
446 global $gamipress_renderer;
447
448 // Reset renderer
449 $gamipress_renderer = false;
450
451 return $block_content;
452 }
453 add_filter( 'render_block', 'gamipress_render_block', 10, 2 );
454
455 /**
456 * Simulates CMB2 options_cb processing
457 *
458 * @since 1.6.0
459 *
460 * @param array $field
461 *
462 * @return array
463 */
464 function gamipress_blocks_parse_options_cb( $field ) {
465
466 $field_options = ( isset( $field['options'] ) ? (array) $field['options'] : array() );
467
468 if ( isset( $field['options_cb'] ) && is_callable( $field['options_cb'] ) ) {
469 $options = call_user_func( $field['options_cb'], gamipress_blocks_cmb_field_object( $field ) );
470
471 if ( $options && is_array( $options ) ) {
472 $field_options = $options + $field_options;
473 }
474 }
475
476 return $field_options;
477
478 }
479
480 /**
481 * Builds a false CMB2 field object
482 *
483 * @since 1.6.0
484 *
485 * @param array $field
486 *
487 * @return stdClass
488 */
489 function gamipress_blocks_cmb_field_object( $field ) {
490 return (object) array(
491 'args' => $field,
492 'value' => '',
493 'escaped_value' => '',
494 );
495 }