7f6d2eccda8ededad48d4ebf6ce53ee612359874
[yaffs-website] / web / core / tests / Drupal / KernelTests / Core / Theme / RegistryTest.php
1 <?php
2
3 namespace Drupal\KernelTests\Core\Theme;
4
5 use Drupal\Core\Path\CurrentPathStack;
6 use Drupal\Core\Path\PathMatcherInterface;
7 use Drupal\Core\Theme\Registry;
8 use Drupal\Core\Utility\ThemeRegistry;
9 use Drupal\KernelTests\KernelTestBase;
10
11 /**
12  * Tests the behavior of the ThemeRegistry class.
13  *
14  * @group Theme
15  */
16 class RegistryTest extends KernelTestBase {
17
18   /**
19    * Modules to enable.
20    *
21    * @var array
22    */
23   public static $modules = ['theme_test', 'system'];
24
25   protected $profile = 'testing';
26
27   /**
28    * Tests the behavior of the theme registry class.
29    */
30   public function testRaceCondition() {
31     // The theme registry is not marked as persistable in case we don't have a
32     // proper request.
33     \Drupal::request()->setMethod('GET');
34     $cid = 'test_theme_registry';
35
36     // Directly instantiate the theme registry, this will cause a base cache
37     // entry to be written in __construct().
38     $cache = \Drupal::cache();
39     $lock_backend = \Drupal::lock();
40     $registry = new ThemeRegistry($cid, $cache, $lock_backend, ['theme_registry'], $this->container->get('module_handler')->isLoaded());
41
42     $this->assertTrue(\Drupal::cache()->get($cid), 'Cache entry was created.');
43
44     // Trigger a cache miss for an offset.
45     $this->assertTrue($registry->get('theme_test_template_test'), 'Offset was returned correctly from the theme registry.');
46     // This will cause the ThemeRegistry class to write an updated version of
47     // the cache entry when it is destroyed, usually at the end of the request.
48     // Before that happens, manually delete the cache entry we created earlier
49     // so that the new entry is written from scratch.
50     \Drupal::cache()->delete($cid);
51
52     // Destroy the class so that it triggers a cache write for the offset.
53     $registry->destruct();
54
55     $this->assertTrue(\Drupal::cache()->get($cid), 'Cache entry was created.');
56
57     // Create a new instance of the class. Confirm that both the offset
58     // requested previously, and one that has not yet been requested are both
59     // available.
60     $registry = new ThemeRegistry($cid, $cache, $lock_backend, ['theme_registry'], $this->container->get('module_handler')->isLoaded());
61     $this->assertTrue($registry->get('theme_test_template_test'), 'Offset was returned correctly from the theme registry');
62     $this->assertTrue($registry->get('theme_test_template_test_2'), 'Offset was returned correctly from the theme registry');
63   }
64
65   /**
66    * Tests the theme registry with multiple subthemes.
67    */
68   public function testMultipleSubThemes() {
69     $theme_handler = \Drupal::service('theme_handler');
70     $theme_handler->install(['test_basetheme', 'test_subtheme', 'test_subsubtheme']);
71
72     $registry_subsub_theme = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $theme_handler, \Drupal::service('theme.initialization'), 'test_subsubtheme');
73     $registry_subsub_theme->setThemeManager(\Drupal::theme());
74     $registry_sub_theme = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $theme_handler, \Drupal::service('theme.initialization'), 'test_subtheme');
75     $registry_sub_theme->setThemeManager(\Drupal::theme());
76     $registry_base_theme = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $theme_handler, \Drupal::service('theme.initialization'), 'test_basetheme');
77     $registry_base_theme->setThemeManager(\Drupal::theme());
78
79     $preprocess_functions = $registry_subsub_theme->get()['theme_test_template_test']['preprocess functions'];
80     $this->assertSame([
81       'template_preprocess',
82       'test_basetheme_preprocess_theme_test_template_test',
83       'test_subtheme_preprocess_theme_test_template_test',
84       'test_subsubtheme_preprocess_theme_test_template_test',
85     ], $preprocess_functions);
86
87     $preprocess_functions = $registry_sub_theme->get()['theme_test_template_test']['preprocess functions'];
88     $this->assertSame([
89       'template_preprocess',
90       'test_basetheme_preprocess_theme_test_template_test',
91       'test_subtheme_preprocess_theme_test_template_test',
92     ], $preprocess_functions);
93
94     $preprocess_functions = $registry_base_theme->get()['theme_test_template_test']['preprocess functions'];
95     $this->assertSame([
96       'template_preprocess',
97       'test_basetheme_preprocess_theme_test_template_test',
98     ], $preprocess_functions);
99
100     $preprocess_functions = $registry_base_theme->get()['theme_test_function_suggestions']['preprocess functions'];
101     $this->assertSame([
102        'template_preprocess_theme_test_function_suggestions',
103        'test_basetheme_preprocess_theme_test_function_suggestions',
104     ], $preprocess_functions, "Theme functions don't have template_preprocess but do have template_preprocess_HOOK");
105   }
106
107   /**
108    * Tests the theme registry with suggestions.
109    */
110   public function testSuggestionPreprocessFunctions() {
111     $theme_handler = \Drupal::service('theme_handler');
112     $theme_handler->install(['test_theme']);
113
114     $registry_theme = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $theme_handler, \Drupal::service('theme.initialization'), 'test_theme');
115     $registry_theme->setThemeManager(\Drupal::theme());
116
117     $suggestions = ['__kitten', '__flamingo'];
118     $expected_preprocess_functions = [
119       'template_preprocess',
120       'theme_test_preprocess_theme_test_preprocess_suggestions',
121     ];
122     $suggestion = '';
123     $hook = 'theme_test_preprocess_suggestions';
124     do {
125       $hook .= "$suggestion";
126       $expected_preprocess_functions[] = "test_theme_preprocess_$hook";
127       $preprocess_functions = $registry_theme->get()[$hook]['preprocess functions'];
128       $this->assertSame($expected_preprocess_functions, $preprocess_functions, "$hook has correct preprocess functions.");
129     } while ($suggestion = array_shift($suggestions));
130
131     $expected_preprocess_functions = [
132       'template_preprocess',
133       'theme_test_preprocess_theme_test_preprocess_suggestions',
134       'test_theme_preprocess_theme_test_preprocess_suggestions',
135       'test_theme_preprocess_theme_test_preprocess_suggestions__kitten',
136     ];
137
138     $preprocess_functions = $registry_theme->get()['theme_test_preprocess_suggestions__kitten__meerkat']['preprocess functions'];
139     $this->assertSame($expected_preprocess_functions, $preprocess_functions, 'Suggestion implemented as a function correctly inherits preprocess functions.');
140
141     $preprocess_functions = $registry_theme->get()['theme_test_preprocess_suggestions__kitten__bearcat']['preprocess functions'];
142     $this->assertSame($expected_preprocess_functions, $preprocess_functions, 'Suggestion implemented as a template correctly inherits preprocess functions.');
143
144     $this->assertTrue(isset($registry_theme->get()['theme_test_preprocess_suggestions__kitten__meerkat__tarsier__moose']), 'Preprocess function with an unimplemented lower-level suggestion is added to the registry.');
145   }
146
147   /**
148    * Tests that the theme registry can be altered by themes.
149    */
150   public function testThemeRegistryAlterByTheme() {
151
152     /** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */
153     $theme_handler = \Drupal::service('theme_handler');
154     $theme_handler->install(['test_theme']);
155     $this->config('system.theme')->set('default', 'test_theme')->save();
156
157     $registry = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $theme_handler, \Drupal::service('theme.initialization'), 'test_theme');
158     $registry->setThemeManager(\Drupal::theme());
159     $this->assertEqual('value', $registry->get()['theme_test_template_test']['variables']['additional']);
160   }
161
162   /**
163    * Tests front node theme suggestion generation.
164    */
165   public function testThemeSuggestions() {
166     // Mock the current page as the front page.
167     /** @var \Drupal\Core\Path\PathMatcherInterface $path_matcher */
168     $path_matcher = $this->prophesize(PathMatcherInterface::class);
169     $path_matcher->isFrontPage()->willReturn(TRUE);
170     $this->container->set('path.matcher', $path_matcher->reveal());
171     /** @var \Drupal\Core\Path\CurrentPathStack $path_matcher */
172     $path_current = $this->prophesize(CurrentPathStack::class);
173     $path_current->getPath()->willReturn('/node/1');
174     $this->container->set('path.current', $path_current->reveal());
175
176     // Check suggestions provided through hook_theme_suggestions_html().
177     $suggestions = \Drupal::moduleHandler()->invokeAll('theme_suggestions_html', [[]]);
178     $this->assertSame([
179       'html__node',
180       'html__node__%',
181       'html__node__1',
182       'html__front',
183     ], $suggestions, 'Found expected html node suggestions.');
184
185     // Check suggestions provided through hook_theme_suggestions_page().
186     $suggestions = \Drupal::moduleHandler()->invokeAll('theme_suggestions_page', [[]]);
187     $this->assertSame([
188       'page__node',
189       'page__node__%',
190       'page__node__1',
191       'page__front',
192     ], $suggestions, 'Found expected page node suggestions.');
193   }
194
195   /**
196    * Tests theme-provided templates that are registered by modules.
197    */
198   public function testThemeTemplatesRegisteredByModules() {
199     $theme_handler = \Drupal::service('theme_handler');
200     $theme_handler->install(['test_theme']);
201
202     $registry_theme = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $theme_handler, \Drupal::service('theme.initialization'), 'test_theme');
203     $registry_theme->setThemeManager(\Drupal::theme());
204
205     $expected = [
206       'template_preprocess',
207       'template_preprocess_container',
208       'template_preprocess_theme_test_registered_by_module'
209     ];
210     $registry = $registry_theme->get();
211     $this->assertEquals($expected, array_values($registry['theme_test_registered_by_module']['preprocess functions']));
212   }
213
214 }