PluginProbe
Content Blocks Builder – Create blocks, repeater blocks with carousel, grid, popup layouts / trunk
Content Blocks Builder – Create blocks, repeater blocks with carousel, grid, popup layouts vtrunk
2.8.14 2.8.13 2.8.12 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.8.0 2.8.1 2.8.10 2.8.11 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 trunk 1.0.1 1.0.2 1.1.0 1.1.1 All 147 releases
← All changes | includes/custom-blocks.php +300 -68 2.7.5trunk View file →
@@ -95,8 +95,10 @@
95 95 private $html_editor_style = '';
96 96
97 97 /**
98 98 * Constructor
99 + *
100 + * @param ContentBlocksBuilder $the_plugin_instance
99 101 */
100 102 public function __construct( $the_plugin_instance ) {
101 103 parent::__construct( $the_plugin_instance );
102 104
@@ -143,13 +145,16 @@
143 145
144 146 // Register codemirror.
145 147 add_action( 'admin_enqueue_scripts', [ $this, 'register_code_editor_scripts' ] );
146 148
149 + // Change the script src to use new version of esprima.
150 + add_filter( 'script_loader_src', [ $this, 'adjust_esprima_script' ], 10, 2 );
151 +
147 152 // Handle save post.
148 153 add_action( 'save_post_' . $this->post_type, [ $this, 'save_post' ], 10, 2 );
149 154
150 155 // Clear the transient cache on upgraded.
151 - add_action( 'cbb_version_upgraded', [ $this, 'clear_transient_cache' ] );
156 + add_action( 'cbb/version_upgraded', [ $this, 'clear_transient_cache' ] );
152 157
153 158 // Enqueue frontend scripts for non-cbb blocks.
154 159 add_filter( 'render_block', [ $this, 'enqueue_frontend_block_scripts' ], 10, 3 );
155 160
@@ -193,8 +198,15 @@
193 198 [
194 199 'rest_base' => 'boldblocks-blocks',
195 200 'menu_icon' => 'dashicons-block-default',
196 201 'menu_position' => 80, // Right after Settings.
202 + 'capabilities' => [
203 + 'read_post' => 'manage_options',
204 + 'edit_post' => 'manage_options',
205 + 'delete_post' => 'manage_options',
206 + 'edit_posts' => 'manage_options',
207 + 'delete_posts' => 'manage_options',
208 + ],
197 209 ],
198 210 [
199 211 'name' => _x( 'Custom Blocks', 'post type general name', 'content-blocks-builder' ),
200 212 'singular_name' => _x( 'Custom Block', 'post type singular name', 'content-blocks-builder' ),
@@ -425,18 +437,27 @@
425 437 'schema' => array(
426 438 'items' => array(
427 439 'type' => 'object',
428 440 'properties' => array(
429 - 'is_module' => array(
441 + 'value' => array(
442 + 'type' => 'string',
443 + ),
444 + 'script_type' => array(
445 + 'type' => 'string',
446 + 'default' => '', // 'module', 'custom', 'default'.
447 + ),
448 + 'handle' => array(
449 + 'type' => 'string',
450 + ),
451 + // is_module is deprecated. it will be removed in the future.
452 + 'is_module' => array(
430 453 'type' => 'boolean',
431 454 'default' => false,
432 455 ),
433 - 'handle' => array(
434 - 'type' => 'string',
456 + 'deps' => array(
457 + 'type' => 'string',
458 + 'default' => '',
435 459 ),
436 - 'value' => array(
437 - 'type' => 'string',
438 - ),
439 460 ),
440 461 ),
441 462 ),
442 463 ),
@@ -496,8 +517,11 @@
496 517 'properties' => array(
497 518 'handle' => array(
498 519 'type' => 'string',
499 520 ),
521 + 'type' => array(
522 + 'type' => 'string',
523 + ),
500 524 'value' => array(
501 525 'type' => 'string',
502 526 ),
503 527 ),
@@ -524,9 +548,9 @@
524 548 'type' => 'string',
525 549 ),
526 550 ),
527 551 'additionalProperties' => array(
528 - 'type' => [ 'string', 'boolean', 'object', 'array' ],
552 + 'type' => [ 'integer', 'number', 'boolean', 'string', 'object', 'array' ], // The order of data type matters.
529 553 ),
530 554 ),
531 555 ),
532 556 ),
@@ -550,9 +574,9 @@
550 574 'type' => 'string',
551 575 ),
552 576 ),
553 577 'additionalProperties' => array(
554 - 'type' => [ 'string', 'boolean', 'object', 'array' ],
578 + 'type' => [ 'integer', 'number', 'boolean', 'string', 'object', 'array' ],
555 579 ),
556 580 ),
557 581 ),
558 582 ),
@@ -644,8 +668,9 @@
644 668 * @param int $limit Number of custom fields to retrieve. Default 30.
645 669 */
646 670 $limit = apply_filters( 'postmeta_form_limit', 30 );
647 671
672 + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
648 673 $keys = $wpdb->get_col(
649 674 $wpdb->prepare(
650 675 "SELECT DISTINCT meta_key
651 676 FROM $wpdb->postmeta
@@ -700,12 +725,9 @@
700 725 // Make name as the key.
701 726 $this->repeater_blocks = array_column( $this->repeater_blocks, null, 'name' );
702 727
703 728 // Get current post.
704 - global $pagenow;
705 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended
706 - $post_id = 'post.php' === $pagenow && isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0;
707 - $post = $post_id ? get_post( $post_id ) : false;
729 + $post = $this->get_current_post();
708 730 $block_name = '';
709 731 $repeater_block_name = '';
710 732
711 733 if ( $post && $this->post_type === $post->post_type ) {
@@ -726,10 +748,12 @@
726 748 // Build block attributes.
727 749 $block_atts = [
728 750 'api_version' => 3,
729 751 'supports' => [
730 - 'cbb' => true,
731 - 'layout' => true,
752 + 'cbb' => true,
753 + 'layout' => true,
754 + 'migrateClass' => ! empty( $args['migrateClass'] ) ? ( isset( $args['id'] ) ? 'wp-block-boldblocks-custom' : 'wp-block-boldblocks-custom-parent' ) : '',
755 + 'CSSClasses' => $args['className'] ?? '',
732 756 ],
733 757 'uses_context' => [ 'postId', 'postType', 'cbb/block-overrides' ],
734 758 ];
735 759
@@ -845,10 +869,11 @@
845 869 }
846 870
847 871 // Scripts & styles.
848 872 $is_backend = is_admin();
849 - $block_inline_handle = 'cbb-' . str_replace( '/', '-', $name );
850 - $block_module_inline_handle = 'cbb-script-module-' . str_replace( '/', '-', $name );
873 + $name_handle = str_replace( '/', '-', $name );
874 + $block_inline_handle = 'cbb-' . $name_handle;
875 + $block_module_inline_handle = 'cbb-script-module-' . $name_handle;
851 876
852 877 if ( ! empty( $args['external_scripts'] ) ) {
853 878 $external_scripts = array_filter(
854 879 $args['external_scripts'],
@@ -895,25 +920,102 @@
895 920 }
896 921 }
897 922 }
898 923
899 - if ( ! $is_backend && ! empty( $args['custom_scripts'] ) ) {
924 + if ( ! empty( $args['custom_scripts'] ) && ! $is_backend ) {
900 925 $custom_scripts = $args['custom_scripts'];
901 926
902 - foreach ( $custom_scripts as $script ) {
903 - if ( ! $script || ! is_array( $script ) || empty( $script['value'] ) ) {
904 - continue;
927 + // Refine custom scripts.
928 + $custom_scripts = array_reduce(
929 + $custom_scripts,
930 + function ( $carry, $script ) {
931 + // Skip if script is empty.
932 + if ( ! $script || ! is_array( $script ) || empty( $script['value'] ) ) {
933 + return $carry;
934 + }
935 +
936 + // Refine script type.
937 + $script_type = $script['script_type'] ?? '';
938 +
939 + // Legacy support for script_type.
940 + if ( ! $script_type ) {
941 + if ( $script['is_module'] ?? false ) {
942 + $script_type = 'module';
943 + } elseif ( ! empty( $script['handle'] ) ) {
944 + $script_type = 'custom';
945 + } else {
946 + $script_type = 'default';
947 + }
948 +
949 + $script['script_type'] = $script_type;
950 + }
951 +
952 + // If custom type but no handle, change to default.
953 + if ( 'custom' === $script_type && empty( $script['handle'] ) ) {
954 + $script['script_type'] = 'default';
955 + }
956 +
957 + $carry[] = $script;
958 +
959 + return $carry;
960 + },
961 + []
962 + );
963 +
964 + $default_handle_scripts = array_filter(
965 + $custom_scripts,
966 + function ( $script ) {
967 + return 'custom' !== $script['script_type'];
905 968 }
969 + );
906 970
907 - $is_module = $script['is_module'] ?? false;
908 - $handle = $is_module ? $block_module_inline_handle : $block_inline_handle;
971 + if ( $default_handle_scripts ) {
972 + $dep_handles = array_reduce(
973 + $default_handle_scripts,
974 + function ( $carry, $script ) {
975 + if ( 'module' === $script['script_type'] ) {
976 + $carry['has_module'] = true;
977 + } elseif ( ! empty( $script['deps'] ) ) {
978 + $deps = explode( ',', $script['deps'] );
979 + foreach ( $deps as $dep ) {
980 + $dep = trim( $dep );
981 + if ( ! $dep || in_array( $dep, $carry['deps'], true ) ) {
982 + continue;
983 + }
909 984
985 + $carry['deps'][] = $dep;
986 + }
987 + }
988 +
989 + return $carry;
990 + },
991 + [
992 + 'has_module' => false,
993 + 'deps' => [],
994 + ]
995 + );
996 +
997 + if ( $dep_handles['has_module'] ) {
998 + // Register the default handle for module scripts.
999 + wp_register_script( $block_module_inline_handle, '', [], BOLDBLOCKS_CBB_VERSION, [ 'in_footer' => true ] );
1000 + }
1001 +
1002 + if ( ! in_array( 'CBB_BLOCK_API', $dep_handles['deps'], true ) ) {
1003 + array_unshift( $dep_handles['deps'], 'CBB_BLOCK_API' );
1004 + }
1005 +
1006 + // Register the default handle for inline scripts.
1007 + wp_register_script( $block_inline_handle, '', explode( ',', $this->refine_script_handle( implode( ',', $dep_handles['deps'] ), $is_backend ) ), BOLDBLOCKS_CBB_VERSION, [ 'in_footer' => true ] );
1008 + }
1009 +
1010 + foreach ( $custom_scripts as $script ) {
1011 + $script_type = $script['script_type'];
1012 +
910 1013 // Determine if a custom handle should be used.
911 - if ( ! empty( $script['handle'] ) && ! $is_module ) {
1014 + if ( 'custom' === $script_type ) {
912 1015 $handle = $this->refine_script_handle( $script['handle'], $is_backend );
913 1016 } else {
914 - // Register the default handle for module and inline scripts.
915 - wp_register_script( $handle, '', [ $this->refine_script_handle( 'CBB_BLOCK_API', $is_backend ) ], false, [ 'in_footer' => true ] );
1017 + $handle = 'module' === $script_type ? $block_module_inline_handle : $block_inline_handle;
916 1018
917 1019 // Add handle to view scripts and editor scripts if backend.
918 1020 if ( ! in_array( $handle, $handles['view_script_handles'], true ) ) {
919 1021 $handles['view_script_handles'][] = $handle;
@@ -970,8 +1072,13 @@
970 1072 $is_preview = ! empty( $args['dependentBlocks'] ) && is_array( $args['dependentBlocks'] ) && count( $args['dependentBlocks'] ) === 1 && 'core/html' === ( $args['dependentBlocks'][0] ?? '' );
971 1073
972 1074 foreach ( $custom_styles as $style ) {
973 1075 if ( $style && is_array( $style ) && $style['value'] ) {
1076 + $snippet_type = $style['type'] ?? 'all';
1077 + if ( ( 'view' === $snippet_type && $is_backend ) || ( 'editor' === $snippet_type && ! $is_backend ) ) {
1078 + continue;
1079 + }
1080 +
974 1081 $value = $style['value'];
975 1082 if ( $is_preview ) {
976 1083 $this->html_editor_style .= $value;
977 1084 }
@@ -977,8 +1084,9 @@
977 1084 }
978 1085
979 1086 if ( empty( $style['handle'] ) ) {
980 1087 $handle = $block_inline_handle;
1088 + // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
981 1089 wp_register_style( $handle, '' );
982 1090
983 1091 // Add the default handle to the block.
984 1092 $handles['style_handles'][] = $handle;
@@ -1030,8 +1138,9 @@
1030 1138 * @return string
1031 1139 */
1032 1140 private function refine_script_handle( $handle, $is_backend = false ) {
1033 1141 if ( $handle ) {
1142 + $handle = str_replace( ' ', '', $handle );
1034 1143 $handle = str_replace( 'CBB_BLOCK_API', $is_backend ? $this->custom_blocks_handle : $this->custom_blocks_frontend_handle, $handle );
1035 1144 $handle = str_replace( 'CBB_CAROUSEL_API', $is_backend ? $this->custom_blocks_handle : $this->carousel_blocks_frontend_handle, $handle );
1036 1145 }
1037 1146
@@ -1063,12 +1172,28 @@
1063 1172 $screen = get_current_screen();
1064 1173 if ( $screen && $screen->is_block_editor ) {
1065 1174 wp_enqueue_code_editor( array( 'type' => 'text/css' ) );
1066 1175 wp_enqueue_code_editor( array( 'type' => 'javascript' ) );
1176 + wp_enqueue_code_editor( array( 'type' => 'application/json' ) );
1067 1177 }
1068 1178 }
1069 1179
1070 1180 /**
1181 + * Adjust the src of the esprima script.
1182 + *
1183 + * @param string $src The source URL of the script.
1184 + * @param string $handle The handle of the script.
1185 + * @return string The adjusted source URL of the script.
1186 + */
1187 + public function adjust_esprima_script( $src, $handle ) {
1188 + if ( 'esprima' === $handle ) {
1189 + $src = 'https://cdn.jsdelivr.net/npm/esprima-next@5.8.4/dist/esprima.js';
1190 + }
1191 +
1192 + return $src;
1193 + }
1194 +
1195 + /**
1071 1196 * Register scripts
1072 1197 *
1073 1198 * @return void
1074 1199 */
@@ -1087,11 +1212,31 @@
1087 1212
1088 1213 // Add translation.
1089 1214 wp_set_script_translations( $this->custom_blocks_handle, 'content-blocks-builder' );
1090 1215
1216 + // Get all blocks.
1217 + $all_custom_blocks = $this->get_all_custom_blocks();
1218 + $current_post = $this->get_current_post();
1219 + if ( $current_post && $this->post_type === $current_post->post_type ) {
1220 + // Hide the current block.
1221 + $all_custom_blocks = array_map(
1222 + function ( $block ) use ( $current_post ) {
1223 + if ( $block['id'] === $current_post->ID ) {
1224 + $block['isHidden'] = true;
1225 + }
1226 + return $block;
1227 + },
1228 + $all_custom_blocks
1229 + );
1230 + }
1231 +
1091 1232 // Define data.
1092 1233 $blocks_scripts = [
1093 - 'blocks' => $this->get_all_custom_blocks(),
1234 + 'blocks' => $all_custom_blocks,
1235 + 'variations' => $this->the_plugin_instance->get_component( Variations::class )->get_all_variations(),
1236 + 'variationNonce' => wp_create_nonce( 'cbb_variation_nonce' ),
1237 + 'animations' => $this->get_animated_blocks(),
1238 + 'canEditCSS' => $this->the_plugin_instance->get_component( CustomStyle::class )->user_can_edit_css(),
1094 1239 ];
1095 1240
1096 1241 // Get block name for current variation.
1097 1242 $block_name = $this->the_plugin_instance->get_component( Variations::class )->get_block_name();
@@ -1099,13 +1244,10 @@
1099 1244 $blocks_scripts['variationBlockName'] = $block_name;
1100 1245 }
1101 1246
1102 1247 // Load all custom blocks for registration.
1103 - wp_add_inline_script( $this->custom_blocks_handle, 'var BoldBlocksBlocks=' . wp_json_encode( $blocks_scripts ), 'before' );
1248 + wp_add_inline_script( $this->custom_blocks_handle, 'var CBBBlocks=' . wp_json_encode( $blocks_scripts ), 'before' );
1104 1249
1105 - // Load all variations for registration.
1106 - wp_add_inline_script( $this->custom_blocks_handle, 'var BoldBlocksVariations=' . wp_json_encode( $this->the_plugin_instance->get_component( Variations::class )->get_all_variations() ), 'before' );
1107 -
1108 1250 // Frontend styles.
1109 1251 wp_register_style(
1110 1252 $this->custom_blocks_handle,
1111 1253 $this->the_plugin_instance->get_file_uri( "build/custom-blocks{$this->the_plugin_instance->get_script_suffix()}.css" ),
@@ -1205,21 +1347,24 @@
1205 1347 *
1206 1348 * @return array
1207 1349 */
1208 1350 public function query_posts() {
1209 - $post_args = [
1210 - 'post_type' => $this->post_type,
1211 - 'posts_per_page' => $this->get_max_items(),
1212 - 'orderby' => [
1213 - 'menu_order' => 'DESC',
1214 - 'date' => 'DESC',
1215 - ],
1216 - ];
1351 + $post_args = apply_filters(
1352 + 'cbb_block_query_args',
1353 + [
1354 + 'post_type' => $this->post_type,
1355 + 'posts_per_page' => $this->get_max_items(),
1356 + 'orderby' => [
1357 + 'menu_order' => 'DESC',
1358 + 'date' => 'DESC',
1359 + ],
1360 + ]
1361 + );
1217 1362
1218 1363 $raw_posts = get_posts( $post_args );
1219 1364
1220 1365 $block_posts = array_map(
1221 - function( $item ) {
1366 + function ( $item ) {
1222 1367 // Template lock.
1223 1368 $template_lock = get_post_meta( $item->ID, 'boldblocks_template_lock', true );
1224 1369
1225 1370 // Convert boolean string to boolean.
@@ -1231,18 +1376,18 @@
1231 1376 $block_external_styles = get_post_meta( $item->ID, 'boldblocks_block_external_styles', true );
1232 1377 $block_custom_styles = get_post_meta( $item->ID, 'boldblocks_block_custom_styles', true );
1233 1378
1234 1379 // Hide on frontend.
1235 - $hide_on_frontend = ! ! get_post_meta( $item->ID, 'boldblocks_hide_on_frontend', true );
1380 + $hide_on_frontend = (bool) get_post_meta( $item->ID, 'boldblocks_hide_on_frontend', true );
1236 1381
1237 1382 // Is a readonly block.
1238 - $is_readonly = ! ! get_post_meta( $item->ID, 'boldblocks_is_readonly', true );
1383 + $is_readonly = (bool) get_post_meta( $item->ID, 'boldblocks_is_readonly', true );
1239 1384
1240 1385 // Is block transformable.
1241 - $is_transformable = ! ! get_post_meta( $item->ID, 'boldblocks_is_transformable', true );
1386 + $is_transformable = (bool) get_post_meta( $item->ID, 'boldblocks_is_transformable', true );
1242 1387
1243 1388 // Is block hidden.
1244 - $is_hidden = ! ! get_post_meta( $item->ID, 'boldblocks_is_hidden', true );
1389 + $is_hidden = (bool) get_post_meta( $item->ID, 'boldblocks_is_hidden', true );
1245 1390
1246 1391 // Parent & ancestor.
1247 1392 $block_parent = get_post_meta( $item->ID, 'boldblocks_block_parent', true );
1248 1393 $block_parent = $block_parent ? array_filter( explode( ',', $block_parent ) ) : [];
@@ -1257,9 +1402,11 @@
1257 1402 } else {
1258 1403 $keywords = false;
1259 1404 }
1260 1405
1261 - $block_name = sprintf( 'boldblocks/%s', $this->sanitize_block_name( $item->post_name ) );
1406 + $block_name = sprintf( 'boldblocks/%s', $this->sanitize_block_name( $item->post_name ) );
1407 + $block_version = get_post_meta( $item->ID, 'boldblocks_block_version', true );
1408 + $migrate_class = version_compare( $block_version, '2.7.14', '<=' );
1262 1409
1263 1410 $block_args = [
1264 1411 'id' => $item->ID,
1265 1412 'name' => $block_name,
@@ -1272,12 +1419,13 @@
1272 1419 'blockIcon' => get_post_meta( $item->ID, 'boldblocks_block_icon', true ),
1273 1420 'blockSupports' => get_post_meta( $item->ID, 'boldblocks_block_supports', true ),
1274 1421 'blockAttributes' => [
1275 1422 'attributes' => get_post_meta( $item->ID, 'boldblocks_block_attributes', true ),
1276 - 'enableCustomAttributes' => ! ! get_post_meta( $item->ID, 'boldblocks_enable_custom_attributes', true ),
1423 + 'enableCustomAttributes' => (bool) get_post_meta( $item->ID, 'boldblocks_enable_custom_attributes', true ),
1277 1424 ],
1278 - 'enableVariationPicker' => ! ! get_post_meta( $item->ID, 'boldblocks_enable_variation_picker', true ),
1279 - 'blockVersion' => get_post_meta( $item->ID, 'boldblocks_block_version', true ),
1425 + 'enableVariationPicker' => (bool) get_post_meta( $item->ID, 'boldblocks_enable_variation_picker', true ),
1426 + 'blockVersion' => $block_version,
1427 + 'migrateClass' => $migrate_class,
1280 1428 'dependentBlocks' => get_post_meta( $item->ID, 'boldblocks_block_dependent_blocks', true ),
1281 1429 'hideOnFrontend' => $hide_on_frontend,
1282 1430 'isTransformable' => $is_transformable,
1283 1431 'isHidden' => $is_hidden,
@@ -1311,18 +1459,20 @@
1311 1459 'blockIcon' => get_post_meta( $item->ID, 'boldblocks_parent_block_icon', true ),
1312 1460 'blockSupports' => get_post_meta( $item->ID, 'boldblocks_parent_block_supports', true ),
1313 1461 'blockAttributes' => [
1314 1462 'attributes' => get_post_meta( $item->ID, 'boldblocks_parent_block_attributes', true ),
1315 - 'enableCustomAttributes' => ! ! get_post_meta( $item->ID, 'boldblocks_parent_enable_custom_attributes', true ),
1463 + 'enableCustomAttributes' => (bool) get_post_meta( $item->ID, 'boldblocks_parent_enable_custom_attributes', true ),
1316 1464 ],
1317 - 'enableVariationPicker' => ! ! get_post_meta( $item->ID, 'boldblocks_parent_enable_variation_picker', true ),
1465 + 'enableVariationPicker' => (bool) get_post_meta( $item->ID, 'boldblocks_parent_enable_variation_picker', true ),
1318 1466 'external_scripts' => $block_external_scripts,
1319 - 'custom_scripts' => $this->refine_custom_scripts( $block_custom_scripts, 'JS', $parent_block_name ),
1467 + 'custom_scripts' => $this->refine_custom_scripts( $block_custom_scripts, 'JS', $parent_block_name, $block_name ),
1320 1468 'external_styles' => $block_external_styles,
1321 - 'custom_styles' => $this->refine_custom_scripts( $block_custom_styles, 'CSS', $parent_block_name ),
1469 + 'custom_styles' => $this->refine_custom_scripts( $block_custom_styles, 'CSS', $parent_block_name, $block_name ),
1322 1470 'hideOnFrontend' => $hide_on_frontend,
1323 1471 'blockParent' => $block_parent,
1324 1472 'blockAncestor' => $block_ancestor,
1473 + 'migrateClass' => $migrate_class,
1474 +
1325 1475 ];
1326 1476
1327 1477 if ( $keywords ) {
1328 1478 $parent_args['keywords'] = $keywords;
@@ -1373,12 +1523,13 @@
1373 1523 * @param string $type
1374 1524 * @param string $block_name
1375 1525 * @return array
1376 1526 */
1377 - private function refine_custom_scripts( $custom_scripts, $type, $block_name ) {
1527 + private function refine_custom_scripts( $custom_scripts, $type, $block_name, $child_block_name = '' ) {
1378 1528 if ( $custom_scripts && is_array( $custom_scripts ) ) {
1379 1529 $custom_style_handler = $this->the_plugin_instance->get_component( CustomStyle::class );
1380 1530 $block_class = '.wp-block-' . str_replace( '/', '-', $block_name );
1531 + $child_block_class = $child_block_name ? '.wp-block-' . str_replace( '/', '-', $child_block_name ) : '';
1381 1532
1382 1533 $custom_scripts = array_filter(
1383 1534 $custom_scripts,
1384 1535 function ( $script ) {
@@ -1386,10 +1537,22 @@
1386 1537 }
1387 1538 );
1388 1539
1389 1540 $custom_scripts = array_map(
1390 - function ( $script ) use ( $custom_style_handler, $block_class, $type ) {
1391 - $tokens = 'CSS' === $type ? [ 'selector' => $block_class ] : [ 'BLOCKSELECTOR' => $block_class ];
1541 + function ( $script ) use ( $custom_style_handler, $block_class, $child_block_class, $type ) {
1542 + $tokens = [];
1543 + if ( 'CSS' === $type ) {
1544 + if ( $child_block_class ) {
1545 + $tokens['childblockselector'] = $child_block_class;
1546 + }
1547 + $tokens['selector'] = $block_class;
1548 + } else {
1549 + if ( $child_block_class ) {
1550 + $tokens['CHILDBLOCKSELECTOR'] = $child_block_class;
1551 + }
1552 + $tokens['BLOCKSELECTOR'] = $block_class;
1553 + }
1554 +
1392 1555 $script['value'] = $custom_style_handler->refine_custom_value( $script['value'], $tokens, $type );
1393 1556
1394 1557 return $script;
1395 1558 },
@@ -1467,9 +1630,9 @@
1467 1630 'parent_block_icon' => esc_html__( 'Parent icon', 'content-blocks-builder' ),
1468 1631 'parent_block_name' => esc_html__( 'Parent block name', 'content-blocks-builder' ),
1469 1632 );
1470 1633
1471 - if ( $this->the_plugin_instance->is_debug_mode() ) {
1634 + if ( apply_filters( 'cbb_display_block_version', $this->the_plugin_instance->is_debug_mode() ) ) {
1472 1635 $custom_columns['block_version'] = esc_html__( 'Block version', 'content-blocks-builder' );
1473 1636 }
1474 1637
1475 1638 // Add after title column.
@@ -1523,9 +1686,9 @@
1523 1686 $block_version = get_post_meta( $post_id, 'boldblocks_block_version', true );
1524 1687 if ( $block_version ) {
1525 1688 echo esc_html( $block_version );
1526 1689 } else {
1527 - esc_html_e( '1.x', 'content-blocks-builder' );
1690 + echo esc_html( '1.x' );
1528 1691 }
1529 1692 break;
1530 1693
1531 1694 // Just break out of the switch statement for everything else.
@@ -1683,9 +1846,9 @@
1683 1846 }
1684 1847
1685 1848 if ( $block_instance->block_type->supports['cbb'] ?? false ) {
1686 1849 $GLOBALS['boldblocks_frontend_loaded'] = true;
1687 - } elseif ( $this->is_enqueue_frontend_script_for_non_cbb_blocks( $block, $block_instance ) ) {
1850 + } elseif ( $this->is_enqueue_frontend_script_for_animations( $block ) || $this->is_enqueue_frontend_script_for_sticky_blocks( $block ) ) {
1688 1851 wp_enqueue_script( $this->custom_blocks_frontend_handle );
1689 1852 wp_enqueue_style( $this->custom_blocks_handle );
1690 1853
1691 1854 $GLOBALS['boldblocks_frontend_loaded'] = true;
@@ -1694,15 +1857,14 @@
1694 1857 return $block_content;
1695 1858 }
1696 1859
1697 1860 /**
1698 - * Whether to load the frontend scripts for non-cbb blocks.
1861 + * Whether to load the frontend scripts for non-cbb sticky blocks.
1699 1862 *
1700 - * @param array $block
1701 - * @param WP_Block $block_instance
1863 + * @param array $block
1702 1864 * @return boolean
1703 1865 */
1704 - private function is_enqueue_frontend_script_for_non_cbb_blocks( $block, $block_instance ) {
1866 + private function is_enqueue_frontend_script_for_sticky_blocks( $block ) {
1705 1867 $block_names = $this->the_plugin_instance->get_component( CustomStyle::class )->non_cbb_blocks;
1706 1868 if ( ! in_array( $block['blockName'] ?? '', $block_names, true ) ) {
1707 1869 return false;
1708 1870 }
@@ -1715,8 +1877,18 @@
1715 1877 return false;
1716 1878 }
1717 1879
1718 1880 /**
1881 + * Whether to load the frontend scripts for non-cbb animation blocks.
1882 + *
1883 + * @param array $block
1884 + * @return boolean
1885 + */
1886 + private function is_enqueue_frontend_script_for_animations( $block ) {
1887 + return ! empty( $block['attrs']['boldblocks']['animations'] ) && in_array( $block['blockName'] ?? '', $this->get_animated_blocks(), true );
1888 + }
1889 +
1890 + /**
1719 1891 * Enqueue frontend scripts for carousel layout in the query loop block
1720 1892 *
1721 1893 * @param string $block_content
1722 1894 * @param array $block
@@ -1789,14 +1961,14 @@
1789 1961 register_rest_field(
1790 1962 $this->post_type,
1791 1963 'keywords',
1792 1964 array(
1793 - 'get_callback' => function( $params ) {
1965 + 'get_callback' => function ( $params ) {
1794 1966 $keywords = wp_list_pluck( wp_get_object_terms( $params['id'], 'boldblocks_block_keywords' ), 'name' );
1795 1967
1796 1968 return \implode( ',', $keywords );
1797 1969 },
1798 - 'update_callback' => function( $value, $post ) {
1970 + 'update_callback' => function ( $value, $post ) {
1799 1971 wp_set_post_terms( $post->ID, $value, 'boldblocks_block_keywords' );
1800 1972 },
1801 1973 'schema' => array(
1802 1974 'type' => 'string',
@@ -1835,9 +2007,9 @@
1835 2007 return $block_content;
1836 2008 }
1837 2009
1838 2010 if ( $block_instance->block_type->supports['hideOnFrontend'] ?? false ) {
1839 - return null;
2011 + return '<!-- ' . esc_html( $block_instance->name ) . ' -->';
1840 2012 }
1841 2013
1842 2014 return $block_content;
1843 2015 }
@@ -1893,9 +2065,9 @@
1893 2065 if ( ! empty( $custom_styles ) ) {
1894 2066 $custom_styles = array_filter(
1895 2067 $custom_styles,
1896 2068 function ( $style ) {
1897 - return ! empty( $style['value'] );
2069 + return ! empty( $style['value'] ) && 'view' !== ( $style['type'] ?? '' );
1898 2070 }
1899 2071 );
1900 2072
1901 2073 $dynamic_style = '';
@@ -1906,8 +2078,9 @@
1906 2078 if ( $dynamic_style ) {
1907 2079 $dynamic_style .= '.wp-block-post-content{position:relative!important;top:unset!important;right:unset!important;bottom:unset!important;left:unset!important;display:block!important;width:auto!important;max-width:none!important;height:auto!important;max-height:none!important;}.is-selected,.has-child-selected,.has-child-selected * {animation:none!important;}';
1908 2080 $handle = 'edit-' . $this->custom_blocks_handle;
1909 2081 if ( ! wp_style_is( $handle, 'registered' ) ) {
2082 + // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
1910 2083 wp_register_style( $handle, '' );
1911 2084 }
1912 2085
1913 2086 wp_add_inline_style( $handle, $dynamic_style );
@@ -2091,20 +2264,24 @@
2091 2264 if ( $queried_object->post_type === $query_post_type || ( is_array( $query_post_type ) && in_array( $queried_object->post_type, $query_post_type, true ) ) ) {
2092 2265 $context_args = $this->query_loop_filter_by_context( $cbb_params, $queried_object );
2093 2266
2094 2267 if ( $context_args['post__not_in'] ?? false ) {
2268 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in
2095 2269 $cbb_args['post__not_in'] = $context_args['post__not_in'];
2096 2270 }
2097 2271
2098 2272 if ( $context_args['tax_query'] ?? false ) {
2099 2273 if ( ( $query_args['tax_query'] ?? false ) && is_array( $query_args['tax_query'] ) ) {
2274 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
2100 2275 $cbb_args['tax_query'] = array_merge( $query_args['tax_query'], [ $context_args['tax_query'] ] );
2101 2276 } else {
2277 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
2102 2278 $cbb_args['tax_query'] = $context_args['tax_query'];
2103 2279 }
2104 2280 }
2105 2281 }
2106 2282
2283 + // ignoreStickyPosts is depreated since WP 6.8.
2107 2284 // Ignore sticky posts not exlude them.
2108 2285 if ( ( $cbb_params['ignoreStickyPosts'] ?? false ) && ( 'exclude' === $query_context['sticky'] ?? '' ) ) {
2109 2286 $cbb_args['ignore_sticky_posts'] = true;
2110 2287 $sticky = get_option( 'sticky_posts' );
@@ -2109,8 +2286,9 @@
2109 2286 $cbb_args['ignore_sticky_posts'] = true;
2110 2287 $sticky = get_option( 'sticky_posts' );
2111 2288 if ( ! empty( $sticky ) && ! empty( $query_args['post__not_in'] ) ) {
2112 2289 // Remove sticky from the post__not_in list.
2290 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in
2113 2291 $query_args['post__not_in'] = array_diff( $query_args['post__not_in'], $sticky );
2114 2292 }
2115 2293 }
2116 2294 }
@@ -2128,9 +2306,9 @@
2128 2306 }
2129 2307
2130 2308 $orderby = array_filter(
2131 2309 array_map(
2132 - function( $item ) {
2310 + function ( $item ) {
2133 2311 return $item ? sanitize_text_field( $item ) : false;
2134 2312 },
2135 2313 $orderby
2136 2314 )
@@ -2147,9 +2325,15 @@
2147 2325 }
2148 2326 }
2149 2327
2150 2328 // Combine post__not_in value.
2329 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in
2151 2330 $cbb_args['post__not_in'] = array_merge( $query_args['post__not_in'], $cbb_args['post__not_in'] ?? [] );
2331 +
2332 + // Don't need pagination.
2333 + if ( $cbb_params['disablePagination'] ?? false ) {
2334 + $cbb_args['no_found_rows'] = true;
2335 + }
2152 2336 }
2153 2337
2154 2338 // Allow third-party to alter the final result.
2155 2339 $query_args = apply_filters( 'cbb_query_loop_block_query_vars', array_merge( $query_args, $cbb_args ), $query_args, $cbb_params, $query_context, $queried_object );
@@ -2220,9 +2404,10 @@
2220 2404 * @return array
2221 2405 */
2222 2406 private function query_loop_filter_by_meta_queries( $params ) {
2223 2407 $meta_query_args = [];
2224 - $queries = $params['metaQuery']['queries'] ?? [];
2408 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
2409 + $queries = $params['metaQuery']['queries'] ?? [];
2225 2410 if ( $queries && count( $queries ) > 0 ) {
2226 2411 $queries = array_map(
2227 2412 function ( $query ) {
2228 2413 $refined_query = [
@@ -2343,10 +2528,12 @@
2343 2528 $instances[ $key ] = absint( $instances[ $key ] ) + 1;
2344 2529 }
2345 2530 }
2346 2531
2532 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
2347 2533 $meta_query_args['meta_query'] = $refined_queries;
2348 2534 if ( count( $queries ) > 1 ) {
2535 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
2349 2536 $meta_query_args['meta_query']['relation'] = $params['metaQuery']['relation'] ?? 'AND';
2350 2537 }
2351 2538 }
2352 2539 }
@@ -2363,8 +2550,9 @@
2363 2550 private function query_loop_filter_by_context( $params, $post ) {
2364 2551 $context_args = [];
2365 2552
2366 2553 if ( $params['ignoreCurrentPost'] ?? false ) {
2554 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in
2367 2555 $context_args['post__not_in'] = [ $post->ID ];
2368 2556 }
2369 2557
2370 2558 if ( $params['queryRelatedPosts'] ?? false ) {
@@ -2387,8 +2575,9 @@
2387 2575 $tax_queries['relation'] = 'OR';
2388 2576 }
2389 2577
2390 2578 if ( $tax_queries ) {
2579 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
2391 2580 $context_args['tax_query'] = $tax_queries;
2392 2581 }
2393 2582 }
2394 2583
@@ -2471,8 +2660,9 @@
2471 2660 'post_type' => $query->query_vars['post_type'] ?? 'any',
2472 2661 'post_status' => 'publish',
2473 2662 'posts_per_page' => $posts_per_page - $found_posts,
2474 2663 'ignore_sticky_posts' => 1,
2664 + // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in
2475 2665 'post__not_in' => array_merge( $query->query_vars['post__not_in'] ?? [], $ignore_posts ),
2476 2666 'no_found_rows' => true,
2477 2667 ];
2478 2668
@@ -2484,8 +2674,50 @@
2484 2674 }
2485 2675 }
2486 2676
2487 2677 return $posts;
2678 + }
2679 +
2680 + /**
2681 + * Get the current post
2682 + *
2683 + * @return string
2684 + */
2685 + public function get_current_post() {
2686 + global $pagenow;
2687 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2688 + $post_id = 'post.php' === $pagenow && isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0;
2689 + $post = $post_id ? get_post( $post_id ) : false;
2690 +
2691 + return $post instanceof \WP_Post ? $post : false;
2692 + }
2693 +
2694 + /**
2695 + * Get animated blocks
2696 + */
2697 + public function get_animated_blocks() {
2698 + return apply_filters(
2699 + 'cbb_get_animated_blocks',
2700 + [
2701 + 'core/heading',
2702 + 'core/paragraph',
2703 + 'core/image',
2704 + 'core/button',
2705 + 'core/buttons',
2706 + 'core/list-item',
2707 + 'core/list',
2708 + 'core/group',
2709 + 'core/columns',
2710 + 'core/column',
2711 + 'core/cover',
2712 + 'core/media-text',
2713 + 'core/post-title',
2714 + 'core/post-excerpt',
2715 + 'core/post-terms',
2716 + 'core/readmore',
2717 + 'boldblocks/svg-block',
2718 + ]
2719 + );
2488 2720 }
2489 2721
2490 2722 /**
2491 2723 * Get max items