TYPO3 CMS  TYPO3_8-7
ConfigurationManagerTest.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
20 class ConfigurationManagerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
21 {
25  protected $subject;
26 
27  protected function setUp()
28  {
30  [
31  'getDefaultConfigurationFileLocation',
32  'getLocalConfigurationFileLocation',
33  ]
34  );
35  }
36 
40  protected function createSubjectWithMockedMethods(array $methods)
41  {
42  $this->subject = $this->getMockBuilder(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class)
43  ->setMethods($methods)
44  ->getMock();
45  }
46 
51  {
52  $this->expectException(\RuntimeException::class);
53  $this->expectExceptionCode(1310203814);
54 
55  $defaultConfigurationFile = PATH_site . 'typo3temp/var/tests/' . $this->getUniqueId('defaultConfiguration');
56  file_put_contents(
57  $defaultConfigurationFile,
58  '<?php throw new \RuntimeException(\'foo\', 1310203814); ?>'
59  );
60  $this->testFilesToDelete[] = $defaultConfigurationFile;
61 
62  $this->subject
63  ->expects($this->once())
64  ->method('getDefaultConfigurationFileLocation')
65  ->will($this->returnValue($defaultConfigurationFile));
66  $this->subject->getDefaultConfiguration();
67  }
68 
73  {
74  $this->expectException(\RuntimeException::class);
75 
76  $configurationFile = PATH_site . 'typo3temp/var/tests/' . $this->getUniqueId('localConfiguration');
77  file_put_contents(
78  $configurationFile,
79  '<?php throw new \RuntimeException(\'foo\', 1310203815); ?>'
80  );
81  $this->testFilesToDelete[] = $configurationFile;
82 
83  $this->subject
84  ->expects($this->once())
85  ->method('getLocalConfigurationFileLocation')
86  ->will($this->returnValue($configurationFile));
87  $this->subject->getLocalConfiguration();
88  }
89 
94  {
95  $currentLocalConfiguration = [
96  'notChanged' => 23,
97  'changed' => 'unChanged',
98  ];
99  $overrideConfiguration = [
100  'changed' => 'changed',
101  'new' => 'new'
102  ];
103  $expectedConfiguration = [
104  'notChanged' => 23,
105  'changed' => 'changed',
106  'new' => 'new',
107  ];
108 
110  [
111  'getLocalConfiguration',
112  'writeLocalConfiguration',
113  ]
114  );
115  $this->subject->expects($this->once())
116  ->method('getLocalConfiguration')
117  ->will($this->returnValue($currentLocalConfiguration));
118  $this->subject->expects($this->once())
119  ->method('writeLocalConfiguration')
120  ->with($expectedConfiguration);
121 
122  $this->subject->updateLocalConfiguration($overrideConfiguration);
123  }
124 
129  {
131  [
132  'getDefaultConfiguration',
133  ]
134  );
135  $this->subject->expects($this->once())
136  ->method('getDefaultConfiguration')
137  ->will($this->returnValue(
138  [
139  'path' => 'value',
140  ]
141  ));
142 
143  $this->assertSame('value', $this->subject->getDefaultConfigurationValueByPath('path'));
144  }
145 
150  {
152  [
153  'getLocalConfiguration',
154  ]
155  );
156  $this->subject->expects($this->once())
157  ->method('getLocalConfiguration')
158  ->will($this->returnValue(
159  [
160  'path' => 'value',
161  ]
162  ));
163 
164  $this->assertSame('value', $this->subject->getLocalConfigurationValueByPath('path'));
165  }
166 
171  {
173  [
174  'getDefaultConfiguration',
175  'getLocalConfiguration',
176  ]
177  );
178  $this->subject->expects($this->once())
179  ->method('getDefaultConfiguration')
180  ->will($this->returnValue(
181  [
182  'path' => 'value',
183  ]
184  ));
185  $this->subject->expects($this->once())
186  ->method('getLocalConfiguration')
187  ->will($this->returnValue(
188  [
189  'path' => 'valueOverride',
190  ]
191  ));
192 
193  $this->assertSame('valueOverride', $this->subject->getConfigurationValueByPath('path'));
194  }
195 
200  {
202  'isValidLocalConfigurationPath',
203  ]);
204  $this->subject->expects($this->once())
205  ->method('isValidLocalConfigurationPath')
206  ->will($this->returnValue(false));
207 
208  $this->assertFalse($this->subject->setLocalConfigurationValueByPath('path', 'value'));
209  }
210 
215  {
216  $currentLocalConfiguration = [
217  'notChanged' => 23,
218  'toUpdate' => 'notUpdated',
219  ];
220  $expectedConfiguration = [
221  'notChanged' => 23,
222  'toUpdate' => 'updated',
223  ];
224 
226  [
227  'isValidLocalConfigurationPath',
228  'getLocalConfiguration',
229  'writeLocalConfiguration',
230  ]
231  );
232  $this->subject->expects($this->once())
233  ->method('isValidLocalConfigurationPath')
234  ->will($this->returnValue(true));
235  $this->subject->expects($this->once())
236  ->method('getLocalConfiguration')
237  ->will($this->returnValue($currentLocalConfiguration));
238  $this->subject->expects($this->once())
239  ->method('writeLocalConfiguration')
240  ->with($expectedConfiguration);
241 
242  $this->subject->setLocalConfigurationValueByPath('toUpdate', 'updated');
243  }
244 
249  {
250  $currentLocalConfiguration = [
251  'notChanged' => 23,
252  'toUpdate' => 'notUpdated',
253  ];
254  $expectedConfiguration = [
255  'notChanged' => 23,
256  'toUpdate' => 'updated',
257  'new' => 'new',
258  ];
259 
261  [
262  'isValidLocalConfigurationPath',
263  'getLocalConfiguration',
264  'writeLocalConfiguration',
265  ]
266  );
267  $this->subject->expects($this->any())
268  ->method('isValidLocalConfigurationPath')
269  ->will($this->returnValue(true));
270  $this->subject->expects($this->once())
271  ->method('getLocalConfiguration')
272  ->will($this->returnValue($currentLocalConfiguration));
273  $this->subject->expects($this->once())
274  ->method('writeLocalConfiguration')
275  ->with($expectedConfiguration);
276 
277  $pairs = [
278  'toUpdate' => 'updated',
279  'new' => 'new'
280  ];
281  $this->subject->setLocalConfigurationValuesByPathValuePairs($pairs);
282  }
283 
288  {
289  $currentLocalConfiguration = [
290  'toRemove1' => 'foo',
291  'notChanged' => 23,
292  'toRemove2' => 'bar',
293  ];
294  $expectedConfiguration = [
295  'notChanged' => 23,
296  ];
297 
299  [
300  'getLocalConfiguration',
301  'writeLocalConfiguration',
302  ]
303  );
304  $this->subject->expects($this->once())
305  ->method('getLocalConfiguration')
306  ->will($this->returnValue($currentLocalConfiguration));
307  $this->subject->expects($this->once())
308  ->method('writeLocalConfiguration')
309  ->with($expectedConfiguration);
310 
311  $removePaths = [
312  'toRemove1',
313  'toRemove2',
314  ];
315  $this->assertTrue($this->subject->removeLocalConfigurationKeysByPath($removePaths));
316  }
317 
322  {
323  $currentLocalConfiguration = [
324  'notChanged' => 23,
325  ];
327  [
328  'getLocalConfiguration',
329  'writeLocalConfiguration',
330  ]
331  );
332  $this->subject->expects($this->once())
333  ->method('getLocalConfiguration')
334  ->will($this->returnValue($currentLocalConfiguration));
335  $this->subject->expects($this->never())
336  ->method('writeLocalConfiguration');
337 
338  $removeNothing = [];
339  $this->assertFalse($this->subject->removeLocalConfigurationKeysByPath($removeNothing));
340  }
341 
346  {
347  $currentLocalConfiguration = [
348  'notChanged' => 23,
349  ];
351  [
352  'getLocalConfiguration',
353  'writeLocalConfiguration',
354  ]
355  );
356  $this->subject->expects($this->once())
357  ->method('getLocalConfiguration')
358  ->will($this->returnValue($currentLocalConfiguration));
359  $this->subject->expects($this->never())
360  ->method('writeLocalConfiguration');
361 
362  $removeNonExisting = ['notPresent'];
363  $this->assertFalse($this->subject->removeLocalConfigurationKeysByPath($removeNonExisting));
364  }
365 
369  public function canWriteConfigurationReturnsFalseIfLocalConfigurationFileIsNotWritable()
370  {
371  if (function_exists('posix_getegid') && posix_getegid() === 0) {
372  $this->markTestSkipped('Test skipped if run on linux as root');
373  }
375  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
376 
377  $file = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
378  $absoluteFile = PATH_site . $file;
379  touch($absoluteFile);
380  $this->testFilesToDelete[] = $absoluteFile;
381  chmod($absoluteFile, 0444);
382  clearstatcache();
383 
384  $subject->_set('localConfigurationFile', $file);
385 
386  $result = $subject->canWriteConfiguration();
387 
388  chmod($absoluteFile, 0644);
389 
390  $this->assertFalse($result);
391  }
392 
396  public function canWriteConfigurationReturnsTrueIfDirectoryAndFilesAreWritable()
397  {
399  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
400 
401  $directory = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
402  $absoluteDirectory = PATH_site . $directory;
403  mkdir($absoluteDirectory);
404 
405  $file = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
406  $absoluteFile1 = PATH_site . $file;
407  touch($absoluteFile1);
408  $this->testFilesToDelete[] = $absoluteFile1;
409  $subject->_set('localConfigurationFile', $absoluteFile1);
410 
411  clearstatcache();
412 
413  $result = $subject->canWriteConfiguration();
414 
415  $this->assertTrue($result);
416  $this->testFilesToDelete[] = $absoluteDirectory;
417  }
418 
423  {
424  $configurationFile = PATH_site . 'typo3temp/var/tests/' . $this->getUniqueId('localConfiguration');
425  if (!is_file($configurationFile)) {
426  if (!$fh = fopen($configurationFile, 'wb')) {
427  $this->markTestSkipped('Can not create file ' . $configurationFile . '. Please check your write permissions.');
428  }
429  fclose($fh);
430  }
431 
432  if (!@is_file($configurationFile)) {
433  throw new \RuntimeException('File ' . $configurationFile . ' could not be found. Please check your write permissions', 1346364362);
434  }
435  $this->testFilesToDelete[] = $configurationFile;
436 
437  $this->subject
438  ->expects($this->any())
439  ->method('getLocalConfigurationFileLocation')
440  ->will($this->returnValue($configurationFile));
441 
442  $pairs = [
443  'foo' => 42,
444  'bar' => 23
445  ];
446  $expectedContent =
447  '<?php' . LF .
448  'return [' . LF .
449  ' \'bar\' => 23,' . LF .
450  ' \'foo\' => 42,' . LF .
451  '];' . LF;
452 
453  $this->subject->writeLocalConfiguration($pairs);
454  $this->assertSame($expectedContent, file_get_contents($configurationFile));
455  }
456 
460  public function createLocalConfigurationFromFactoryConfigurationThrowsExceptionIfFileExists()
461  {
462  $this->expectException(\RuntimeException::class);
463 
465  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
466 
467  $file = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
468  $absoluteFile = PATH_site . $file;
469  touch($absoluteFile);
470  $this->testFilesToDelete[] = $absoluteFile;
471  $subject->_set('localConfigurationFile', $file);
472 
473  $subject->createLocalConfigurationFromFactoryConfiguration();
474  }
475 
479  public function createLocalConfigurationFromFactoryConfigurationWritesContentFromFactoryFile()
480  {
482  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['writeLocalConfiguration']);
483  $subject->_set('localConfigurationFile', 'typo3temp/var/tests/' . $this->getUniqueId('dummy_'));
484 
485  $factoryConfigurationFile = 'typo3temp/var/tests/' . $this->getUniqueId('test_') . '.php';
486  $factoryConfigurationAbsoluteFile = PATH_site . $factoryConfigurationFile;
487  $uniqueContentString = $this->getUniqueId('string_');
488  $validFactoryConfigurationFileContent =
489  '<?php' . LF .
490  'return [' . LF .
491  '\'' . $uniqueContentString . '\' => \'foo\',' . LF .
492  '];' . LF;
493  file_put_contents(
494  $factoryConfigurationAbsoluteFile,
495  $validFactoryConfigurationFileContent
496  );
497  $this->testFilesToDelete[] = $factoryConfigurationAbsoluteFile;
498 
499  $subject->_set('factoryConfigurationFile', $factoryConfigurationFile);
500 
501  $subject
502  ->expects($this->once())
503  ->method('writeLocalConfiguration')
504  ->with($this->arrayHasKey($uniqueContentString));
505  $subject->createLocalConfigurationFromFactoryConfiguration();
506  }
507 
511  public function createLocalConfigurationFromFactoryConfigurationMergesConfigurationWithAdditionalFactoryFile()
512  {
514  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['writeLocalConfiguration']);
515  $subject->_set('localConfigurationFile', 'typo3temp/var/tests/' . $this->getUniqueId('dummy_'));
516 
517  $factoryConfigurationFile = 'typo3temp/var/tests/' . $this->getUniqueId('test_') . '.php';
518  $factoryConfigurationAbsoluteFile = PATH_site . $factoryConfigurationFile;
519  $validFactoryConfigurationFileContent =
520  '<?php' . LF .
521  'return [];' . LF;
522  file_put_contents(
523  $factoryConfigurationAbsoluteFile,
524  $validFactoryConfigurationFileContent
525  );
526  $this->testFilesToDelete[] = $factoryConfigurationAbsoluteFile;
527  $subject->_set('factoryConfigurationFile', $factoryConfigurationFile);
528 
529  $additionalFactoryConfigurationFile = 'typo3temp/var/tests/' . $this->getUniqueId('test_') . '.php';
530  $additionalFactoryConfigurationAbsoluteFile = PATH_site . $additionalFactoryConfigurationFile;
531  $uniqueContentString = $this->getUniqueId('string_');
532  $validAdditionalFactoryConfigurationFileContent =
533  '<?php' . LF .
534  'return [' . LF .
535  '\'' . $uniqueContentString . '\' => \'foo\',' . LF .
536  '];' . LF;
537  file_put_contents(
538  $additionalFactoryConfigurationAbsoluteFile,
539  $validAdditionalFactoryConfigurationFileContent
540  );
541  $this->testFilesToDelete[] = $additionalFactoryConfigurationAbsoluteFile;
542  $subject->_set('additionalFactoryConfigurationFile', $additionalFactoryConfigurationFile);
543 
544  $subject
545  ->expects($this->once())
546  ->method('writeLocalConfiguration')
547  ->with($this->arrayHasKey($uniqueContentString));
548  $subject->createLocalConfigurationFromFactoryConfiguration();
549  }
550 
554  public function isValidLocalConfigurationPathAcceptsWhitelistedPath()
555  {
557  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
558  $subject->_set('whiteListedLocalConfigurationPaths', ['foo/bar']);
559  $this->assertTrue($subject->_call('isValidLocalConfigurationPath', 'foo/bar/baz'));
560  }
561 
565  public function isValidLocalConfigurationPathDeniesNotWhitelistedPath()
566  {
568  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
569  $subject->_set('whiteListedLocalConfigurationPaths', ['foo/bar']);
570  $this->assertFalse($subject->_call('isValidLocalConfigurationPath', 'bar/baz'));
571  }
572 }