524a95b34817adb28fa95b69ada1d03ed551c072
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Controller / Action / Step / DatabaseData.php
1 <?php
2 namespace TYPO3\CMS\Install\Controller\Action\Step;
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
17 use TYPO3\CMS\Core\Configuration\ConfigurationManager;
18 use TYPO3\CMS\Install\Status\ErrorStatus;
19
20 /**
21 * Populate base tables, insert admin user, set install tool password
22 */
23 class DatabaseData extends AbstractStepAction {
24
25 /**
26 * Import tables and data, create admin user, create install tool password
27 *
28 * @return \TYPO3\CMS\Install\Status\StatusInterface[]
29 */
30 public function execute() {
31 $result = array();
32
33 /** @var ConfigurationManager $configurationManager */
34 $configurationManager = $this->objectManager->get(ConfigurationManager::class);
35
36 $postValues = $this->postValues['values'];
37
38 $username = (string)$postValues['username'] !== '' ? $postValues['username'] : 'admin';
39
40 // Check password and return early if not good enough
41 $password = $postValues['password'];
42 if (strlen($password) < 8) {
43 $errorStatus = $this->objectManager->get(ErrorStatus::class);
44 $errorStatus->setTitle('Administrator password not secure enough!');
45 $errorStatus->setMessage(
46 'You are setting an important password here! It gives an attacker full control over your instance if cracked.' .
47 ' It should be strong (include lower and upper case characters, special characters and numbers) and must be at least eight characters long.'
48 );
49 $result[] = $errorStatus;
50 return $result;
51 }
52
53 // Set site name
54 if (!empty($postValues['sitename'])) {
55 $configurationManager->setLocalConfigurationValueByPath('SYS/sitename', $postValues['sitename']);
56 }
57
58 $result = $this->importDatabaseData();
59 if (!empty($result)) {
60 return $result;
61 }
62
63 // Insert admin user
64 $adminUserFields = array(
65 'username' => $username,
66 'password' => $this->getHashedPassword($password),
67 'admin' => 1,
68 'tstamp' => $GLOBALS['EXEC_TIME'],
69 'crdate' => $GLOBALS['EXEC_TIME']
70 );
71 if (FALSE === $this->getDatabaseConnection()->exec_INSERTquery('be_users', $adminUserFields)) {
72 $errorStatus = $this->objectManager->get(ErrorStatus::class);
73 $errorStatus->setTitle('Administrator account not created!');
74 $errorStatus->setMessage(
75 'The administrator account could not be created. The following error occurred:' . LF .
76 $this->getDatabaseConnection()->sql_error()
77 );
78 $result[] = $errorStatus;
79 return $result;
80 };
81
82 // Set password as install tool password
83 $configurationManager->setLocalConfigurationValueByPath('BE/installToolPassword', $this->getHashedPassword($password));
84
85 // Mark the initial import as done
86 $this->markImportDatabaseDone();
87
88 return $result;
89 }
90
91 /**
92 * Step needs to be executed if there are no tables in database
93 *
94 * @return bool
95 */
96 public function needsExecution() {
97 $existingTables = $this->getDatabaseConnection()->admin_get_tables();
98 if (empty($existingTables)) {
99 $result = TRUE;
100 } else {
101 $result = !$this->isImportDatabaseDone();
102 }
103 return $result;
104 }
105
106 /**
107 * Executes the step
108 *
109 * @return string Rendered content
110 */
111 protected function executeAction() {
112 $this->assignSteps();
113 return $this->view->render();
114 }
115
116 /**
117 * Create tables and import static rows
118 *
119 * @return \TYPO3\CMS\Install\Status\StatusInterface[]
120 */
121 protected function importDatabaseData() {
122 $result = array();
123 // Will load ext_localconf and ext_tables. This is pretty safe here since we are
124 // in first install (database empty), so it is very likely that no extension is loaded
125 // that could trigger a fatal at this point.
126 $this->loadExtLocalconfDatabaseAndExtTables();
127
128 // Import database data
129 $database = $this->getDatabaseConnection();
130 /** @var \TYPO3\CMS\Install\Service\SqlSchemaMigrationService $schemaMigrationService */
131 $schemaMigrationService = $this->objectManager->get(\TYPO3\CMS\Install\Service\SqlSchemaMigrationService::class);
132 /** @var \TYPO3\CMS\Install\Service\SqlExpectedSchemaService $expectedSchemaService */
133 $expectedSchemaService = $this->objectManager->get(\TYPO3\CMS\Install\Service\SqlExpectedSchemaService::class);
134
135 // Raw concatenated ext_tables.sql and friends string
136 $expectedSchemaString = $expectedSchemaService->getTablesDefinitionString(TRUE);
137 $statements = $schemaMigrationService->getStatementArray($expectedSchemaString, TRUE);
138 list($_, $insertCount) = $schemaMigrationService->getCreateTables($statements, TRUE);
139 $fieldDefinitionsFile = $schemaMigrationService->getFieldDefinitions_fileContent($expectedSchemaString);
140 $fieldDefinitionsDatabase = $schemaMigrationService->getFieldDefinitions_database();
141 $difference = $schemaMigrationService->getDatabaseExtra($fieldDefinitionsFile, $fieldDefinitionsDatabase);
142 $updateStatements = $schemaMigrationService->getUpdateSuggestions($difference);
143
144 foreach (array('add', 'change', 'create_table') as $action) {
145 $updateStatus = $schemaMigrationService->performUpdateQueries($updateStatements[$action], $updateStatements[$action]);
146 if ($updateStatus !== TRUE) {
147 foreach ($updateStatus as $statementIdentifier => $errorMessage) {
148 $result[$updateStatements[$action][$statementIdentifier]] = $errorMessage;
149 }
150 }
151 }
152
153 if (empty($result)) {
154 foreach ($insertCount as $table => $count) {
155 $insertStatements = $schemaMigrationService->getTableInsertStatements($statements, $table);
156 foreach ($insertStatements as $insertQuery) {
157 $insertQuery = rtrim($insertQuery, ';');
158 $database->admin_query($insertQuery);
159 if ($database->sql_error()) {
160 $result[$insertQuery] = $database->sql_error();
161 }
162 }
163 }
164 }
165
166 foreach ($result as $statement => &$message) {
167 $errorStatus = $this->objectManager->get(ErrorStatus::class);
168 $errorStatus->setTitle('Database query failed!');
169 $errorStatus->setMessage(
170 'Query:' . LF .
171 ' ' . $statement . LF .
172 'Error:' . LF .
173 ' ' . $message
174 );
175 $message = $errorStatus;
176 }
177
178 return array_values($result);
179 }
180
181 /**
182 * Persist the information that the initial import has been performed
183 */
184 protected function markImportDatabaseDone() {
185 $this->objectManager->get(ConfigurationManager::class)
186 ->setLocalConfigurationValueByPath('SYS/isInitialDatabaseImportDone', TRUE);
187 }
188
189 /**
190 * Checks if the initial import has been performed
191 *
192 * @return bool
193 */
194 protected function isImportDatabaseDone() {
195 return $this->objectManager->get(ConfigurationManager::class)
196 ->getLocalConfigurationValueByPath('SYS/isInitialDatabaseImportDone');
197 }
198
199 }