| @@ -1,9 +1,8 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | 3 | namespace ABlocks\API; |
| 4 | 4 | |
| 5 | -use ABlocks\Helper; | |
| 6 | 5 | use WP_REST_Server; |
| 7 | 6 | use WP_REST_Response; |
| 8 | 7 | |
| 9 | 8 | if ( ! defined( 'ABSPATH' ) ) { |
| @@ -85,8 +84,9 @@ | ||
| 85 | 84 | /* ---------------- ARCHIVE LOGIC (UNCHANGED) ---------------- */ |
| 86 | 85 | |
| 87 | 86 | if ( $is_archive ) { |
| 88 | 87 | |
| 88 | + $template_slug = ''; | |
| 89 | 89 | if ( ! empty( $payload['archive_post_type'] ) ) { |
| 90 | 90 | $template_slug = 'archive-' . $payload['archive_post_type']; |
| 91 | 91 | |
| 92 | 92 | } elseif ( ! empty( $payload['taxonomy'] ) ) { |
| @@ -113,29 +113,40 @@ | ||
| 113 | 113 | ], |
| 114 | 114 | ], |
| 115 | 115 | ]); |
| 116 | 116 | |
| 117 | - $post_content = current( $template_posts )->post_content; | |
| 118 | - $blocks = parse_blocks( $post_content ); | |
| 117 | + $template_post = current( $template_posts ); | |
| 118 | + $blocks = $template_post ? parse_blocks( $template_post->post_content ) : []; | |
| 119 | 119 | |
| 120 | - $block_data = Helper::get_block_attributes_recursive( | |
| 121 | - $loop_builder_block_id, | |
| 122 | - 'ablocks/loop-builder', | |
| 123 | - $blocks | |
| 124 | - ); | |
| 120 | + } else { | |
| 125 | 121 | |
| 126 | - } else { | |
| 122 | + $post = get_post( $post_id ); | |
| 123 | + $blocks = $this->is_post_readable( $post ) ? parse_blocks( $post->post_content ) : []; | |
| 124 | + }//end if | |
| 127 | 125 | |
| 128 | - $block_data = Helper::get_block_attributes( | |
| 129 | - $post_id, | |
| 130 | - $loop_builder_block_id, | |
| 131 | - 'ablocks/loop-builder' | |
| 126 | + // The loop may sit inside a synced pattern or template part referenced | |
| 127 | + // from the content, or in the theme template rendered around the post. | |
| 128 | + $loop_builder_block = $this->find_block( $blocks, $loop_builder_block_id, 'ablocks/loop-builder' ); | |
| 129 | + if ( ! $loop_builder_block ) { | |
| 130 | + $loop_builder_block = $this->find_block_in_theme_templates( $loop_builder_block_id, 'ablocks/loop-builder' ); | |
| 131 | + } | |
| 132 | + | |
| 133 | + 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 | |
| 132 | 144 | ); |
| 145 | + } | |
| 133 | 146 | |
| 134 | - $post = get_post( $post_id ); | |
| 135 | - $post_content = $post->post_content; | |
| 136 | - $blocks = parse_blocks( $post_content ); | |
| 137 | - }//end if | |
| 147 | + $block_data = [ 'parentAttributes' => $loop_builder_block['attrs'] ]; | |
| 148 | + $blocks = [ $loop_builder_block ]; | |
| 138 | 149 | |
| 139 | 150 | /* ---------------- QUERY LOGIC (UNCHANGED) ---------------- */ |
| 140 | 151 | |
| 141 | 152 | $query_vars = isset( $block_data['parentAttributes']['query'] ) |
| @@ -162,13 +173,8 @@ | ||
| 162 | 173 | ], |
| 163 | 174 | ]; |
| 164 | 175 | } |
| 165 | 176 | |
| 166 | - $blocks = $this->get_loop_builder_blocks_by_block_id( | |
| 167 | - $blocks, | |
| 168 | - $loop_builder_block_id | |
| 169 | - ); | |
| 170 | - | |
| 171 | 177 | $updated_blocks = $this->update_loop_builder_query( |
| 172 | 178 | $blocks, |
| 173 | 179 | $loop_template_block_id, |
| 174 | 180 | $query_vars, |
| @@ -180,9 +186,16 @@ | ||
| 180 | 186 | foreach ( $updated_blocks as $block ) { |
| 181 | 187 | $html .= serialize_block( $block ); |
| 182 | 188 | } |
| 183 | 189 | |
| 184 | - $rendered = apply_filters( 'the_content', do_blocks( $html ) ); | |
| 190 | + // Render the fragment the way block templates are rendered. Running the | |
| 191 | + // already-rendered markup through the_content re-applied wpautop (stray | |
| 192 | + // <p> tags) and let other plugins append their post-content extras. | |
| 193 | + $rendered = do_shortcode( shortcode_unautop( $html ) ); | |
| 194 | + $rendered = do_blocks( $rendered ); | |
| 195 | + $rendered = wptexturize( $rendered ); | |
| 196 | + $rendered = convert_smilies( $rendered ); | |
| 197 | + $rendered = wp_filter_content_tags( $rendered, 'template' ); | |
| 185 | 198 | |
| 186 | 199 | /* ---------------- REST RESPONSE (ONLY CHANGE) ---------------- */ |
| 187 | 200 | |
| 188 | 201 | return new WP_REST_Response( |
| @@ -195,8 +208,96 @@ | ||
| 195 | 208 | ], |
| 196 | 209 | ], |
| 197 | 210 | 200 |
| 198 | 211 | ); |
| 212 | + } | |
| 213 | + | |
| 214 | + /** | |
| 215 | + * Only published, non-password-protected content is public; anything else | |
| 216 | + * needs the current user to be able to read it. | |
| 217 | + */ | |
| 218 | + private function is_post_readable( $post ) { | |
| 219 | + if ( ! $post instanceof \WP_Post ) { | |
| 220 | + return false; | |
| 221 | + } | |
| 222 | + if ( 'publish' === $post->post_status && ! post_password_required( $post ) ) { | |
| 223 | + return true; | |
| 224 | + } | |
| 225 | + return current_user_can( 'read_post', $post->ID ); | |
| 226 | + } | |
| 227 | + | |
| 228 | + /** | |
| 229 | + * Find a block by name + block_id, following synced pattern references | |
| 230 | + * (core/block) and template parts (core/template-part). | |
| 231 | + */ | |
| 232 | + private function find_block( array $blocks, $block_id, $block_name, array $visited = [] ) { | |
| 233 | + foreach ( $blocks as $block ) { | |
| 234 | + $name = isset( $block['blockName'] ) ? $block['blockName'] : ''; | |
| 235 | + | |
| 236 | + if ( $name === $block_name && ( isset( $block['attrs']['block_id'] ) ? $block['attrs']['block_id'] : '' ) === $block_id ) { | |
| 237 | + return $block; | |
| 238 | + } | |
| 239 | + | |
| 240 | + if ( ! empty( $block['innerBlocks'] ) ) { | |
| 241 | + $found = $this->find_block( $block['innerBlocks'], $block_id, $block_name, $visited ); | |
| 242 | + if ( $found ) { | |
| 243 | + return $found; | |
| 244 | + } | |
| 245 | + } | |
| 246 | + | |
| 247 | + $ref_key = ''; | |
| 248 | + $content = null; | |
| 249 | + if ( 'core/block' === $name && ! empty( $block['attrs']['ref'] ) ) { | |
| 250 | + $ref_key = 'wp_block:' . (int) $block['attrs']['ref']; | |
| 251 | + if ( ! isset( $visited[ $ref_key ] ) ) { | |
| 252 | + $ref_post = get_post( (int) $block['attrs']['ref'] ); | |
| 253 | + if ( $ref_post && 'wp_block' === $ref_post->post_type && $this->is_post_readable( $ref_post ) ) { | |
| 254 | + $content = $ref_post->post_content; | |
| 255 | + } | |
| 256 | + } | |
| 257 | + } elseif ( 'core/template-part' === $name && ! empty( $block['attrs']['slug'] ) ) { | |
| 258 | + $theme = ! empty( $block['attrs']['theme'] ) ? $block['attrs']['theme'] : get_stylesheet(); | |
| 259 | + $ref_key = 'wp_template_part:' . $theme . '//' . $block['attrs']['slug']; | |
| 260 | + if ( ! isset( $visited[ $ref_key ] ) ) { | |
| 261 | + $part = get_block_template( $theme . '//' . $block['attrs']['slug'], 'wp_template_part' ); | |
| 262 | + if ( $part && 'publish' === $part->status ) { | |
| 263 | + $content = $part->content; | |
| 264 | + } | |
| 265 | + } | |
| 266 | + } | |
| 267 | + | |
| 268 | + if ( is_string( $content ) && '' !== $content ) { | |
| 269 | + $visited[ $ref_key ] = true; | |
| 270 | + $found = $this->find_block( parse_blocks( $content ), $block_id, $block_name, $visited ); | |
| 271 | + if ( $found ) { | |
| 272 | + return $found; | |
| 273 | + } | |
| 274 | + } | |
| 275 | + }//end foreach | |
| 276 | + return null; | |
| 277 | + } | |
| 278 | + | |
| 279 | + /** | |
| 280 | + * Fallback for loops placed in the active theme's templates or template | |
| 281 | + * parts rather than in the post content itself. | |
| 282 | + */ | |
| 283 | + private function find_block_in_theme_templates( $block_id, $block_name ) { | |
| 284 | + foreach ( [ 'wp_template', 'wp_template_part' ] as $template_type ) { | |
| 285 | + foreach ( get_block_templates( [], $template_type ) as $template ) { | |
| 286 | + $content = (string) $template->content; | |
| 287 | + if ( | |
| 288 | + 'publish' !== $template->status || | |
| 289 | + ( false === strpos( $content, $block_id ) && false === strpos( $content, '<!-- wp:block ' ) && false === strpos( $content, '<!-- wp:template-part ' ) ) | |
| 290 | + ) { | |
| 291 | + continue; | |
| 292 | + } | |
| 293 | + $found = $this->find_block( parse_blocks( $content ), $block_id, $block_name ); | |
| 294 | + if ( $found ) { | |
| 295 | + return $found; | |
| 296 | + } | |
| 297 | + } | |
| 298 | + } | |
| 299 | + return null; | |
| 199 | 300 | } |
| 200 | 301 | |
| 201 | 302 | public function get_loop_builder_blocks_by_block_id( $blocks, $target_block_id ) { |
| 202 | 303 | foreach ( $blocks as $block ) { |