13becfec50c8f43358d7de43edbf5be9dfa39568
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Updates / FinalDatabaseSchemaUpdate.php
1 <?php
2 namespace TYPO3\CMS\Install\Updates;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2014 Stephan Großberndt <stephan@grossberndt.de>
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 * A copy is found in the text file GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 /**
31 * Contains the update class to create and alter tables, fields and keys to comply to the database schema
32 *
33 * @author Stephan Großberndt <stephan@grossberndt.de>
34 */
35 class FinalDatabaseSchemaUpdate extends AbstractDatabaseSchemaUpdate {
36
37 /**
38 * Constructor function.
39 */
40 public function __construct() {
41 parent::__construct();
42 $this->title = 'Update database schema: Modify tables and fields';
43 }
44
45 /**
46 * Checks if an update is needed
47 *
48 * @param string &$description The description for the update
49 * @return bool TRUE if an update is needed, FALSE otherwise
50 */
51 public function checkForUpdate(&$description) {
52 $description = 'There are tables or fields in the database which need to be changed.<br /><br />' .
53 'This update wizard can be run only when there are no other update wizards left to make sure they have all needed fields unchanged.<br /><br />' .
54 'If you want to apply changes selectively, <a href="Install.php?install[action]=importantActions&amp;install[context]={context}&amp;install[controller]=tool">go to Database Analyzer</a>.';
55
56 $databaseDifferences = $this->getDatabaseDifferences();
57 $updateSuggestions = $this->schemaMigrationService->getUpdateSuggestions($databaseDifferences);
58
59 return isset($updateSuggestions['change']);
60 }
61
62 /**
63 * Second step: Show tables, fields and keys to create or update
64 *
65 * @param string $inputPrefix input prefix, all names of form fields have to start with this. Append custom name in [ ... ]
66 * @return string HTML output
67 */
68 public function getUserInput($inputPrefix) {
69 $result = '';
70
71 $databaseDifferences = $this->getDatabaseDifferences();
72 $updateSuggestions = $this->schemaMigrationService->getUpdateSuggestions($databaseDifferences);
73
74 if (!isset($updateSuggestions['change'])) {
75 return $result;
76 }
77
78 $fieldsList = '
79 <p>
80 Change the following fields in tables:
81 </p>
82 <fieldset>
83 <ol class="t3-install-form-label-after">%s</ol>
84 </fieldset>';
85 $keysList = '
86 <p>
87 Change the following keys in tables:
88 </p>
89 <fieldset>
90 <ol class="t3-install-form-label-after">%s</ol>
91 </fieldset>';
92 $item = '
93 <li class="labelAfter">
94 <label><strong>%1$s</strong>: %2$s</label>
95 </li>';
96
97 $fieldItems = array();
98 $keyItems = array();
99 foreach ($databaseDifferences['diff'] as $tableName => $difference) {
100 if ($difference['fields']) {
101 $fieldNames = array();
102 foreach ($difference['fields'] as $fieldName => $sql) {
103 $fieldNames[] = $fieldName;
104 }
105 $fieldItems[] = sprintf($item, $tableName, implode(', ', $fieldNames));
106 }
107 if ($difference['keys']) {
108 $keyNames = array();
109 foreach ($difference['keys'] as $keyName => $sql) {
110 $keyNames[] = $keyName;
111 }
112 $keyItems[] = sprintf($item, $tableName, implode(', ', $keyNames));
113 }
114 }
115 if (!empty($fieldItems)) {
116 $result .= sprintf($fieldsList, implode('', $fieldItems));
117 }
118 if (!empty($keyItems)) {
119 $result .= sprintf($keysList, implode('', $keyItems));
120 }
121
122 return $result;
123 }
124
125
126 /**
127 * Performs the database update.
128 *
129 * @param array &$dbQueries Queries done in this update
130 * @param mixed &$customMessages Custom messages
131 * @return bool TRUE on success, FALSE on error
132 */
133 public function performUpdate(array &$dbQueries, &$customMessages) {
134 // First perform all add update statements to database
135 $databaseDifferences = $this->getDatabaseDifferences();
136 $updateStatements = $this->schemaMigrationService->getUpdateSuggestions($databaseDifferences);
137
138 $customMessagesArray = array();
139 foreach ((array)$updateStatements['change'] as $query) {
140 $GLOBALS['TYPO3_DB']->admin_query($query);
141 $dbQueries[] = $query;
142 if ($GLOBALS['TYPO3_DB']->sql_error()) {
143 $customMessagesArray[] = 'SQL-ERROR: ' . htmlspecialchars($GLOBALS['TYPO3_DB']->sql_error());
144 }
145 }
146
147 if (!empty($customMessagesArray)) {
148 $customMessages = 'Update process not fully processed. This can happen because of dependencies of table fields and ' .
149 'indexes. Please repeat this step! Following errors occurred:' . LF . LF . implode(LF, $customMessagesArray);
150 }
151
152 return count($customMessagesArray) === 0;
153 }
154 }