369c3ab1ac1caa5dbe02557008c263070c3a984c
[yaffs-website] / web / core / modules / simpletest / src / InstallerTestBase.php
1 <?php
2
3 namespace Drupal\simpletest;
4
5 @trigger_error(__NAMESPACE__ . '\InstallerTestBase is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\FunctionalTests\Installer\InstallerTestBase, see https://www.drupal.org/node/2988752.', E_USER_DEPRECATED);
6
7 use Drupal\Core\DrupalKernel;
8 use Drupal\Core\Language\Language;
9 use Drupal\Core\Session\UserSession;
10 use Drupal\Core\Site\Settings;
11 use Symfony\Component\DependencyInjection\ContainerBuilder;
12 use Symfony\Component\DependencyInjection\Reference;
13 use Symfony\Component\HttpFoundation\Request;
14 use Symfony\Component\HttpFoundation\RequestStack;
15
16 /**
17  * Base class for testing the interactive installer.
18  *
19  * @deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0.
20  * Use \Drupal\FunctionalTests\Installer\InstallerTestBase. See
21  * https://www.drupal.org/node/2988752
22  */
23 abstract class InstallerTestBase extends WebTestBase {
24
25   /**
26    * Custom settings.php values to write for a test run.
27    *
28    * @var array
29    *   An array of settings to write out, in the format expected by
30    *   drupal_rewrite_settings().
31    */
32   protected $settings = [];
33
34   /**
35    * The language code in which to install Drupal.
36    *
37    * @var string
38    */
39   protected $langcode = 'en';
40
41   /**
42    * The installation profile to install.
43    *
44    * @var string
45    */
46   protected $profile = 'testing';
47
48   /**
49    * Additional parameters to use for installer screens.
50    *
51    * @see WebTestBase::installParameters()
52    *
53    * @var array
54    */
55   protected $parameters = [];
56
57   /**
58    * A string translation map used for translated installer screens.
59    *
60    * Keys are English strings, values are translated strings.
61    *
62    * @var array
63    */
64   protected $translations = [
65     'Save and continue' => 'Save and continue',
66   ];
67
68   /**
69    * Whether the installer has completed.
70    *
71    * @var bool
72    */
73   protected $isInstalled = FALSE;
74
75   /**
76    * {@inheritdoc}
77    */
78   protected function setUp() {
79     $this->isInstalled = FALSE;
80
81     // Define information about the user 1 account.
82     $this->rootUser = new UserSession([
83       'uid' => 1,
84       'name' => 'admin',
85       'mail' => 'admin@example.com',
86       'pass_raw' => $this->randomMachineName(),
87     ]);
88
89     // If any $settings are defined for this test, copy and prepare an actual
90     // settings.php, so as to resemble a regular installation.
91     if (!empty($this->settings)) {
92       // Not using File API; a potential error must trigger a PHP warning.
93       copy(DRUPAL_ROOT . '/sites/default/default.settings.php', DRUPAL_ROOT . '/' . $this->siteDirectory . '/settings.php');
94       $this->writeSettings($this->settings);
95     }
96
97     // Note that WebTestBase::installParameters() returns form input values
98     // suitable for a programmed \Drupal::formBuilder()->submitForm().
99     // @see WebTestBase::translatePostValues()
100     $this->parameters = $this->installParameters();
101
102     // Set up a minimal container (required by WebTestBase). Set cookie and
103     // server information so that XDebug works.
104     // @see install_begin_request()
105     $request = Request::create($GLOBALS['base_url'] . '/core/install.php', 'GET', [], $_COOKIE, [], $_SERVER);
106     $this->container = new ContainerBuilder();
107     $request_stack = new RequestStack();
108     $request_stack->push($request);
109     $this->container
110       ->set('request_stack', $request_stack);
111     $this->container
112       ->setParameter('language.default_values', Language::$defaultValues);
113     $this->container
114       ->register('language.default', 'Drupal\Core\Language\LanguageDefault')
115       ->addArgument('%language.default_values%');
116     $this->container
117       ->register('string_translation', 'Drupal\Core\StringTranslation\TranslationManager')
118       ->addArgument(new Reference('language.default'));
119     $this->container
120       ->set('app.root', DRUPAL_ROOT);
121     \Drupal::setContainer($this->container);
122
123     $this->visitInstaller();
124
125     // Select language.
126     $this->setUpLanguage();
127
128     // Select profile.
129     $this->setUpProfile();
130
131     // Address the requirements problem screen, if any.
132     $this->setUpRequirementsProblem();
133
134     // Configure settings.
135     $this->setUpSettings();
136
137     // @todo Allow test classes based on this class to act on further installer
138     //   screens.
139
140     // Configure site.
141     $this->setUpSite();
142
143     if ($this->isInstalled) {
144       // Import new settings.php written by the installer.
145       $request = Request::createFromGlobals();
146       $class_loader = require $this->container->get('app.root') . '/autoload.php';
147       Settings::initialize($this->container->get('app.root'), DrupalKernel::findSitePath($request), $class_loader);
148       foreach ($GLOBALS['config_directories'] as $type => $path) {
149         $this->configDirectories[$type] = $path;
150       }
151
152       // After writing settings.php, the installer removes write permissions
153       // from the site directory. To allow drupal_generate_test_ua() to write
154       // a file containing the private key for drupal_valid_test_ua(), the site
155       // directory has to be writable.
156       // WebTestBase::tearDown() will delete the entire test site directory.
157       // Not using File API; a potential error must trigger a PHP warning.
158       chmod($this->container->get('app.root') . '/' . $this->siteDirectory, 0777);
159       $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', FALSE);
160       $this->kernel->prepareLegacyRequest($request);
161       $this->container = $this->kernel->getContainer();
162
163       // Manually configure the test mail collector implementation to prevent
164       // tests from sending out emails and collect them in state instead.
165       $this->container->get('config.factory')
166         ->getEditable('system.mail')
167         ->set('interface.default', 'test_mail_collector')
168         ->save();
169     }
170   }
171
172   /**
173    * Visits the interactive installer.
174    */
175   protected function visitInstaller() {
176     $this->drupalGet($GLOBALS['base_url'] . '/core/install.php');
177   }
178
179   /**
180    * Installer step: Select language.
181    */
182   protected function setUpLanguage() {
183     $edit = [
184       'langcode' => $this->langcode,
185     ];
186     $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']);
187   }
188
189   /**
190    * Installer step: Select installation profile.
191    */
192   protected function setUpProfile() {
193     $edit = [
194       'profile' => $this->profile,
195     ];
196     $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']);
197   }
198
199   /**
200    * Installer step: Configure settings.
201    */
202   protected function setUpSettings() {
203     $edit = $this->translatePostValues($this->parameters['forms']['install_settings_form']);
204     $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']);
205   }
206
207   /**
208    * Installer step: Requirements problem.
209    *
210    * Override this method to test specific requirements warnings or errors
211    * during the installer.
212    *
213    * @see system_requirements()
214    */
215   protected function setUpRequirementsProblem() {
216     // By default, skip the "recommended PHP version" warning on older test
217     // environments. This allows the installer to be tested consistently on
218     // both recommended PHP versions and older (but still supported) versions.
219     if (version_compare(phpversion(), '7.0') < 0) {
220       $this->continueOnExpectedWarnings(['PHP']);
221     }
222   }
223
224   /**
225    * Final installer step: Configure site.
226    */
227   protected function setUpSite() {
228     $edit = $this->translatePostValues($this->parameters['forms']['install_configure_form']);
229     $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']);
230     // If we've got to this point the site is installed using the regular
231     // installation workflow.
232     $this->isInstalled = TRUE;
233   }
234
235   /**
236    * {@inheritdoc}
237    *
238    * WebTestBase::refreshVariables() tries to operate on persistent storage,
239    * which is only available after the installer completed.
240    */
241   protected function refreshVariables() {
242     if ($this->isInstalled) {
243       parent::refreshVariables();
244     }
245   }
246
247   /**
248    * Continues installation when an expected warning is found.
249    *
250    * @param string[] $expected_warnings
251    *   A list of warning summaries to expect on the requirements screen (e.g.
252    *   'PHP', 'PHP OPcode caching', etc.). If only the expected warnings
253    *   are found, the test will click the "continue anyway" link to go to the
254    *   next screen of the installer. If an expected warning is not found, or if
255    *   a warning not in the list is present, a fail is raised.
256    */
257   protected function continueOnExpectedWarnings($expected_warnings = []) {
258     // Don't try to continue if there are errors.
259     if (strpos($this->getTextContent(), 'Errors found') !== FALSE) {
260       return;
261     }
262     // Allow only details elements that are directly after the warning header
263     // or each other. There is no guaranteed wrapper we can rely on across
264     // distributions. When there are multiple warnings, the selectors will be:
265     // - h3#warning+details summary
266     // - h3#warning+details+details summary
267     // - etc.
268     // We add one more selector than expected warnings to confirm that there
269     // isn't any other warning before clicking the link.
270     // @todo Make this more reliable in
271     //   https://www.drupal.org/project/drupal/issues/2927345.
272     $selectors = [];
273     for ($i = 0; $i <= count($expected_warnings); $i++) {
274       $selectors[] = 'h3#warning' . implode('', array_fill(0, $i + 1, '+details')) . ' summary';
275     }
276     $warning_elements = $this->cssSelect(implode(', ', $selectors));
277
278     // Confirm that there are only the expected warnings.
279     $warnings = [];
280     foreach ($warning_elements as $warning) {
281       $warnings[] = trim((string) $warning);
282     }
283     $this->assertEqual($expected_warnings, $warnings);
284     $this->clickLink('continue anyway');
285   }
286
287 }