'card.php', 'flat-card' => 'card.php', 'dark-panel' => 'card.php', 'light-accent' => 'card.php', 'gradient-banner' => 'card.php', ); return $map[ $layout ] ?? 'card.php'; } /** * Class list for a plan's outer wrapper, shared by every template. */ public static function wrapper_classes( array $plan, array $extra = array() ): string { $classes = array_merge( array( 'cfbk-pricing-item-wrapper' ), $extra ); if ( ! empty( $plan['highlighted'] ) ) { $classes[] = 'cfbk-highlighted'; } return implode( ' ', $classes ); } /** * Feature rows with a non-empty label, ready to render as list items. * Each row is normalized to [ 'text' => string, 'icon' => 'check'|'cross' ]. */ public static function active_features( array $plan ): array { $features = is_array( $plan['features'] ?? null ) ? $plan['features'] : array(); $active = array(); foreach ( $features as $feature ) { $feature = is_array( $feature ) ? $feature : array( 'text' => $feature ); $text = trim( (string) ( $feature['text'] ?? '' ) ); if ( '' === $text ) { continue; } $active[] = array( 'text' => $text, 'icon' => 'cross' === ( $feature['icon'] ?? 'check' ) ? 'cross' : 'check', ); } return $active; } /** * CSS custom-property declarations for the block wrapper, built from * the color attributes -- only set the ones the user actually chose, * so anything left empty falls through to each template SCSS file's * own `var(--cfbk-accent, #...)` default instead of forcing a value. */ public static function color_style_vars( array $attributes ): string { $map = array( 'badgeTextColor' => '--cfbk-badge-color', 'badgeBackgroundColor' => '--cfbk-badge-bg', 'accentColor' => '--cfbk-accent', ); $vars = array(); foreach ( $map as $attribute => $css_var ) { $value = self::sanitize_color_value( (string) ( $attributes[ $attribute ] ?? '' ) ); if ( '' !== $value ) { $vars[] = $css_var . ':' . $value; } } return implode( ';', $vars ); } /** * Splits a price into currency/integer/decimal spans, so the markup * can share one `` breakdown across * every template and price role (original vs. current). */ public static function price_markup( string $price, string $currency_symbol, string $currency_position ): string { $price = trim( $price ); if ( '' === $price ) { return ''; } $pieces = explode( '.', $price ); $integer = $pieces[0]; // A trailing "." with nothing after it (e.g. a price saved as // "99." from the editor) must render as no decimal at all, not a // bare "." -- `isset()` alone is true for an empty string too. $decimal = ! empty( $pieces[1] ) ? '.' . $pieces[1] : ''; $currency = '' . esc_html( $currency_symbol ) . ''; $out = 'left' === $currency_position ? $currency : ''; $out .= '' . esc_html( $integer ) . ''; $out .= '' . esc_html( $decimal ) . ''; $out .= 'right' === $currency_position ? $currency : ''; return $out; } }