PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.6
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.6
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 1.3.20 1.3.19 All 49 releases
fluent-cart / app / Services / Theme / Readers / KadenceSettingsReader.php

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

265 lines 8.3 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 use FluentCart\Framework\Support\Arr;
8
9 /**
10 * Kadence's Customizer colours, read from its theme mods rather than its slots.
11 *
12 * Kadence keeps each semantic colour in its own setting — Links
13 * (`link_color`), Base Font (`base_font`), Content and Site Background
14 * (`content_background`, `site_background`) and Buttons (`buttons_background`,
15 * `buttons_color`) — each holding a palette slug (`palette3`) or a custom
16 * colour. The button is not tied to the link colour, so each role is read
17 * from its own setting through `\Kadence\kadence()->sub_option()`, the same
18 * call Kadence's own styles component prints from.
19 *
20 * A slug is written the way Kadence writes it (`Kadence_CSS::render_color()`):
21 * `paletteN` becomes `var(--global-paletteN)`, which ThemePalette resolves to
22 * `var(--global-paletteN, #hex)` from `palette_option()` (the active palette
23 * of three; see paletteValues()). A sub-key `sub_option()` answers null for —
24 * cleared, or missing from a saved setting — takes Kadence's own default.
25 *
26 * Kadence has no border setting (its borders use the static
27 * `--global-gray-400`), so no border is stated and FluentCart keeps deriving it.
28 *
29 * Verified against Kadence 1.5.0.
30 */
31 class KadenceSettingsReader implements ThemeSettingsReader
32 {
33 /**
34 * Kadence's defaults per setting and sub-key
35 * (inc/components/options/component.php, defaults()).
36 *
37 * @var array
38 */
39 protected static $defaults = [
40 'link_color' => ['highlight' => 'palette1'],
41 'base_font' => ['color' => 'palette4'],
42 'buttons_background' => ['color' => 'palette1', 'hover' => 'palette2'],
43 'buttons_color' => ['color' => 'palette9', 'hover' => 'palette9'],
44 ];
45
46 /**
47 * Detected by Kadence's own template-tags API, not by theme name, so a
48 * child theme or renamed folder keeps working.
49 *
50 * @return bool
51 */
52 public static function applies(): bool
53 {
54 $kadence = self::api();
55
56 return $kadence !== null
57 && is_callable([$kadence, 'sub_option'])
58 && is_callable([$kadence, 'palette_option']);
59 }
60
61 /**
62 * @return array Role => hex or `var(--global-paletteN, #hex)`.
63 */
64 public static function roles(): array
65 {
66 if (!self::applies()) {
67 return [];
68 }
69
70 $roles = [
71 'accent' => self::read('link_color', 'highlight'),
72 'text' => self::read('base_font', 'color'),
73 'surface' => self::surface(),
74 ];
75
76 // Kadence states both halves of its button, resting and hover. The
77 // hover belongs to the resting button: without one there is no hover.
78 $button = self::buttonPair('color');
79
80 if ($button) {
81 $roles = array_merge($roles, $button, self::buttonPair('hover', 'button_hover_'));
82 }
83
84 return array_filter($roles, function ($value) {
85 return $value !== '';
86 });
87 }
88
89 /**
90 * Each palette slot's property and current colour:
91 * `--global-paletteN` => colour, from the palette Kadence has active — the
92 * same `palette_option()` Kadence prints the properties from.
93 *
94 * @return array Property => colour, as Kadence answers it (palette10 can
95 * be an oklch() expression; ThemePalette drops non-hex).
96 */
97 public static function paletteValues(): array
98 {
99 if (!self::applies()) {
100 return [];
101 }
102
103 $values = [];
104
105 try {
106 $kadence = self::api();
107
108 foreach (range(1, 15) as $index) {
109 $values['--global-palette' . $index] = (string)$kadence->palette_option('palette' . $index);
110 }
111 } catch (\Throwable $e) {
112 // Kadence's API misbehaving means no palette values: references
113 // stay bare and unmeasurable, which resolve() already refuses.
114 return [];
115 }
116
117 return $values;
118 }
119
120 /**
121 * One button half-pair: background from `buttons_background`, text from
122 * `buttons_color`, both at the same state.
123 *
124 * A background that is set but unwritable (a gradient, an rgba()) is not
125 * replaced by a default — Kadence is painting it, just not in a form
126 * FluentCart can write — so the pair is omitted. A text that cannot be
127 * written gets the colour that reads on the background.
128 *
129 * @param string $state 'color' (resting) or 'hover'.
130 * @param string $prefix Role prefix.
131 * @return array
132 */
133 protected static function buttonPair(string $state, string $prefix = 'button_'): array
134 {
135 $background = self::read('buttons_background', $state);
136
137 if ($background === '') {
138 return [];
139 }
140
141 $text = self::read('buttons_color', $state);
142
143 if ($text === '') {
144 $text = ColorMath::readableText(ThemePalette::measurable($background));
145 }
146
147 return [
148 $prefix . 'bg' => $background,
149 $prefix . 'text' => $text,
150 ];
151 }
152
153 /**
154 * The content background, falling back to the site background.
155 *
156 * Kadence paints `.content-bg` (and the unboxed `.site`) with the content
157 * background and the body with the site background; both are saved per
158 * device, and desktop is the unprefixed rule that speaks for all. A
159 * gradient paints no colour, so it states no surface — and the site
160 * background is not under the content either, so it is not used instead.
161 *
162 * @return string
163 */
164 protected static function surface(): string
165 {
166 foreach (['content_background', 'site_background'] as $setting) {
167 $value = self::subOption($setting, 'desktop');
168
169 if (!is_array($value)) {
170 continue;
171 }
172
173 if (Arr::get($value, 'type', 'color') === 'gradient' && Arr::get($value, 'gradient', '') !== '') {
174 return '';
175 }
176
177 $color = Arr::get($value, 'color', '');
178
179 if (is_string($color) && trim($color) !== '') {
180 return self::normalise($color);
181 }
182 }
183
184 return '';
185 }
186
187 /**
188 * One colour setting at one sub-key, over Kadence's default for it.
189 *
190 * @param string $setting
191 * @param string $subKey
192 * @return string
193 */
194 protected static function read(string $setting, string $subKey): string
195 {
196 $raw = self::subOption($setting, $subKey);
197
198 if (!is_string($raw) || trim($raw) === '') {
199 $raw = (string)Arr::get(self::$defaults, $setting . '.' . $subKey, '');
200 }
201
202 return self::normalise($raw);
203 }
204
205 /**
206 * A Kadence colour value as FluentCart writes it.
207 *
208 * `paletteN` is written as Kadence writes it, `var(--global-paletteN)`,
209 * and resolved through ThemePalette::settingValue() like every other
210 * reader's value. A value that cannot be measured — a gradient, rgba(),
211 * or palette10's oklch() complement — is not stated.
212 *
213 * @param string $raw
214 * @return string
215 */
216 protected static function normalise(string $raw): string
217 {
218 $raw = trim($raw);
219
220 if (preg_match('/^palette(\d{1,2})$/', $raw, $matches)) {
221 $raw = 'var(--global-palette' . $matches[1] . ')';
222 }
223
224 $value = ThemePalette::settingValue($raw);
225
226 return ThemePalette::measurable($value) !== '' ? $value : '';
227 }
228
229 /**
230 * `sub_option()`, shielded from Kadence's API throwing.
231 *
232 * @param string $setting
233 * @param string $subKey
234 * @return mixed
235 */
236 protected static function subOption(string $setting, string $subKey)
237 {
238 try {
239 return self::api()->sub_option($setting, $subKey);
240 } catch (\Throwable $e) {
241 return null;
242 }
243 }
244
245 /**
246 * Kadence's template-tags object, or null when Kadence is not loaded.
247 *
248 * @return object|null
249 */
250 protected static function api()
251 {
252 if (!function_exists('Kadence\\kadence')) {
253 return null;
254 }
255
256 try {
257 $kadence = \Kadence\kadence();
258 } catch (\Throwable $e) {
259 return null;
260 }
261
262 return is_object($kadence) ? $kadence : null;
263 }
264 }
265