[BUGFIX] Fix various issues in Core Updater
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Resources / Public / JavaScript / Modules / CoreUpdate.js
1 /*
2 * This file is part of the TYPO3 CMS project.
3 *
4 * It is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, either version 2
6 * of the License, or any later version.
7 *
8 * For the full copyright and license information, please read the
9 * LICENSE.txt file that was distributed with this source code.
10 *
11 * The TYPO3 project - inspiring people to share!
12 */
13
14 /**
15 * Module: TYPO3/CMS/Install/CoreUpdate
16 */
17 define([
18 'jquery',
19 'TYPO3/CMS/Install/Router',
20 'TYPO3/CMS/Install/FlashMessage',
21 'TYPO3/CMS/Install/Severity',
22 'TYPO3/CMS/Backend/Notification'
23 ], function($, Router, FlashMessage, Severity, Notification) {
24 'use strict';
25
26 return {
27 /**
28 * The action queue defines what actions are called in which order
29 */
30 actionQueue: {
31 coreUpdateIsUpdateAvailable: {
32 loadingMessage: 'Checking for possible regular or security update',
33 finishMessage: undefined,
34 nextActionName: undefined
35 },
36 coreUpdateCheckPreConditions: {
37 loadingMessage: 'Checking if update is possible',
38 finishMessage: 'System can be updated',
39 nextActionName: 'coreUpdateDownload'
40 },
41 coreUpdateDownload: {
42 loadingMessage: 'Downloading new core',
43 finishMessage: undefined,
44 nextActionName: 'coreUpdateVerifyChecksum'
45 },
46 coreUpdateVerifyChecksum: {
47 loadingMessage: 'Verifying checksum of downloaded core',
48 finishMessage: undefined,
49 nextActionName: 'coreUpdateUnpack'
50 },
51 coreUpdateUnpack: {
52 loadingMessage: 'Unpacking core',
53 finishMessage: undefined,
54 nextActionName: 'coreUpdateMove'
55 },
56 coreUpdateMove: {
57 loadingMessage: 'Moving core',
58 finishMessage: undefined,
59 nextActionName: 'coreUpdateActivate'
60 },
61 coreUpdateActivate: {
62 loadingMessage: 'Activating core',
63 finishMessage: 'Core updated - please reload your browser',
64 nextActionName: undefined
65 }
66 },
67
68 selectorModalBody: '.t3js-modal-body',
69 selectorOutput: '.t3js-coreUpdate-output',
70 selectorTemplate: '.t3js-coreUpdate-buttonTemplate',
71
72 /**
73 * Clone of a DOM object acts as button template
74 */
75 buttonTemplate: null,
76
77 /**
78 * Fetching the templates out of the DOM
79 */
80 initialize: function(currentModal) {
81 var self = this;
82 this.currentModal = currentModal;
83 this.getData().done(function() {
84 var buttonTemplateSection = currentModal.find(self.selectorTemplate);
85 self.buttonTemplate = buttonTemplateSection.children().clone();
86 });
87
88 currentModal.on('click', '.t3js-coreUpdate-init', function(e) {
89 e.preventDefault();
90 var action = $(e.target).data('action');
91 currentModal.find(self.selectorOutput).empty();
92 self[action]();
93 });
94 },
95
96 getData: function() {
97 var modalContent = this.currentModal.find(this.selectorModalBody);
98 return $.ajax({
99 url: Router.getUrl('coreUpdateGetData'),
100 cache: false,
101 success: function(data) {
102 if (data.success === true) {
103 modalContent.empty().append(data.html);
104 } else {
105 Notification.error('Something went wrong');
106 }
107 },
108 error: function(xhr) {
109 Router.handleAjaxError(xhr, modalContent);
110 }
111 });
112 },
113
114 /**
115 * Public method checkForUpdate
116 */
117 checkForUpdate: function() {
118 this.callAction('coreUpdateIsUpdateAvailable');
119 },
120
121 /**
122 * Public method updateDevelopment
123 */
124 updateDevelopment: function() {
125 this.update('development');
126 },
127
128 updateRegular: function() {
129 this.update('regular');
130 },
131
132 /**
133 * Execute core update.
134 *
135 * @param type Either 'development' or 'regular'
136 */
137 update: function(type) {
138 if (type !== 'development') {
139 type = 'regular';
140 }
141 this.callAction('coreUpdateCheckPreConditions', type);
142 },
143
144 /**
145 * Generic method to call actions from the queue
146 *
147 * @param actionName Name of the action to be called
148 * @param type Update type (optional)
149 */
150 callAction: function(actionName, type) {
151 var self = this;
152 var data = {
153 install: {
154 action: actionName
155 }
156 };
157 if (type !== undefined) {
158 data.install["type"] = type;
159 }
160 this.addLoadingMessage(this.actionQueue[actionName].loadingMessage);
161 $.ajax({
162 url: Router.getUrl(),
163 data: data,
164 cache: false,
165 success: function(result) {
166 var canContinue = self.handleResult(result, self.actionQueue[actionName].finishMessage);
167 if (canContinue === true && (self.actionQueue[actionName].nextActionName !== undefined)) {
168 self.callAction(self.actionQueue[actionName].nextActionName, type);
169 }
170 },
171 error: function(xhr) {
172 Router.handleAjaxError(xhr, self.currentModal.find(self.selectorModalBody));
173 }
174 });
175 },
176
177 /**
178 * Handle ajax result of core update step.
179 *
180 * @param data
181 * @param successMessage Optional success message
182 */
183 handleResult: function(data, successMessage) {
184 var canContinue = data.success;
185 this.removeLoadingMessage();
186
187 if (data.status && typeof(data.status) === 'object') {
188 this.showStatusMessages(data.status);
189 }
190 if (data.action && typeof(data.action) === 'object') {
191 this.showActionButton(data.action);
192 }
193 if (successMessage) {
194 this.addMessage(Severity.ok, successMessage);
195 }
196 return canContinue;
197 },
198
199 /**
200 * Add a loading message with some text.
201 *
202 * @param messageTitle
203 */
204 addLoadingMessage: function(messageTitle) {
205 var domMessage = FlashMessage.render(Severity.loading, messageTitle);
206 this.currentModal.find(this.selectorOutput).append(domMessage);
207 },
208
209 /**
210 * Remove an enabled loading message
211 */
212 removeLoadingMessage: function() {
213 this.currentModal.find(this.selectorOutput).find('.alert-loading').remove();
214 },
215
216 /**
217 * Show a list of status messages
218 *
219 * @param messages
220 */
221 showStatusMessages: function(messages) {
222 var self = this;
223 $.each(messages, function(index, element) {
224 var title = false;
225 var message = false;
226 var severity = element.severity;
227 if (element.title) {
228 title = element.title;
229 }
230 if (element.message) {
231 message = element.message;
232 }
233 self.addMessage(severity, title, message);
234 });
235 },
236
237 /**
238 * Show an action button
239 *
240 * @param button
241 */
242 showActionButton: function(button) {
243 var title = false;
244 var action = false;
245 if (button.title) {
246 title = button.title;
247 }
248 if (button.action) {
249 action = button.action;
250 }
251 var domButton = this.buttonTemplate;
252 if (action) {
253 domButton.data('action', action);
254 }
255 if (title) {
256 domButton.text(title);
257 }
258 this.currentModal.find(this.selectorOutput).append(domButton);
259 },
260
261 /**
262 * Show a status message
263 *
264 * @param severity
265 * @param title
266 * @param message
267 */
268 addMessage: function(severity, title, message) {
269 var domMessage = FlashMessage.render(severity, title, message);
270 this.currentModal.find(this.selectorOutput).append(domMessage);
271 }
272 };
273 });