Dashboard
PHP:
8.4.22
OS:
Linux
User:
provencez
/
/
home
/
provencez
/
www
/
wp-content
/
plugins
/
flexa-block
/
build
/
blocks
/
rss
📤 Upload
📝 New File
📁 New Folder
Close
Editing: render.php
<?php /** * RSS block — server-side render. * * CSS is generated at save time by Rss_CSS and printed inline on the front end. * This file fetches the configured RSS/Atom feed with WordPress `fetch_feed()` * (SimplePie, transient-cached for the chosen number of minutes) and outputs a * list or grid of item cards (thumbnail, meta, title, excerpt, read-more link). * Every dynamic value is escaped on output. * * @package Flexa\Block * * @var array $attributes Block attributes. * @var string $content Save content (unused — dynamic block). * @var WP_Block $block Block instance. */ if ( ! defined( 'ABSPATH' ) ) { exit; } // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- $attributes provided by WP block API. use Flexa\Block\HTML_Helpers; $block_id = $attributes['blockId'] ?? ''; $anchor = $attributes['anchor'] ?? ''; $html_tag = HTML_Helpers::get_html_tag( $attributes, 'section' ); $container_type = 'full-width' === ( $attributes['containerType'] ?? 'boxed' ) ? 'full-width' : 'boxed'; $layout = 'list' === ( $attributes['feedLayout'] ?? 'grid' ) ? 'list' : 'grid'; // --- Source attributes (sanitized). --- $feed_url = esc_url_raw( trim( (string) ( $attributes['feedUrl'] ?? '' ) ) ); $items_count = max( 1, min( 30, (int) ( $attributes['itemsToShow'] ?? 5 ) ) ); $cache_min = max( 5, min( 1440, (int) ( $attributes['cacheTime'] ?? 60 ) ) ); $newest_first = false !== ( $attributes['sortNewestFirst'] ?? true ); $new_tab = false !== ( $attributes['openInNewTab'] ?? true ); // --- Element toggles. --- $show_image = false !== ( $attributes['showImage'] ?? true ); $show_title = false !== ( $attributes['showTitle'] ?? true ); $title_tag = in_array( $attributes['titleTag'] ?? 'h3', [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'span', 'div' ], true ) ? $attributes['titleTag'] : 'h3'; $show_meta = false !== ( $attributes['showMeta'] ?? true ); $show_date = false !== ( $attributes['showDate'] ?? true ); $show_author = false !== ( $attributes['showAuthor'] ?? true ); $show_source = ! empty( $attributes['showSource'] ); $show_excerpt = false !== ( $attributes['showExcerpt'] ?? true ); $excerpt_length = max( 0, (int) ( $attributes['excerptLength'] ?? 20 ) ); $show_read_more = false !== ( $attributes['showReadMore'] ?? true ); $read_more_text = (string) ( $attributes['readMoreText'] ?? '' ); $read_more_text = '' !== trim( $read_more_text ) ? $read_more_text : __( 'Read more', 'flexa-block' ); // --- Pagination (client-side over the fetched pool). --- $pag_type = in_array( $attributes['paginationType'] ?? 'none', [ 'none', 'numbered', 'loadmore' ], true ) ? $attributes['paginationType'] : 'none'; $per_page = max( 1, min( 30, (int) ( $attributes['perPage'] ?? 6 ) ) ); $load_more_text = (string) ( $attributes['loadMoreText'] ?? '' ); $load_more_text = '' !== trim( $load_more_text ) ? $load_more_text : __( 'Load more', 'flexa-block' ); // --- Wrapper classes + attributes. --- $classes = [ 'flexa-rss', 'flexa-rss--' . $layout, 'flexa-rss--' . $container_type ]; if ( '' !== $block_id ) { $classes[] = 'flexa-rss-' . sanitize_html_class( $block_id ); } $classes = HTML_Helpers::build_wrapper_classes( $classes, $attributes ); $wrapper_args = [ 'class' => implode( ' ', $classes ) ]; if ( $anchor ) { $wrapper_args['id'] = sanitize_html_class( $anchor ); } // Pagination config for the view script (no-JS shows every item; JS pages them). if ( 'none' !== $pag_type ) { $wrapper_args['data-flexa-rss-pagination'] = $pag_type; $wrapper_args['data-per-page'] = (string) $per_page; $wrapper_args['data-loadmore-rows'] = '2'; if ( 'numbered' === $pag_type ) { $prev = trim( (string) ( $attributes['prevLabel'] ?? '' ) ); $next = trim( (string) ( $attributes['nextLabel'] ?? '' ) ); $wrapper_args['data-prev-label'] = '' !== $prev ? $prev : '‹'; $wrapper_args['data-next-label'] = '' !== $next ? $next : '›'; } } $wrapper_attributes = get_block_wrapper_attributes( $wrapper_args ); $data_attrs = HTML_Helpers::build_data_attrs( $attributes ); $link_target = $new_tab ? ' target="_blank" rel="noopener noreferrer"' : ''; $date_format = (string) get_option( 'date_format' ); // Inline aspect-ratio for the "no image" placeholder so it matches the chosen ratio. $image_ratio = trim( (string) ( $attributes['imageRatio'] ?? '' ) ); $ratio_style = ( '' !== $image_ratio && preg_match( '#^[0-9]+\s*/\s*[0-9]+$#', $image_ratio ) ) ? 'aspect-ratio:' . $image_ratio : ''; // --- Fetch + normalise the feed (shared with the editor preview). --- $items = \Flexa\Block\Rss_Feed::items( $feed_url, $items_count, $newest_first, $cache_min ); // --- Build the item cards. --- $cards_html = ''; foreach ( $items as $item ) { $permalink = esc_url( (string) $item['link'] ); // Thumbnail when the item carried an image URL — otherwise a neutral // placeholder glyph so cards keep a consistent height/layout. $image_html = ''; if ( $show_image ) { if ( '' !== (string) $item['image'] ) { $img = '<img class="flexa-rss__image" src="' . esc_url( (string) $item['image'] ) . '" alt="" loading="lazy" decoding="async" />'; $image_html = '<div class="flexa-rss__image-wrap"><a class="flexa-rss__image-link" href="' . $permalink . '"' . $link_target . ' tabindex="-1" aria-hidden="true">' . $img . '</a></div>'; } else { $image_html = '<div class="flexa-rss__image-wrap">' . HTML_Helpers::image_placeholder( '', $ratio_style ) . '</div>'; } } // Meta line: date · author · source. $meta_html = ''; if ( $show_meta ) { $parts = []; if ( $show_date && (int) $item['timestamp'] > 0 ) { $ts = (int) $item['timestamp']; $parts[] = '<time class="flexa-rss__date" datetime="' . esc_attr( gmdate( 'c', $ts ) ) . '">' . esc_html( date_i18n( $date_format, $ts ) ) . '</time>'; } if ( $show_author && '' !== (string) $item['author'] ) { $parts[] = '<span class="flexa-rss__author">' . esc_html( (string) $item['author'] ) . '</span>'; } if ( $show_source && '' !== (string) $item['source'] ) { $parts[] = '<span class="flexa-rss__source">' . esc_html( (string) $item['source'] ) . '</span>'; } if ( ! empty( $parts ) ) { $meta_html = '<div class="flexa-rss__meta">' . implode( '<span class="flexa-rss__meta-sep" aria-hidden="true">·</span>', $parts ) . '</div>'; } } // Title (linked). $title_html = ''; if ( $show_title ) { $title_text = trim( (string) $item['title'] ); if ( '' === $title_text ) { $title_text = __( '(untitled)', 'flexa-block' ); } $title_html = '<' . $title_tag . ' class="flexa-rss__title"><a class="flexa-rss__title-link" href="' . $permalink . '"' . $link_target . '>' . esc_html( $title_text ) . '</a></' . $title_tag . '>'; } // Excerpt (already plain text; trimmed to the chosen word count). $excerpt_html = ''; if ( $show_excerpt && $excerpt_length > 0 ) { $trimmed = wp_trim_words( (string) $item['description'], $excerpt_length, '…' ); if ( '' !== trim( $trimmed ) ) { $excerpt_html = '<div class="flexa-rss__excerpt">' . esc_html( $trimmed ) . '</div>'; } } // Read-more link. $read_more_html = ''; if ( $show_read_more ) { $read_more_html = '<a class="flexa-rss__readmore wp-element-button" href="' . $permalink . '"' . $link_target . '>' . esc_html( $read_more_text ) . '</a>'; } $body_html = '<div class="flexa-rss__body">' . $meta_html . $title_html . $excerpt_html . $read_more_html . '</div>'; $cards_html .= '<article class="flexa-rss__item">' . $image_html . $body_html . '</article>'; } // --- Pagination control (filled/toggled by view.js; no-JS shows every item). --- $pagination_html = ''; if ( '' !== $cards_html && 'numbered' === $pag_type ) { $pagination_html = '<nav class="flexa-pagination" aria-label="' . esc_attr__( 'Feed navigation', 'flexa-block' ) . '"></nav>'; } elseif ( '' !== $cards_html && 'loadmore' === $pag_type ) { $pagination_html = '<div class="flexa-pagination-loadmore"><button type="button" class="flexa-pagination-loadmore__btn wp-element-button">' . esc_html( $load_more_text ) . '</button></div>'; } // --- Body: the cards, or a graceful empty state. --- if ( '' !== $cards_html ) { $inner_html = '<div class="flexa-rss__grid">' . $cards_html . '</div>' . $pagination_html; } elseif ( '' === $feed_url ) { $inner_html = '<p class="flexa-rss__empty">' . esc_html__( 'Add a feed URL to show entries.', 'flexa-block' ) . '</p>'; } else { $inner_html = '<p class="flexa-rss__empty">' . esc_html__( 'No feed entries could be loaded.', 'flexa-block' ) . '</p>'; } printf( '<%1$s %2$s%3$s><div class="flexa-rss__inner">%4$s</div></%1$s>', esc_html( $html_tag ), $wrapper_attributes, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- built via get_block_wrapper_attributes. $data_attrs, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- keys sanitized, values escaped in helper. $inner_html // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- titles/dates/excerpts esc_html'd, urls esc_url'd, image markup built with escaped src. );
Save
Cancel