PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.11.0
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.11.0
2.11.0 2.10.0 2.10.01 2.9.1 2.9.0 2.8.1 2.8.0 2.7.7 2.7.5 2.7.0 2.6.01 2.6.0 2.5.0 2.4.01 trunk 1.0.90 1.0.91 1.0.92 1.0.93 1.0.94 1.0.95 1.0.96 1.0.97 1.0.98 1.0.99 All 78 releases
← All changes | vendor/wpfluent/framework/src/WPFluent/Foundation/Config.php +104 -18 2.6.012.11.0 View file →
@@ -6,48 +6,91 @@
6 6
7 7 class Config
8 8 {
9 9 /**
10 - * The config data
10 + * Eagerly-set or lazily-loaded config data, keyed by top-level config name.
11 11 * @var array
12 12 */
13 13 protected $data = [];
14 14
15 15 /**
16 - * Construct the Config instance
17 - * @param array $data
16 + * Map of top-level key (e.g. 'i18n', 'app') → absolute file path.
17 + * Files are required on first access to their top-level key. Defers
18 + * any side-effecting code in config files (notably `__()` calls in
19 + * config/i18n.php) until consumers actually read them — which always
20 + * happens after `init`, so WP 6.7+'s `_doing_it_wrong` notice on
21 + * early textdomain load is no longer triggered by the framework.
22 + *
23 + * Eagerly-supplied $data still works (back-compat for tests / direct
24 + * construction without a file map).
25 + *
26 + * @var array<string, string>
18 27 */
19 - public function __construct($data)
28 + protected $files = [];
29 +
30 + /**
31 + * Top-level keys whose backing file has been required. Tracks loaded
32 + * state separately from $data because a config file may legitimately
33 + * `return null` / `return []`, and we must not re-require those.
34 + *
35 + * @var array<string, bool>
36 + */
37 + protected $loaded = [];
38 +
39 + /**
40 + * Construct the Config instance.
41 + *
42 + * @param array $data Eagerly-populated data (keyed by top-level name).
43 + * @param array $files Map of top-level name → file path for lazy load.
44 + */
45 + public function __construct($data, $files = [])
20 46 {
21 47 $this->data = $data;
48 + $this->files = $files;
49 +
50 + // Anything passed in $data is already resolved.
51 + foreach (array_keys($data) as $top) {
52 + $this->loaded[$top] = true;
53 + }
22 54 }
23 55
24 56 /**
25 - * Retrieve all config data
57 + * Retrieve all config data. Force-loads every lazy file.
58 + *
26 59 * @return array
27 60 */
28 61 public function all()
29 62 {
30 - return $this->get();
63 + foreach (array_keys($this->files) as $top) {
64 + $this->ensureLoaded($top);
65 + }
66 +
67 + return $this->data;
31 68 }
32 69
33 70 /**
34 71 * Retrieve specific item from config array.
35 - *
72 + *
36 73 * @param string $key
37 - * @param string $default
74 + * @param mixed $default
38 75 * @return mixed
39 76 */
40 77 public function get($key = null, $default = null)
41 78 {
79 + if ($key === null || $key === '') {
80 + return $this->all();
81 + }
82 +
42 83 $key = $this->resolveKey($key);
43 84
44 - return $key ? Arr::get($this->data, $key, $default) : $this->data;
85 + $this->ensureLoaded($this->topKey($key));
86 +
87 + return Arr::get($this->data, $key, $default);
45 88 }
46 89
47 90 /**
48 91 * Get only specific items from the config array.
49 - *
92 + *
50 93 * @param string|array $key ($key1, $key2 or [$key1, $key2])
51 94 * @return array
52 95 */
53 96 public function only($key)
@@ -53,13 +96,14 @@
53 96 public function only($key)
54 97 {
55 98 $keys = array_map(function ($key) {
56 99 return $this->resolveKey($key);
57 - }, is_Array($key) ? $key : func_get_args());
100 + }, is_array($key) ? $key : func_get_args());
58 101
59 102 $result = [];
60 103
61 104 foreach ($keys as $key) {
105 + $this->ensureLoaded($this->topKey($key));
62 106 $result[] = Arr::get($this->data, $key);
63 107 }
64 108
65 109 return array_values(array_filter($result));
@@ -65,30 +109,72 @@
65 109 return array_values(array_filter($result));
66 110 }
67 111
68 112 /**
69 - * Set an item into the config array on the fly.
113 + * Set an item into the config array on the fly. Forces the underlying
114 + * file to load first, so the write isn't clobbered by a later lazy load.
115 + *
70 116 * @param string $key
71 - * @param mixed $value
117 + * @param mixed $value
72 118 */
73 119 public function set($key, $value)
74 120 {
121 + $key = $this->resolveKey($key);
122 + $this->ensureLoaded($this->topKey($key));
75 123 Arr::set($this->data, $key, $value);
76 124 }
77 125
78 126 /**
79 - * Resolove the config key, add app. prefix if needed.
80 - *
127 + * Lazy-load a config file the first time its top-level key is touched.
128 + * Idempotent: subsequent calls are no-ops.
129 + *
130 + * @param string $topKey
131 + * @return void
132 + */
133 + protected function ensureLoaded($topKey)
134 + {
135 + if (!$topKey || isset($this->loaded[$topKey])) {
136 + return;
137 + }
138 +
139 + if (isset($this->files[$topKey])) {
140 + $this->data[$topKey] = require $this->files[$topKey];
141 + }
142 +
143 + $this->loaded[$topKey] = true;
144 + }
145 +
146 + /**
147 + * Extract the top-level key from a dotted path. 'app.text_domain' → 'app'.
148 + *
81 149 * @param string $key
82 150 * @return string
83 151 */
152 + protected function topKey($key)
153 + {
154 + $dot = strpos($key, '.');
155 + return $dot === false ? $key : substr($key, 0, $dot);
156 + }
157 +
158 + /**
159 + * Resolve the config key, add `app.` prefix when the key is short and
160 + * not a known top-level config name (matches eagerly-loaded data OR a
161 + * deferred file). Without the file lookup, `get('i18n')` would resolve
162 + * to `app.i18n` before the i18n config file had been touched.
163 + *
164 + * @param string $key
165 + * @return string
166 + */
84 167 protected function resolveKey($key)
85 168 {
86 169 if (!$key) return $key;
87 -
88 - if (array_key_exists($key, $this->data)) {
170 +
171 + if (
172 + array_key_exists($key, $this->data)
173 + || array_key_exists($key, $this->files)
174 + ) {
89 175 return $key;
90 176 }
91 -
177 +
92 178 return str_contains($key, '.') ? $key : "app.{$key}";
93 179 }
94 180 }