ae6134a4b0686bf2363f6f8c0a1e8c35a9d7ef84
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Controller / Action / Tool / ImportantActions.php
1 <?php
2 namespace TYPO3\CMS\Install\Controller\Action\Tool;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2013 Christian Kuhn <lolli@schwarzbu.ch>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26
27 use TYPO3\CMS\Install\Controller\Action;
28 use TYPO3\CMS\Core\Utility\GeneralUtility;
29
30 /**
31 * Handle important actions
32 */
33 class ImportantActions extends Action\AbstractAction implements Action\ActionInterface {
34
35 /**
36 * Handle this action
37 *
38 * @return string content
39 */
40 public function handle() {
41 $this->initializeHandle();
42
43 if (isset($this->postValues['set']['changeEncryptionKey'])) {
44 $this->setNewEncryptionKeyAndLogOut();
45 }
46
47 $actionMessages = array();
48 if (isset($this->postValues['set']['changeInstallToolPassword'])) {
49 $actionMessages[] = $this->changeInstallToolPassword();
50 }
51 if (isset($this->postValues['set']['changeSiteName'])) {
52 $actionMessages[] = $this->changeSiteName();
53 }
54 if (isset($this->postValues['set']['createAdministrator'])) {
55 $actionMessages[] = $this->createAdministrator();
56 }
57 if (isset($this->postValues['set']['clearAllCache'])) {
58 $actionMessages[] = $this->clearAllCache();
59 }
60
61 // Database analyzer handling
62 if (isset($this->postValues['set']['databaseAnalyzerExecute'])
63 || isset($this->postValues['set']['databaseAnalyzerAnalyze'])
64 ) {
65 $this->loadExtLocalconfDatabaseAndExtTables();
66 }
67 if (isset($this->postValues['set']['databaseAnalyzerExecute'])) {
68 $actionMessages = array_merge($actionMessages, $this->databaseAnalyzerExecute());
69 }
70 if (isset($this->postValues['set']['databaseAnalyzerAnalyze'])) {
71 $actionMessages[] = $this->databaseAnalyzerAnalyze();
72 }
73
74 $this->view->assign('actionMessages', $actionMessages);
75
76 $operatingSystem = TYPO3_OS === 'WIN' ? 'Windows' : 'Unix';
77 $cgiDetected = (PHP_SAPI == 'fpm-fcgi' || PHP_SAPI == 'cgi' || PHP_SAPI == 'isapi' || PHP_SAPI == 'cgi-fcgi')
78 ? TRUE
79 : FALSE;
80
81 $this->view
82 ->assign('operatingSystem', $operatingSystem)
83 ->assign('cgiDetected', $cgiDetected)
84 ->assign('databaseName', $GLOBALS['TYPO3_CONF_VARS']['DB']['database'])
85 ->assign('databaseUsername', $GLOBALS['TYPO3_CONF_VARS']['DB']['username'])
86 ->assign('databaseHost', $GLOBALS['TYPO3_CONF_VARS']['DB']['host'])
87 ->assign('databasePort', $GLOBALS['TYPO3_CONF_VARS']['DB']['port'])
88 ->assign('databaseSocket', $GLOBALS['TYPO3_CONF_VARS']['DB']['socket'])
89 ->assign('databaseNumberOfTables', count($this->getDatabase()->admin_get_tables()))
90 ->assign('extensionCompatibilityTesterProtocolFile', GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . 'typo3temp/ExtensionCompatibilityTester.txt');
91
92 return $this->view->render();
93 }
94
95 /**
96 * Set new password if requested
97 *
98 * @return \TYPO3\CMS\Install\Status\StatusInterface
99 */
100 protected function changeInstallToolPassword() {
101 $values = $this->postValues['values'];
102 if ($values['newInstallToolPassword'] !== $values['newInstallToolPasswordCheck']) {
103 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
104 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\ErrorStatus');
105 $message->setTitle('Install tool password not changed');
106 $message->setMessage('Given passwords do not match.');
107 } elseif (strlen($values['newInstallToolPassword']) < 8) {
108 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
109 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\ErrorStatus');
110 $message->setTitle('Install tool password not changed');
111 $message->setMessage('Given passwords must be a least eight characters long.');
112 } else {
113 /** @var \TYPO3\CMS\Core\Configuration\ConfigurationManager $configurationManager */
114 $configurationManager = $this->objectManager->get('TYPO3\\CMS\\Core\\Configuration\\ConfigurationManager');
115 $configurationManager->setLocalConfigurationValueByPath('BE/installToolPassword', md5($values['newInstallToolPassword']));
116 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
117 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\OkStatus');
118 $message->setTitle('Install tool password changed');
119 }
120 return $message;
121 }
122
123 /**
124 * Set new site name
125 *
126 * @return \TYPO3\CMS\Install\Status\StatusInterface
127 */
128 protected function changeSiteName() {
129 $values = $this->postValues['values'];
130 if (isset($values['newSiteName']) && strlen($values['newSiteName']) > 0) {
131 /** @var \TYPO3\CMS\Core\Configuration\ConfigurationManager $configurationManager */
132 $configurationManager = $this->objectManager->get('TYPO3\\CMS\\Core\\Configuration\\ConfigurationManager');
133 $configurationManager->setLocalConfigurationValueByPath('SYS/sitename', $values['newSiteName']);
134 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
135 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\OkStatus');
136 $message->setTitle('Site name changed');
137 $this->view->assign('siteName', $values['newSiteName']);
138 } else {
139 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
140 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\ErrorStatus');
141 $message->setTitle('Site name not changed');
142 $message->setMessage('Site name must be at least one character long.');
143 }
144 return $message;
145 }
146
147 /**
148 * Clear all caches
149 *
150 * @return \TYPO3\CMS\Install\Status\StatusInterface
151 */
152 protected function clearAllCache() {
153 /** @var \TYPO3\CMS\Install\Service\ClearCacheService $clearCacheService */
154 $clearCacheService = $this->objectManager->get('TYPO3\\CMS\\Install\\Service\\ClearCacheService');
155 $clearCacheService->clearAll();
156 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\OkStatus');
157 $message->setTitle('Successfully cleared all caches');
158 return $message;
159 }
160
161 /**
162 * Set new encryption key
163 *
164 * @return void
165 */
166 protected function setNewEncryptionKeyAndLogOut() {
167 $newKey = \TYPO3\CMS\Core\Utility\GeneralUtility::getRandomHexString(96);
168 /** @var \TYPO3\CMS\Core\Configuration\ConfigurationManager $configurationManager */
169 $configurationManager = $this->objectManager->get('TYPO3\\CMS\\Core\\Configuration\\ConfigurationManager');
170 $configurationManager->setLocalConfigurationValueByPath('SYS/encryptionKey', $newKey);
171 /** @var $formProtection \TYPO3\CMS\Core\FormProtection\InstallToolFormProtection */
172 $formProtection = \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get(
173 'TYPO3\\CMS\\Core\\FormProtection\\InstallToolFormProtection'
174 );
175 $formProtection->clean();
176 /** @var \TYPO3\CMS\Install\Service\SessionService $session */
177 $session = $this->objectManager->get('TYPO3\\CMS\\Install\\Service\\SessionService');
178 $session->destroySession();
179 \TYPO3\CMS\Core\Utility\HttpUtility::redirect('Install.php?install[context]=' . $this->getContext());
180 }
181
182 /**
183 * Create administrator user
184 *
185 * @return \TYPO3\CMS\Install\Status\StatusInterface
186 */
187 protected function createAdministrator() {
188 $values = $this->postValues['values'];
189 $username = preg_replace('/[^\\da-z._]/i', '', trim($values['newUserUsername']));
190 $password = $values['newUserPassword'];
191 $passwordCheck = $values['newUserPasswordCheck'];
192
193 if (strlen($username) < 1) {
194 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
195 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\ErrorStatus');
196 $message->setTitle('Administrator user not created');
197 $message->setMessage('No valid username given.');
198 } elseif ($password !== $passwordCheck) {
199 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
200 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\ErrorStatus');
201 $message->setTitle('Administrator user not created');
202 $message->setMessage('Passwords do not match.');
203 } elseif (strlen($password) < 8) {
204 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
205 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\ErrorStatus');
206 $message->setTitle('Administrator user not created');
207 $message->setMessage('Password must be at least eight characters long.');
208 } else {
209 $database = $this->getDatabase();
210 $userExists = $database->exec_SELECTcountRows(
211 'uid',
212 'be_users',
213 'username=' . $database->fullQuoteStr($username, 'be_users')
214 );
215 if ($userExists) {
216 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
217 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\ErrorStatus');
218 $message->setTitle('Administrator user not created');
219 $message->setMessage('A user with username ' . $username . ' exists already.');
220 } else {
221 $saltFactory = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance(NULL, 'BE');
222 $hashedPassword = $saltFactory->getHashedPassword($password);
223
224 $adminUserFields = array(
225 'username' => $username,
226 'password' => $hashedPassword,
227 'admin' => 1,
228 'tstamp' => $GLOBALS['EXEC_TIME'],
229 'crdate' => $GLOBALS['EXEC_TIME']
230 );
231 $database->exec_INSERTquery('be_users', $adminUserFields);
232 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
233 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\OkStatus');
234 $message->setTitle('Administrator created');
235 }
236 }
237
238 return $message;
239 }
240
241 /**
242 * Execute database migration
243 *
244 * @return array<\TYPO3\CMS\Install\Status\StatusInterface>
245 */
246 protected function databaseAnalyzerExecute() {
247 $messages = array();
248
249 // Early return in case no updade was selected
250 if (empty($this->postValues['values'])) {
251 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
252 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\WarningStatus');
253 $message->setTitle('No database changes selected');
254 $messages[] = $message;
255 return $message;
256 }
257
258 /** @var \TYPO3\CMS\Install\Service\SqlSchemaMigrationService $schemaMigrationService */
259 $schemaMigrationService = $this->objectManager->get('TYPO3\\CMS\\Install\\Service\\SqlSchemaMigrationService');
260 /** @var \TYPO3\CMS\Install\Service\SqlExpectedSchemaService $expectedSchemaService */
261 $expectedSchemaService = $this->objectManager->get('TYPO3\\CMS\\Install\\Service\\SqlExpectedSchemaService');
262 $expectedSchema = $expectedSchemaService->getExpectedDatabaseSchema();
263 $currentSchema = $schemaMigrationService->getFieldDefinitions_database();
264
265 $statementHashesToPerform = $this->postValues['values'];
266
267 $results = array();
268
269 // Difference from expected to current
270 $addCreateChange = $schemaMigrationService->getDatabaseExtra($expectedSchema, $currentSchema);
271 $addCreateChange = $schemaMigrationService->getUpdateSuggestions($addCreateChange);
272 $results[] = $schemaMigrationService->performUpdateQueries($addCreateChange['add'], $statementHashesToPerform);
273 $results[] = $schemaMigrationService->performUpdateQueries($addCreateChange['change'], $statementHashesToPerform);
274 $results[] = $schemaMigrationService->performUpdateQueries($addCreateChange['create_table'], $statementHashesToPerform);
275
276 // Difference from current to expected
277 $dropRename = $schemaMigrationService->getDatabaseExtra($currentSchema, $expectedSchema);
278 $dropRename = $schemaMigrationService->getUpdateSuggestions($dropRename, 'remove');
279 $results[] = $schemaMigrationService->performUpdateQueries($dropRename['change'], $statementHashesToPerform);
280 $results[] = $schemaMigrationService->performUpdateQueries($dropRename['drop'], $statementHashesToPerform);
281 $results[] = $schemaMigrationService->performUpdateQueries($dropRename['change_table'], $statementHashesToPerform);
282 $results[] = $schemaMigrationService->performUpdateQueries($dropRename['drop_table'], $statementHashesToPerform);
283
284 // Create error flash messages if any
285 foreach ($results as $resultSet) {
286 if (is_array($resultSet)) {
287 foreach ($resultSet as $errorMessage) {
288 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
289 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\ErrorStatus');
290 $message->setTitle('Database update failed');
291 $message->setMessage('Error: ' . $errorMessage);
292 $messages[] = $message;
293 }
294 }
295 }
296
297 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
298 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\OkStatus');
299 $message->setTitle('Executed database updates');
300 $messages[] = $message;
301
302 return $messages;
303 }
304
305 /**
306 * "Compare" action of analyzer
307 *
308 * @TODO: The SchemaMigration API is a mess and should be refactored
309 * @TODO: Refactoring this should aim to make EM and dbal independent from ext:install by moving SchemaMigration to ext:core
310 * @return \TYPO3\CMS\Install\Status\StatusInterface
311 */
312 protected function databaseAnalyzerAnalyze() {
313 /** @var \TYPO3\CMS\Install\Service\SqlSchemaMigrationService $schemaMigrationService */
314 $schemaMigrationService = $this->objectManager->get('TYPO3\\CMS\\Install\\Service\\SqlSchemaMigrationService');
315 /** @var \TYPO3\CMS\Install\Service\SqlExpectedSchemaService $expectedSchemaService */
316 $expectedSchemaService = $this->objectManager->get('TYPO3\\CMS\\Install\\Service\\SqlExpectedSchemaService');
317 $expectedSchema = $expectedSchemaService->getExpectedDatabaseSchema();
318
319 $currentSchema = $schemaMigrationService->getFieldDefinitions_database();
320
321 $databaseAnalyzerSuggestion = array();
322
323 // Difference from expected to current
324 $addCreateChange = $schemaMigrationService->getDatabaseExtra($expectedSchema, $currentSchema);
325 $addCreateChange = $schemaMigrationService->getUpdateSuggestions($addCreateChange);
326 if (isset($addCreateChange['create_table'])) {
327 $databaseAnalyzerSuggestion['addTable'] = array();
328 foreach ($addCreateChange['create_table'] as $hash => $statement) {
329 $databaseAnalyzerSuggestion['addTable'][$hash] = array(
330 'hash' => $hash,
331 'statement' => $statement,
332 );
333 }
334 }
335 if (isset($addCreateChange['add'])) {
336 $databaseAnalyzerSuggestion['addField'] = array();
337 foreach ($addCreateChange['add'] as $hash => $statement) {
338 $databaseAnalyzerSuggestion['addField'][$hash] = array(
339 'hash' => $hash,
340 'statement' => $statement,
341 );
342 }
343 }
344 if (isset($addCreateChange['change'])) {
345 $databaseAnalyzerSuggestion['change'] = array();
346 foreach ($addCreateChange['change'] as $hash => $statement) {
347 $databaseAnalyzerSuggestion['change'][$hash] = array(
348 'hash' => $hash,
349 'statement' => $statement,
350 );
351 if (isset($addCreateChange['change_currentValue'][$hash])) {
352 $databaseAnalyzerSuggestion['change'][$hash]['current'] = $addCreateChange['change_currentValue'][$hash];
353 }
354 }
355 }
356
357 // Difference from current to expected
358 $dropRename = $schemaMigrationService->getDatabaseExtra($currentSchema, $expectedSchema);
359 $dropRename = $schemaMigrationService->getUpdateSuggestions($dropRename, 'remove');
360 if (isset($dropRename['change_table'])) {
361 $databaseAnalyzerSuggestion['renameTableToUnused'] = array();
362 foreach ($dropRename['change_table'] as $hash => $statement) {
363 $databaseAnalyzerSuggestion['renameTableToUnused'][$hash] = array(
364 'hash' => $hash,
365 'statement' => $statement,
366 );
367 if (!empty($dropRename['tables_count'][$hash])) {
368 $databaseAnalyzerSuggestion['renameTableToUnused'][$hash]['count'] = $dropRename['tables_count'][$hash];
369 }
370 }
371 }
372 if (isset($dropRename['change'])) {
373 $databaseAnalyzerSuggestion['renameTableFieldToUnused'] = array();
374 foreach ($dropRename['change'] as $hash => $statement) {
375 $databaseAnalyzerSuggestion['renameTableFieldToUnused'][$hash] = array(
376 'hash' => $hash,
377 'statement' => $statement,
378 );
379 }
380 }
381 if (isset($dropRename['drop'])) {
382 $databaseAnalyzerSuggestion['deleteField'] = array();
383 foreach ($dropRename['drop'] as $hash => $statement) {
384 $databaseAnalyzerSuggestion['deleteField'][$hash] = array(
385 'hash' => $hash,
386 'statement' => $statement,
387 );
388 }
389 }
390 if (isset($dropRename['drop_table'])) {
391 $databaseAnalyzerSuggestion['deleteTable'] = array();
392 foreach ($dropRename['drop_table'] as $hash => $statement) {
393 $databaseAnalyzerSuggestion['deleteTable'][$hash] = array(
394 'hash' => $hash,
395 'statement' => $statement,
396 );
397 if (!empty($dropRename['tables_count'][$hash])) {
398 $databaseAnalyzerSuggestion['deleteTable'][$hash]['count'] = $dropRename['tables_count'][$hash];
399 }
400 }
401 }
402
403 $this->view->assign('databaseAnalyzerSuggestion', $databaseAnalyzerSuggestion);
404
405 /** @var $message \TYPO3\CMS\Install\Status\StatusInterface */
406 $message = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\OkStatus');
407 $message->setTitle('Analyzed current database');
408 return $message;
409 }
410 }
411 ?>