PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / trunk
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder vtrunk
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 1.2.0 1.2.1 All 78 releases
ablocks / includes / api / loop-builder-controller.php

loop-builder-controller.php in aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder trunk, at includes/api/loop-builder-controller.php

329 lines 8.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace ABlocks\API;
4
5 use ABlocks\Helper;
6 use WP_REST_Server;
7 use WP_REST_Response;
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 class LoopBuilderController {
14
15 public function __construct() {
16 add_action( 'rest_api_init', [ $this, 'register_routes' ] );
17 }
18
19 public function register_routes() {
20
21 register_rest_route(
22 ABLOCKS_REST_NAMESPACE,
23 '/loop-builder',
24 [
25 'methods' => WP_REST_Server::READABLE,
26 'callback' => [ $this, 'render_loop_builder' ],
27 'permission_callback' => '__return_true',
28 'args' => [
29 'loop_builder_block_id' => [
30 'required' => true,
31 'type' => 'string',
32 'sanitize_callback' => 'sanitize_text_field',
33 ],
34 'loop_template_block_id' => [
35 'required' => true,
36 'type' => 'string',
37 'sanitize_callback' => 'sanitize_text_field',
38 ],
39 'taxonomy' => [
40 'required' => false,
41 'type' => 'string',
42 'sanitize_callback' => 'sanitize_key',
43 ],
44 'post_id' => [
45 'required' => false,
46 'type' => 'integer',
47 'sanitize_callback' => 'absint',
48 ],
49 'term_id' => [
50 'required' => false,
51 'type' => 'integer',
52 'sanitize_callback' => 'absint',
53 ],
54 'page' => [
55 'required' => false,
56 'type' => 'integer',
57 'default' => 1,
58 'sanitize_callback' => 'absint',
59 ],
60 'is_archive' => [
61 'required' => false,
62 'type' => 'boolean',
63 'default' => false,
64 ],
65 'archive_post_type' => [
66 'required' => false,
67 'type' => 'string',
68 'sanitize_callback' => 'sanitize_key',
69 ],
70 ],
71 ]
72 );
73 }
74
75 public function render_loop_builder( $payload ) {
76
77 $post_id = $payload['post_id'];
78 $loop_builder_block_id = $payload['loop_builder_block_id'];
79 $loop_template_block_id = $payload['loop_template_block_id'];
80 $taxonomy = $payload['taxonomy'];
81 $term_id = (int) $payload['term_id'];
82 $page = (int) ( isset( $payload['page'] ) ? $payload['page'] : 1 );
83 $is_archive = (bool) ( isset( $payload['is_archive'] ) ? $payload['is_archive'] : false );
84
85 /* ---------------- ARCHIVE LOGIC (UNCHANGED) ---------------- */
86
87 if ( $is_archive ) {
88
89 if ( ! empty( $payload['archive_post_type'] ) ) {
90 $template_slug = 'archive-' . $payload['archive_post_type'];
91
92 } elseif ( ! empty( $payload['taxonomy'] ) ) {
93
94 if ( ! empty( $payload['term_slug'] ) ) {
95 $template_slug = 'archive-' . $payload['taxonomy'] . '-' . $payload['term_slug'];
96 } else {
97 $template_slug = 'archive-' . $payload['taxonomy'];
98 }
99 }
100
101 $theme_slug = wp_get_theme()->get_stylesheet();
102
103 $template_posts = get_posts([
104 'post_type' => 'wp_template',
105 'post_status' => 'publish',
106 'numberposts' => 1,
107 'name' => $template_slug,
108 'tax_query' => [
109 [
110 'taxonomy' => 'wp_theme',
111 'field' => 'slug',
112 'terms' => $theme_slug,
113 ],
114 ],
115 ]);
116
117 $post_content = current( $template_posts )->post_content;
118 $blocks = parse_blocks( $post_content );
119
120 $block_data = Helper::get_block_attributes_recursive(
121 $loop_builder_block_id,
122 'ablocks/loop-builder',
123 $blocks
124 );
125
126 } else {
127
128 $block_data = Helper::get_block_attributes(
129 $post_id,
130 $loop_builder_block_id,
131 'ablocks/loop-builder'
132 );
133
134 $post = get_post( $post_id );
135 $post_content = $post->post_content;
136 $blocks = parse_blocks( $post_content );
137 }//end if
138
139 /* ---------------- QUERY LOGIC (UNCHANGED) ---------------- */
140
141 $query_vars = isset( $block_data['parentAttributes']['query'] )
142 ? $this->convert_to_wp_query_args( $block_data['parentAttributes']['query'] )
143 : [
144 'post_type' => 'post',
145 'post_status' => 'publish',
146 'posts_per_page' => get_option( 'posts_per_page' ),
147 ];
148
149 if ( $is_archive && ! empty( $payload['archive_post_type'] ) ) {
150 $query_vars['post_type'] = $payload['archive_post_type'];
151 }
152
153 $query_vars['posts_per_page'] = $query_vars['posts_per_page'] * $page;
154
155 if ( ! empty( $taxonomy ) && $term_id ) {
156 $query_vars['tax_query'] = [
157 [
158 'taxonomy' => $taxonomy,
159 'field' => 'term_id',
160 'terms' => [ $term_id ],
161 'operator' => 'IN',
162 ],
163 ];
164 }
165
166 $blocks = $this->get_loop_builder_blocks_by_block_id(
167 $blocks,
168 $loop_builder_block_id
169 );
170
171 $updated_blocks = $this->update_loop_builder_query(
172 $blocks,
173 $loop_template_block_id,
174 $query_vars,
175 $term_id
176 );
177
178 $html = '';
179
180 foreach ( $updated_blocks as $block ) {
181 $html .= serialize_block( $block );
182 }
183
184 $rendered = apply_filters( 'the_content', do_blocks( $html ) );
185
186 /* ---------------- REST RESPONSE (ONLY CHANGE) ---------------- */
187
188 return new WP_REST_Response(
189 [
190 'success' => true,
191 'data' => [
192 'html' => $rendered,
193 'term_id' => $term_id,
194 'post_id' => $post_id,
195 ],
196 ],
197 200
198 );
199 }
200
201 public function get_loop_builder_blocks_by_block_id( $blocks, $target_block_id ) {
202 foreach ( $blocks as $block ) {
203 if ( ! empty( $block['attrs']['block_id'] ) && $block['attrs']['block_id'] === $target_block_id ) {
204 return [ $block ];
205 }
206 if ( ! empty( $block['innerBlocks'] ) ) {
207 $found = $this->get_loop_builder_blocks_by_block_id( $block['innerBlocks'], $target_block_id );
208 if ( ! empty( $found ) ) {
209 return $found;
210 }
211 }
212 }
213 return [];
214 }
215
216 public function update_loop_builder_query( $blocks, $loop_template_block_id, $query_vars, $term_id ) {
217 foreach ( $blocks as &$block ) {
218 // perfectly not worked if multiple loop used
219 // !empty($block['attrs']['block_id']) && $block['attrs']['block_id'] === $loop_template_block_id
220
221 if ( ! empty( $block['blockName'] ) && $block['blockName'] === 'ablocks/loop-template' ) {
222 if ( ! isset( $block['attrs']['query'] ) ) {
223 $block['attrs']['query'] = [];
224 }
225 // Merge new query vars
226 $block['attrs']['query'] = array_merge( $block['attrs']['query'], $query_vars );
227 }
228
229 if ( 'ablocks/loop-filter' === $block['blockName'] ) {
230 $block['attrs']['active_term_id'] = $term_id;
231 }
232
233 // Recurse into inner blocks
234 if ( ! empty( $block['innerBlocks'] ) ) {
235 $block['innerBlocks'] = $this->update_loop_builder_query( $block['innerBlocks'], $loop_template_block_id, $query_vars, $term_id );
236 }
237 }//end foreach
238 return $blocks;
239 }
240
241 public function convert_to_wp_query_args( array $input ): array {
242 $args = [
243 'post_status' => 'publish',
244 ];
245
246 // Basic pagination
247 $args['posts_per_page'] = isset( $input['perPage'] ) ? (int) $input['perPage'] : get_option( 'posts_per_page' );
248 $args['paged'] = isset( $input['pages'] ) && $input['pages'] > 0 ? (int) $input['pages'] : 1;
249
250 // Post type
251 if ( ! empty( $input['postType'] ) ) {
252 $args['post_type'] = $input['postType'];
253 }
254
255 // Order and orderby
256 if ( ! empty( $input['order'] ) ) {
257 $args['order'] = $input['order'];
258 }
259
260 if ( ! empty( $input['orderBy'] ) ) {
261 $args['orderby'] = $input['orderBy'];
262 }
263
264 // Author
265 if ( ! empty( $input['author'] ) ) {
266 $args['author'] = $input['author'];
267 }
268
269 // Search
270 if ( ! empty( $input['search'] ) ) {
271 $args['s'] = $input['search'];
272 }
273
274 // Exclude posts
275 if ( ! empty( $input['exclude'] ) && is_array( $input['exclude'] ) ) {
276 $args['post__not_in'] = array_map( 'intval', $input['exclude'] );
277 }
278
279 // Sticky posts
280 if ( ! empty( $input['sticky'] ) ) {
281 if ( $input['sticky'] === 'include' ) {
282 $args['ignore_sticky_posts'] = 0;
283 } elseif ( $input['sticky'] === 'exclude' ) {
284 $args['ignore_sticky_posts'] = 1;
285 }
286 }
287
288 // Post parent (for hierarchical post types like pages)
289 if ( ! empty( $input['parents'] ) && is_array( $input['parents'] ) ) {
290 $args['post_parent__in'] = array_map( 'intval', $input['parents'] );
291 }
292
293 // Offset
294 if ( isset( $input['offset'] ) ) {
295 $args['offset'] = (int) $input['offset'];
296 }
297
298 // Format (post format taxonomy)
299 if ( ! empty( $input['format'] ) ) {
300 $args['tax_query'][] = [
301 'taxonomy' => 'post_format',
302 'field' => 'slug',
303 'terms' => [ 'post-format-' . sanitize_title( $input['format'] ) ],
304 ];
305 }
306
307 // Category
308 if ( ! empty( $input['category'] ) ) {
309 $args['category_name'] = $input['category'];
310 }
311
312 // Tag
313 if ( ! empty( $input['tag'] ) ) {
314 $args['tag'] = $input['tag'];
315 }
316
317 // Generic taxonomy query
318 if ( ! empty( $input['taxonomy'] ) && ! empty( $input['value'] ) ) {
319 $args['tax_query'][] = [
320 'taxonomy' => $input['taxonomy'],
321 'field' => 'slug',
322 'terms' => is_array( $input['value'] ) ? $input['value'] : [ $input['value'] ],
323 ];
324 }
325
326 return $args;
327 }
328 }
329