PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / 2.13.1
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder v2.13.1
2.13.0 2.13.1 2.12.0 2.11.1 2.11.0 2.10.0 2.9.0 2.7.4 2.7.5 2.7.6 2.7.7 2.8.0 2.8.1 2.9.1 trunk 1.0 1.0-beta1 1.0-beta2 1.0-beta3 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 All 80 releases
← All changes | includes/api/loop-builder-controller.php +44 -12 2.13.02.13.1 View file →
@@ -80,8 +80,19 @@
80 80 $term_id = (int) $payload['term_id'];
81 81 $page = (int) ( isset( $payload['page'] ) ? $payload['page'] : 1 );
82 82 $is_archive = (bool) ( isset( $payload['is_archive'] ) ? $payload['is_archive'] : false );
83 83
84 + // This route is public, so the request may only narrow the loop to a
85 + // post type or taxonomy the site already exposes to visitors. sanitize_key
86 + // fixes the spelling, not the visibility: without this an anonymous
87 + // request could point an archive loop at an internal post type.
88 + if ( ! empty( $payload['archive_post_type'] ) && ! is_post_type_viewable( (string) $payload['archive_post_type'] ) ) {
89 + return $this->empty_response( $term_id, $post_id, 400 );
90 + }
91 + if ( ! empty( $taxonomy ) && ! is_taxonomy_viewable( (string) $taxonomy ) ) {
92 + return $this->empty_response( $term_id, $post_id, 400 );
93 + }
94 +
84 95 /* ---------------- ARCHIVE LOGIC (UNCHANGED) ---------------- */
85 96
86 97 if ( $is_archive ) {
87 98
@@ -130,19 +141,9 @@
130 141 $loop_builder_block = $this->find_block_in_theme_templates( $loop_builder_block_id, 'ablocks/loop-builder' );
131 142 }
132 143
133 144 if ( ! $loop_builder_block ) {
134 - return new WP_REST_Response(
135 - [
136 - 'success' => false,
137 - 'data' => [
138 - 'html' => '',
139 - 'term_id' => $term_id,
140 - 'post_id' => $post_id,
141 - ],
142 - ],
143 - 404
144 - );
145 + return $this->empty_response( $term_id, $post_id, 404 );
145 146 }
146 147
147 148 $block_data = [ 'parentAttributes' => $loop_builder_block['attrs'] ];
148 149 $blocks = [ $loop_builder_block ];
@@ -160,9 +161,23 @@
160 161 if ( $is_archive && ! empty( $payload['archive_post_type'] ) ) {
161 162 $query_vars['post_type'] = $payload['archive_post_type'];
162 163 }
163 164
164 - $query_vars['posts_per_page'] = $query_vars['posts_per_page'] * $page;
165 + // "Load more" asks for page N and receives the first N pages at once, so
166 + // the request's page number multiplies the stored page size. It comes
167 + // from an anonymous request, so bound the result: at most
168 + // `ablocks/loop_builder/max_posts_per_request` posts (never fewer than
169 + // one stored page), however large the page number.
170 + $per_page = (int) $query_vars['posts_per_page'];
171 + $max_posts = (int) apply_filters( 'ablocks/loop_builder/max_posts_per_request', 100, $block_data['parentAttributes'] );
172 + if ( $per_page < 1 ) {
173 + // A loop set to show every post still gets the bound.
174 + $query_vars['posts_per_page'] = max( 1, $max_posts );
175 + } else {
176 + $max_posts = max( $per_page, $max_posts );
177 + $page = max( 1, min( $page, (int) ceil( $max_posts / $per_page ) ) );
178 + $query_vars['posts_per_page'] = min( $per_page * $page, $max_posts );
179 + }
165 180
166 181 if ( ! empty( $taxonomy ) && $term_id ) {
167 182 $query_vars['tax_query'] = [
168 183 [
@@ -207,8 +222,25 @@
207 222 'post_id' => $post_id,
208 223 ],
209 224 ],
210 225 200
226 + );
227 + }
228 +
229 + /**
230 + * The response for a request that cannot be rendered.
231 + */
232 + private function empty_response( $term_id, $post_id, $status ) {
233 + return new WP_REST_Response(
234 + [
235 + 'success' => false,
236 + 'data' => [
237 + 'html' => '',
238 + 'term_id' => $term_id,
239 + 'post_id' => $post_id,
240 + ],
241 + ],
242 + $status
211 243 );
212 244 }
213 245
214 246 /**