]> git.mxchange.org Git - friendica.git/blob - src/Util/ConfigFileLoader.php
Merge pull request #7738 from annando/clean-url
[friendica.git] / src / Util / ConfigFileLoader.php
1 <?php
2
3 namespace Friendica\Util;
4
5 use Exception;
6 use Friendica\Core\Addon;
7 use Friendica\Core\Config\Cache\ConfigCache;
8
9 /**
10  * The ConfigFileLoader loads config-files and stores them in a ConfigCache ( @see ConfigCache )
11  *
12  * It is capable of loading the following config files:
13  * - *.config.php   (current)
14  * - *.ini.php      (deprecated)
15  * - *.htconfig.php (deprecated)
16  */
17 class ConfigFileLoader
18 {
19         /**
20          * The Sub directory of the config-files
21          *
22          * @var string
23          */
24         const CONFIG_DIR = 'config';
25
26         /**
27          * The Sub directory of the static config-files
28          *
29          * @var string
30          */
31         const STATIC_DIR = 'static';
32
33         /**
34          * The default name of the user defined ini file
35          *
36          * @var string
37          */
38         const CONFIG_INI = 'local';
39
40         /**
41          * The default name of the user defined legacy config file
42          *
43          * @var string
44          */
45         const CONFIG_HTCONFIG = 'htconfig';
46
47         /**
48          * The sample string inside the configs, which shouldn't get loaded
49          *
50          * @var string
51          */
52         const SAMPLE_END = '-sample';
53
54         /**
55          * @var string
56          */
57         private $baseDir;
58         /**
59          * @var string
60          */
61         private $configDir;
62         /**
63          * @var string
64          */
65         private $staticDir;
66
67         public function __construct(string $basePath)
68         {
69                 $this->baseDir   = $basePath;
70                 $this->configDir = $this->baseDir . DIRECTORY_SEPARATOR . self::CONFIG_DIR;
71                 $this->staticDir = $this->baseDir . DIRECTORY_SEPARATOR . self::STATIC_DIR;
72         }
73
74         /**
75          * Load the configuration files into an configuration cache
76          *
77          * First loads the default value for all the configuration keys, then the legacy configuration files, then the
78          * expected local.config.php
79          *
80          * @param ConfigCache $config The config cache to load to
81          * @param bool        $raw    Setup the raw config format
82          *
83          * @throws Exception
84          */
85         public function setupCache(ConfigCache $config, $raw = false)
86         {
87                 // Load static config files first, the order is important
88                 $config->load($this->loadStaticConfig('defaults'));
89                 $config->load($this->loadStaticConfig('settings'));
90
91                 // try to load the legacy config first
92                 $config->load($this->loadLegacyConfig('htpreconfig'), true);
93                 $config->load($this->loadLegacyConfig('htconfig'), true);
94
95                 // Now load every other config you find inside the 'config/' directory
96                 $this->loadCoreConfig($config);
97
98                 // In case of install mode, add the found basepath (because there isn't a basepath set yet
99                 if (!$raw && empty($config->get('system', 'basepath'))) {
100                         // Setting at least the basepath we know
101                         $config->set('system', 'basepath', $this->baseDir);
102                 }
103         }
104
105         /**
106          * Tries to load the static core-configuration and returns the config array.
107          *
108          * @param string $name The name of the configuration
109          *
110          * @return array The config array (empty if no config found)
111          *
112          * @throws Exception if the configuration file isn't readable
113          */
114         private function loadStaticConfig($name)
115         {
116                 $configName = $this->staticDir . DIRECTORY_SEPARATOR . $name . '.config.php';
117                 $iniName    = $this->staticDir . DIRECTORY_SEPARATOR . $name . '.ini.php';
118
119                 if (file_exists($configName)) {
120                         return $this->loadConfigFile($configName);
121                 } elseif (file_exists($iniName)) {
122                         return $this->loadINIConfigFile($iniName);
123                 } else {
124                         return [];
125                 }
126         }
127
128         /**
129          * Tries to load the specified core-configuration into the config cache.
130          *
131          * @param ConfigCache $config The Config cache
132          *
133          * @return array The config array (empty if no config found)
134          *
135          * @throws Exception if the configuration file isn't readable
136          */
137         private function loadCoreConfig(ConfigCache $config)
138         {
139                 // try to load legacy ini-files first
140                 foreach ($this->getConfigFiles(true) as $configFile) {
141                         $config->load($this->loadINIConfigFile($configFile), true);
142                 }
143
144                 // try to load supported config at last to overwrite it
145                 foreach ($this->getConfigFiles() as $configFile) {
146                         $config->load($this->loadConfigFile($configFile), true);
147                 }
148
149                 return [];
150         }
151
152         /**
153          * Tries to load the specified addon-configuration and returns the config array.
154          *
155          * @param string $name The name of the configuration
156          *
157          * @return array The config array (empty if no config found)
158          *
159          * @throws Exception if the configuration file isn't readable
160          */
161         public function loadAddonConfig($name)
162         {
163                 $filepath = $this->baseDir . DIRECTORY_SEPARATOR .   // /var/www/html/
164                             Addon::DIRECTORY . DIRECTORY_SEPARATOR . // addon/
165                             $name . DIRECTORY_SEPARATOR .            // openstreetmap/
166                             self::CONFIG_DIR . DIRECTORY_SEPARATOR . // config/
167                             $name . ".config.php";                   // openstreetmap.config.php
168
169                 if (file_exists($filepath)) {
170                         return $this->loadConfigFile($filepath);
171                 } else {
172                         return [];
173                 }
174         }
175
176         /**
177          * Get the config files of the config-directory
178          *
179          * @param bool $ini True, if scan for ini-files instead of config files
180          *
181          * @return array
182          */
183         private function getConfigFiles(bool $ini = false)
184         {
185                 $files = scandir($this->configDir);
186                 $found = array();
187
188                 $filePattern = ($ini ? '*.ini.php' : '*.config.php');
189
190                 // Don't load sample files
191                 $sampleEnd = self::SAMPLE_END . ($ini ? '.ini.php' : '.config.php');
192
193                 foreach ($files as $filename) {
194                         if (fnmatch($filePattern, $filename) && substr_compare($filename, $sampleEnd, -strlen($sampleEnd))) {
195                                 $found[] = $this->configDir . '/' . $filename;
196                         }
197                 }
198
199                 return $found;
200         }
201
202         /**
203          * Tries to load the legacy config files (.htconfig.php, .htpreconfig.php) and returns the config array.
204          *
205          * @param string $name The name of the config file (default is empty, which means .htconfig.php)
206          *
207          * @return array The configuration array (empty if no config found)
208          *
209          * @deprecated since version 2018.09
210          */
211         private function loadLegacyConfig($name = '')
212         {
213                 $name     = !empty($name) ? $name : self::CONFIG_HTCONFIG;
214                 $fullName = $this->baseDir . DIRECTORY_SEPARATOR . '.' . $name . '.php';
215
216                 $config = [];
217                 if (file_exists($fullName)) {
218                         $a         = new \stdClass();
219                         $a->config = [];
220                         include $fullName;
221
222                         $htConfigCategories = array_keys($a->config);
223
224                         // map the legacy configuration structure to the current structure
225                         foreach ($htConfigCategories as $htConfigCategory) {
226                                 if (is_array($a->config[$htConfigCategory])) {
227                                         $keys = array_keys($a->config[$htConfigCategory]);
228
229                                         foreach ($keys as $key) {
230                                                 $config[$htConfigCategory][$key] = $a->config[$htConfigCategory][$key];
231                                         }
232                                 } else {
233                                         $config['config'][$htConfigCategory] = $a->config[$htConfigCategory];
234                                 }
235                         }
236
237                         unset($a);
238
239                         if (isset($db_host)) {
240                                 $config['database']['hostname'] = $db_host;
241                                 unset($db_host);
242                         }
243                         if (isset($db_user)) {
244                                 $config['database']['username'] = $db_user;
245                                 unset($db_user);
246                         }
247                         if (isset($db_pass)) {
248                                 $config['database']['password'] = $db_pass;
249                                 unset($db_pass);
250                         }
251                         if (isset($db_data)) {
252                                 $config['database']['database'] = $db_data;
253                                 unset($db_data);
254                         }
255                         if (isset($config['system']['db_charset'])) {
256                                 $config['database']['charset'] = $config['system']['db_charset'];
257                         }
258                         if (isset($pidfile)) {
259                                 $config['system']['pidfile'] = $pidfile;
260                                 unset($pidfile);
261                         }
262                         if (isset($default_timezone)) {
263                                 $config['system']['default_timezone'] = $default_timezone;
264                                 unset($default_timezone);
265                         }
266                         if (isset($lang)) {
267                                 $config['system']['language'] = $lang;
268                                 unset($lang);
269                         }
270                 }
271
272                 return $config;
273         }
274
275         /**
276          * Tries to load the specified legacy configuration file and returns the config array.
277          *
278          * @param string $filepath
279          *
280          * @return array The configuration array
281          * @throws Exception
282          * @deprecated since version 2018.12
283          */
284         private function loadINIConfigFile($filepath)
285         {
286                 $contents = include($filepath);
287
288                 $config = parse_ini_string($contents, true, INI_SCANNER_TYPED);
289
290                 if ($config === false) {
291                         throw new Exception('Error parsing INI config file ' . $filepath);
292                 }
293
294                 return $config;
295         }
296
297         /**
298          * Tries to load the specified configuration file and returns the config array.
299          *
300          * The config format is PHP array and the template for configuration files is the following:
301          *
302          * <?php return [
303          *      'section' => [
304          *          'key' => 'value',
305          *      ],
306          * ];
307          *
308          * @param string $filepath The filepath of the
309          *
310          * @return array The config array0
311          *
312          * @throws Exception if the config cannot get loaded.
313          */
314         private function loadConfigFile($filepath)
315         {
316                 $config = include($filepath);
317
318                 if (!is_array($config)) {
319                         throw new Exception('Error loading config file ' . $filepath);
320                 }
321
322                 return $config;
323         }
324 }