Dashboard
PHP:
8.4.22
OS:
Linux
User:
provencez
/
/
home
/
provencez
/
www
/
wp-content
/
plugins
/
flexa-block
/
build
/
blocks
/
countdown
📤 Upload
📝 New File
📁 New Folder
Close
Editing: render.php
<?php /** * Countdown block — server-side render. * * CSS is generated at save time by Countdown_CSS and printed inline on the front * end. This file outputs the timer markup with server-computed initial digits * (so there is no flash of "00" before view.js starts ticking) plus the data * attributes the front-end script needs. The digits 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 ); $end = (string) ( $attributes['endDate'] ?? '' ); // Interpret the stored wall-clock date in the chosen UTC offset (block setting, // else the site's gmt_offset) so the target resolves to the same instant for // every visitor regardless of their local timezone. $tz_attr = (string) ( $attributes['timezone'] ?? '' ); $offset_hrs = '' !== $tz_attr ? (float) $tz_attr : (float) get_option( 'gmt_offset', 0 ); $target_ts = false; if ( '' !== $end ) { if ( preg_match( '/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::(\d{2}))?$/', $end, $m ) ) { $utc = gmmktime( (int) $m[4], (int) $m[5], isset( $m[6] ) ? (int) $m[6] : 0, (int) $m[2], (int) $m[3], (int) $m[1] ); $target_ts = $utc - (int) round( $offset_hrs * 3600 ); } else { $target_ts = strtotime( $end ); } } $remaining = ( false !== $target_ts ) ? max( 0, $target_ts - time() ) : 0; $expired = $attributes['expiredAction'] ?? []; $expired_type = in_array( $expired['type'] ?? 'hide', [ 'hide', 'zero', 'message' ], true ) ? $expired['type'] : 'hide'; $expired_msg = (string) ( $expired['message'] ?? '' ); $is_expired_now = ( false !== $target_ts ) && $remaining <= 0; // Hand the front-end script a fully-resolved UTC instant so it can parse it // unambiguously (no wall-clock/timezone guessing on the client). $data_end = ( false !== $target_ts ) ? gmdate( 'c', $target_ts ) : ''; // An already-finished countdown set to "hide" outputs nothing at all. if ( $is_expired_now && 'hide' === $expired_type ) { return; } // Which units to show + their labels. $units = [ 'days', 'hours', 'minutes', 'seconds' ]; $unit_flags = [ 'days' => false !== ( $attributes['showDays'] ?? true ), 'hours' => false !== ( $attributes['showHours'] ?? true ), 'minutes' => false !== ( $attributes['showMinutes'] ?? true ), 'seconds' => false !== ( $attributes['showSeconds'] ?? true ), ]; $active = array_values( array_filter( $units, static fn( $u ) => $unit_flags[ $u ] ) ); // Roll a remaining duration into the visible units (hidden higher units roll // into the next visible one) — mirrors shared.ts remainingParts(). $unit_seconds = [ 'days' => 86400, 'hours' => 3600, 'minutes' => 60, 'seconds' => 1 ]; $parts = [ 'days' => 0, 'hours' => 0, 'minutes' => 0, 'seconds' => 0 ]; $rem = $remaining; foreach ( $units as $u ) { if ( ! $unit_flags[ $u ] ) { continue; } if ( 'seconds' === $u ) { $parts['seconds'] = $rem; } else { $parts[ $u ] = (int) floor( $rem / $unit_seconds[ $u ] ); $rem -= $parts[ $u ] * $unit_seconds[ $u ]; } } // Labels. $labels = $attributes['labels'] ?? []; $show_labels = false !== ( $labels['show'] ?? true ); $labels_below = 'above' !== ( $labels['position'] ?? 'below' ); // Separator character. $separator = $attributes['separator'] ?? []; $sep_type = $separator['type'] ?? 'none'; $sep_char = ''; if ( 'colon' === $sep_type ) { $sep_char = ':'; } elseif ( 'dash' === $sep_type ) { $sep_char = '-'; } elseif ( 'custom' === $sep_type ) { $sep_char = (string) ( $separator['custom'] ?? '' ); } // Build the timer inner markup. $timer_inner = ''; $count = count( $active ); foreach ( $active as $index => $unit ) { $digit = sprintf( '<span class="flexa-countdown__digit" data-unit="%1$s">%2$s</span>', esc_attr( $unit ), esc_html( str_pad( (string) max( 0, $parts[ $unit ] ), 2, '0', STR_PAD_LEFT ) ) ); $label = ''; if ( $show_labels ) { $label = '<span class="flexa-countdown__label">' . esc_html( (string) ( $labels[ $unit ] ?? '' ) ) . '</span>'; } $unit_html = '<div class="flexa-countdown__unit flexa-countdown__unit--' . esc_attr( $unit ) . '">'; $unit_html .= $labels_below ? $digit . $label : $label . $digit; $unit_html .= '</div>'; $timer_inner .= '<div class="flexa-countdown__group">' . $unit_html; if ( '' !== $sep_char && $index < $count - 1 ) { $timer_inner .= '<span class="flexa-countdown__separator" aria-hidden="true">' . esc_html( $sep_char ) . '</span>'; } $timer_inner .= '</div>'; } // Wrapper classes + attributes. $classes = [ 'flexa-countdown' ]; if ( '' !== $block_id ) { $classes[] = 'flexa-countdown-' . 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 ); // Countdown data attributes for view.js. $aria_live = in_array( $attributes['ariaLive'] ?? 'off', [ 'off', 'polite', 'assertive' ], true ) ? $attributes['ariaLive'] : 'off'; $cd_attrs = ' data-flexa-countdown data-end="' . esc_attr( $data_end ) . '" data-expired-action="' . esc_attr( $expired_type ) . '"'; if ( 'message' === $expired_type ) { $cd_attrs .= ' data-expired-message="' . esc_attr( $expired_msg ) . '"'; } if ( 'off' !== $aria_live ) { $cd_attrs .= ' aria-live="' . esc_attr( $aria_live ) . '"'; } // 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' : ''; // If already finished and set to "message", show the message instead of the timer. if ( $is_expired_now && 'message' === $expired_type ) { $inner = '<div class="flexa-countdown__message">' . esc_html( $expired_msg ) . '</div>'; } else { $inner = '<div class="flexa-countdown__timer">' . $timer_inner . '</div>'; } printf( '<%1$s %2$s%3$s%4$s%5$s>%6$s</%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. $cd_attrs, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static keys, values esc_attr'd above. $lazy_marker, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal. $inner // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- tags static, text esc_html'd above. );
Save
Cancel