$attributes Block attributes. * @param string $content Inner blocks content. * @param \WP_Block|null $block Block instance. * @return string */ public static function render( array $attributes, string $content = '', ?\WP_Block $block = null ): string { unset( $content, $block ); $attributes = AttributeSanitizer::sanitize( $attributes ); $attributes = self::apply_pagination_context( $attributes ); $cache_enabled = ! empty( $attributes['cacheResults'] ); $cache_ttl = (int) $attributes['cacheTTL']; $paged = (int) $attributes['paged']; $cache_key = 'loopsi_' . md5( wp_json_encode( $attributes ) ); if ( $cache_enabled ) { $cached = get_transient( $cache_key ); if ( is_string( $cached ) && '' !== $cached ) { return $cached; } } $query = QueryBuilder::make( $attributes )->get(); if ( ! $query->have_posts() ) { $output = '

' . esc_html__( 'No posts found.', 'loopsi-blocks' ) . '

'; if ( $cache_enabled ) { CacheManager::remember_transient( $cache_key, $output, $cache_ttl ); } return $output; } ob_start(); echo '
'; self::render_grid_open( $attributes, (int) $query->max_num_pages ); self::render_posts( $query, $attributes ); self::render_grid_close(); wp_reset_postdata(); self::render_pagination( $query, $attributes, $paged ); echo '
'; $output = ob_get_clean(); if ( ! is_string( $output ) ) { $output = ''; } if ( $cache_enabled ) { CacheManager::remember_transient( $cache_key, $output, $cache_ttl ); } return $output; } /** * Render posts for AJAX pagination (grid contents only). * * @param array $attributes Block attributes. * @return array{html: string, has_more: bool} */ public static function render_ajax_page( array $attributes ): array { $attributes = AttributeSanitizer::sanitize( $attributes ); $paged = (int) $attributes['paged']; $query = QueryBuilder::make( $attributes )->get(); if ( ! $query->have_posts() ) { return array( 'html' => '', 'has_more' => false, ); } ob_start(); self::render_posts( $query, $attributes ); wp_reset_postdata(); $html = ob_get_clean(); return array( 'html' => is_string( $html ) ? $html : '', 'has_more' => $paged < (int) $query->max_num_pages, ); } /** * @param array $attributes Block attributes. */ private static function apply_pagination_context( array $attributes ): array { $loopsi_page = filter_input( INPUT_GET, 'loopsi_page', FILTER_VALIDATE_INT ); if ( is_int( $loopsi_page ) && $loopsi_page > 0 ) { $attributes['paged'] = $loopsi_page; } return $attributes; } /** * @param array $attributes Block attributes. * @param int $max_pages Total query pages. */ private static function render_grid_open( array $attributes, int $max_pages = 1 ): void { $layout = sanitize_key( (string) $attributes['layout'] ); $pagination_type = (string) ( $attributes['paginationType'] ?? 'none' ); $columns = max( 1, min( 6, (int) ( $attributes['columns'] ?? 3 ) ) ); $query_for_script = $attributes; unset( $query_for_script['paged'] ); $classes = array( 'loopsi-post-grid', 'loopsi-layout-' . $layout, ); if ( 'grid' === $layout ) { $classes[] = 'loopsi-columns-' . $columns; } ?>
style="" data-page="" data-max-pages="" data-pagination-type="" data-loopsi-query="" > '; } /** * @param \WP_Query $query Query instance. * @param array $attributes Block attributes. */ private static function render_posts( \WP_Query $query, array $attributes ): void { $display = self::get_display_settings( $attributes ); while ( $query->have_posts() ) { $query->the_post(); PostCardRenderer::render( $display ); } } /** * @param array $attributes Block attributes. * @return array */ private static function get_display_settings( array $attributes ): array { return array( 'showTitle' => ! empty( $attributes['showTitle'] ), 'showThumbnail' => ! empty( $attributes['showThumbnail'] ) || ! empty( $attributes['showFeaturedImage'] ), 'showFeaturedImage' => ! empty( $attributes['showThumbnail'] ) || ! empty( $attributes['showFeaturedImage'] ), 'showExcerpt' => ! empty( $attributes['showExcerpt'] ), 'showAuthor' => ! empty( $attributes['showAuthor'] ), 'showReadMore' => ! empty( $attributes['showReadMore'] ), 'readMoreText' => (string) ( $attributes['readMoreText'] ?? __( 'Read more', 'loopsi-blocks' ) ), ); } /** * @param \WP_Query $query Query instance. * @param array $attributes Block attributes. * @param int $paged Current page. */ private static function render_pagination( \WP_Query $query, array $attributes, int $paged ): void { $pagination_type = (string) ( $attributes['paginationType'] ?? 'none' ); $total_pages = (int) $query->max_num_pages; if ( 'none' === $pagination_type || $total_pages <= 1 ) { return; } ?>