PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / 8.0.5
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI v8.0.5
8.0.5 8.0.4 8.0.3 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 All 47 releases
← All changes | includes/blocks.php +495 -0 7.8.8 → 8.0.5 View file →
@@ -1,0 +1,495 @@
1 +<?php
2 +/**
3 + * Blocks
4 + *
5 + * @package GamiPress\Blocks
6 + * @author GamiPress <[email protected]>, Ruben Garcia <[email protected]>
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 +}