TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
ConfigurationManagerTest.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Configuration;
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 
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  'path' => 'value',
139  ]
140  ));
141 
142  $this->assertSame('value', $this->subject->getDefaultConfigurationValueByPath('path'));
143  }
144 
149  {
151  [
152  'getLocalConfiguration',
153  ]
154  );
155  $this->subject->expects($this->once())
156  ->method('getLocalConfiguration')
157  ->will($this->returnValue([
158  'path' => 'value',
159  ]
160  ));
161 
162  $this->assertSame('value', $this->subject->getLocalConfigurationValueByPath('path'));
163  }
164 
169  {
171  [
172  'getDefaultConfiguration',
173  'getLocalConfiguration',
174  ]
175  );
176  $this->subject->expects($this->once())
177  ->method('getDefaultConfiguration')
178  ->will($this->returnValue([
179  'path' => 'value',
180  ]
181  ));
182  $this->subject->expects($this->once())
183  ->method('getLocalConfiguration')
184  ->will($this->returnValue([
185  'path' => 'valueOverride',
186  ]
187  ));
188 
189  $this->assertSame('valueOverride', $this->subject->getConfigurationValueByPath('path'));
190  }
191 
196  {
198  'isValidLocalConfigurationPath',
199  ]);
200  $this->subject->expects($this->once())
201  ->method('isValidLocalConfigurationPath')
202  ->will($this->returnValue(false));
203 
204  $this->assertFalse($this->subject->setLocalConfigurationValueByPath('path', 'value'));
205  }
206 
211  {
212  $currentLocalConfiguration = [
213  'notChanged' => 23,
214  'toUpdate' => 'notUpdated',
215  ];
216  $expectedConfiguration = [
217  'notChanged' => 23,
218  'toUpdate' => 'updated',
219  ];
220 
222  [
223  'isValidLocalConfigurationPath',
224  'getLocalConfiguration',
225  'writeLocalConfiguration',
226  ]
227  );
228  $this->subject->expects($this->once())
229  ->method('isValidLocalConfigurationPath')
230  ->will($this->returnValue(true));
231  $this->subject->expects($this->once())
232  ->method('getLocalConfiguration')
233  ->will($this->returnValue($currentLocalConfiguration));
234  $this->subject->expects($this->once())
235  ->method('writeLocalConfiguration')
236  ->with($expectedConfiguration);
237 
238  $this->subject->setLocalConfigurationValueByPath('toUpdate', 'updated');
239  }
240 
245  {
246  $currentLocalConfiguration = [
247  'notChanged' => 23,
248  'toUpdate' => 'notUpdated',
249  ];
250  $expectedConfiguration = [
251  'notChanged' => 23,
252  'toUpdate' => 'updated',
253  'new' => 'new',
254  ];
255 
257  [
258  'isValidLocalConfigurationPath',
259  'getLocalConfiguration',
260  'writeLocalConfiguration',
261  ]
262  );
263  $this->subject->expects($this->any())
264  ->method('isValidLocalConfigurationPath')
265  ->will($this->returnValue(true));
266  $this->subject->expects($this->once())
267  ->method('getLocalConfiguration')
268  ->will($this->returnValue($currentLocalConfiguration));
269  $this->subject->expects($this->once())
270  ->method('writeLocalConfiguration')
271  ->with($expectedConfiguration);
272 
273  $pairs = [
274  'toUpdate' => 'updated',
275  'new' => 'new'
276  ];
277  $this->subject->setLocalConfigurationValuesByPathValuePairs($pairs);
278  }
279 
284  {
285  $currentLocalConfiguration = [
286  'toRemove1' => 'foo',
287  'notChanged' => 23,
288  'toRemove2' => 'bar',
289  ];
290  $expectedConfiguration = [
291  'notChanged' => 23,
292  ];
293 
295  [
296  'getLocalConfiguration',
297  'writeLocalConfiguration',
298  ]
299  );
300  $this->subject->expects($this->once())
301  ->method('getLocalConfiguration')
302  ->will($this->returnValue($currentLocalConfiguration));
303  $this->subject->expects($this->once())
304  ->method('writeLocalConfiguration')
305  ->with($expectedConfiguration);
306 
307  $removePaths = [
308  'toRemove1',
309  'toRemove2',
310  ];
311  $this->assertTrue($this->subject->removeLocalConfigurationKeysByPath($removePaths));
312  }
313 
318  {
319  $currentLocalConfiguration = [
320  'notChanged' => 23,
321  ];
323  [
324  'getLocalConfiguration',
325  'writeLocalConfiguration',
326  ]
327  );
328  $this->subject->expects($this->once())
329  ->method('getLocalConfiguration')
330  ->will($this->returnValue($currentLocalConfiguration));
331  $this->subject->expects($this->never())
332  ->method('writeLocalConfiguration');
333 
334  $removeNothing = [];
335  $this->assertFalse($this->subject->removeLocalConfigurationKeysByPath($removeNothing));
336  }
337 
342  {
343  $currentLocalConfiguration = [
344  'notChanged' => 23,
345  ];
347  [
348  'getLocalConfiguration',
349  'writeLocalConfiguration',
350  ]
351  );
352  $this->subject->expects($this->once())
353  ->method('getLocalConfiguration')
354  ->will($this->returnValue($currentLocalConfiguration));
355  $this->subject->expects($this->never())
356  ->method('writeLocalConfiguration');
357 
358  $removeNonExisting = ['notPresent'];
359  $this->assertFalse($this->subject->removeLocalConfigurationKeysByPath($removeNonExisting));
360  }
361 
365  public function canWriteConfigurationReturnsFalseIfLocalConfigurationFileIsNotWritable()
366  {
367  if (function_exists('posix_getegid') && posix_getegid() === 0) {
368  $this->markTestSkipped('Test skipped if run on linux as root');
369  }
371  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
372 
373  $file = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
374  $absoluteFile = PATH_site . $file;
375  touch($absoluteFile);
376  $this->testFilesToDelete[] = $absoluteFile;
377  chmod($absoluteFile, 0444);
378  clearstatcache();
379 
380  $subject->_set('localConfigurationFile', $file);
381 
382  $result = $subject->canWriteConfiguration();
383 
384  chmod($absoluteFile, 0644);
385 
386  $this->assertFalse($result);
387  }
388 
392  public function canWriteConfigurationReturnsTrueIfDirectoryAndFilesAreWritable()
393  {
395  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
396 
397  $directory = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
398  $absoluteDirectory = PATH_site . $directory;
399  mkdir($absoluteDirectory);
400  $subject->_set('pathTypo3Conf', $absoluteDirectory);
401 
402  $file1 = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
403  $absoluteFile1 = PATH_site . $file1;
404  touch($absoluteFile1);
405  $this->testFilesToDelete[] = $absoluteFile1;
406  $subject->_set('localConfigurationFile', $absoluteFile1);
407 
408  $file2 = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
409  $absoluteFile2 = PATH_site . $file2;
410  touch($absoluteFile2);
411  $this->testFilesToDelete[] = $absoluteFile2;
412  $subject->_set('localconfFile', $absoluteFile2);
413 
414  clearstatcache();
415 
416  $result = $subject->canWriteConfiguration();
417 
418  $this->assertTrue($result);
419  $this->testFilesToDelete[] = $absoluteDirectory;
420  }
421 
426  {
427  $configurationFile = PATH_site . 'typo3temp/var/tests/' . $this->getUniqueId('localConfiguration');
428  if (!is_file($configurationFile)) {
429  if (!$fh = fopen($configurationFile, 'wb')) {
430  $this->markTestSkipped('Can not create file ' . $configurationFile . '. Please check your write permissions.');
431  }
432  fclose($fh);
433  }
434 
435  if (!@is_file($configurationFile)) {
436  throw new \RuntimeException('File ' . $configurationFile . ' could not be found. Please check your write permissions', 1346364362);
437  }
438  $this->testFilesToDelete[] = $configurationFile;
439 
440  $this->subject
441  ->expects($this->any())
442  ->method('getLocalConfigurationFileLocation')
443  ->will($this->returnValue($configurationFile));
444 
445  $pairs = [
446  'foo' => 42,
447  'bar' => 23
448  ];
449  $expectedContent =
450  '<?php' . LF .
451  'return [' . LF .
452  ' \'bar\' => 23,' . LF .
453  ' \'foo\' => 42,' . LF .
454  '];' . LF;
455 
456  $this->subject->writeLocalConfiguration($pairs);
457  $this->assertSame($expectedContent, file_get_contents($configurationFile));
458  }
459 
463  public function createLocalConfigurationFromFactoryConfigurationThrowsExceptionIfFileExists()
464  {
465  $this->expectException(\RuntimeException::class);
466 
468  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
469 
470  $file = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
471  $absoluteFile = PATH_site . $file;
472  touch($absoluteFile);
473  $this->testFilesToDelete[] = $absoluteFile;
474  $subject->_set('localConfigurationFile', $file);
475 
476  $subject->createLocalConfigurationFromFactoryConfiguration();
477  }
478 
482  public function createLocalConfigurationFromFactoryConfigurationWritesContentFromFactoryFile()
483  {
485  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['writeLocalConfiguration']);
486  $subject->_set('localConfigurationFile', 'typo3temp/var/tests/' . $this->getUniqueId('dummy_'));
487 
488  $factoryConfigurationFile = 'typo3temp/var/tests/' . $this->getUniqueId('test_') . '.php';
489  $factoryConfigurationAbsoluteFile = PATH_site . $factoryConfigurationFile;
490  $uniqueContentString = $this->getUniqueId('string_');
491  $validFactoryConfigurationFileContent =
492  '<?php' . LF .
493  'return array(' . LF .
494  $uniqueContentString . ' => foo,' . LF .
495  ');' . LF;
496  file_put_contents(
497  $factoryConfigurationAbsoluteFile,
498  $validFactoryConfigurationFileContent
499  );
500  $this->testFilesToDelete[] = $factoryConfigurationAbsoluteFile;
501 
502  $subject->_set('factoryConfigurationFile', $factoryConfigurationFile);
503 
504  $subject
505  ->expects($this->once())
506  ->method('writeLocalConfiguration')
507  ->with($this->arrayHasKey($uniqueContentString));
508  $subject->createLocalConfigurationFromFactoryConfiguration();
509  }
510 
514  public function createLocalConfigurationFromFactoryConfigurationMergesConfigurationWithAdditionalFactoryFile()
515  {
517  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['writeLocalConfiguration']);
518  $subject->_set('localConfigurationFile', 'typo3temp/var/tests/' . $this->getUniqueId('dummy_'));
519 
520  $factoryConfigurationFile = 'typo3temp/var/tests/' . $this->getUniqueId('test_') . '.php';
521  $factoryConfigurationAbsoluteFile = PATH_site . $factoryConfigurationFile;
522  $validFactoryConfigurationFileContent =
523  '<?php' . LF .
524  'return [];' . LF;
525  file_put_contents(
526  $factoryConfigurationAbsoluteFile,
527  $validFactoryConfigurationFileContent
528  );
529  $this->testFilesToDelete[] = $factoryConfigurationAbsoluteFile;
530  $subject->_set('factoryConfigurationFile', $factoryConfigurationFile);
531 
532  $additionalFactoryConfigurationFile = 'typo3temp/var/tests/' . $this->getUniqueId('test_') . '.php';
533  $additionalFactoryConfigurationAbsoluteFile = PATH_site . $additionalFactoryConfigurationFile;
534  $uniqueContentString = $this->getUniqueId('string_');
535  $validAdditionalFactoryConfigurationFileContent =
536  '<?php' . LF .
537  'return [' . LF .
538  $uniqueContentString . ' => foo,' . LF .
539  '];' . LF;
540  file_put_contents(
541  $additionalFactoryConfigurationAbsoluteFile,
542  $validAdditionalFactoryConfigurationFileContent
543  );
544  $this->testFilesToDelete[] = $additionalFactoryConfigurationAbsoluteFile;
545  $subject->_set('additionalFactoryConfigurationFile', $additionalFactoryConfigurationFile);
546 
547  $subject
548  ->expects($this->once())
549  ->method('writeLocalConfiguration')
550  ->with($this->arrayHasKey($uniqueContentString));
551  $subject->createLocalConfigurationFromFactoryConfiguration();
552  }
553 
557  public function isValidLocalConfigurationPathAcceptsWhitelistedPath()
558  {
560  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
561  $subject->_set('whiteListedLocalConfigurationPaths', ['foo/bar']);
562  $this->assertTrue($subject->_call('isValidLocalConfigurationPath', 'foo/bar/baz'));
563  }
564 
568  public function isValidLocalConfigurationPathDeniesNotWhitelistedPath()
569  {
571  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
572  $subject->_set('whiteListedLocalConfigurationPaths', ['foo/bar']);
573  $this->assertFalse($subject->_call('isValidLocalConfigurationPath', 'bar/baz'));
574  }
575 }
getAccessibleMock($originalClassName, $methods=[], array $arguments=[], $mockClassName= '', $callOriginalConstructor=true, $callOriginalClone=true, $callAutoload=true)