Dashboard
PHP:
8.4.22
OS:
Linux
User:
provencez
/
/
home
/
provencez
/
www
/
wp-content
/
plugins
/
flexa-block
/
build
/
blocks
/
timeline
📤 Upload
📝 New File
📁 New Folder
Close
Editing: render.php
<?php /** * Timeline block — server-side render. * * CSS is generated at save time by Timeline_CSS and printed inline on the front * end. This file outputs the chronological timeline: one item per event, each * with its marker (an icon, else an empty node), a connecting line to the next * event, a date, a title and a description. In the "alternate" layout entries * zig-zag left/right of the line; in "left"/"right" they sit on a single side. * Dates, titles and descriptions inherit the theme's typography unless the user * overrode it. * * @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 ); $items = $attributes['items'] ?? []; if ( ! is_array( $items ) || empty( $items ) ) { return; } $layout = in_array( $attributes['timelineLayout'] ?? 'alternate', [ 'alternate', 'left', 'right' ], true ) ? $attributes['timelineLayout'] : 'alternate'; $marker_shape = in_array( $attributes['markerShape'] ?? 'circle', [ 'circle', 'square', 'rounded' ], true ) ? $attributes['markerShape'] : 'circle'; $date_position = in_array( $attributes['datePosition'] ?? 'above', [ 'inline', 'above' ], true ) ? $attributes['datePosition'] : 'above'; $image_position = in_array( $attributes['imagePosition'] ?? 'top', [ 'top', 'bottom' ], true ) ? $attributes['imagePosition'] : 'top'; $connector_show = false !== ( $attributes['connectorShow'] ?? true ); // Inline formatting allowed inside the title / date. $title_allowed = [ 'strong' => [], 'em' => [], 'b' => [], 'i' => [], 'br' => [], 'span' => [], ]; // Build the timeline items. $items_html = ''; $rows = array_values( $items ); $total = count( $rows ); $position = 0; foreach ( $rows as $index => $item ) { if ( ! is_array( $item ) ) { continue; } $date = wp_kses( (string) ( $item['date'] ?? '' ), $title_allowed ); $title = wp_kses( (string) ( $item['title'] ?? '' ), $title_allowed ); $desc = wp_kses( (string) ( $item['description'] ?? '' ), $title_allowed ); $has_image = '' !== (string) ( ( is_array( $item['image'] ?? null ) ? $item['image']['url'] ?? '' : '' ) ); if ( '' === trim( wp_strip_all_tags( $title ) ) && '' === trim( wp_strip_all_tags( $desc ) ) && '' === trim( wp_strip_all_tags( $date ) ) && ! $has_image ) { continue; } // Marker inner content: an icon (uploaded image or inline SVG), else empty. $marker_inner = ''; $icon_cfg = is_array( $item['icon'] ?? null ) ? $item['icon'] : []; $source = (string) ( $icon_cfg['source'] ?? 'none' ); $markup = (string) ( $icon_cfg['markup'] ?? '' ); $icon_url = (string) ( $icon_cfg['url'] ?? '' ); if ( 'upload' === $source && '' !== $icon_url ) { $marker_inner = '<img src="' . esc_url( $icon_url ) . '" alt="" width="24" height="24" loading="lazy" />'; } elseif ( 'none' !== $source && '' !== $markup ) { $marker_inner = HTML_Helpers::svg_kses( $markup ); } // Side placement: alternate zig-zags, otherwise a fixed single side. $side = 'alternate' === $layout ? ( 0 === $position % 2 ? 'left' : 'right' ) : $layout; ++$position; $item_class = 'flexa-timeline__item is-' . sanitize_html_class( $side ); $is_last = ( $index === $total - 1 ); $connector_html = ( $connector_show && ! $is_last ) ? '<span class="flexa-timeline__connector" aria-hidden="true"></span>' : ''; $date_html = '' !== trim( wp_strip_all_tags( $date ) ) ? '<span class="flexa-timeline__date">' . $date . '</span>' : ''; $title_html = '' !== trim( wp_strip_all_tags( $title ) ) ? '<span class="flexa-timeline__title">' . $title . '</span>' : ''; $desc_html = '' !== trim( wp_strip_all_tags( $desc ) ) ? '<span class="flexa-timeline__description">' . $desc . '</span>' : ''; // Optional per-entry image, placed above or below the text per imagePosition. $image_html = ''; $image_cfg = is_array( $item['image'] ?? null ) ? $item['image'] : []; $image_url = (string) ( $image_cfg['url'] ?? '' ); if ( '' !== $image_url ) { $image_alt = esc_attr( (string) ( $image_cfg['alt'] ?? '' ) ); $image_html = '<img class="flexa-timeline__image flexa-timeline__image--' . esc_attr( $image_position ) . '" src="' . esc_url( $image_url ) . '" alt="' . $image_alt . '" loading="lazy" />'; } $content_html = 'top' === $image_position ? $image_html . $date_html . $title_html . $desc_html : $date_html . $title_html . $desc_html . $image_html; $items_html .= '<div class="' . esc_attr( $item_class ) . '"' . \Flexa\Block\Inline_Editor::item_attr( $index ) . '>'; $items_html .= '<div class="flexa-timeline__aside"><span class="flexa-timeline__marker">' . $marker_inner . '</span>' . $connector_html . '</div>'; $items_html .= '<div class="flexa-timeline__content"><div class="flexa-timeline__card">' . $content_html . '</div></div>'; $items_html .= '</div>'; } if ( '' === $items_html ) { return; } // Wrapper classes + attributes. $classes = [ 'flexa-timeline', 'flexa-timeline--' . sanitize_html_class( $layout ), 'flexa-timeline--marker-' . sanitize_html_class( $marker_shape ), 'flexa-timeline--date-' . sanitize_html_class( $date_position ), ]; if ( '' !== $block_id ) { $classes[] = 'flexa-timeline-' . 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 ); } $wrapper_attributes = get_block_wrapper_attributes( $wrapper_args ); $data_attrs = HTML_Helpers::build_data_attrs( $attributes ); // Lazy background marker. $background = $attributes['background'] ?? []; $is_lazy_bg = ! empty( $background['lazyLoad'] ) && 'image' === ( $background['type'] ?? 'none' ) && '' !== ( $background['image']['url'] ?? '' ); $lazy_marker = $is_lazy_bg ? ' data-flexa-lazy-bg' : ''; printf( '<%1$s %2$s%3$s%4$s><div class="flexa-timeline__list">%5$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. $lazy_marker, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal. $items_html // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- date/title/desc wp_kses'd, marker svg_kses/esc_url'd above. );
Save
Cancel