PluginProbe ʕ •ᴥ•ʔ
Kirki – Freeform Page Builder, Website Builder & Customizer / 6.0.13
Kirki – Freeform Page Builder, Website Builder & Customizer v6.0.13
6.1.1 6.1.0 6.0.14 6.0.13 6.0.12 6.0.11 6.0.10 6.0.9 6.0.8 6.0.7 6.0.6 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 4.0.19 4.0.20 4.0.21 4.0.22 4.0.23 4.0.24 4.1 4.2.0 5.0.0 5.1.0 5.1.1 5.2.0 5.2.1 5.2.2 5.2.3 6.0.0 trunk 3.0.40 3.0.41 3.0.42 3.0.43 3.0.44 3.0.45 3.1.0 3.1.1 3.1.2
kirki / libraries / framework / Managers / OptionManager.php
kirki / libraries / framework / Managers Last commit date
DateManager.php 2 weeks ago EventManager.php 2 weeks ago LogManager.php 2 weeks ago OptionManager.php 2 weeks ago PolicyManager.php 2 weeks ago
OptionManager.php
289 lines
1 <?php
2
3 /**
4 * Namespaced wrapper around WordPress update_option and get_option with in-memory caching.
5 * Applies and strips application prefixes for plugin-scoped settings.
6 * Provides bulk get, delete, and Option model integration for advanced queries.
7 *
8 * @package Framework
9 * @subpackage Managers
10 * @since 1.0.0
11 */
12 namespace Kirki\Framework\Managers;
13
14 \defined('ABSPATH') || exit;
15 use Kirki\Framework\Collections\Collection;
16 use Kirki\Framework\Supports\Arr;
17 use Kirki\Framework\Wordpress\Models\Option;
18 use function Kirki\Framework\collection;
19 use function Kirki\Framework\with_prefix;
20 use function Kirki\Framework\without_prefix;
21 class OptionManager
22 {
23 /**
24 * The cache of the options.
25 *
26 * @var array
27 *
28 * @since 1.0.0
29 */
30 protected static array $cache = [];
31 /**
32 * Set the value of an option.
33 *
34 * Stores the given value in the WordPress options table using a namespaced option name.
35 *
36 * @param string $name The option key to set.
37 * @param mixed $value The value to store for the option.
38 * @param bool|null $autoload Whether to autoload the option.
39 * @param mixed $with_prefix The with prefix.
40 *
41 * @return bool True if the value was updated, false otherwise.
42 *
43 * @since 1.0.0
44 */
45 public function set(string $name, $value, $autoload = null, $with_prefix = \true)
46 {
47 $key = $this->prepare_option_name($name, $with_prefix);
48 $result = update_option($key, $value, $autoload);
49 $option = (object) ['option_name' => $key, 'option_value' => $value];
50 $this->update_cache($option);
51 return $result;
52 }
53 /**
54 * Retrieve the value of an option.
55 *
56 * Gets the value from the WordPress options table using a namespaced option name.
57 * Returns the default value if the option does not exist.
58 *
59 * @param string|array $name The option key to retrieve.
60 * @param mixed|null $default The default value to return if the option does not exist.
61 * @param mixed $with_prefix The with prefix.
62 *
63 * @return mixed The value of the option or the default value.
64 *
65 * @since 1.0.0
66 */
67 public function get($name, $default = null, $with_prefix = \true)
68 {
69 $must_be_array = \is_array($name);
70 $names = $this->get_option_name($name, $with_prefix);
71 $fresh_option_names = collection($names)->reject(function ($name) {
72 return $this->is_cached($name);
73 });
74 $cached_option_names = collection($names)->accept(function ($name) {
75 return $this->is_cached($name);
76 });
77 $options = $this->get_options_from_cache($cached_option_names);
78 if (!$fresh_option_names->empty()) {
79 $fresh_options = Option::query()->where_in('option_name', $fresh_option_names->all())->get()->map(fn($value) => $this->value($value));
80 $this->sync_cache($fresh_options);
81 $plucked = $fresh_options->pluck('option_value', 'option_name');
82 $options = $options->merge($plucked);
83 }
84 if ($options->empty()) {
85 if (!$must_be_array) {
86 return $default;
87 }
88 return $this->refill_missing_keys_with_defaults([], $names, $default, $with_prefix);
89 }
90 if (!$must_be_array) {
91 return $options->first() ?? $default;
92 }
93 // Fill with defaults for the missing keys
94 $results = $options->map(function ($value, $key) use($default) {
95 if (\is_array($default)) {
96 return !\is_null($value) ? $value : $default[$key] ?? null;
97 }
98 return \is_null($value) ? $default : $value;
99 })->all();
100 $results = $this->refill_missing_keys_with_defaults($results, $names, $default, $with_prefix);
101 return $this->rebase_keys($results, $with_prefix);
102 }
103 /**
104 * Get the options from the cache.
105 *
106 * @param Collection $options The options to get.
107 *
108 * @return Collection The options from the cache.
109 *
110 * @since 1.0.0
111 */
112 protected function get_options_from_cache(Collection $options)
113 {
114 $data = [];
115 foreach ($options as $option_name) {
116 $data[$option_name] = static::$cache[$option_name];
117 }
118 return new Collection($data);
119 }
120 /**
121 * Get the value of the option.
122 *
123 * @param mixed $value The value of the option.
124 *
125 * @return mixed The value of the option.
126 *
127 * @since 1.0.0
128 */
129 protected function value($value)
130 {
131 return maybe_unserialize($value);
132 }
133 /**
134 * Sync the cache with the options.
135 *
136 * @param Collection $options The options to sync.
137 *
138 * @return void
139 *
140 * @since 1.0.0
141 */
142 protected function sync_cache(Collection $options)
143 {
144 foreach ($options as $option) {
145 $this->update_cache($option);
146 }
147 }
148 /**
149 * Update the cache with the option name and value.
150 *
151 * @param object $option The option object.
152 *
153 * @return void
154 *
155 * @since 1.0.0
156 */
157 protected function update_cache($option)
158 {
159 static::$cache[$option->option_name] = $option->option_value;
160 }
161 /**
162 * Remove the option from the cache.
163 *
164 * @param string $option_name The name of the option.
165 *
166 * @return void
167 *
168 * @since 1.0.0
169 */
170 protected function remove_from_cache($option_name)
171 {
172 unset(static::$cache[$option_name]);
173 }
174 /**
175 * Clear the cache.
176 *
177 * @return void
178 *
179 * @since 1.0.0
180 */
181 protected function clear_cache()
182 {
183 static::$cache = [];
184 }
185 /**
186 * Check if the option is cached.
187 *
188 * @param string $option_name The name of the option.
189 *
190 * @return bool
191 *
192 * @since 1.0.0
193 */
194 protected function is_cached($option_name)
195 {
196 return isset(static::$cache[$option_name]);
197 }
198 /**
199 * Refill the missing keys with the defaults.
200 *
201 * @param array $results The results to refill.
202 * @param array $names The names to refill.
203 * @param mixed $default The default value to refill.
204 * @param mixed $with_prefix The with prefix.
205 *
206 * @return array The refilled results.
207 *
208 * @since 1.0.0
209 */
210 protected function refill_missing_keys_with_defaults(array $results, array $names, $default, $with_prefix)
211 {
212 foreach ($names as $key) {
213 if (!isset($results[$key])) {
214 $key_without_prefix = $with_prefix ? without_prefix($key) : $key;
215 $results[$key] = \is_array($default) ? $default[$key_without_prefix] ?? null : $default;
216 }
217 }
218 return $results;
219 }
220 /**
221 * Rebase the keys of the results.
222 *
223 * @param array $results The results to rebase.
224 * @param mixed $with_prefix The with prefix.
225 *
226 * @return array The rebased results.
227 *
228 * @since 1.0.0
229 */
230 protected function rebase_keys(array $results, $with_prefix)
231 {
232 return collection($results)->map(function ($value, $key) use($with_prefix) {
233 $key_without_prefix = $with_prefix ? without_prefix($key) : $key;
234 return [$key_without_prefix => $value];
235 })->collapse()->all();
236 }
237 /**
238 * Delete an option.
239 *
240 * Removes the option from the WordPress options table using a namespaced option name.
241 *
242 * @param string $name The option key to delete.
243 * @param mixed $with_prefix The with prefix.
244 *
245 * @return bool True if the option was deleted, false otherwise.
246 *
247 * @since 1.0.0
248 */
249 public function delete(string $name, $with_prefix = \true)
250 {
251 $result = delete_option($this->prepare_option_name($name, $with_prefix));
252 $this->remove_from_cache($this->prepare_option_name($name, $with_prefix));
253 return $result;
254 }
255 /**
256 * Generate the full option name with namespace prefix.
257 *
258 * Prepends the app prefix to the given option key.
259 *
260 * @param string|array<string> $name The base option key.
261 * @param mixed $with_prefix The with prefix.
262 *
263 * @return array The namespaced option key.
264 *
265 * @since 1.0.0
266 */
267 protected function get_option_name($name, $with_prefix = \true)
268 {
269 $name = Arr::wrap($name);
270 return collection($name)->map(function ($name) use($with_prefix) {
271 return $this->prepare_option_name($name, $with_prefix);
272 })->all();
273 }
274 /**
275 * Prepare the option name.
276 *
277 * @param string $name The name of the option.
278 * @param bool $with_prefix Whether to prefix the name.
279 *
280 * @return string The prepared option name.
281 *
282 * @since 1.0.0
283 */
284 protected function prepare_option_name(string $name, bool $with_prefix = \true)
285 {
286 return $with_prefix ? with_prefix($name) : $name;
287 }
288 }
289