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
fluent-cart / app / Services / Theme / Readers / DiviSettingsReader.php

DiviSettingsReader.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.7.1, at app/Services/Theme/Readers/DiviSettingsReader.php

219 lines 7.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Services\Theme\Readers;
4
5 use FluentCart\App\Services\Theme\ColorMath;
6 use FluentCart\App\Services\Theme\ThemePalette;
7
8 /**
9 * Divi's Customizer colours, read from its settings.
10 *
11 * Divi publishes no palette to theme.json, so without a reader inheritance has
12 * nothing to follow. Its Customizer keeps the colours as flat values in the
13 * `et_divi` option row, read through `et_get_option()` — the call Divi's own
14 * `et_divi_add_customizer_css()` prints them from: Theme Accent Color
15 * (`accent_color`), Body Text Color (`font_color`), and the Buttons section
16 * (`all_buttons_bg_color`, `all_buttons_text_color` and their `_hover` pair).
17 * The content area is painted from the core `background_color` theme mod
18 * (`et_divi_add_main_content_background_css()`).
19 *
20 * Accent and body text are Divi 5's Customizer global colours, printed as
21 * `--gcid-primary-color` and `--gcid-body-color` from these same options
22 * (GlobalData::get_customizer_colors()), so they are stated live with the
23 * option's hex as the fallback: `var(--gcid-primary-color, #hex)`. The button
24 * and background settings have no property, so they are stated as hex.
25 *
26 * Divi's default button is an outline: a transparent background
27 * (`rgba(0,0,0,0)`), the accent as its text and border. Only a background the
28 * owner set to a solid hex is a filled button; anything else states no button
29 * and FluentCart falls back as it did before.
30 *
31 * An empty value is what Divi's own CSS treats as unset — its static
32 * stylesheet paints the default — so it takes Divi's default here too. A
33 * value FluentCart cannot write (rgb(), rgba(), Divi 5's `hsl(from var(--gcid…))`
34 * or a `$variable(…)$` reference) is not stated.
35 *
36 * Its Buttons → Border Radius (`all_buttons_border_radius`) is the button
37 * radius (see radii()). Divi has no form-field or product-card radius setting.
38 *
39 * Verified against Divi 5.0.1.
40 */
41 class DiviSettingsReader implements ThemeSettingsReader, ThemeRadiusReader
42 {
43 /**
44 * Divi's defaults (GlobalData::$customizer_colors, the Customizer settings
45 * and the static stylesheet).
46 *
47 * @var array
48 */
49 protected static $defaults = [
50 'accent_color' => '#2ea3f2',
51 'font_color' => '#666666',
52 // `#main-content { background-color: #fff }` in Divi's stylesheet.
53 'content' => '#ffffff',
54 ];
55
56 /**
57 * Detected by Divi's own option API and customizer printer, and by the
58 * `$shortname` Divi's `et_setup_theme()` sets: `et_get_option()` is shared
59 * by every Elegant Themes product and reads the row named after that
60 * global, so only 'divi' means the `et_divi` row these settings live in.
61 * Theme name is not used, so a child theme keeps working.
62 *
63 * @return bool
64 */
65 public static function applies(): bool
66 {
67 return function_exists('et_get_option')
68 && function_exists('et_divi_add_customizer_css')
69 && isset($GLOBALS['shortname'])
70 && $GLOBALS['shortname'] === 'divi';
71 }
72
73 /**
74 * @return array Role => hex or `var(--gcid-…, #hex)`.
75 */
76 public static function roles(): array
77 {
78 if (!self::applies()) {
79 return [];
80 }
81
82 $accentHex = self::hex(et_get_option('accent_color', self::$defaults['accent_color']), self::$defaults['accent_color']);
83 $textHex = self::hex(et_get_option('font_color', self::$defaults['font_color']), self::$defaults['font_color']);
84
85 $roles = [
86 'accent' => $accentHex !== '' ? 'var(--gcid-primary-color, ' . $accentHex . ')' : '',
87 'text' => $textHex !== '' ? 'var(--gcid-body-color, ' . $textHex . ')' : '',
88 'surface' => self::surface(),
89 ];
90
91 $button = self::button($roles['accent']);
92
93 if ($button) {
94 $roles = array_merge($roles, $button);
95 }
96
97 return array_filter($roles, function ($value) {
98 return $value !== '';
99 });
100 }
101
102 /**
103 * The filled button and its hover, when Divi paints one.
104 *
105 * A background that is not a solid hex — Divi's transparent default, an
106 * rgba() — is an outline or a tint, not a fill, so no button is stated and
107 * its hover goes with it.
108 *
109 * An empty text keeps what Divi paints on a button, the accent, while that
110 * reads on the background (WCAG 4.5:1); otherwise the colour that does.
111 * Divi prints no hover text when it is empty, so the resting text carries
112 * over — which resolve() already does when no hover text is stated. A
113 * hover background that is not a solid hex (Divi's default white tint)
114 * states no hover, and FluentCart derives it from the button as before.
115 *
116 * @param string $accent The stated accent, or ''.
117 * @return array
118 */
119 protected static function button(string $accent): array
120 {
121 $background = self::hex(et_get_option('all_buttons_bg_color', 'rgba(0,0,0,0)'));
122
123 if ($background === '') {
124 return [];
125 }
126
127 $text = self::hex(et_get_option('all_buttons_text_color', ''));
128
129 if ($text === '') {
130 $accentHex = ThemePalette::measurable($accent);
131
132 $text = $accentHex !== '' && ColorMath::contrast($background, $accentHex) >= 4.5
133 ? $accent
134 : ColorMath::readableText($background);
135 }
136
137 $roles = [
138 'button_bg' => $background,
139 'button_text' => $text,
140 ];
141
142 $hoverBg = self::hex(et_get_option('all_buttons_bg_color_hover', 'rgba(255,255,255,0.2)'));
143
144 if ($hoverBg !== '') {
145 $roles['button_hover_bg'] = $hoverBg;
146 $roles['button_hover_text'] = self::hex(et_get_option('all_buttons_text_color_hover', ''));
147 }
148
149 return $roles;
150 }
151
152 /**
153 * The content background.
154 *
155 * Outside the Divi Builder, Divi paints `#main-content` with the core
156 * Background Color and turns it transparent over a Background Image
157 * (`et_divi_add_main_content_background_css()`); with neither, its
158 * stylesheet paints it white. An image paints no colour, so it states no
159 * surface. The theme mod is saved without its `#`.
160 *
161 * @return string
162 */
163 protected static function surface(): string
164 {
165 if ((string)get_theme_mod('background_image', '') !== '') {
166 return '';
167 }
168
169 $color = trim((string)get_theme_mod('background_color', ''));
170
171 if ($color === '') {
172 return self::$defaults['content'];
173 }
174
175 return self::hex('#' . ltrim($color, '#'));
176 }
177
178 /**
179 * A Divi colour value as a hex FluentCart can write.
180 *
181 * Empty or missing takes `$default` — what Divi's own stylesheet paints
182 * when the setting prints nothing. Anything but a hex is not stated.
183 *
184 * @param mixed $raw
185 * @param string $default
186 * @return string Lowercase hex, or ''.
187 */
188 protected static function hex($raw, string $default = ''): string
189 {
190 if (!is_string($raw) || trim($raw) === '') {
191 $raw = $default;
192 }
193
194 $raw = trim($raw);
195
196 return preg_match('/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/', $raw) ? strtolower(ColorMath::hex($raw)) : '';
197 }
198
199 /**
200 * The button radius.
201 *
202 * `all_buttons_border_radius` is a whole number of px (sanitised with
203 * `absint`, range 0–100), read exactly as Divi's customizer CSS reads it:
204 * `absint( et_get_option( 'all_buttons_border_radius', '3' ) )`
205 * (functions.php). Divi prints it when it is not 3; at 3 its stylesheet
206 * paints the same 3px.
207 *
208 * @return array Role => length.
209 */
210 public static function radii(): array
211 {
212 if (!self::applies()) {
213 return [];
214 }
215
216 return ['btn' => absint(et_get_option('all_buttons_border_radius', '3')) . 'px'];
217 }
218 }
219