PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.7.1
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.7.1
1.7.1 1.7.0 1.6.6 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 All 51 releases
← All changes | app/Services/Theme/FrontendTheme.php +142 -6 1.6.6 → 1.7.1 View file →
@@ -5,9 +5,9 @@
5 5 use FluentCart\Api\StoreSettings;
6 6 use FluentCart\Framework\Support\Arr;
7 7
8 8 /**
9 - * Writes the storefront's global colour custom properties.
9 + * Writes the storefront's global colour and border-radius custom properties.
10 10 *
11 11 * FluentCart's stylesheets declare every scoped colour as
12 12 * `var(--fct-<global>, <fallback>)`, so the globals printed here cascade to the
13 13 * whole store — shop grid, product page, cart drawer, checkout and the customer
@@ -311,11 +311,13 @@
311 311 }
312 312
313 313 /*
314 314 * Not escaped on output because it cannot carry anything to escape:
315 - * every property name comes from the ColorPalette registry and every
316 - * value has been through sanitize_hex_color(), so the string is only
317 - * ever `--fct-name: #rrggbb;`.
315 + * every property name comes from the ColorPalette or RadiusPalette
316 + * registry, every colour value is a hex or a bare var() reference
317 + * (sanitizeDeclarationValue()), and every radius value is one plain
318 + * length (RadiusPalette::sanitizeLength()), so the string is only ever
319 + * `--fct-name:#rrggbb;`, `--fct-name:var(--x);` or `--fct-name:8px;`.
318 320 */
319 321 echo '<style id="' . esc_attr(self::STYLE_ID) . '">' . $css . '</style>' . "\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
320 322 }
321 323
@@ -526,14 +528,148 @@
526 528 return $measured;
527 529 }
528 530
529 531 /**
530 - * Build the `:root` declaration block.
532 + * The radii the store owner set by hand, role => length.
531 533 *
534 + * Stored as typed lengths (a bare number is pixels); re-checked here the
535 + * same way the sanitiser checks them on save, so a stale or hand-edited
536 + * option never reaches the page.
537 + *
538 + * @return array Role key => length (`12px`, `0.5rem`, `1em`).
539 + */
540 + public static function getCustomRadii(): array
541 + {
542 + $stored = (new StoreSettings())->get('appearance_radius', []);
543 +
544 + return RadiusPalette::sanitizeOwnerMap($stored);
545 + }
546 +
547 + /**
548 + * The radii the active theme states, role => length.
549 + *
550 + * @return array
551 + */
552 + protected static function getThemeRadii(): array
553 + {
554 + $radii = ThemePalette::radii();
555 +
556 + return is_array($radii) ? $radii : [];
557 + }
558 +
559 + /**
560 + * Every radius that will actually be written, role => normalised length.
561 + *
562 + * Same three sources as the colours: the owner's own radii under
563 + * `customize`, the theme's under `inherit_from_theme`, and none under
564 + * `default` — FluentCart's look must not move.
565 + *
566 + * @return array
567 + */
568 + public static function getEffectiveRadii(): array
569 + {
570 + return self::radiiFor(self::getSource());
571 + }
572 +
573 + /**
574 + * The radii a given source would write, after the storefront filter.
575 + *
576 + * The settings preview asks for the inherited radii while another source
577 + * is saved, so it shows exactly what choosing that source would print.
578 + *
579 + * @param string $source One of the ColorPalette::SOURCE_* constants.
580 + * @return array Role key => normalised length.
581 + */
582 + public static function radiiFor(string $source): array
583 + {
584 + if ($source === ColorPalette::SOURCE_CUSTOM) {
585 + $radii = self::getCustomRadii();
586 + } elseif ($source === ColorPalette::SOURCE_THEME) {
587 + $radii = self::getThemeRadii();
588 + } else {
589 + $radii = [];
590 + }
591 +
592 + /**
593 + * Filter the storefront border radii before they are written to the page.
594 + *
595 + * @param array $radii Role key (card|btn|input) => length (`0`, `8px`, `0.5rem`).
596 + * @param array $context Read-only context: ['source' => appearance source].
597 + */
598 + $filtered = apply_filters('fluent_cart/theme/storefront_radii', $radii, [
599 + 'source' => $source,
600 + ]);
601 +
602 + if (!is_array($filtered)) {
603 + $filtered = $radii;
604 + }
605 +
606 + // Re-checked after the filter: registry roles only, one plain length
607 + // each, in registry order.
608 + $effective = [];
609 +
610 + foreach (array_keys(RadiusPalette::roles()) as $role) {
611 + if (!isset($filtered[$role])) {
612 + continue;
613 + }
614 +
615 + $length = RadiusPalette::sanitizeLength($filtered[$role]);
616 +
617 + if ($length !== '') {
618 + $effective[$role] = $length;
619 + }
620 + }
621 +
622 + return $effective;
623 + }
624 +
625 + /**
626 + * Build the `:root` declaration block: colours first, then radii.
627 + *
628 + * Either half prints without the other — a store can set radii and keep
629 + * FluentCart's colours, or the reverse.
630 + *
532 631 * @return string CSS, or '' when there is nothing to write.
533 632 */
534 633 public static function buildCss(): string
535 634 {
635 + $declarations = self::buildColorDeclarations() . self::buildRadiusDeclarations();
636 +
637 + return $declarations === '' ? '' : ':root{' . $declarations . '}';
638 + }
639 +
640 + /**
641 + * The radius declarations, without the surrounding block.
642 + *
643 + * @return string
644 + */
645 + protected static function buildRadiusDeclarations(): string
646 + {
647 + $roles = RadiusPalette::roles();
648 + $declarations = '';
649 +
650 + foreach (self::getEffectiveRadii() as $role => $length) {
651 + if (!isset($roles[$role])) {
652 + continue;
653 + }
654 +
655 + $safe = RadiusPalette::sanitizeLength($length);
656 +
657 + if ($safe !== '') {
658 + $declarations .= $roles[$role]['var'] . ':' . $safe . ';';
659 + }
660 + }
661 +
662 + return $declarations;
663 + }
664 +
665 + /**
666 + * The colour declarations, without the surrounding block.
667 + *
668 + * @return string
669 + */
670 + protected static function buildColorDeclarations(): string
671 + {
536 672 $colors = self::getEffectiveColors();
537 673
538 674 if (!$colors) {
539 675 return '';
@@ -559,7 +695,7 @@
559 695 $declarations .= $property . ':' . $safe . ';';
560 696 }
561 697 }
562 698
563 - return $declarations === '' ? '' : ':root{' . $declarations . '}';
699 + return $declarations;
564 700 }
565 701 }