TYPO3 CMS  TYPO3_7-6
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 
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->getMock(
43  \TYPO3\CMS\Core\Configuration\ConfigurationManager::class,
44  $methods
45  );
46  }
47 
53  {
54  $defaultConfigurationFile = PATH_site . 'typo3temp/' . $this->getUniqueId('defaultConfiguration');
55  file_put_contents(
56  $defaultConfigurationFile,
57  '<?php throw new \RuntimeException(\'foo\', 1310203814); ?>'
58  );
59  $this->testFilesToDelete[] = $defaultConfigurationFile;
60 
61  $this->subject
62  ->expects($this->once())
63  ->method('getDefaultConfigurationFileLocation')
64  ->will($this->returnValue($defaultConfigurationFile));
65  $this->subject->getDefaultConfiguration();
66  }
67 
73  {
74  $configurationFile = PATH_site . 'typo3temp/' . $this->getUniqueId('localConfiguration');
75  file_put_contents(
76  $configurationFile,
77  '<?php throw new \RuntimeException(\'foo\', 1310203815); ?>'
78  );
79  $this->testFilesToDelete[] = $configurationFile;
80 
81  $this->subject
82  ->expects($this->once())
83  ->method('getLocalConfigurationFileLocation')
84  ->will($this->returnValue($configurationFile));
85  $this->subject->getLocalConfiguration();
86  }
87 
92  {
93  $currentLocalConfiguration = [
94  'notChanged' => 23,
95  'changed' => 'unChanged',
96  ];
97  $overrideConfiguration = [
98  'changed' => 'changed',
99  'new' => 'new'
100  ];
101  $expectedConfiguration = [
102  'notChanged' => 23,
103  'changed' => 'changed',
104  'new' => 'new',
105  ];
106 
107  $this->createsubjectWithMockedMethods(
108  [
109  'getLocalConfiguration',
110  'writeLocalConfiguration',
111  ]
112  );
113  $this->subject->expects($this->once())
114  ->method('getLocalConfiguration')
115  ->will($this->returnValue($currentLocalConfiguration));
116  $this->subject->expects($this->once())
117  ->method('writeLocalConfiguration')
118  ->with($expectedConfiguration);
119 
120  $this->subject->updateLocalConfiguration($overrideConfiguration);
121  }
122 
127  {
128  $this->createsubjectWithMockedMethods(
129  [
130  'getDefaultConfiguration',
131  ]
132  );
133  $this->subject->expects($this->once())
134  ->method('getDefaultConfiguration')
135  ->will($this->returnValue([
136  'path' => 'value',
137  ]
138  ));
139 
140  $this->assertSame('value', $this->subject->getDefaultConfigurationValueByPath('path'));
141  }
142 
147  {
148  $this->createsubjectWithMockedMethods(
149  [
150  'getLocalConfiguration',
151  ]
152  );
153  $this->subject->expects($this->once())
154  ->method('getLocalConfiguration')
155  ->will($this->returnValue([
156  'path' => 'value',
157  ]
158  ));
159 
160  $this->assertSame('value', $this->subject->getLocalConfigurationValueByPath('path'));
161  }
162 
167  {
168  $this->createsubjectWithMockedMethods(
169  [
170  'getDefaultConfiguration',
171  'getLocalConfiguration',
172  ]
173  );
174  $this->subject->expects($this->once())
175  ->method('getDefaultConfiguration')
176  ->will($this->returnValue([
177  'path' => 'value',
178  ]
179  ));
180  $this->subject->expects($this->once())
181  ->method('getLocalConfiguration')
182  ->will($this->returnValue([
183  'path' => 'valueOverride',
184  ]
185  ));
186 
187  $this->assertSame('valueOverride', $this->subject->getConfigurationValueByPath('path'));
188  }
189 
194  {
195  $this->createsubjectWithMockedMethods([
196  'isValidLocalConfigurationPath',
197  ]);
198  $this->subject->expects($this->once())
199  ->method('isValidLocalConfigurationPath')
200  ->will($this->returnValue(false));
201 
202  $this->assertFalse($this->subject->setLocalConfigurationValueByPath('path', 'value'));
203  }
204 
209  {
210  $currentLocalConfiguration = [
211  'notChanged' => 23,
212  'toUpdate' => 'notUpdated',
213  ];
214  $expectedConfiguration = [
215  'notChanged' => 23,
216  'toUpdate' => 'updated',
217  ];
218 
219  $this->createsubjectWithMockedMethods(
220  [
221  'isValidLocalConfigurationPath',
222  'getLocalConfiguration',
223  'writeLocalConfiguration',
224  ]
225  );
226  $this->subject->expects($this->once())
227  ->method('isValidLocalConfigurationPath')
228  ->will($this->returnValue(true));
229  $this->subject->expects($this->once())
230  ->method('getLocalConfiguration')
231  ->will($this->returnValue($currentLocalConfiguration));
232  $this->subject->expects($this->once())
233  ->method('writeLocalConfiguration')
234  ->with($expectedConfiguration);
235 
236  $this->subject->setLocalConfigurationValueByPath('toUpdate', 'updated');
237  }
238 
243  {
244  $currentLocalConfiguration = [
245  'notChanged' => 23,
246  'toUpdate' => 'notUpdated',
247  ];
248  $expectedConfiguration = [
249  'notChanged' => 23,
250  'toUpdate' => 'updated',
251  'new' => 'new',
252  ];
253 
254  $this->createsubjectWithMockedMethods(
255  [
256  'isValidLocalConfigurationPath',
257  'getLocalConfiguration',
258  'writeLocalConfiguration',
259  ]
260  );
261  $this->subject->expects($this->any())
262  ->method('isValidLocalConfigurationPath')
263  ->will($this->returnValue(true));
264  $this->subject->expects($this->once())
265  ->method('getLocalConfiguration')
266  ->will($this->returnValue($currentLocalConfiguration));
267  $this->subject->expects($this->once())
268  ->method('writeLocalConfiguration')
269  ->with($expectedConfiguration);
270 
271  $pairs = [
272  'toUpdate' => 'updated',
273  'new' => 'new'
274  ];
275  $this->subject->setLocalConfigurationValuesByPathValuePairs($pairs);
276  }
277 
282  {
283  $currentLocalConfiguration = [
284  'toRemove1' => 'foo',
285  'notChanged' => 23,
286  'toRemove2' => 'bar',
287  ];
288  $expectedConfiguration = [
289  'notChanged' => 23,
290  ];
291 
292  $this->createsubjectWithMockedMethods(
293  [
294  'getLocalConfiguration',
295  'writeLocalConfiguration',
296  ]
297  );
298  $this->subject->expects($this->once())
299  ->method('getLocalConfiguration')
300  ->will($this->returnValue($currentLocalConfiguration));
301  $this->subject->expects($this->once())
302  ->method('writeLocalConfiguration')
303  ->with($expectedConfiguration);
304 
305  $removePaths = [
306  'toRemove1',
307  'toRemove2',
308  ];
309  $this->assertTrue($this->subject->removeLocalConfigurationKeysByPath($removePaths));
310  }
311 
316  {
317  $currentLocalConfiguration = [
318  'notChanged' => 23,
319  ];
320  $this->createsubjectWithMockedMethods(
321  [
322  'getLocalConfiguration',
323  'writeLocalConfiguration',
324  ]
325  );
326  $this->subject->expects($this->once())
327  ->method('getLocalConfiguration')
328  ->will($this->returnValue($currentLocalConfiguration));
329  $this->subject->expects($this->never())
330  ->method('writeLocalConfiguration');
331 
332  $removeNothing = [];
333  $this->assertFalse($this->subject->removeLocalConfigurationKeysByPath($removeNothing));
334  }
335 
340  {
341  $currentLocalConfiguration = [
342  'notChanged' => 23,
343  ];
344  $this->createsubjectWithMockedMethods(
345  [
346  'getLocalConfiguration',
347  'writeLocalConfiguration',
348  ]
349  );
350  $this->subject->expects($this->once())
351  ->method('getLocalConfiguration')
352  ->will($this->returnValue($currentLocalConfiguration));
353  $this->subject->expects($this->never())
354  ->method('writeLocalConfiguration');
355 
356  $removeNonExisting = ['notPresent'];
357  $this->assertFalse($this->subject->removeLocalConfigurationKeysByPath($removeNonExisting));
358  }
359 
363  public function canWriteConfigurationReturnsFalseIfDirectoryIsNotWritable()
364  {
365  if (function_exists('posix_getegid') && posix_getegid() === 0) {
366  $this->markTestSkipped('Test skipped if run on linux as root');
367  } elseif (TYPO3_OS == 'WIN') {
368  $this->markTestSkipped('Not available on Windows');
369  }
371  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
372 
373  $directory = 'typo3temp/' . $this->getUniqueId('test_');
374  $absoluteDirectory = PATH_site . $directory;
375  mkdir($absoluteDirectory);
376  chmod($absoluteDirectory, 0544);
377  clearstatcache();
378 
379  $subject->_set('pathTypo3Conf', $directory);
380 
381  $result = $subject->canWriteConfiguration();
382 
383  chmod($absoluteDirectory, 0755);
384  rmdir($absoluteDirectory);
385 
386  $this->assertFalse($result);
387  }
388 
392  public function canWriteConfigurationReturnsFalseIfLocalConfigurationFileIsNotWritable()
393  {
394  if (function_exists('posix_getegid') && posix_getegid() === 0) {
395  $this->markTestSkipped('Test skipped if run on linux as root');
396  } elseif (TYPO3_OS == 'WIN') {
397  $this->markTestSkipped('Not available on Windows');
398  }
400  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
401 
402  $file = 'typo3temp/' . $this->getUniqueId('test_');
403  $absoluteFile = PATH_site . $file;
404  touch($absoluteFile);
405  $this->testFilesToDelete[] = $absoluteFile;
406  chmod($absoluteFile, 0444);
407  clearstatcache();
408 
409  $subject->_set('localConfigurationFile', $file);
410 
411  $result = $subject->canWriteConfiguration();
412 
413  chmod($absoluteFile, 0644);
414 
415  $this->assertFalse($result);
416  }
417 
421  public function canWriteConfigurationReturnsTrueIfDirectoryAndFilesAreWritable()
422  {
424  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
425 
426  $directory = 'typo3temp/' . $this->getUniqueId('test_');
427  $absoluteDirectory = PATH_site . $directory;
428  mkdir($absoluteDirectory);
429  $subject->_set('pathTypo3Conf', $absoluteDirectory);
430 
431  $file1 = 'typo3temp/' . $this->getUniqueId('test_');
432  $absoluteFile1 = PATH_site . $file1;
433  touch($absoluteFile1);
434  $this->testFilesToDelete[] = $absoluteFile1;
435  $subject->_set('localConfigurationFile', $absoluteFile1);
436 
437  $file2 = 'typo3temp/' . $this->getUniqueId('test_');
438  $absoluteFile2 = PATH_site . $file2;
439  touch($absoluteFile2);
440  $this->testFilesToDelete[] = $absoluteFile2;
441  $subject->_set('localconfFile', $absoluteFile2);
442 
443  clearstatcache();
444 
445  $result = $subject->canWriteConfiguration();
446 
447  $this->assertTrue($result);
448  $this->testFilesToDelete[] = $absoluteDirectory;
449  }
450 
455  {
456  $configurationFile = PATH_site . 'typo3temp/' . $this->getUniqueId('localConfiguration');
457  if (!is_file($configurationFile)) {
458  if (!$fh = fopen($configurationFile, 'wb')) {
459  $this->markTestSkipped('Can not create file ' . $configurationFile . '. Please check your write permissions.');
460  }
461  fclose($fh);
462  }
463 
464  if (!@is_file($configurationFile)) {
465  throw new \RuntimeException('File ' . $configurationFile . ' could not be found. Please check your write permissions', 1346364362);
466  }
467  $this->testFilesToDelete[] = $configurationFile;
468 
469  $this->subject
470  ->expects($this->any())
471  ->method('getLocalConfigurationFileLocation')
472  ->will($this->returnValue($configurationFile));
473 
474  $pairs = [
475  'foo' => 42,
476  'bar' => 23
477  ];
478  $expectedContent =
479  '<?php' . LF .
480  'return [' . LF .
481  ' \'bar\' => 23,' . LF .
482  ' \'foo\' => 42,' . LF .
483  '];' . LF;
484 
485  $this->subject->writeLocalConfiguration($pairs);
486  $this->assertSame($expectedContent, file_get_contents($configurationFile));
487  }
488 
493  public function createLocalConfigurationFromFactoryConfigurationThrowsExceptionIfFileExists()
494  {
496  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
497 
498  $file = 'typo3temp/' . $this->getUniqueId('test_');
499  $absoluteFile = PATH_site . $file;
500  touch($absoluteFile);
501  $this->testFilesToDelete[] = $absoluteFile;
502  $subject->_set('localConfigurationFile', $file);
503 
504  $subject->createLocalConfigurationFromFactoryConfiguration();
505  }
506 
510  public function createLocalConfigurationFromFactoryConfigurationWritesContentFromFactoryFile()
511  {
513  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['writeLocalConfiguration']);
514  $subject->_set('localConfigurationFile', 'typo3temp/' . $this->getUniqueId('dummy_'));
515 
516  $factoryConfigurationFile = 'typo3temp/' . $this->getUniqueId('test_') . '.php';
517  $factoryConfigurationAbsoluteFile = PATH_site . $factoryConfigurationFile;
518  $uniqueContentString = $this->getUniqueId('string_');
519  $validFactoryConfigurationFileContent =
520  '<?php' . LF .
521  'return [' . LF .
522  '\'' . $uniqueContentString . '\' => \'foo\',' . LF .
523  '];' . LF;
524  file_put_contents(
525  $factoryConfigurationAbsoluteFile,
526  $validFactoryConfigurationFileContent
527  );
528  $this->testFilesToDelete[] = $factoryConfigurationAbsoluteFile;
529 
530  $subject->_set('factoryConfigurationFile', $factoryConfigurationFile);
531 
532  $subject
533  ->expects($this->once())
534  ->method('writeLocalConfiguration')
535  ->with($this->arrayHasKey($uniqueContentString));
536  $subject->createLocalConfigurationFromFactoryConfiguration();
537  }
538 
542  public function createLocalConfigurationFromFactoryConfigurationMergesConfigurationWithAdditionalFactoryFile()
543  {
545  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['writeLocalConfiguration']);
546  $subject->_set('localConfigurationFile', 'typo3temp/' . $this->getUniqueId('dummy_'));
547 
548  $factoryConfigurationFile = 'typo3temp/' . $this->getUniqueId('test_') . '.php';
549  $factoryConfigurationAbsoluteFile = PATH_site . $factoryConfigurationFile;
550  $validFactoryConfigurationFileContent =
551  '<?php' . LF .
552  'return [];' . LF;
553  file_put_contents(
554  $factoryConfigurationAbsoluteFile,
555  $validFactoryConfigurationFileContent
556  );
557  $this->testFilesToDelete[] = $factoryConfigurationAbsoluteFile;
558  $subject->_set('factoryConfigurationFile', $factoryConfigurationFile);
559 
560  $additionalFactoryConfigurationFile = 'typo3temp/' . $this->getUniqueId('test_') . '.php';
561  $additionalFactoryConfigurationAbsoluteFile = PATH_site . $additionalFactoryConfigurationFile;
562  $uniqueContentString = $this->getUniqueId('string_');
563  $validAdditionalFactoryConfigurationFileContent =
564  '<?php' . LF .
565  'return [' . LF .
566  '\'' . $uniqueContentString . '\' => \'foo\',' . LF .
567  '];' . LF;
568  file_put_contents(
569  $additionalFactoryConfigurationAbsoluteFile,
570  $validAdditionalFactoryConfigurationFileContent
571  );
572  $this->testFilesToDelete[] = $additionalFactoryConfigurationAbsoluteFile;
573  $subject->_set('additionalFactoryConfigurationFile', $additionalFactoryConfigurationFile);
574 
575  $subject
576  ->expects($this->once())
577  ->method('writeLocalConfiguration')
578  ->with($this->arrayHasKey($uniqueContentString));
579  $subject->createLocalConfigurationFromFactoryConfiguration();
580  }
581 
585  public function isValidLocalConfigurationPathAcceptsWhitelistedPath()
586  {
588  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
589  $subject->_set('whiteListedLocalConfigurationPaths', ['foo/bar']);
590  $this->assertTrue($subject->_call('isValidLocalConfigurationPath', 'foo/bar/baz'));
591  }
592 
596  public function isValidLocalConfigurationPathDeniesNotWhitelistedPath()
597  {
599  $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, ['dummy']);
600  $subject->_set('whiteListedLocalConfigurationPaths', ['foo/bar']);
601  $this->assertFalse($subject->_call('isValidLocalConfigurationPath', 'bar/baz'));
602  }
603 }
getAccessibleMock( $originalClassName, $methods=[], array $arguments=[], $mockClassName='', $callOriginalConstructor=true, $callOriginalClone=true, $callAutoload=true)