|
15 | 15 |
|
16 | 16 | /** |
17 | 17 | * Class process source, cache them and retrieve value by path |
18 | | - * |
19 | | - * @package Magento\Config\App\Config\Type |
20 | 18 | */ |
21 | 19 | class System implements ConfigTypeInterface |
22 | 20 | { |
@@ -59,6 +57,16 @@ class System implements ConfigTypeInterface |
59 | 57 | */ |
60 | 58 | private $fallback; |
61 | 59 |
|
| 60 | + /** |
| 61 | + * Key name for flag which displays whether configuration is cached or not. |
| 62 | + * |
| 63 | + * Once configuration is cached additional flag pushed to cache storage |
| 64 | + * to be able check cache existence without data load. |
| 65 | + * |
| 66 | + * @var string |
| 67 | + */ |
| 68 | + private $cacheExistenceKey = self::CONFIG_TYPE . '_CACHE_EXISTS'; |
| 69 | + |
62 | 70 | /** |
63 | 71 | * System constructor. |
64 | 72 | * @param ConfigSourceInterface $source |
@@ -92,20 +100,120 @@ public function get($path = '') |
92 | 100 | if ($path === null) { |
93 | 101 | $path = ''; |
94 | 102 | } |
95 | | - if (!$this->data) { |
96 | | - $data = $this->cache->load(self::CONFIG_TYPE); |
97 | | - if (!$data) { |
98 | | - $data = $this->preProcessor->process($this->source->get()); |
99 | | - $this->data = new DataObject($data); |
100 | | - $data = $this->fallback->process($data); |
101 | | - $this->data = new DataObject($data); |
102 | | - $data = $this->postProcessor->process($data); |
103 | | - $this->data = new DataObject($data); |
104 | | - $this->cache->save(serialize($this->data), self::CONFIG_TYPE, [self::CACHE_TAG]); |
105 | | - } else { |
106 | | - $this->data = unserialize($data); |
| 103 | + |
| 104 | + if ($this->isConfigRead($path)) { |
| 105 | + return $this->data->getData($path); |
| 106 | + } |
| 107 | + |
| 108 | + if (!empty($path) && $this->isCacheExists()) { |
| 109 | + return $this->readFromCache($path); |
| 110 | + } |
| 111 | + |
| 112 | + $config = $this->loadConfig(); |
| 113 | + $this->cacheConfig($config); |
| 114 | + $this->data = new DataObject($config); |
| 115 | + return $this->data->getData($path); |
| 116 | + } |
| 117 | + |
| 118 | + /** |
| 119 | + * Check whether configuration is cached |
| 120 | + * @return bool |
| 121 | + */ |
| 122 | + private function isCacheExists() |
| 123 | + { |
| 124 | + return $this->cache->load($this->cacheExistenceKey) !== false; |
| 125 | + } |
| 126 | + |
| 127 | + /** |
| 128 | + * Explode path by '/'(forward slash) separator |
| 129 | + * |
| 130 | + * @param string $path |
| 131 | + * @return array |
| 132 | + */ |
| 133 | + private function getPathParts($path) |
| 134 | + { |
| 135 | + $pathParts = []; |
| 136 | + if (strpos($path, '/') !== false) { |
| 137 | + $pathParts = explode('/', $path); |
| 138 | + } |
| 139 | + return $pathParts; |
| 140 | + } |
| 141 | + |
| 142 | + /** |
| 143 | + * Check whether requested configuration data is read to memory |
| 144 | + * |
| 145 | + * @param string $path |
| 146 | + * @return bool |
| 147 | + */ |
| 148 | + private function isConfigRead($path) |
| 149 | + { |
| 150 | + $pathParts = $this->getPathParts($path); |
| 151 | + return !empty($pathParts) && isset($this->data[$pathParts[0]][$pathParts[1]]); |
| 152 | + } |
| 153 | + |
| 154 | + /** |
| 155 | + * Load configuration from all the sources |
| 156 | + * |
| 157 | + * @return array |
| 158 | + */ |
| 159 | + private function loadConfig() |
| 160 | + { |
| 161 | + $data = $this->preProcessor->process($this->source->get()); |
| 162 | + $this->data = new DataObject($data); |
| 163 | + $data = $this->fallback->process($data); |
| 164 | + $this->data = new DataObject($data); |
| 165 | + |
| 166 | + return $this->postProcessor->process($data); |
| 167 | + } |
| 168 | + |
| 169 | + /** |
| 170 | + * |
| 171 | + * Load configuration and caching it by parts. |
| 172 | + * |
| 173 | + * To be cached configuration is loaded first. |
| 174 | + * Then it is cached by parts to minimize memory usage on load. |
| 175 | + * Additional flag cached as well to give possibility check cache existence without data load. |
| 176 | + * |
| 177 | + * @param array $data |
| 178 | + * @return void |
| 179 | + */ |
| 180 | + private function cacheConfig($data) |
| 181 | + { |
| 182 | + foreach ($data as $scope => $scopeData) { |
| 183 | + foreach ($scopeData as $key => $config) { |
| 184 | + $this->cache->save( |
| 185 | + serialize($config), |
| 186 | + self::CONFIG_TYPE . '_' . $scope . $key, |
| 187 | + [self::CACHE_TAG] |
| 188 | + ); |
107 | 189 | } |
108 | 190 | } |
| 191 | + $this->cache->save('1', $this->cacheExistenceKey, [self::CACHE_TAG]); |
| 192 | + } |
| 193 | + |
| 194 | + /** |
| 195 | + * Read cached configuration |
| 196 | + * |
| 197 | + * @param string $path |
| 198 | + * @return mixed |
| 199 | + */ |
| 200 | + private function readFromCache($path) |
| 201 | + { |
| 202 | + if ($this->data === null) { |
| 203 | + $this->data = new DataObject(); |
| 204 | + } |
| 205 | + |
| 206 | + $result = null; |
| 207 | + $pathParts = $this->getPathParts($path); |
| 208 | + if (!empty($pathParts)) { |
| 209 | + $result = $this->cache->load(self::CONFIG_TYPE . '_' . $pathParts[0] . $pathParts[1]); |
| 210 | + } |
| 211 | + |
| 212 | + if ($result !== false && $result !== null) { |
| 213 | + $readData = $this->data->getData(); |
| 214 | + $readData[$pathParts[0]][$pathParts[1]] = unserialize($result); |
| 215 | + $this->data = new DataObject($readData); |
| 216 | + } |
109 | 217 |
|
110 | 218 | return $this->data->getData($path); |
111 | 219 | } |
|
0 commit comments