Upgraded drupal core with security updates
[yaffs-website] / web / core / tests / Drupal / Tests / Core / Extension / ThemeHandlerTest.php
1 <?php
2
3 /**
4  * @file
5  * Contains \Drupal\Tests\Core\Extension\ThemeHandlerTest.
6  */
7
8 namespace Drupal\Tests\Core\Extension;
9
10 use Drupal\Core\Cache\MemoryBackend;
11 use Drupal\Core\Extension\Extension;
12 use Drupal\Core\Extension\InfoParser;
13 use Drupal\Core\Extension\ThemeHandler;
14 use Drupal\Core\KeyValueStore\KeyValueMemoryFactory;
15 use Drupal\Core\Lock\NullLockBackend;
16 use Drupal\Core\State\State;
17 use Drupal\Tests\UnitTestCase;
18
19 /**
20  * @coversDefaultClass \Drupal\Core\Extension\ThemeHandler
21  * @group Extension
22  */
23 class ThemeHandlerTest extends UnitTestCase {
24
25   /**
26    * The mocked info parser.
27    *
28    * @var \Drupal\Core\Extension\InfoParserInterface|\PHPUnit_Framework_MockObject_MockObject
29    */
30   protected $infoParser;
31
32   /**
33    * The mocked state backend.
34    *
35    * @var \Drupal\Core\State\StateInterface|\PHPUnit_Framework_MockObject_MockObject
36    */
37   protected $state;
38
39   /**
40    * The mocked config factory.
41    *
42    * @var \Drupal\Core\Config\ConfigFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
43    */
44   protected $configFactory;
45
46   /**
47    * The mocked module handler.
48    *
49    * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
50    */
51   protected $moduleHandler;
52
53   /**
54    * The extension discovery.
55    *
56    * @var \Drupal\Core\Extension\ExtensionDiscovery|\PHPUnit_Framework_MockObject_MockObject
57    */
58   protected $extensionDiscovery;
59
60   /**
61    * The tested theme handler.
62    *
63    * @var \Drupal\Core\Extension\ThemeHandler|\Drupal\Tests\Core\Extension\StubThemeHandler
64    */
65   protected $themeHandler;
66
67   /**
68    * {@inheritdoc}
69    */
70   protected function setUp() {
71     parent::setUp();
72
73     $this->configFactory = $this->getConfigFactoryStub([
74       'core.extension' => [
75         'module' => [],
76         'theme' => [],
77         'disabled' => [
78           'theme' => [],
79         ],
80       ],
81     ]);
82     $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
83     $this->state = new State(new KeyValueMemoryFactory(), new MemoryBackend('test'), new NullLockBackend());
84     $this->infoParser = $this->getMock('Drupal\Core\Extension\InfoParserInterface');
85     $this->extensionDiscovery = $this->getMockBuilder('Drupal\Core\Extension\ExtensionDiscovery')
86       ->disableOriginalConstructor()
87       ->getMock();
88     $this->themeHandler = new StubThemeHandler($this->root, $this->configFactory, $this->moduleHandler, $this->state, $this->infoParser, $this->extensionDiscovery);
89
90     $cache_tags_invalidator = $this->getMock('Drupal\Core\Cache\CacheTagsInvalidatorInterface');
91     $this->getContainerWithCacheTagsInvalidator($cache_tags_invalidator);
92   }
93
94   /**
95    * Tests rebuilding the theme data.
96    *
97    * @see \Drupal\Core\Extension\ThemeHandler::rebuildThemeData()
98    */
99   public function testRebuildThemeData() {
100     $this->extensionDiscovery->expects($this->at(0))
101       ->method('scan')
102       ->with('theme')
103       ->will($this->returnValue([
104         'seven' => new Extension($this->root, 'theme', $this->root . '/core/themes/seven/seven.info.yml', 'seven.theme'),
105       ]));
106     $this->extensionDiscovery->expects($this->at(1))
107       ->method('scan')
108       ->with('theme_engine')
109       ->will($this->returnValue([
110         'twig' => new Extension($this->root, 'theme_engine', $this->root . '/core/themes/engines/twig/twig.info.yml', 'twig.engine'),
111       ]));
112     $this->infoParser->expects($this->once())
113       ->method('parse')
114       ->with($this->root . '/core/themes/seven/seven.info.yml')
115       ->will($this->returnCallback(function ($file) {
116         $info_parser = new InfoParser();
117         return $info_parser->parse($file);
118       }));
119     $this->moduleHandler->expects($this->once())
120       ->method('buildModuleDependencies')
121       ->will($this->returnArgument(0));
122
123     $this->moduleHandler->expects($this->once())
124       ->method('alter');
125
126     $theme_data = $this->themeHandler->rebuildThemeData();
127     $this->assertCount(1, $theme_data);
128     $info = $theme_data['seven'];
129
130     // Ensure some basic properties.
131     $this->assertInstanceOf('Drupal\Core\Extension\Extension', $info);
132     $this->assertEquals('seven', $info->getName());
133     $this->assertEquals($this->root . '/core/themes/seven/seven.info.yml', $info->getPathname());
134     $this->assertEquals($this->root . '/core/themes/seven/seven.theme', $info->getExtensionPathname());
135     $this->assertEquals($this->root . '/core/themes/engines/twig/twig.engine', $info->owner);
136     $this->assertEquals('twig', $info->prefix);
137
138     $this->assertEquals('twig', $info->info['engine']);
139     $this->assertEquals(['seven/global-styling'], $info->info['libraries']);
140   }
141
142   /**
143    * Tests empty libraries in theme.info.yml file.
144    */
145   public function testThemeLibrariesEmpty() {
146     $theme = new Extension($this->root, 'theme', '/core/modules/system/tests/themes/test_theme_libraries_empty', 'test_theme_libraries_empty.info.yml');
147     try {
148       $this->themeHandler->addTheme($theme);
149       $this->assertTrue(TRUE, 'Empty libraries key in theme.info.yml does not cause PHP warning');
150     }
151     catch (\Exception $e) {
152       $this->fail('Empty libraries key in theme.info.yml causes PHP warning.');
153     }
154   }
155
156   /**
157    * Tests rebuild the theme data with theme parents.
158    */
159   public function testRebuildThemeDataWithThemeParents() {
160     $this->extensionDiscovery->expects($this->at(0))
161       ->method('scan')
162       ->with('theme')
163       ->will($this->returnValue([
164         'test_subtheme' => new Extension($this->root, 'theme', $this->root . '/core/modules/system/tests/themes/test_subtheme/test_subtheme.info.yml', 'test_subtheme.info.yml'),
165         'test_basetheme' => new Extension($this->root, 'theme', $this->root . '/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml', 'test_basetheme.info.yml'),
166       ]));
167     $this->extensionDiscovery->expects($this->at(1))
168       ->method('scan')
169       ->with('theme_engine')
170       ->will($this->returnValue([
171         'twig' => new Extension($this->root, 'theme_engine', $this->root . '/core/themes/engines/twig/twig.info.yml', 'twig.engine'),
172       ]));
173     $this->infoParser->expects($this->at(0))
174       ->method('parse')
175       ->with($this->root . '/core/modules/system/tests/themes/test_subtheme/test_subtheme.info.yml')
176       ->will($this->returnCallback(function ($file) {
177         $info_parser = new InfoParser();
178         return $info_parser->parse($file);
179       }));
180     $this->infoParser->expects($this->at(1))
181       ->method('parse')
182       ->with($this->root . '/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml')
183       ->will($this->returnCallback(function ($file) {
184         $info_parser = new InfoParser();
185         return $info_parser->parse($file);
186       }));
187     $this->moduleHandler->expects($this->once())
188       ->method('buildModuleDependencies')
189       ->will($this->returnArgument(0));
190
191     $theme_data = $this->themeHandler->rebuildThemeData();
192     $this->assertCount(2, $theme_data);
193
194     $info_basetheme = $theme_data['test_basetheme'];
195     $info_subtheme = $theme_data['test_subtheme'];
196
197     // Ensure some basic properties.
198     $this->assertInstanceOf('Drupal\Core\Extension\Extension', $info_basetheme);
199     $this->assertEquals('test_basetheme', $info_basetheme->getName());
200     $this->assertInstanceOf('Drupal\Core\Extension\Extension', $info_subtheme);
201     $this->assertEquals('test_subtheme', $info_subtheme->getName());
202
203     // Test the parent/child-theme properties.
204     $info_subtheme->info['base theme'] = 'test_basetheme';
205     $info_basetheme->sub_themes = ['test_subtheme'];
206
207     $this->assertEquals($this->root . '/core/themes/engines/twig/twig.engine', $info_basetheme->owner);
208     $this->assertEquals('twig', $info_basetheme->prefix);
209     $this->assertEquals($this->root . '/core/themes/engines/twig/twig.engine', $info_subtheme->owner);
210     $this->assertEquals('twig', $info_subtheme->prefix);
211   }
212
213   /**
214    * Tests getting the base themes for a set a defines themes.
215    *
216    * @param array $themes
217    *   An array of available themes, keyed by the theme name.
218    * @param string $theme
219    *   The theme name to find all its base themes.
220    * @param array $expected
221    *   The expected base themes.
222    *
223    * @dataProvider providerTestGetBaseThemes
224    */
225   public function testGetBaseThemes(array $themes, $theme, array $expected) {
226     $base_themes = $this->themeHandler->getBaseThemes($themes, $theme);
227     $this->assertEquals($expected, $base_themes);
228   }
229
230   /**
231    * Provides test data for testGetBaseThemes.
232    *
233    * @return array
234    *   An array of theme test data.
235    */
236   public function providerTestGetBaseThemes() {
237     $data = [];
238
239     // Tests a theme without any base theme.
240     $themes = [];
241     $themes['test_1'] = (object) [
242       'name' => 'test_1',
243       'info' => [
244         'name' => 'test_1',
245       ],
246     ];
247     $data[] = [$themes, 'test_1', []];
248
249     // Tests a theme with a non existing base theme.
250     $themes = [];
251     $themes['test_1'] = (object) [
252       'name' => 'test_1',
253       'info' => [
254         'name' => 'test_1',
255         'base theme' => 'test_2',
256       ],
257     ];
258     $data[] = [$themes, 'test_1', ['test_2' => NULL]];
259
260     // Tests a theme with a single existing base theme.
261     $themes = [];
262     $themes['test_1'] = (object) [
263       'name' => 'test_1',
264       'info' => [
265         'name' => 'test_1',
266         'base theme' => 'test_2',
267       ],
268     ];
269     $themes['test_2'] = (object) [
270       'name' => 'test_2',
271       'info' => [
272         'name' => 'test_2',
273       ],
274     ];
275     $data[] = [$themes, 'test_1', ['test_2' => 'test_2']];
276
277     // Tests a theme with multiple base themes.
278     $themes = [];
279     $themes['test_1'] = (object) [
280       'name' => 'test_1',
281       'info' => [
282         'name' => 'test_1',
283         'base theme' => 'test_2',
284       ],
285     ];
286     $themes['test_2'] = (object) [
287       'name' => 'test_2',
288       'info' => [
289         'name' => 'test_2',
290         'base theme' => 'test_3',
291       ],
292     ];
293     $themes['test_3'] = (object) [
294       'name' => 'test_3',
295       'info' => [
296         'name' => 'test_3',
297       ],
298     ];
299     $data[] = [
300       $themes,
301       'test_1',
302       ['test_2' => 'test_2', 'test_3' => 'test_3'],
303     ];
304
305     return $data;
306   }
307
308 }
309
310 /**
311  * Extends the default theme handler to mock some drupal_ methods.
312  */
313 class StubThemeHandler extends ThemeHandler {
314
315   /**
316    * Whether the CSS cache was cleared.
317    *
318    * @var bool
319    */
320   protected $clearedCssCache;
321
322   /**
323    * Whether the registry should be rebuilt.
324    *
325    * @var bool
326    */
327   protected $registryRebuild;
328
329   /**
330    * A list of themes keyed by name.
331    *
332    * @var array
333    */
334   protected $systemList;
335
336   /**
337    * {@inheritdoc}
338    */
339   protected function clearCssCache() {
340     $this->clearedCssCache = TRUE;
341   }
342
343   /**
344    * {@inheritdoc}
345    */
346   protected function themeRegistryRebuild() {
347     $this->registryRebuild = TRUE;
348   }
349
350   /**
351    * {@inheritdoc}
352    */
353   protected function systemThemeList() {
354     return $this->systemList;
355   }
356
357   /**
358    * {@inheritdoc}
359    */
360   protected function systemListReset() {
361   }
362
363 }
364
365 if (!defined('DRUPAL_EXTENSION_NAME_MAX_LENGTH')) {
366   define('DRUPAL_EXTENSION_NAME_MAX_LENGTH', 50);
367 }
368 if (!defined('DRUPAL_PHP_FUNCTION_PATTERN')) {
369   define('DRUPAL_PHP_FUNCTION_PATTERN', '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*');
370 }
371 if (!defined('DRUPAL_MINIMUM_PHP')) {
372   define('DRUPAL_MINIMUM_PHP', '5.3.10');
373 }