]> git.mxchange.org Git - friendica.git/blob - tests/src/Core/Config/Cache/ConfigFileManagerTest.php
Apply feedback and describe the encoding method
[friendica.git] / tests / src / Core / Config / Cache / ConfigFileManagerTest.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2023, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Test\src\Core\Config\Cache;
23
24 use Friendica\Core\Config\Factory\Config;
25 use Friendica\Core\Config\ValueObject\Cache;
26 use Friendica\Test\MockedTest;
27 use Friendica\Test\Util\VFSTrait;
28 use Friendica\Core\Config\Util\ConfigFileManager;
29 use org\bovigo\vfs\vfsStream;
30
31 class ConfigFileManagerTest extends MockedTest
32 {
33         use VFSTrait;
34
35         protected function setUp(): void
36         {
37                 parent::setUp();
38
39                 $this->setUpVfsDir();
40         }
41
42         /**
43          * Test the loadConfigFiles() method with default values
44          */
45         public function testLoadConfigFiles()
46         {
47                 $this->delConfigFile('local.config.php');
48
49                 $configFileLoader = new ConfigFileManager(
50                         $this->root->url(),
51                         $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
52                         $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
53                 );
54
55                 $configCache = new Cache();
56
57                 $configFileLoader->setupCache($configCache);
58
59                 self::assertEquals($this->root->url(), $configCache->get('system', 'basepath'));
60         }
61
62         /**
63          * Test the loadConfigFiles() method with a wrong local.config.php
64          *
65          */
66         public function testLoadConfigWrong()
67         {
68                 $this->expectExceptionMessageMatches("/Error loading config file \w+/");
69                 $this->expectException(\Exception::class);
70                 $this->delConfigFile('local.config.php');
71
72                 vfsStream::newFile('local.config.php')
73                                  ->at($this->root->getChild('config'))
74                                  ->setContent('<?php return true;');
75
76                 $configFileLoader = new ConfigFileManager(
77                         $this->root->url(),
78                         $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
79                         $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
80                 );
81                 $configCache      = new Cache();
82
83                 $configFileLoader->setupCache($configCache);
84         }
85
86         /**
87          * Test the loadConfigFiles() method with a local.config.php file
88          */
89         public function testLoadConfigFilesLocal()
90         {
91                 $this->delConfigFile('local.config.php');
92
93                 $file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
94                                 '..' . DIRECTORY_SEPARATOR .
95                                 '..' . DIRECTORY_SEPARATOR .
96                                 '..' . DIRECTORY_SEPARATOR .
97                                 'datasets' . DIRECTORY_SEPARATOR .
98                                 'config' . DIRECTORY_SEPARATOR .
99                                 'A.config.php';
100
101                 vfsStream::newFile('local.config.php')
102                                  ->at($this->root->getChild('config'))
103                                  ->setContent(file_get_contents($file));
104
105                 $configFileLoader = new ConfigFileManager(
106                         $this->root->url(),
107                         $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
108                         $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
109                 );
110                 $configCache      = new Cache();
111
112                 $configFileLoader->setupCache($configCache);
113
114                 self::assertEquals('testhost', $configCache->get('database', 'hostname'));
115                 self::assertEquals('testuser', $configCache->get('database', 'username'));
116                 self::assertEquals('testpw', $configCache->get('database', 'password'));
117                 self::assertEquals('testdb', $configCache->get('database', 'database'));
118
119                 self::assertEquals('admin@test.it', $configCache->get('config', 'admin_email'));
120                 self::assertEquals('Friendica Social Network', $configCache->get('config', 'sitename'));
121         }
122
123         /**
124          * Test the loadConfigFile() method with a local.ini.php file
125          */
126         public function testLoadConfigFilesINI()
127         {
128                 $this->delConfigFile('local.config.php');
129
130                 $file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
131                                 '..' . DIRECTORY_SEPARATOR .
132                                 '..' . DIRECTORY_SEPARATOR .
133                                 '..' . DIRECTORY_SEPARATOR .
134                                 'datasets' . DIRECTORY_SEPARATOR .
135                                 'config' . DIRECTORY_SEPARATOR .
136                                 'A.ini.php';
137
138                 vfsStream::newFile('local.ini.php')
139                                  ->at($this->root->getChild('config'))
140                                  ->setContent(file_get_contents($file));
141
142                 $configFileLoader = new ConfigFileManager(
143                         $this->root->url(),
144                         $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
145                         $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
146                 );
147                 $configCache      = new Cache();
148
149                 $configFileLoader->setupCache($configCache);
150
151                 self::assertEquals('testhost', $configCache->get('database', 'hostname'));
152                 self::assertEquals('testuser', $configCache->get('database', 'username'));
153                 self::assertEquals('testpw', $configCache->get('database', 'password'));
154                 self::assertEquals('testdb', $configCache->get('database', 'database'));
155
156                 self::assertEquals('admin@test.it', $configCache->get('config', 'admin_email'));
157         }
158
159         /**
160          * Test the loadConfigFile() method with a .htconfig.php file
161          */
162         public function testLoadConfigFilesHtconfig()
163         {
164                 $this->delConfigFile('local.config.php');
165
166                 $file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
167                                 '..' . DIRECTORY_SEPARATOR .
168                                 '..' . DIRECTORY_SEPARATOR .
169                                 '..' . DIRECTORY_SEPARATOR .
170                                 'datasets' . DIRECTORY_SEPARATOR .
171                                 'config' . DIRECTORY_SEPARATOR .
172                                 '.htconfig.php';
173
174                 vfsStream::newFile('.htconfig.php')
175                                  ->at($this->root)
176                                  ->setContent(file_get_contents($file));
177
178                 $configFileLoader = new ConfigFileManager(
179                         $this->root->url(),
180                         $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
181                         $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
182                 );
183                 $configCache      = new Cache();
184
185                 $configFileLoader->setupCache($configCache);
186
187                 self::assertEquals('testhost', $configCache->get('database', 'hostname'));
188                 self::assertEquals('testuser', $configCache->get('database', 'username'));
189                 self::assertEquals('testpw', $configCache->get('database', 'password'));
190                 self::assertEquals('testdb', $configCache->get('database', 'database'));
191                 self::assertEquals('anotherCharset', $configCache->get('database', 'charset'));
192
193                 self::assertEquals('/var/run/friendica.pid', $configCache->get('system', 'pidfile'));
194                 self::assertEquals('Europe/Berlin', $configCache->get('system', 'default_timezone'));
195                 self::assertEquals('fr', $configCache->get('system', 'language'));
196
197                 self::assertEquals('admin@test.it', $configCache->get('config', 'admin_email'));
198                 self::assertEquals('Friendly admin', $configCache->get('config', 'admin_nickname'));
199
200                 self::assertEquals('/another/php', $configCache->get('config', 'php_path'));
201                 self::assertEquals('999', $configCache->get('config', 'max_import_size'));
202                 self::assertEquals('666', $configCache->get('system', 'maximagesize'));
203
204                 self::assertEquals('frio,vier', $configCache->get('system', 'allowed_themes'));
205                 self::assertEquals('1', $configCache->get('system', 'no_regfullname'));
206         }
207
208         public function testLoadAddonConfig()
209         {
210                 $structure = [
211                         'addon' => [
212                                 'test' => [
213                                         'config' => [],
214                                 ],
215                         ],
216                 ];
217
218                 vfsStream::create($structure, $this->root);
219
220                 $file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
221                                 '..' . DIRECTORY_SEPARATOR .
222                                 '..' . DIRECTORY_SEPARATOR .
223                                 '..' . DIRECTORY_SEPARATOR .
224                                 'datasets' . DIRECTORY_SEPARATOR .
225                                 'config' . DIRECTORY_SEPARATOR .
226                                 'A.config.php';
227
228                 vfsStream::newFile('test.config.php')
229                                  ->at($this->root->getChild('addon')->getChild('test')->getChild('config'))
230                                  ->setContent(file_get_contents($file));
231
232                 $configFileLoader = new ConfigFileManager(
233                         $this->root->url(),
234                         $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
235                         $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
236                 );
237
238                 $conf = $configFileLoader->loadAddonConfig('test');
239
240                 self::assertEquals('testhost', $conf['database']['hostname']);
241                 self::assertEquals('testuser', $conf['database']['username']);
242                 self::assertEquals('testpw', $conf['database']['password']);
243                 self::assertEquals('testdb', $conf['database']['database']);
244
245                 self::assertEquals('admin@test.it', $conf['config']['admin_email']);
246         }
247
248         /**
249          * test loading multiple config files - the last config should work
250          */
251         public function testLoadMultipleConfigs()
252         {
253                 $this->delConfigFile('local.config.php');
254
255                 $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
256                                    '..' . DIRECTORY_SEPARATOR .
257                                    '..' . DIRECTORY_SEPARATOR .
258                                    '..' . DIRECTORY_SEPARATOR .
259                                    'datasets' . DIRECTORY_SEPARATOR .
260                                    'config' . DIRECTORY_SEPARATOR;
261
262                 vfsStream::newFile('A.config.php')
263                                  ->at($this->root->getChild('config'))
264                                  ->setContent(file_get_contents($fileDir . 'A.config.php'));
265                 vfsStream::newFile('B.config.php')
266                                  ->at($this->root->getChild('config'))
267                                  ->setContent(file_get_contents($fileDir . 'B.config.php'));
268
269                 $configFileLoader = new ConfigFileManager(
270                         $this->root->url(),
271                         $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
272                         $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
273                 );
274                 $configCache      = new Cache();
275
276                 $configFileLoader->setupCache($configCache);
277
278                 self::assertEquals('admin@overwritten.local', $configCache->get('config', 'admin_email'));
279                 self::assertEquals('newValue', $configCache->get('system', 'newKey'));
280         }
281
282         /**
283          * test loading multiple config files - the last config should work (INI-version)
284          */
285         public function testLoadMultipleInis()
286         {
287                 $this->delConfigFile('local.config.php');
288
289                 $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
290                                    '..' . DIRECTORY_SEPARATOR .
291                                    '..' . DIRECTORY_SEPARATOR .
292                                    '..' . DIRECTORY_SEPARATOR .
293                                    'datasets' . DIRECTORY_SEPARATOR .
294                                    'config' . DIRECTORY_SEPARATOR;
295
296                 vfsStream::newFile('A.ini.php')
297                                  ->at($this->root->getChild('config'))
298                                  ->setContent(file_get_contents($fileDir . 'A.ini.php'));
299                 vfsStream::newFile('B.ini.php')
300                                  ->at($this->root->getChild('config'))
301                                  ->setContent(file_get_contents($fileDir . 'B.ini.php'));
302
303                 $configFileLoader = new ConfigFileManager(
304                         $this->root->url(),
305                         $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
306                         $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
307                 );
308                 $configCache      = new Cache();
309
310                 $configFileLoader->setupCache($configCache);
311
312                 self::assertEquals('admin@overwritten.local', $configCache->get('config', 'admin_email'));
313                 self::assertEquals('newValue', $configCache->get('system', 'newKey'));
314         }
315
316         /**
317          * Test that sample-files (e.g. local-sample.config.php) is never loaded
318          */
319         public function testNotLoadingSamples()
320         {
321                 $this->delConfigFile('local.config.php');
322
323                 $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
324                                    '..' . DIRECTORY_SEPARATOR .
325                                    '..' . DIRECTORY_SEPARATOR .
326                                    '..' . DIRECTORY_SEPARATOR .
327                                    'datasets' . DIRECTORY_SEPARATOR .
328                                    'config' . DIRECTORY_SEPARATOR;
329
330                 vfsStream::newFile('A.ini.php')
331                                  ->at($this->root->getChild('config'))
332                                  ->setContent(file_get_contents($fileDir . 'A.ini.php'));
333                 vfsStream::newFile('B-sample.ini.php')
334                                  ->at($this->root->getChild('config'))
335                                  ->setContent(file_get_contents($fileDir . 'B.ini.php'));
336
337                 $configFileLoader = new ConfigFileManager(
338                         $this->root->url(),
339                         $this->root->url() . DIRECTORY_SEPARATOR . Config::CONFIG_DIR,
340                         $this->root->url() . DIRECTORY_SEPARATOR . Config::STATIC_DIR
341                 );
342
343                 $configCache = new Cache();
344
345                 $configFileLoader->setupCache($configCache);
346
347                 self::assertEquals('admin@test.it', $configCache->get('config', 'admin_email'));
348                 self::assertEmpty($configCache->get('system', 'NewKey'));
349         }
350
351         /**
352          * Test that using a wrong configuration directory leads to the "normal" config path
353          */
354         public function testWrongEnvDir()
355         {
356                 $this->delConfigFile('local.config.php');
357
358                 $configFileManager = (new Config())->createConfigFileManager($this->root->url(), ['FRIENDICA_CONFIG_DIR' => '/a/wrong/dir/']);
359                 $configCache       = new Cache();
360
361                 $configFileManager->setupCache($configCache);
362
363                 self::assertEquals($this->root->url(), $configCache->get('system', 'basepath'));
364         }
365
366         /**
367          * Test that a different location of the configuration directory produces the expected output
368          */
369         public function testRightEnvDir()
370         {
371                 $this->delConfigFile('local.config.php');
372
373                 $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
374                                    '..' . DIRECTORY_SEPARATOR .
375                                    '..' . DIRECTORY_SEPARATOR .
376                                    '..' . DIRECTORY_SEPARATOR .
377                                    'datasets' . DIRECTORY_SEPARATOR .
378                                    'config' . DIRECTORY_SEPARATOR;
379
380                 vfsStream::newFile('B.config.php')
381                                  ->at($this->root->getChild('config2'))
382                                  ->setContent(file_get_contents($fileDir . 'B.config.php'));
383
384                 $configFileManager = (new Config())->createConfigFileManager($this->root->url(),
385                         [
386                                 'FRIENDICA_CONFIG_DIR' => $this->root->getChild('config2')->url(),
387                         ]);
388                 $configCache       = new Cache();
389
390                 $configFileManager->setupCache($configCache);
391
392                 self::assertEquals('newValue', $configCache->get('system', 'newKey'));
393         }
394
395         public function testSaveData()
396         {
397                 $this->delConfigFile('local.config.php');
398
399                 $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
400                                    '..' . DIRECTORY_SEPARATOR .
401                                    '..' . DIRECTORY_SEPARATOR .
402                                    '..' . DIRECTORY_SEPARATOR .
403                                    'datasets' . DIRECTORY_SEPARATOR .
404                                    'config' . DIRECTORY_SEPARATOR;
405
406                 vfsStream::newFile('B.config.php')
407                                  ->at($this->root->getChild('config2'))
408                                  ->setContent(file_get_contents($fileDir . 'B.config.php'));
409
410                 $configFileManager = (new Config())->createConfigFileManager($this->root->url(),
411                         [
412                                 'FRIENDICA_CONFIG_DIR' => $this->root->getChild('config2')->url(),
413                         ]);
414                 $configCache       = new Cache();
415
416                 $configFileManager->setupCache($configCache);
417
418                 $specialChars = '!"§$%&/()(/&%$\'><?$a,;:[]}{}\\?¿¿ß';
419
420                 // overwrite some data and save it back to the config file
421                 $configCache->set('system', 'test', 'it', Cache::SOURCE_DATA);
422                 $configCache->set('config', 'test', 'it', Cache::SOURCE_DATA);
423                 $configCache->set('system', 'test_2', 2, Cache::SOURCE_DATA);
424                 $configCache->set('special_chars', 'special', $specialChars, Cache::SOURCE_DATA);
425                 $configFileManager->saveData($configCache);
426
427                 // Reload the configCache with the new values
428                 $configCache2 = new Cache();
429                 $configFileManager->setupCache($configCache2);
430
431                 self::assertEquals($configCache, $configCache2);
432                 self::assertEquals([
433                         'system'        => [
434                                 'test'   => 'it',
435                                 'test_2' => 2
436                         ],
437                         'config'        => [
438                                 'test' => 'it',
439                         ],
440                         'special_chars' => [
441                                 'special' => $specialChars,
442                         ]], $configCache2->getDataBySource(Cache::SOURCE_DATA));
443         }
444
445         /**
446          * If we delete something with the Cache::delete() functionality, be sure to override the underlying source as well
447          */
448         public function testDeleteKeyOverwrite()
449         {
450                 $this->delConfigFile('node.config.php');
451
452                 $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
453                                    '..' . DIRECTORY_SEPARATOR .
454                                    '..' . DIRECTORY_SEPARATOR .
455                                    '..' . DIRECTORY_SEPARATOR .
456                                    'datasets' . DIRECTORY_SEPARATOR .
457                                    'config' . DIRECTORY_SEPARATOR;
458
459                 vfsStream::newFile('B.config.php')
460                                  ->at($this->root->getChild('config'))
461                                  ->setContent(file_get_contents($fileDir . 'B.config.php'));
462
463                 $configFileManager = (new Config())->createConfigFileManager($this->root->url());
464                 $configCache       = new Cache();
465
466                 $configFileManager->setupCache($configCache);
467
468                 $configCache->delete('system', 'default_timezone', Cache::SOURCE_DATA);
469
470                 $configFileManager->saveData($configCache);
471
472                 // assert that system.default_timezone is now null, even it's set with settings.conf.php
473                 $configCache       = new Cache();
474
475                 $configFileManager->setupCache($configCache);
476
477                 self::assertNull($configCache->get('system', 'default_timezone'));
478         }
479
480         /**
481          * If we delete something with the Cache::delete() functionality, be sure to override the underlying source as well
482          */
483         public function testDeleteCategoryOverwrite()
484         {
485                 $this->delConfigFile('node.config.php');
486
487                 $fileDir = dirname(__DIR__) . DIRECTORY_SEPARATOR .
488                                    '..' . DIRECTORY_SEPARATOR .
489                                    '..' . DIRECTORY_SEPARATOR .
490                                    '..' . DIRECTORY_SEPARATOR .
491                                    'datasets' . DIRECTORY_SEPARATOR .
492                                    'config' . DIRECTORY_SEPARATOR;
493
494                 vfsStream::newFile('B.config.php')
495                                  ->at($this->root->getChild('config'))
496                                  ->setContent(file_get_contents($fileDir . 'B.config.php'));
497
498                 $configFileManager = (new Config())->createConfigFileManager($this->root->url());
499                 $configCache       = new Cache();
500
501                 $configFileManager->setupCache($configCache);
502
503                 $configCache->delete('system');
504
505                 $configFileManager->saveData($configCache);
506
507                 // assert that system.default_timezone is now null, even it's set with settings.conf.php
508                 $configCache       = new Cache();
509
510                 $configFileManager->setupCache($configCache);
511
512                 self::assertNull($configCache->get('system', 'default_timezone'));
513         }
514
515         /**
516          * Test for empty node.config.php
517          */
518         public function testEmptyFile()
519         {
520                 $this->delConfigFile('node.config.php');
521
522                 vfsStream::newFile('node.config.php')
523                                  ->at($this->root->getChild('config'))
524                                  ->setContent('');
525
526                 $configFileManager = (new Config())->createConfigFileManager($this->root->url());
527                 $configCache       = new Cache();
528
529                 $configFileManager->setupCache($configCache);
530
531                 self::assertEquals(1,1);
532         }
533 }