PluginProbe
bBlocks – Essential Gutenberg Blocks & Patterns Collection / 2.1.7
bBlocks – Essential Gutenberg Blocks & Patterns Collection v2.1.7
2.1.7 2.1.6 2.1.5 2.1.4 2.1.3 2.1.2 2.1.1 2.1.0 2.0.43 2.0.42 2.0.41 2.0.40 2.0.39 2.0.38 trunk 1.0 1.1 1.2 1.3 1.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 All 107 releases
← All changes | includes/Templates/Templates.php +128 -10 2.0.432.1.7 View file →
@@ -11,19 +11,121 @@
11 11 public function __construct() {
12 12 add_action( 'wp_ajax_bblocks_templates_main', [$this, 'bblocks_templates_main'] );
13 13 add_action( 'wp_ajax_bblocks_templates', [$this, 'bblocks_templates'] );
14 14 add_action( 'wp_ajax_bblocks_template_import', [$this, 'bblocks_template_import'] );
15 + add_action( 'wp_ajax_bblocks_template_counts', [$this, 'bblocks_template_counts'] );
15 16 }
16 17
18 + /**
19 + * Accurate Free/Pro counts per category for a type.
20 + *
21 + * The taxonomy endpoint only exposes a category total plus a single global
22 + * "pro" total, with no per-category free/pro split. So we pull the full
23 + * lightweight catalog once (ID + category only, 100/page) and tally it.
24 + * Result is cached in a transient since the catalog changes rarely.
25 + *
26 + * Shape: { all, free, pro, categories: { <cat>: { total, free, pro } } }
27 + */
28 + public function bblocks_template_counts(){
29 + $nonce = sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ?? '' ) );
30 +
31 + if( !wp_verify_nonce( $nonce, 'wp_ajax' )){
32 + wp_send_json_error( 'Invalid Request' );
33 + }
34 +
35 + if ( ! current_user_can( 'edit_posts' ) ) {
36 + wp_send_json_error( 'Unauthorized' );
37 + }
38 +
39 + $type = 'pages' === sanitize_text_field( wp_unslash( $_POST['type'] ?? 'patterns' ) ) ? 'pages' : 'patterns';
40 +
41 + $cacheKey = 'bblocks_tpl_counts_' . $type;
42 + $cached = get_transient( $cacheKey );
43 + if ( false !== $cached ) {
44 + wp_send_json_success( $cached );
45 + }
46 +
47 + $limit = 100;
48 + $page = 0;
49 + $items = [];
50 + $batch = [];
51 + $total = 0;
52 + $guard = 0;
53 +
54 + do {
55 + $response = wp_remote_get( 'https://templates.bplugins.com/wp-json/gutenberg-templates/v1/blocks?' . http_build_query( [
56 + 'type' => $type,
57 + 'start' => $page,
58 + 'end' => $page + 1,
59 + 'category' => 'all',
60 + 'keywords' => '',
61 + 'limit' => $limit,
62 + 'fields' => 'ID,category',
63 + ] ), [ 'timeout' => 20 ] );
64 +
65 + if ( is_wp_error( $response ) ) {
66 + break;
67 + }
68 +
69 + $body = json_decode( wp_remote_retrieve_body( $response ), true );
70 + $batch = isset( $body['patterns'] ) && is_array( $body['patterns'] ) ? $body['patterns'] : [];
71 + $total = isset( $body['count'] ) ? (int) $body['count'] : count( $items );
72 + $items = array_merge( $items, $batch );
73 +
74 + $page++;
75 + $guard++;
76 + } while ( count( $batch ) === $limit && count( $items ) < $total && $guard < 20 );
77 +
78 + $cats = [];
79 + $allFree = 0;
80 + $allPro = 0;
81 +
82 + foreach ( $items as $it ) {
83 + $itemCats = isset( $it['category'] ) && is_array( $it['category'] ) ? $it['category'] : [];
84 + $isPro = in_array( 'pro', $itemCats, true );
85 +
86 + if ( $isPro ) { $allPro++; } else { $allFree++; }
87 +
88 + foreach ( $itemCats as $c ) {
89 + if ( 'pro' === $c || 'free' === $c ) {
90 + continue;
91 + }
92 + if ( ! isset( $cats[ $c ] ) ) {
93 + $cats[ $c ] = [ 'total' => 0, 'free' => 0, 'pro' => 0 ];
94 + }
95 + $cats[ $c ]['total']++;
96 + if ( $isPro ) { $cats[ $c ]['pro']++; } else { $cats[ $c ]['free']++; }
97 + }
98 + }
99 +
100 + $data = [
101 + 'all' => count( $items ),
102 + 'free' => $allFree,
103 + 'pro' => $allPro,
104 + 'categories' => (object) $cats,
105 + ];
106 +
107 + // Cache only a complete tally (don't cache partial results from a failed run).
108 + if ( count( $items ) >= $total && $total > 0 ) {
109 + set_transient( $cacheKey, $data, 6 * HOUR_IN_SECONDS );
110 + }
111 +
112 + wp_send_json_success( $data );
113 + }
114 +
17 115 public function bblocks_templates_main(){
18 116 $nonce = sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ?? null ) );
19 - $type = sanitize_text_field( $_POST['type'] ?? 'pages');
117 + $type = sanitize_text_field( wp_unslash( $_POST['type'] ?? 'patterns' ) );
20 118
21 119 if( !wp_verify_nonce( $nonce, 'wp_ajax' )){
22 120 wp_send_json_error( 'Invalid Request' );
23 121 }
24 122
25 - $typeFilter = 'pages' === $type ? 'pages-category': 'patterns-category';
123 + if ( ! current_user_can( 'edit_posts' ) ) {
124 + wp_send_json_error( 'Unauthorized' );
125 + }
126 +
127 + $typeFilter = 'patterns' === $type ? 'patterns-category': 'pages-category';
26 128 // $response = wp_remote_get('https://templates.bplugins.com/wp-json/gutenberg-templates/v1/taxonomy/taxonomies/plugin,type,'.$typeFilter.'-category');
27 129 $response = wp_remote_get("https://templates.bplugins.com/wp-json/gutenberg-templates/v1/taxonomy/taxonomies/plugin,type,{$typeFilter}");
28 130
29 131 $body = json_decode( wp_remote_retrieve_body( $response ) );
@@ -36,18 +138,30 @@
36 138 if( !wp_verify_nonce( $nonce, 'wp_ajax' )){
37 139 wp_send_json_error( 'Invalid Request' );
38 140 }
39 141
40 - $type = sanitize_text_field( wp_unslash( $_POST['type'] ?? 'pages') ) ;
142 + if ( ! current_user_can( 'edit_posts' ) ) {
143 + wp_send_json_error( 'Unauthorized' );
144 + }
145 +
146 + $type = sanitize_text_field( wp_unslash( $_POST['type'] ?? 'patterns') ) ;
41 147 $category = sanitize_text_field( wp_unslash( $_POST['category'] ?? 'all' ) );
42 - $pageNumber = absint( wp_unslash( $_POST['pageNumber'] ) ) ?? 1;
148 + $pageNumber = absint( wp_unslash( $_POST['pageNumber'] ?? 1 ) );
149 + $pageNumber = $pageNumber > 0 ? $pageNumber : 1;
43 150 $start = $pageNumber - 1;
44 - $search = sanitize_text_field( wp_unslash( $_POST['search'] ) ) ?? '';
151 + $search = sanitize_text_field( wp_unslash( $_POST['search'] ?? '' ) );
45 152
46 - $typeFilter = 'pages' === $type ? 'pages': 'patterns';
153 + $typeFilter = 'patterns' === $type ? 'patterns': 'pages';
47 154
48 155 try {
49 - $response = wp_remote_get( "https://templates.bplugins.com/wp-json/gutenberg-templates/v1/blocks?type=$typeFilter&start=$start&end=$pageNumber&category=$category&keywords=$search&fields=ID,category,keywords,original_content,thumbnail,title,type,url" );
156 + $response = wp_remote_get( 'https://templates.bplugins.com/wp-json/gutenberg-templates/v1/blocks?' . http_build_query( [
157 + 'type' => $typeFilter,
158 + 'start' => $start,
159 + 'end' => $pageNumber,
160 + 'category' => $category,
161 + 'keywords' => $search,
162 + 'fields' => 'ID,category,keywords,original_content,thumbnail,title,type,url',
163 + ] ) );
50 164
51 165 // old
52 166 // $response = wp_remote_get( "https://templates.bplugins.com/wp-json/gutenberg-templates/v1/$typeFilter?start=$start&end=$pageNumber&category=$category&keywords=$search&fields=ID,category,keywords,original_content,thumbnail,title,type,url" );
53 167
@@ -58,16 +172,20 @@
58 172 }
59 173 }
60 174
61 175 public function bblocks_template_import(){
62 - $nonce = sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ) ?? null;
176 + $nonce = sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ?? '' ) );
63 177
64 178 if( !wp_verify_nonce( $nonce, 'wp_ajax' )){
65 179 wp_send_json_error( 'Invalid Request' );
66 180 }
67 -
181 +
182 + if ( ! current_user_can( 'edit_posts' ) ) {
183 + wp_send_json_error( 'Unauthorized' );
184 + }
185 +
68 186 try {
69 - $data = Image::instance()->maybe_import_images( wp_unslash( $_POST['original_content'] ) ?? '' );
187 + $data = Image::instance()->maybe_import_images( wp_unslash( $_POST['original_content'] ?? '' ) );
70 188 wp_send_json_success( $data );
71 189 } catch ( \Throwable $th ) {
72 190 wp_send_json_error( $th->getMessage() );
73 191 }