PluginProbe
UpdraftCentral Dashboard / 0.8.26
UpdraftCentral Dashboard v0.8.26
0.8.33 0.7.2 0.7.3 0.7.4 0.8.0 0.8.1 0.8.10 0.8.11 0.8.12 0.8.13 0.8.14 0.8.15 0.8.16 0.8.17 0.8.18 0.8.19 0.8.2 0.8.20 0.8.21 0.8.22 0.8.23 0.8.24 0.8.25 0.8.26 0.8.27 All 51 releases
updraftcentral / modules / updraftplus / updraftplus.js

updraftplus.js in UpdraftCentral Dashboard 0.8.26, at modules/updraftplus/updraftplus.js

2,760 lines 121.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 jQuery(function($) {
2 UpdraftCentral_Module_UpdraftPlus = new UpdraftCentral_UpdraftPlus_Module();
3
4 // To allow labelauty remote storage buttons to be used with keyboard
5 jQuery(document).on('keyup', function(event) {
6 if (event.keyCode === 32 || event.keyCode === 13) {
7 if (jQuery(document.activeElement).is("input.labelauty + label")) {
8 var for_box = jQuery(document.activeElement).attr("for");
9 if (for_box) {
10 jQuery("#"+for_box).trigger('change');
11 }
12 }
13 }
14 });
15
16 /*
17 * Handlebars helper function to replace all password chars into asterisk char
18 *
19 * @param {string} password Required. The plain-text password
20 *
21 * @return {string}
22 */
23 Handlebars.registerHelper('maskPassword', function(password) {
24 return password.replace(/./gi,'*');
25 });
26
27 /*
28 * Handlebars helper function that wraps javascript encodeURIComponent so that it could encode the following characters: , / ? : @ & = + $ #
29 *
30 * @param {string} uri Required. The URI to be encoded
31 */
32 Handlebars.registerHelper('encodeURIComponent', function(uri) {
33 return encodeURIComponent(uri);
34 });
35
36 /**
37 * Handlebars helper function to compare two values using a specifed operator
38 *
39 * @see https://stackoverflow.com/questions/8853396/logical-operator-in-a-handlebars-js-if-conditional#answer-16315366
40 *
41 * @param {mixed} v1 the first value to compare
42 * @param {mixed} v2 the second value to compare
43 *
44 * @return {boolean} true if the first value matched against the second value, false otherwise
45 */
46 Handlebars.registerHelper('ifCond', function(v1, operator, v2, options) {
47 switch (operator) {
48 case '==':
49 return (v1 == v2) ? options.fn(this) : options.inverse(this);
50 case '===':
51 return (v1 === v2) ? options.fn(this) : options.inverse(this);
52 case '!=':
53 return (v1 != v2) ? options.fn(this) : options.inverse(this);
54 case '!==':
55 return (v1 !== v2) ? options.fn(this) : options.inverse(this);
56 case '<':
57 return (v1 < v2) ? options.fn(this) : options.inverse(this);
58 case '<=':
59 return (v1 <= v2) ? options.fn(this) : options.inverse(this);
60 case '>':
61 return (v1 > v2) ? options.fn(this) : options.inverse(this);
62 case '>=':
63 return (v1 >= v2) ? options.fn(this) : options.inverse(this);
64 case '&&':
65 return (v1 && v2) ? options.fn(this) : options.inverse(this);
66 case '||':
67 return (v1 || v2) ? options.fn(this) : options.inverse(this);
68 case 'typeof':
69 return (v1 === typeof v2) ? options.fn(this) : options.inverse(this);
70 case 'not_typeof':
71 return (v1 !== typeof v2) ? options.fn(this) : options.inverse(this);
72 default:
73 return options.inverse(this);
74 }
75 });
76
77 /**
78 * Handlebars helper function for looping through a block of code a specified number of times
79 *
80 * @param {mixed} from the start value
81 * @param {mixed} to the end value where the loop will stop
82 * @param {mixed} incr the increment number
83 *
84 * @return {mixed} the current processing number
85 */
86 Handlebars.registerHelper('for', function(from, to, incr, block) {
87 var accum = '';
88 for (var i = from; i < to; i += incr)
89 accum += block.fn(i);
90 return accum;
91 });
92
93 /**
94 * Assign value into a variable
95 *
96 * @param {string} name the variable name
97 * @param {mixed} val the value
98 */
99 Handlebars.registerHelper('set_var', function(name, val, options) {
100 if (!options.data.root) {
101 options.data.root = {};
102 }
103 options.data.root[name] = val;
104 });
105
106 /**
107 * Get length of an array/object
108 *
109 * @param {mixed} object the object
110 */
111 Handlebars.registerHelper('get_length', function(object) {
112 if ("undefined" !== typeof object && false === object instanceof Array) {
113 return Object.keys(object).length;
114 } else if (true === object instanceof Array) {
115 return object.length;
116 } else {
117 return 0;
118 }
119 });
120
121 /**
122 * Return a space-separated list of CSS classes suitable for rows in the configuration section
123 *
124 * @see UpdraftPlus_BackupModule::get_css_classes()
125 *
126 * @param {boolean} include_instance a boolean value to indicate if we want to include the instance_id in the css class, we may not want to include the instance if it's for a UI element that we don't want to be removed along with other UI elements that do include a instance id
127 * @return {string} the list of CSS classes
128 */
129 Handlebars.registerHelper('get_template_css_classes', function(include_instance, options) {
130 var css_classes = options.data.root.css_class + ' ' + options.data.root.method_id;
131 if (!include_instance || !options.data.root['is_multi_options_feature_supported']) return css_classes;
132 if (options.data.root['is_config_templates_feature_supported']) {
133 css_classes += ' ' + options.data.root.method_id + '-' + options.data.root.instance_id;
134 } else {
135 css_classes += ' ' + options.data.root.method_id + '-' + options.data.root._instance_id;
136 }
137 return css_classes;
138 });
139
140 /**
141 * Output the value of an id or name attribute, as if currently within an input tag
142 * This assumes standardised options handling (i.e. that the options array is updraft_(method-id))
143 *
144 * @see UpdraftPlus_BackupModule::output_settings_field_name_and_id()
145 *
146 * @param {string} input_attribute The attribute of an input tag
147 * @param {mixed} fields the field identifiers
148 * @return {string} a specific value to the given input attribute
149 */
150 Handlebars.registerHelper('get_template_input_attribute_value', function(input_attribute, fields, options) {
151 var instance_id = options.data.root['is_config_templates_feature_supported'] ? options.data.root.instance_id : options.data.root._instance_id;
152 var id = ename = '';
153 var method_id = options.data.root.method_id;
154 try {
155 fields = JSON.parse(fields);
156 } catch (e) {}
157 if ("undefined" !== typeof fields && Array === fields.constructor) {
158 for (var i=0; i<fields.length; i++) {
159 id += '_' + fields[i];
160 ename += '[' + fields[i] + ']';
161 }
162 } else {
163 id = '_' + fields;
164 ename = '[' + fields + ']';
165 }
166 if ('id' === input_attribute) {
167 return 'updraft_'+method_id+id+'_'+instance_id;
168 } else if ('name' === input_attribute) {
169 return 'updraft_'+method_id+'[settings]['+instance_id+']'+ename;
170 } else {
171 return '';
172 }
173 });
174
175 /**
176 * Return HTML a row of HTML elements for a test button
177 *
178 * @see UpdraftPlus_BackupModule::get_test_button_html()
179 *
180 * @param {string} title The text to be used in the button
181 * @return {string} The HTML to be inserted into the settings page
182 */
183 Handlebars.registerHelper('get_template_test_button_html', function(title, options) {
184 var instance_id = options.data.root['is_config_templates_feature_supported'] ? Handlebars.escapeExpression(options.data.root.instance_id) : Handlebars.escapeExpression(options.data.root._instance_id);
185 var css_classes = Handlebars.escapeExpression(Handlebars.helpers.get_template_css_classes.apply(this, [true, options]));
186 var input_label = Handlebars.escapeExpression(options.data.root.input_test_label);
187 var method_id = Handlebars.escapeExpression(options.data.root.method_id);
188 return '\
189 <tr class="'+css_classes+'"> \
190 <th></th> \
191 <td> \
192 <p> \
193 <button id="updraft-'+method_id+'-test-'+instance_id+'" type="button" class="button-primary updraft-test-button updraft-'+method_id+'-test-'+instance_id+'" data-instance_id="'+instance_id+'" data-method="'+method_id+'" data-method_label="'+title+'">'+input_label+'</button> \
194 </p> \
195 </td> \
196 </tr>';
197 });
198 });
199
200 /**
201 * UpdraftCentral UpdraftPlus Module
202 *
203 * @return {void}
204 */
205 function UpdraftCentral_UpdraftPlus_Module() {
206
207 var $ = jQuery;
208
209 var settings_css_sub_prefix = '.updraftcentral_row_extracontents .updraft_site_settings_output ';
210 var settings_css_prefix = '#updraftcentral_dashboard_existingsites '+settings_css_sub_prefix;
211
212 var backup_listener_ticks = {};
213 var restored_items = new UpdraftCentral_Collection();
214 var selected_items = new UpdraftCentral_Collection();
215 var delete_action = 'single';
216
217 /**
218 * Inserts bulk delete elements (input boxes, bulk delete button) along with the collapsable info
219 * to an existing template pulled from the remote controlled website for the "Existing Backups" section.
220 *
221 * @param {Object} site_row - the jQuery object of the row that the existing backup data was pulled from
222 * @return {void}
223 */
224 function insert_bulk_delete($site_row) {
225 var keys = [];
226 $site_row.find('tr.updraft_existing_backups_row').each(function() {
227 var key = $(this).data('key');
228 var buttons = $(this).find('button.updraft_download_button');
229
230 if (buttons.length) {
231 var container = buttons[0].closest('td');
232 if (-1 === $.inArray(key, keys)) {
233 keys.push(key);
234
235 $(container).prepend('<a class="show-backup-data" data-key="'+key+'"><span class="dashicons dashicons-arrow-right"></span> '+udclion.updraftplus.select_backup_data+'</a>');
236 $(container).find('button.updraft_download_button').wrapAll('<span class="backup-data-'+key+' hide-backup-data"></span>');
237 }
238 }
239 });
240
241 UpdraftCentral.register_event_handler('click', 'a.show-backup-data', function() {
242 var key = $(this).data('key');
243
244 $(this).find('span.dashicons').toggleClass('dashicons-arrow-right dashicons-arrow-down');
245 $(this).parent().find('.backup-label-container-'+key).toggleClass('hide-backup-data');
246 $(this).parent().find('.backup-data-'+key).toggleClass('hide-backup-data');
247 });
248
249 var $backup_date_label = $site_row.find('.updraftcentral_row_extracontents div.backup_date_label');
250 if (!$backup_date_label.length) {
251 $site_row.find('.updraftcentral_row_extracontents td.updraft_existingbackup_date').each(function() {
252 var backup_item = $(this);
253 backup_item.wrapInner('<div class="backup_date_label"></div>');
254 });
255
256 $backup_date_label = $site_row.find('.updraftcentral_row_extracontents div.backup_date_label');
257 }
258
259 if ($backup_date_label.length) {
260 $backup_date_label.prepend('<div class="delete-backup-container"><input type="checkbox" class="delete_backup_item" name="delete_backup" value="1" /></div>');
261
262 var $backup_container = $site_row.find('.updraftcentral_row_extracontents div.updraft_existing_backups');
263 $backup_container.append('<button id="btn-backup-bulk-delete" class="btn btn-secondary">'+udclion.updraftplus.delete_selected+'</button>');
264 }
265
266 // Adding new columns for backup label and storage
267 insert_storage_column($site_row);
268 insert_label_column($site_row);
269 }
270
271 /**
272 * Inserts column to the existing backups table
273 *
274 * @param {Object} $site_row The jQuery object of the row that the existing backup data was pulled from
275 * @param {String} column The desired column name
276 * @param {Boolean} [add_class] Optional - A flag whether to add the 'updraft_existingbackup_data' class.
277 * @return {Object} jQuery object representing the backups table
278 */
279 function insert_existingbackup_column($site_row, column, add_class) {
280 var $table = $site_row.find('.updraftcentral_row_extracontents table.existing-backups-table');
281 var $header = $table.find('thead th.backup-date');
282 var $content = $table.find('tbody td.updraft_existingbackup_date');
283 if ('undefined' !== typeof add_class && add_class) $content.next('td').attr('class', 'updraft_existingbackup_data');
284
285 $('<th class="backup-'+column+'">'+udclion.updraftplus.backup+' '+column+'</th>').insertAfter($header);
286 $('<td class="updraft_existingbackup_'+column+'"></td>').insertAfter($content);
287
288 return $table;
289 }
290
291 /**
292 * Inserts the storage column
293 *
294 * @param {Object} $site_row The jQuery object of the row that the existing backup data was pulled from
295 * @return {void}
296 */
297 function insert_storage_column($site_row) {
298 $table = insert_existingbackup_column($site_row, 'storage', true);
299 $table.find('tr.updraft_existing_backups_row').each(function() {
300 var $tr = $(this);
301 $tr.find('.backup_date_label img.stored_icon').each(function() {
302 $(this).appendTo($tr.find('td.updraft_existingbackup_storage'));
303 });
304 });
305 }
306
307 /**
308 * Inserts the label column
309 *
310 * @param {Object} $site_row The jQuery object of the row that the existing backup data was pulled from
311 * @return {void}
312 */
313 function insert_label_column($site_row) {
314 var $table = $site_row.find('.updraftcentral_row_extracontents table.existing-backups-table');
315 $table.find('tr.updraft_existing_backups_row').each(function() {
316 var $tr = $(this);
317 var $show_backup_data = $tr.find('td.updraft_existingbackup_data a.show-backup-data');
318 var class_name = 'backup-label-container-'+$show_backup_data.data('key');
319 $('<div class="'+class_name+' hide-backup-data"></div>').insertAfter($show_backup_data);
320
321 $tr.find('.backup_date_label br').wrap('<span></span>');
322 $tr.find('.backup_date_label .clear-right ~ span').appendTo($tr.find('div.'+class_name));
323 });
324 }
325
326 // Backup now listeners
327
328 /**
329 * Listener function for handling "Backup Now" listeners
330 *
331 * @param {Object} site_listener_row - the jQuery object of the row of the listener
332 * @param {Object} site_row - the jQuery object of the row that the backup is for
333 * @param {number} site_id - the site ID of the site that the backup is for
334 *
335 * @return {void}
336 */
337 function listener_processor_updraftplus_backup(site_listener_row, site_row, site_id) {
338
339 if ($(site_listener_row).find('.updraft_finished').length > 0) {
340 if (UpdraftCentral.get_debug_level() > 1) {
341 console.log("UDCentral: UpdraftPlus backup listener: job finished");
342 }
343 // This means, "finished, and close it after a delay")
344 return 0;
345 }
346
347 var job_id = $(site_listener_row).data('job_id');
348
349 if (!backup_listener_ticks.hasOwnProperty(job_id)) { backup_listener_ticks[job_id] = 0; }
350
351 backup_listener_ticks[job_id]++;
352
353 if (backup_listener_ticks[job_id] < 30 || 0 == backup_listener_ticks[job_id] % 3) {
354 return { call: 'updraftplus.backup_progress', data: { job_id: job_id } };
355 } else {
356 // Means "do nothing, but not because we're finished"
357 return null;
358 }
359 }
360
361 /**
362 * Listener function for handling "Backup Now" listener results
363 *
364 * @param {Object} site_listener_row - the jQuery object of the row of the listener
365 * @param {Object} site_row - the jQuery object of the row that the backup is for
366 * @param {number} site_id - the site ID of the site that the backup is for
367 * @param {*} data - the data returned by the remote call to get the backup progress
368 *
369 * @return {void}
370 */
371 function result_listener_processor_updraftplus_backup_progress(site_listener_row, site_row, site_id, data) {
372 var output = '';
373 if (data.hasOwnProperty('l')) {
374 output += '<strong>'+udclion.updraftplus.lastlogline+':</strong> '+data.l+'<br>';
375 }
376 if (data.hasOwnProperty('j')) {
377 output += data.j;
378 }
379 $(site_listener_row).find('.backup_state:first').html(UpdraftCentral_Library.sanitize_html(output));
380
381 // here we get the attributes that come with the response and make our own progressbar using bootstrap's one.
382 var info = (jQuery.type($(site_listener_row).find('.updraft_percentage').data('info')) === "undefined" ) ? udclion.updraftplus.missing_data_attributes : UpdraftCentral_Library.sanitize_html($(site_listener_row).find('.updraft_percentage').data('info'));
383 var stage = (jQuery.type($(site_listener_row).find('.updraft_percentage').data('progress')) === "undefined" ) ? '0' : UpdraftCentral_Library.quote_attribute($(site_listener_row).find('.updraft_percentage').data('progress'));
384
385 var html_to_show = "<div class='text-center' id='info"+site_id+"'>"+info+"</div>";
386 html_to_show +="<progress class='progress progress-updraftcentral' value='"+stage+"' max='100' ></progress>";
387
388 $(site_listener_row).find('.curstage').html(html_to_show);
389 }
390 UpdraftCentral.register_listener_processor('updraftplus_backup', listener_processor_updraftplus_backup);
391 UpdraftCentral.register_listener_processor('updraftplus.backup_progress', result_listener_processor_updraftplus_backup_progress);
392
393 /**
394 * A listener function for feeding back on what downloads need monitoring
395 *
396 * @param {Object} site_listener_row - jQuery object of the listener row involved
397 * @param {Object} site_row - jQuery object of the site row of the site involved
398 * @param {number} site_id - the site ID (an integer)
399 *
400 * @return {void}
401 */
402 function listener_processor_updraftplus_download(site_listener_row, site_row, site_id) {
403
404 var items = [];
405 var all_finished = null;
406 $(site_listener_row).find('.updraftplus_downloader').each(function(index, item) {
407 if ($(item).data('updraft_finished')) {
408 if (null === all_finished) { all_finished = true; }
409 } else {
410 all_finished = false;
411 }
412 var findex = $(item).data('findex');
413 var what = $(item).data('what');
414 var backup_timestamp = $(item).data('backup_timestamp');
415 // <base(arbitrary - put anything you want returned)>,<timestamp>,<type>(,<findex>)
416 items.push(site_id+','+backup_timestamp+','+what+','+findex);
417 });
418
419 if (all_finished) {
420 console.log("UDCentral: UpdraftPlus download listener: job finished - will not poll any more");
421 // 1 means "don't poll this any more, but don't close it either"
422 return 1;
423 }
424
425 return { call: 'updraftplus.get_download_status', data: items };
426 }
427
428 /**
429 * Update the listener(s) with the returned download info
430 *
431 * @param {Object} status - an object with various properties corresponding to the download state as returned by UD
432 *
433 * @return {number} - whether to not bother with polling again (advisory)
434 */
435 function updraft_downloader_status_update(status) {
436
437 var site_id = status.base;
438 var fullpath = status.f;
439 var findex = status.findex;
440 var message = status.m;
441 var percent = status.hasOwnProperty('p') ? status.p : null;
442 var size_downloaded = status.s;
443 var total_size = status.t;
444 var backup_timestamp = status.timestamp;
445 var what = status.what;
446
447 var stid = site_id+'_'+backup_timestamp+'_'+what+'_'+findex;
448 var stid_selector = '#updraftcentral_notice_container .'+stid;
449
450 var cancel_repeat = 0;
451
452 if (status.hasOwnProperty('failed') && status.failed) {
453 $(stid_selector).data('updraft_finished', true);
454 }
455
456 if (status.hasOwnProperty('e') && status.e) {
457 $(stid_selector+' .raw').html('<strong>'+udclion.error+':</strong> '+status.e);
458 console.log("UDCentral: UpdraftPlus: downloader ("+stid+"): an error was returned (follows)");
459 console.log(status);
460 } else if (status.p !== null) {
461 $(stid_selector+'_st .dlfileprogress').width(status.p+'%');
462 // Is a restart appropriate?
463 // status.a, if set, indicates that a) the download is incomplete and b) the value is the number of seconds since the file was last modified...
464 if (status.a != null && status.a > 0) {
465
466 var time_now = (new Date).getTime();
467
468 var last_time_began = $(stid_selector).data('last_time_began');
469 // Remember that this is in milliseconds
470 var since_last_restart = time_now - last_time_began;
471
472 if (status.a > 90 && since_last_restart > 60000) {
473 console.log("UDCentral: UpdraftPlus: "+stid+": restarting download: file_age="+status.a+", since_last_restart_ms="+since_last_restart);
474
475 var downloader_params = {
476 type: what,
477 timestamp: backup_timestamp,
478 findex: findex
479 };
480
481 var $site_row = $('#updraftcentral_dashboard_existingsites .updraftcentral_site_row[data-site_id="'+site_id+'"');
482
483 // We set this, regardless of success/failure, because we don't want to send the same request multiple times, whether it succeeds or not, until an interval has passed
484 $(stid_selector).data('last_time_began', (new Date).getTime());
485
486 // We don't do anything with a positive result, in terms of creating listeners, etc., because those already exist
487 UpdraftCentral.send_site_rpc('updraftplus.downloader', downloader_params, $site_row, function(response, code, error_code) {
488 if ('ok' != code) {
489 $(stid_selector+' .raw').html(udclion.updraftplus.backup_start_failed);
490 console.log("code="+code+", error_code="+error_code);
491 console.log(response);
492 }
493 });
494
495 }
496 }
497
498 if (status.hasOwnProperty('m') && status.m != null) {
499
500 if (status.p < 100) {
501 $(stid_selector+' .raw').html(status.m);
502 } else {
503
504 msg = template_replace('updraftplus-downloaded', {
505 file_ready: udclion.updraftplus.file_ready,
506 download_to_computer: udclion.updraftplus.download_to_computer,
507 and_then: udclion.updraftplus.and_then,
508 you_should: udclion.updraftplus.you_should,
509 backup_timestamp: backup_timestamp,
510 site_id: site_id,
511 what: what,
512 findex: findex,
513 delete_from_server: udclion.updraftplus.delete_from_server
514 });
515 $(stid_selector).data('updraft_finished', true);
516 $(stid_selector+' .raw').html(msg);
517 }
518 }
519
520 // dlstatus_lastlog = response;
521 } else if (status.m != null) {
522 $(stid_selector+' .raw').html(status.m);
523 } else {
524 $(stid_selector+' .raw').html(udclion.updraftplus.backup_start_failed);
525 cancel_repeat = 1;
526 }
527 return cancel_repeat;
528 }
529
530 /**
531 * Process the results of the request for updates on the download status
532 *
533 * @param {Object} site_listener_row - jQuery object for the listener that made the request (not used)
534 * @param {Object} site_row - jQuery object for the site that the request was to (not used)
535 * @param {number} site_id - the site ID for the site that the request was to (not used)
536 * @param {array} data - the returned download statuses (one array member for each downloader that information was requested on)
537 *
538 * @return {void}
539 */
540 function result_listener_processor_updraftplus_get_download_status(site_listener_row, site_row, site_id, data) {
541 $.each(data, function(index, status) {
542 // Though the site_id is returned by UpdraftCentral's listener handling, it also comes back in the result - so, we don't need to pass anything on
543 if (status.hasOwnProperty('base')) {
544 var cancel_repeat = updraft_downloader_status_update(status);
545 }
546 });
547 }
548 UpdraftCentral.register_listener_processor('updraftplus_download', listener_processor_updraftplus_download);
549 UpdraftCentral.register_listener_processor('updraftplus.get_download_status', result_listener_processor_updraftplus_get_download_status);
550
551 /**
552 * Opens the dialog box for starting a "Backup Now" backup, via fetching the dialog contents (so that we get the relevant options) from the remote site
553 *
554 * @param {boolean} backupnow_nodb - indicate whether to exclude the database from the backup
555 * @param {boolean} backupnow_nofiles - indicate whether to exclude the files from the backup
556 * @param {boolean} backupnow_nocloud - indicate whether to skip sending the backup to any configured remote destination
557 * @param {string} [onlythesefileentities] - a comma-separated list of file entities to back up (only relevant if files are being backed up)
558 * @param {String} [onlythesetableentities] a comma-separated list of table entities to back up (only relevant if databases are being backed up)
559 * @param {*} [extradata] - arbitrary extra data to send with the backup request (though, of course, only relevant data will have any effect)
560 * @param {string} [label] - a label to give to the backup
561 * @param {String} onlythesecloudservices An array of remote sorage locations to be backed up to
562 *
563 * @return {void}
564 */
565 this.backupnow_go = function(backupnow_nodb, backupnow_nofiles, backupnow_nocloud, onlythesefileentities, extradata, label, onlythesetableentities, onlythesecloudservices) {
566
567 var listener_title;
568 if (extradata && extradata.hasOwnProperty('_listener_title')) {
569 listener_title = extradata._listener_title;
570 delete extradata._listener_title;
571 }
572
573 var params = {
574 backupnow_nodb: backupnow_nodb,
575 backupnow_nofiles: backupnow_nofiles,
576 backupnow_nocloud: backupnow_nocloud,
577 backupnow_label: label,
578 extradata: extradata
579 };
580
581 if ('' != onlythesefileentities) {
582 params.onlythisfileentity = onlythesefileentities;
583 }
584
585 if ('' != onlythesetableentities) {
586 params.onlythesetableentities = onlythesetableentities;
587 }
588
589 if ('' != onlythesecloudservices) {
590 params.onlythesecloudservices = onlythesecloudservices;
591 }
592
593 params.always_keep = (typeof extradata.always_keep !== 'undefined') ? extradata.always_keep : 0;
594
595 params.incremental = (typeof extradata.incremental !== 'undefined') ? extradata.incremental : 0;
596
597 UpdraftCentral.send_site_rpc('updraftplus.backupnow', params, UpdraftCentral.$site_row, function(response, code, error_code) {
598 if ('ok' == code && false !== response && response.hasOwnProperty('data')) {
599 if (response.data.hasOwnProperty('nonce')) {
600
601 var listener_message = '<div class="backup_state">'+udclion.updraftplus.backupstarted +'</div>';
602
603 var job_id = response.data.nonce;
604 backup_listener_ticks[job_id] = 0;
605
606 UpdraftCentral.create_dashboard_listener('updraftplus_backup', UpdraftCentral.$site_row, listener_message, { job_id: response.data.nonce }, listener_title);
607
608 } else {
609 UpdraftCentral.add_dashboard_notice('<h2>'+UpdraftCentral.$site_row.data('site_description')+'</h2>'+udclion.updraftplus.backup_start_failed, 'error');
610 }
611 }
612 });
613
614 }
615
616 /**
617 * Create a download listener
618 *
619 * @param {number} site_id - the ID of the site that the downloader is for
620 * @param {number} backup_timestamp - the epoch time of the backup
621 * @param {string} what - the entity name to download (e.g. "plugins")
622 * @param {string} set_contents - comma-separated list of indexes corresponding to files to download
623 * @param {string} pretty_date - the formatted date of the backup
624 * @param {boolean} async - (unused; future possibility) whether to send the request asynchronously, or not
625 * @param {Object} spinner_where - a jQuery object indicating where to place the spinner
626 *
627 * @return {void}
628 */
629 function updraft_downloader(site_id, backup_timestamp, what, set_contents, pretty_date, async, spinner_where) {
630
631 if (typeof set_contents !== "string") set_contents = set_contents.toString();
632 async = async ? true : false;
633
634 set_contents = set_contents.split(',');
635
636 // If there's an existing listener downloading from this site, then add our widget to it instead of creating another.
637 var $listener = $('#updraftcentral_notice_container .updraftcentral_listener_updraftplus_download[data-site_id="'+site_id+'"');
638 if ($listener.length == 0) { $listener = false; }
639
640 for (var i=0; i<set_contents.length; i++) {
641
642 // Create somewhere for the status to be found
643
644 var findex = set_contents[i];
645 var stid = site_id+'_'+backup_timestamp+'_'+what+'_'+findex;
646 var stid_selector = '.'+stid;
647
648 if ($(stid_selector).length) {
649 console.log("UDCentral: There already appears to be an active downloader for this entity (stid: "+stid+")");
650 return;
651 }
652
653 // Now send the actual request to kick it all off
654
655 var downloader_params = {
656 type: what,
657 timestamp: backup_timestamp,
658 findex: findex
659 };
660
661 UpdraftCentral.send_site_rpc('updraftplus.downloader', downloader_params, UpdraftCentral.$site_row, function(response, code, error_code) {
662 if ('ok' == code && false !== response && response.hasOwnProperty('data') && response.data.hasOwnProperty('result')) {
663
664 var result = response.data.result;
665 var request = response.data.request;
666
667 var backup_timestamp = request.timestamp;
668 var what = request.type;
669 var findex = parseInt(request.findex);
670
671 var stid = site_id+'_'+backup_timestamp+'_'+what+'_'+findex;
672 var stid_selector = '.'+stid;
673
674 var msg = '??';
675
676 var last_time_began = (new Date).getTime();
677
678 var show_index = findex+1;
679 var itext = (findex == 0) ? '' : ' ('+show_index+')';
680 var prdate = (pretty_date) ? pretty_date : backup_timestamp;
681
682 // This is the parent object, that contains the results. The updated results go into div.raw within this.
683 widgets_html = template_replace('updraftplus-downloader', {
684 stid: stid,
685 download_verb: udclion.updraftplus.download_verb,
686 what: what,
687 itext: itext,
688 pretty_date: prdate,
689 begun_looking: udclion.updraftplus.begun_looking,
690 site_id: site_id,
691 backup_timestamp: backup_timestamp,
692 findex: findex
693 });
694
695 // deleted|downloaded|needs_download|download_failed
696 if ('downloaded' == result) {
697 msg = template_replace('updraftplus-downloaded', {
698 file_ready: udclion.updraftplus.file_ready,
699 download_to_computer: udclion.updraftplus.download_to_computer,
700 and_then: udclion.updraftplus.and_then,
701 you_should: udclion.updraftplus.you_should,
702 backup_timestamp: backup_timestamp,
703 site_id: site_id,
704 what: what,
705 findex: findex,
706 delete_from_server: udclion.updraftplus.delete_from_server
707 });
708 } else if ('needs_download' == result) {
709 msg = udclion.updraftplus.needs_download;
710 } else if ('download_failed' == result) {
711 msg = udclion.updraftplus.download_failed;
712 }
713
714 if (false === $listener) {
715 $listener = UpdraftCentral.create_dashboard_listener('updraftplus_download', UpdraftCentral.$site_row, widgets_html);
716 } else {
717 // Add a new widget into that listener
718 $listener.append(widgets_html);
719 }
720 // If it was already marked as 'finished', then it won't be polled - we want it to start being polled again
721 $listener.data('finished', false);
722 $listener.find(stid_selector).data('last_time_began', last_time_began);
723 $listener.find(stid_selector+' .raw').html(msg);
724
725
726 } else {
727 UpdraftCentral.add_dashboard_notice('<h2>'+UpdraftCentral.$site_row.data('site_description')+'</h2>'+udclion.updraftplus.download_start_failed, 'error');
728 }
729 });
730
731 }
732 }
733
734 var updraftplus_morefiles_lastind = 0;
735 var updraftplus_version = 0;
736
737 /**
738 * Get the "Settings" panel from the remote UpdraftPlus
739 *
740 * @param {Object} $site_row - jQuery object for the row of the site for which the information is being requested
741 *
742 * @return {void}
743 */
744 function updraft_get_existing_backup_settings($site_row) {
745
746 $site_row.find('.updraftcentral_row_extracontents').css('opacity', '0.3');
747
748 UpdraftCentral.send_site_rpc('updraftplus.get_settings', {
749 include_database_decrypter: 0,
750 include_adverts: 0,
751 include_save_button: 1
752 }, $site_row, function(response, code, error_code) {
753 $site_row.find('.updraftcentral_row_extracontents').css('opacity', '1.0');
754 if ('ok' == code && response) {
755 $site_row.find('.updraftcentral_row_extracontents').html('<div class="updraft_site_settings_output"><button class="btn btn-refresh updraftcentral_site_backup_settings"><span class="dashicons dashicons-image-rotate "></span></button>'+UpdraftCentral_Library.sanitize_html(response.data.settings)+'</div>');
756 update_additional_path_description();
757 if (response.data.hasOwnProperty('remote_storage_templates') && response.data.hasOwnProperty('remote_storage_options')) {
758 var html = '',
759 option = null,
760 not_instance_ids = ['default', 'template_properties'];
761 for (var method in response.data.remote_storage_templates) {
762 option = response.data.remote_storage_options[method];
763
764 // Using "typeof" with an array returns 'object', thus we need to make sure that
765 // the item that gets pass through here has a "default" property with type object.
766 // the if statement below uses a different approach than the one on UDP plugin, it determines whether a storage method has an instance by checking the data type of its 'default' variable, if it's an object then surely it must have an instance.
767 // On UDP plugin, we check the length of the option/response.data.remote_storage_options[method] variable, if it contains more than one property, then instance setting must be one of them
768 if ('undefined' != typeof option && !Array.isArray(option.default) && 'object' === typeof option.default) {
769 var template = Handlebars.compile(response.data.remote_storage_templates[method]);
770 if (response.data.hasOwnProperty('remote_storage_partial_templates')) {
771 for (var partial_template_name in response.data.remote_storage_partial_templates[method]) {
772 Handlebars.registerPartial(partial_template_name, Handlebars.compile(response.data.remote_storage_partial_templates[method][partial_template_name]));
773 }
774 }
775 var first_instance = true,
776 template_properties = response.data.remote_storage_options[method]['template_properties'] || {};
777 for (var instance_id in response.data.remote_storage_options[method]) {
778 if (not_instance_ids.indexOf(instance_id) > -1) continue;
779 var context = {}; // Initiate a reference by assigning an empty object to a variable (in this case the context variable) so that it can be used as a target of merging one or more other objects. Unlike basic values (boolean, string, integer, etc.), in Javascript objects and arrays are passed by reference
780 // copy what are in the template properties to the context overwriting the same object properties, and then copy what are in the instance settings to the context overwriting all the same properties from the previous merging operation (if any). The context properties are overwritten by other objects that have the same properties later in the parameters order
781 Object.assign(context, template_properties, response.data.remote_storage_options[method][instance_id]);
782
783 if ('undefined' == typeof context['instance_conditional_logic']) {
784 context['instance_conditional_logic'] = {
785 type: '', // always by default
786 rules: [],
787 };
788 }
789 context['instance_conditional_logic'].day_of_the_week_options = udclion.updraftplus.conditional_logic.day_of_the_week_options;
790 context['instance_conditional_logic'].logic_options = udclion.updraftplus.conditional_logic.logic_options;
791 context['instance_conditional_logic'].operand_options = udclion.updraftplus.conditional_logic.operand_options;
792 context['instance_conditional_logic'].operator_options = udclion.updraftplus.conditional_logic.operator_options;
793
794 context['first_instance'] = first_instance;
795 if ('undefined' == typeof context['instance_enabled']) {
796 context['instance_enabled'] = 1;
797 }
798 html += template(context);
799 first_instance = false;
800 }
801 } else {
802 html += response.data.remote_storage_templates[method];
803 }
804 }
805 $('#remote-storage-holder').append(html);
806 }
807
808 $('.updraftcentral_row_extracontents #remote-storage-holder').on('click', '.updraftplusmethod a.updraft_add_instance', function(e) {
809 e.preventDefault();
810
811 var method = $(this).data('method');
812 add_new_instance(method);
813 });
814
815 $('.updraftcentral_row_extracontents #remote-storage-holder').on('click', '.updraftplusmethod a.updraft_delete_instance', function(e) {
816 e.preventDefault();
817
818 var method = $(this).data('method');
819 var instance_id = $(this).data('instance_id');
820
821 if (1 === $('.' + method + '_updraft_remote_storage_border').length) {
822 add_new_instance(method);
823 }
824
825 $('.' + method + '-' + instance_id).hide('slow', function() {
826 $(this).remove();
827 });
828 });
829
830 /**
831 * This method will get the default options and compile a template with them
832 *
833 * @param {string} method - the remote storage name
834 * @param {boolean} first_instance - indicates if this is the first instance of this type
835 */
836 function add_new_instance(method) {
837 var template = Handlebars.compile(response.data.remote_storage_templates[method]),
838 template_properties = response.data.remote_storage_options[method]['template_properties'] || {},
839 method_name,
840 context = {}; // Initiate a reference by assigning an empty object to a variable (in this case the context variable) so that it can be used as a target of merging one or more other objects. Unlike basic values (boolean, string, integer, etc.), in Javascript objects and arrays are passed by reference
841 // copy what are in the template properties to the context overwriting the same object properties, and then copy what are in the default instance settings to the context overwriting all the same properties from the previous merging opeartion (if any). The context properties are overwritten by other objects that have the same properties later in the parameters order
842 Object.assign(context, template_properties, response.data.remote_storage_options[method]['default']);
843 method_name = context.method_display_name || '';
844 if ('' != method_name) method_name += ' ';
845
846 context['instance_id'] = 's-' + generate_instance_id(32);
847 context['instance_enabled'] = 1;
848 context['instance_label'] = method_name + '(' + (jQuery('.updraftcentral_row_extracontents #remote-storage-holder .' + method + '_updraft_remote_storage_border').length + 1) + ')';
849 context['instance_conditional_logic'] = {
850 type: '', // always by default
851 rules: [],
852 day_of_the_week_options: udclion.updraftplus.conditional_logic.day_of_the_week_options,
853 logic_options: udclion.updraftplus.conditional_logic.logic_options,
854 operand_options: udclion.updraftplus.conditional_logic.operand_options,
855 operator_options: udclion.updraftplus.conditional_logic.operator_options,
856 };
857 var html = template(context);
858 $(html).hide().insertAfter('.' + method + '_add_instance_container:first').show('slow');
859
860 maybe_insert_remote_label(method, context['instance_id']);
861 }
862
863 /**
864 * This method will return a random instance id string
865 *
866 * @param {integer} length - the length of the string to be generated
867 *
868 * @return string - the instance id
869 */
870 function generate_instance_id(length) {
871 var uuid = '';
872 var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
873
874 for (var i = 0; i < length; i++) {
875 uuid += characters.charAt(Math.floor(Math.random() * characters.length));
876 }
877
878 return uuid;
879 }
880
881 $('.updraftcentral_row_extracontents #remote-storage-holder').on("change", "input[class='updraft_instance_toggle']", function () {
882 if ($(this).is(':checked')) {
883 $(this).siblings('label').html(udclion.updraftplus.instance_enabled);
884 } else {
885 $(this).siblings('label').html(udclion.updraftplus.instance_disabled);
886 }
887 });
888
889 jQuery('.updraftcentral_row_extracontents #remote-storage-holder').on("change", "select[class='logic_type']", function () {
890 updraft_settings_form_changed = true;
891 if ('' !== this.value) {
892 jQuery('div.logic', jQuery(this).parents('tr.updraftplusmethod')).show();
893 jQuery(this).parents('tr.updraftplusmethod').find('div.logic ul.rules > li').each(function() {
894 jQuery(this).find('select').each(function() {
895 jQuery(this).prop('disabled', false);
896 })
897 });
898 } else {
899 jQuery(this).parents('tr.updraftplusmethod').find('div.logic ul.rules > li').each(function() {
900 jQuery(this).find('select').each(function() {
901 jQuery(this).prop('disabled', true);
902 })
903 });
904 jQuery(this).parents('tr.updraftplusmethod').find('div.logic').hide();
905 }
906 });
907
908 jQuery('.updraftcentral_row_extracontents #remote-storage-holder').on("change", "select[class='conditional_logic_operand']", function () {
909 updraft_settings_form_changed = true;
910 jQuery(this).parent().find('select:nth(2)').empty();
911 if ('day_of_the_week' === jQuery(this).val()) {
912 for (i=0; i<udclion.updraftplus.conditional_logic.day_of_the_week_options.length; i++) {
913 jQuery(this).parent().find('select:nth(2)').append(jQuery('<option value="'+udclion.updraftplus.conditional_logic.day_of_the_week_options[i].index+'"></option>').text(udclion.updraftplus.conditional_logic.day_of_the_week_options[i].value));
914 }
915 } else if ('day_of_the_month' === jQuery(this).val()) {
916 for (i=1; i<=31; i++) {
917 jQuery(this).parent().find('select:nth(2)').append(jQuery('<option value="'+i+'"></option>').text(i));
918 }
919 }
920 });
921
922 jQuery('.updraftcentral_row_extracontents #remote-storage-holder').on("click", "div.conditional_remote_backup ul.rules li span", function () {
923 updraft_settings_form_changed = true;
924 var $ul = jQuery(this).parents('ul.rules');
925 if (jQuery(this).hasClass('remove-rule')) {
926 jQuery(this).parent().slideUp(function() {
927 jQuery(this).remove();
928 if (jQuery($ul).find('> li').length < 2) {
929 jQuery('li:nth(0) span.remove-rule', $ul).remove();
930 }
931 });
932 }
933 });
934
935 jQuery('.updraftcentral_row_extracontents #remote-storage-holder').on('click', '.updraftplusmethod .updraft_edit_label_instance', function(e) {
936 if ('true' === jQuery(this).data('is-editing')) return;
937 var input = jQuery('<input type="text" class="updraft_edit_label_instance">');
938 input.val(jQuery(this).text());
939 jQuery(this).text('');
940 input.data('instance_id', jQuery(this).data('instance_id'));
941 input.data('method', jQuery(this).data('method'));
942 input.appendTo(jQuery(this));
943 input.trigger('focus');
944 jQuery(this).data('is-editing', 'true');
945 });
946
947 $('.updraftcentral_row_extracontents #remote-storage-holder').on('keyup', '.updraftplusmethod input.updraft_edit_label_instance', function(e) {
948 var method = jQuery(this).data('method');
949 var instance_id = jQuery(this).data('instance_id');
950 var content = jQuery(this).val();
951
952 $('#updraft_' + method + '_instance_label_' + instance_id).val(content);
953 });
954
955 jQuery('.updraftcentral_row_extracontents #remote-storage-holder').on('blur', '.updraftplusmethod input.updraft_edit_label_instance', function(e) {
956 jQuery(this).parent().append(jQuery(this).val()+'<span class="dashicons dashicons-edit"></span>');
957 jQuery(this).parent().data('is-editing', 'false');
958 jQuery(this).remove();
959 });
960
961 $('.updraftcentral_row_extracontents #remote-storage-holder').on('keypress', '.updraftplusmethod input.updraft_edit_label_instance', function(e) {
962 if (13 === e.which) {
963 $(this).trigger('blur');
964 }
965 });
966
967 jQuery('.updraftcentral_row_extracontents #remote-storage-holder').on("click", "div.conditional_remote_backup input.add-new-rule", function () {
968 var $ul = jQuery(this).parent().find('ul.rules');
969 if (jQuery($ul).find('> li').length < 2) {
970 jQuery($ul).find('li:nth(0)').append('<span class="remove-rule"><svg viewbox="0 0 25 25"><line x1="6.5" y1="18.5" x2="18.5" y2="6.5" fill="none" stroke="#FF6347" stroke-width="3" vector-effect="non-scaling-stroke" ></line><line y1="6.5" x1="6.5" y2="18.5" x2="18.5" fill="none" stroke="#FF6347" stroke-width="3" vector-effect="non-scaling-stroke" ></line></svg></span>');
971 }
972 $cloned_item = jQuery($ul).find('> li').last().clone();
973 jQuery($cloned_item).find('> select').each(function() {
974 jQuery(this).prop('name', jQuery(this).prop('name').replace(/\[instance_conditional_logic\]\[rules\]\[[0-9]+\]/gi, '[instance_conditional_logic][rules]['+jQuery($ul).data('rules')+']'));
975 });
976 jQuery($ul).append($cloned_item);
977 jQuery($ul).data('rules', parseInt(jQuery($ul).data('rules')) + 1);
978 jQuery($cloned_item).find('select[name*="[operand]"]').trigger('change');
979 });
980
981 /**
982 * For some reason, the google caja sanitizer is removing the "aria-label" attribute or is currently
983 * not supported. The "aria-label" is intended for accessibility and used by the labelauty to update the label
984 * tag's attribute. Thus, we're rebuilding the aria-label attribute based from the value of the checkbox element
985 * to restore the lost keyboard support (e.g. tab, etc.)
986 */
987 $site_row.find('.updraftcentral_row_extracontents #remote-storage-container > input[type="checkbox"]').each(function() {
988 var input = jQuery(this);
989 input.attr('aria-label', udclion.updraftplus.backup_using + ' ' + input.val() + '?');
990 });
991
992
993 // Set the initial state of the schedule selection text and widgetry
994 updraft_check_same_times();
995
996 updraft_remote_storage_tabs_setup();
997
998 updraft_extra_dbs = 0;
999 updraftplus_morefiles_lastind = 0;
1000
1001 if (response.data.hasOwnProperty('meta')) {
1002
1003 var meta = response.data.meta;
1004
1005 if (meta.hasOwnProperty('retain_rules') && meta.retain_rules.hasOwnProperty('files')) {
1006 setup_retain_rules(meta.retain_rules.files, meta.retain_rules.db);
1007 }
1008
1009 if (meta.hasOwnProperty('extra_dbs')) {
1010 $.each(meta.extra_dbs, function(i, db) {
1011 if (db.hasOwnProperty('host')) {
1012 extradbs_add(db.host, db.user, db.name, db.pass, db.prefix);
1013 }
1014 });
1015 }
1016 }
1017
1018 if (response.data.hasOwnProperty('updraftplus_version')) {
1019 updraftplus_version = response.data.updraftplus_version;
1020 }
1021
1022 setup_file_entity_exclude_field('uploads');
1023 setup_file_entity_exclude_field('others');
1024 setup_file_entity_exclude_field('wpcore');
1025
1026 reportbox_index = $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output #updraft_report_cell .updraft_reportbox').length + 2;
1027
1028 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output #updraft_include_more_paths input.updraft_include_more_path').each(function(i, input) {
1029 var mp_index = $(input).data(mp_index);
1030 if (mp_index > updraftplus_morefiles_lastind) { updraftplus_morefiles_lastind = mp_index; }
1031 });
1032
1033 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output input[type="submit"]').removeClass().addClass('btn btn-primary-outline');
1034
1035 // Update the WebDAV URL setting as the user edits
1036 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output').on("change keyup paste", '.updraft_webdav_settings', function() {
1037
1038 var updraft_webdav_settings = [];
1039 var instance_id = "";
1040 $('.updraft_webdav_settings').each(function(index, item) {
1041
1042 var id = $(item).attr('id');
1043
1044 // The first part of the "if" is to handle the old options format and can be removed in future
1045 if (id && 'updraft_webdav_settings_' == id.substring(0, 24)) {
1046 var which_one = id.substring(24);
1047 updraft_webdav_settings[which_one] = this.value;
1048 } else if (id && 'updraft_webdav_' == id.substring(0, 15)) {
1049 var which_one = id.substring(15);
1050 id_split = which_one.split('_');
1051 which_one = id_split[0];
1052 instance_id = id_split[1];
1053 if ('undefined' == typeof updraft_webdav_settings[instance_id]) updraft_webdav_settings[instance_id] = [];
1054 updraft_webdav_settings[instance_id][which_one] = this.value;
1055 }
1056
1057 });
1058
1059 var updraft_webdav_url = "";
1060 var host = "@";
1061 var slash = "/";
1062 var colon = ":";
1063 var colon_port = ":";
1064
1065 for (var instance_id in updraft_webdav_settings) {
1066
1067 if (updraft_webdav_settings[instance_id]['host'].indexOf("@") >= 0 || "" === updraft_webdav_settings[instance_id]['host']) {
1068 host = "";
1069 }
1070
1071 if (updraft_webdav_settings[instance_id]['host'].indexOf("/") >= 0 ) {
1072 $('.webdav-'+instance_id+' .updraft_webdav_host_error').show();
1073 } else {
1074 $('.webdav-'+instance_id+' .updraft_webdav_host_error').hide();
1075 }
1076
1077 if (updraft_webdav_settings[instance_id]['path'].indexOf("/") == 0 || "" === updraft_webdav_settings[instance_id]['path']) {
1078 slash = "";
1079 }
1080
1081 if ("" === updraft_webdav_settings[instance_id]['user'] || "" === updraft_webdav_settings[instance_id]['pass']) {
1082 colon = "";
1083 }
1084
1085 if ("" === updraft_webdav_settings[instance_id]['host'] || "" === updraft_webdav_settings[instance_id]['port']) {
1086 colon_port = "";
1087 }
1088
1089 updraft_webdav_url = updraft_webdav_settings[instance_id]['webdav'] + updraft_webdav_settings[instance_id]['user'] + colon + updraft_webdav_settings[instance_id]['pass'] + host + encodeURIComponent(updraft_webdav_settings[instance_id]['host']) + colon_port + updraft_webdav_settings[instance_id]['port'] + slash + updraft_webdav_settings[instance_id]['path'];
1090 masked_webdav_url = updraft_webdav_settings[instance_id]['webdav'] + updraft_webdav_settings[instance_id]['user'] + colon + updraft_webdav_settings[instance_id]['pass'].replace(/./gi, '*') + host + encodeURIComponent(updraft_webdav_settings[instance_id]['host']) + colon_port + updraft_webdav_settings[instance_id]['port'] + slash + updraft_webdav_settings[instance_id]['path'];
1091
1092 // The first part of the "if" is to handle the old options format and can be removed in future
1093 if ("" == instance_id) {
1094 $('#updraftcentral_dashboard .updraft_site_settings_output #updraft_webdav_settings_url').val(updraft_webdav_url);
1095 } else {
1096 $('#updraftcentral_dashboard .updraft_site_settings_output #updraft_webdav_url_' + instance_id).val(updraft_webdav_url);
1097 $('#updraftcentral_dashboard .updraft_site_settings_output #updraft_webdav_masked_url_' + instance_id).val(masked_webdav_url);
1098 }
1099 }
1100 });
1101
1102 }
1103 });
1104 }
1105
1106 var updraft_extra_dbs = 0;
1107 /**
1108 * Add a box for configuring backing of an extra database
1109 *
1110 * @param {string} host - The hostname of the MySQL database to be backed up
1111 * @param {string} user - The MySQL username
1112 * @param {string} name - The name of the MySQL database
1113 * @param {string} pass - The MySQL password
1114 * @param {string} prefix - Only tables prefixed with this string will be backed up. Pass an empty string to back them all up.
1115 *
1116 * @return {void}
1117 */
1118 function extradbs_add(host, user, name, pass, prefix) {
1119 updraft_extra_dbs++;
1120 $(template_replace('updraftplus-settings-extra-db', {
1121 updraft_extra_dbs: updraft_extra_dbs,
1122 remove: udclion.updraftplus.remove,
1123 backup_external_database: udclion.updraftplus.backup_external_database,
1124 host: udclion.updraftplus.host,
1125 database: udclion.updraftplus.database,
1126 username: udclion.updraftplus.username,
1127 password: udclion.updraftplus.password,
1128 table_prefix: udclion.updraftplus.table_prefix,
1129 backup_tables_with_prefixes: udclion.updraftplus.backup_tables_with_prefixes,
1130 test_connection: udclion.updraftplus.test_connection
1131 }, {
1132 host_attr: host,
1133 user_attr: user,
1134 name_attr: name,
1135 pass_attr: pass,
1136 prefix_attr: prefix
1137 })).appendTo($('#updraft_backupextradbs')).fadeIn();
1138 }
1139
1140 /**
1141 * Registers listeners that occur on all tabs.
1142 *
1143 * @return {void}
1144 */
1145 function register_global_listeners() {
1146 UpdraftCentral.register_row_clicker('.row_backupnow, .updraftcentral_site_backup_now', function($site_row) {
1147 backup_now($site_row, 'new');
1148 });
1149
1150 UpdraftCentral.register_row_clicker('.row_backupnow, .updraftcentral_site_backup_now_increment', function ($site_row) {
1151 backup_now($site_row, 'incremental');
1152 });
1153
1154 UpdraftCentral.register_modal_listener('#backupnow_includefiles_showmoreoptions', function(e) {
1155 e.preventDefault();
1156 $('#updraftcentral_modal #backupnow_includefiles_moreoptions').slideToggle();
1157 });
1158
1159 UpdraftCentral.register_modal_listener('#backupnow_database_showmoreoptions', function(e) {
1160 e.preventDefault();
1161 $('#updraftcentral_modal #backupnow_database_moreoptions').slideToggle();
1162 });
1163
1164 UpdraftCentral.register_modal_listener('#backupnow_includecloud_showmoreoptions', function(e) {
1165 e.preventDefault();
1166 $('#updraftcentral_modal #backupnow_includecloud_moreoptions').slideToggle();
1167 });
1168
1169 UpdraftCentral.register_event_handler('click', '.updraftcentral_notice_contents [id^=updraftplus_manual_authorisation_submit_]', function() {
1170 var event = arguments[arguments.length - 1];
1171 event.preventDefault();
1172
1173 var method = $(this).data('method');
1174 var auth_data = $('#updraftplus_manual_authentication_data_'+method).val();
1175 $('#updraftplus_manual_authentication_error_'+method).text();
1176 $('#updraft-wrap #updraftplus_manual_authorisation_template_'+method+' .updraftplus_spinner.spinner').addClass('visible');
1177 $('#updraftplus_manual_authorisation_submit_'+method).prop('disabled', true);
1178 manual_remote_storage_auth(method, auth_data);
1179 });
1180 }
1181
1182 /**
1183 * This method will send the ajax request to manually authenticate the remote storage method and then update the page with the response
1184 *
1185 * @param {string} method - the remote storage method
1186 * @param {string} auth_data - the auth data as a base64 json encoded string
1187 */
1188 function manual_remote_storage_auth(method, auth_data) {
1189 UpdraftCentral.send_site_rpc('updraftplus.manual_remote_storage_authentication', {method: method, auth_data: auth_data}, UpdraftCentral.$site_row, function(response, code, error_code) {
1190 if ('rpcok' == response.response && response.hasOwnProperty('data')) {
1191 var response = response.data;
1192
1193 $('#updraft-wrap #updraftplus_manual_authorisation_template_'+method+' .updraftplus_spinner.spinner').removeClass('visible');
1194 if (response.hasOwnProperty('result') && 'success' === response.result) {
1195 UpdraftCentral_Library.dialog.alert('<h2>'+udclion.updraftplus.manual_auth_result+'</h2>'+response.data);
1196 $('#updraft-wrap #updraftplus_manual_authorisation_template_'+method).parent().remove();
1197 $('#updraft-wrap .updraft_authenticate_'+method).remove();
1198 } else if (response.hasOwnProperty('result') && 'error' === response.result) {
1199 $('#updraftplus_manual_authentication_error_'+method).text(response.data);
1200 $('#updraftplus_manual_authorisation_submit_'+method).prop('disabled', false);
1201 }
1202 }
1203 });
1204 }
1205
1206 if ('notices' != UpdraftCentral.get_dashboard_mode()) { register_global_listeners(); }
1207
1208 // Register the row clickers for all tabs
1209 $('#updraftcentral_dashboard_existingsites').on('updraftcentral_dashboard_mode_set', function(event, data) {
1210
1211 // The 'upgrade' tab has no sites rows visible
1212 if (data && data.hasOwnProperty('new_mode') && 'notices' == data.new_mode) { return; }
1213
1214 register_global_listeners();
1215
1216 });
1217
1218 // Register the row clickers for this tab
1219 $('#updraftcentral_dashboard_existingsites').on('updraftcentral_dashboard_mode_set_backups', function() {
1220
1221 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output #updraft_backupextradb_another', function() {
1222 extradbs_add('', '', '', '', '');
1223 });
1224
1225 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output #updraft_backupextradbs .updraft_backupextradbs_row_delete', function() {
1226 $(this).parents('.updraft_backupextradbs_row').fadeOut('medium', function() {
1227 $(this).remove();
1228 });
1229 });
1230
1231 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output #updraft_backupextradbs .updraft_backupextradbs_row_testconnection', function() {
1232 var $row = $(this).closest('.updraft_backupextradbs_row');
1233 $row.find('.updraft_backupextradbs_testresultarea').html('<p><em>'+udclion.updraftplus.testing+'</em></p>');
1234
1235 var data = {
1236 row: $row.attr('id'),
1237 host: $row.find('.extradb_host').val(),
1238 user: $row.find('.extradb_user').val(),
1239 pass: $row.find('.extradb_pass').val(),
1240 name: $row.find('.extradb_name').val(),
1241 prefix: $row.find('.extradb_prefix').val()
1242 };
1243
1244 UpdraftCentral.send_site_rpc('updraftplus.extradb_testconnection', data, UpdraftCentral.$site_row, function(response, code, error_code) {
1245 if ('ok' == code && response) {
1246 $row.find('.updraft_backupextradbs_testresultarea').html(UpdraftCentral_Library.sanitize_html(response.data.m));
1247 }
1248 }, $row);
1249 });
1250
1251 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output .updraftplusmethod button.updraft-test-button', function() {
1252
1253 var $method_button = $(this);
1254 var instance_id = jQuery(this).data('instance_id');
1255 var method = $method_button.data('method');
1256
1257 updraft_remote_storage_test($method_button, function(response, code, error_code, data) {
1258
1259 if ('sftp' != method) { return false; }
1260
1261 if ('undefined' !== typeof data && data.hasOwnProperty('scp') && data.scp) {
1262 UpdraftCentral_Library.dialog.alert('<h2>'+sprintf(udclion.updraftplus.settings_test_result, 'SCP')+'</h2> '+response.data.output);
1263 } else {
1264 UpdraftCentral_Library.dialog.alert('<h2>'+sprintf(udclion.updraftplus.settings_test_result, 'SFTP')+'</h2> '+response.data.output);
1265 }
1266
1267 if (response.hasOwnProperty('data') && response.data) {
1268 if (response.data.hasOwnProperty('data') && response.data.data) {
1269 if ('undefined' !== typeof response.data.data.valid_md5_fingerprint) {
1270 $('#updraft_sftp_fingerprint_'+instance_id).val(response.data.data.valid_md5_fingerprint);
1271 }
1272 }
1273 }
1274
1275 return true;
1276
1277 });
1278 });
1279
1280 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output #updraftplus-settings-save', function($site_row, site_id) {
1281
1282 // Gather data
1283 var form_data = $(settings_css_prefix+' input, '+settings_css_prefix+' textarea, '+settings_css_prefix+' select').serialize();
1284
1285 // include unchecked checkboxes. user filter to only include unchecked boxes.
1286 $.each($(settings_css_prefix+' input[type=checkbox]')
1287 .filter(function(idx) {
1288 return $(this).prop('checked') == false
1289 }),
1290 function(idx, el) {
1291 // attach matched element names to the form_data with chosen value.
1292 var empty_val = '0';
1293 form_data += '&' + $(el).attr('name') + '=' + empty_val;
1294 }
1295 );
1296
1297 spin_this = $(this).closest('td');
1298
1299 form_data += '&updraftplus_version=' + updraftplus_version;
1300
1301 UpdraftCentral.send_site_rpc('updraftplus.save_settings', form_data, $site_row, function(response, code, error_code) {
1302
1303 if ('ok' === code) {
1304
1305 // If backup dir is not writable, change the text, and grey out the 'Backup Now' button
1306 var backup_dir_writable = response.data.backup_dir.writable;
1307 var backup_dir_message = response.data.backup_dir.message;
1308 var backup_button_title = response.data.backup_dir.button_title;
1309
1310 if (backup_dir_writable == false) {
1311 // $('#updraft-backupnow-button').attr('disabled', 'disabled');
1312 // $('#updraft-backupnow-button').attr('title', backup_button_title);
1313 $(settings_css_prefix+'#updraft_writable_mess').html(backup_dir_message);
1314 $(settings_css_prefix+'.backupdirrow').show();
1315 } else {
1316 // $('#updraft-backupnow-button').removeAttr('disabled');
1317 // $('#updraft-backupnow-button').removeAttr('title');
1318 $(settings_css_prefix+'.backupdirrow').hide();
1319 }
1320
1321 var site_url = $site_row.data('site_url');
1322
1323 // Get rid of any existing results-of-saving-settings boxes
1324 $('#updraftcentral_notice_container .updraftplus_saved_settings').closest('.updraftcentral_notice').remove();
1325
1326 var $new_notice = add_dashboard_notice('<h2>'+udclion.updraftplus.settings_saved+' - '+site_url+'</h2><div class="updraftplus_saved_settings" data-site_id="'+site_id+'">'+response.data.messages+'</div>', 'notice', false);
1327
1328 $('#updraft-central-content').animate({
1329 scrollTop: $new_notice.offset().top
1330 }, 1000);
1331 }
1332
1333 }, spin_this);
1334
1335 });
1336
1337 UpdraftCentral.register_row_clicker(settings_css_sub_prefix+'.backupdirrow a.updraft_backup_dir_reset', function() {
1338 $(settings_css_prefix+'#updraft_dir').val('updraft');
1339 });
1340
1341 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output .enableexpertmode', function() {
1342 $('.updraftcentral_row_extracontents .updraft_site_settings_output .expertmode').fadeIn();
1343 $('.updraftcentral_row_extracontents .updraft_site_settings_output .enableexpertmode').off('click');
1344 });
1345
1346 UpdraftCentral.register_row_clicker(settings_css_sub_prefix+' a.updraft_authlink', function($site_row) {
1347 var href = $(this).attr('href');
1348 if ('undefined' === typeof href) { return; }
1349 var spinner_where = $(this).closest('td');
1350 UpdraftCentral_Library.open_browser_at($site_row, { module: 'direct_url', url: href }, spinner_where);
1351 });
1352
1353 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output .updraft_include_entity', function() {
1354 var has_exclude_field = $(this).data('toggle_exclude_field');
1355 if (has_exclude_field) {
1356 setup_file_entity_exclude_field(has_exclude_field, false);
1357 }
1358 }, false, 'change');
1359
1360 UpdraftCentral.register_row_clicker('.updraft_existing_backups_output .updraft_existingbackup_date', function($site_row) {
1361 var nonce = $(this).data('nonce');
1362 var timestamp = $(this).data('timestamp');
1363
1364 UpdraftCentral.send_site_rpc('updraftplus.rawbackup_history', {
1365 nonce: nonce,
1366 timestamp: timestamp
1367 }, UpdraftCentral.$site_row, function (response, code, error_code) {
1368 if ('ok' == code && false !== response && response.hasOwnProperty('data')) {
1369 if (response.data.hasOwnProperty('rawbackup')) {
1370 UpdraftCentral.close_modal();
1371 UpdraftCentral.open_modal(udclion.updraftplus.raw, response.data.rawbackup, true, false, null, false, 'modal-lg');
1372 }
1373 }
1374 });
1375 }, false, 'dblclick');
1376
1377 register_modal_listener('#always_keep_this_backup', function(e) {
1378 var backup_key = $(this).data('backup_key');
1379 UpdraftCentral.send_site_rpc('updraftplus.always_keep_this_backup', {
1380 backup_key: backup_key,
1381 always_keep: $(this).is(':checked') ? 1 : 0
1382 }, UpdraftCentral.$site_row, function (response, code, error_code) {
1383 if ('ok' == code && false !== response && response.hasOwnProperty('data')) {
1384 if (response.data.hasOwnProperty('rawbackup')) {
1385 UpdraftCentral.close_modal();
1386 UpdraftCentral.open_modal(udclion.updraftplus.raw, response.data.rawbackup, true, false);
1387 }
1388 }
1389 });
1390 }, 'change');
1391
1392 UpdraftCentral.register_row_clicker('.updraft_existing_backups_output .choose-components-button', function($site_row) {
1393 var this_button = this;
1394 var entities = $(this_button).data('entities');
1395 var spinner_where = $(this_button).closest('td');
1396 if (entities) {
1397
1398 // Alert the user of possible consequences of restoring + other relevant info, before proceeding.
1399 UpdraftCentral_Library.dialog.confirm('<h2>'+udclion.updraftplus.restore_backup+'</h2>'+udclion.updraftplus.pre_restore_message, function(go_ahead) {
1400 if (!go_ahead) { return; }
1401 UpdraftCentral_Library.open_browser_at($site_row, { module: 'updraftplus', action: 'initiate_restore', data: {
1402 entities: entities,
1403 backup_timestamp: $(this_button).data('backup_timestamp'),
1404 showdata: $(this_button).data('showdata')
1405 } }, spinner_where);
1406
1407 restored_items.add($(this_button).data('backup_timestamp'), $(this_button).closest('tr.updraft_existing_backups_row').data('nonce'));
1408 });
1409
1410 }
1411 });
1412
1413 UpdraftCentral.register_row_clicker('.updraft_existing_backups_output .updraft_download_button', function($site_row) {
1414
1415 var site_id = $site_row.data('site_id');
1416 var backup_timestamp = $(this).data('backup_timestamp');
1417 var what = $(this).data('what');
1418 var set_contents = $(this).data('set_contents');
1419 var pretty_date = $(this).data('prettydate');
1420 var async = true;
1421
1422 var spinner_where = $(this).closest('td');
1423
1424 updraft_downloader(site_id, backup_timestamp, what, set_contents, pretty_date, async, spinner_where);
1425
1426 });
1427
1428 UpdraftCentral.register_row_clicker('.updraft_existing_backups_output button.updraft-upload-link', function ($site_row) {
1429 $(this).hide();
1430 var nonce = $(this).data('nonce').toString();
1431 var key = $(this).data('key').toString();
1432 if (nonce) {
1433 UpdraftCentral.send_site_rpc('updraftplus.upload_local_backup', {
1434 use_nonce: nonce,
1435 use_timestamp: key
1436 }, UpdraftCentral.$site_row, function (response, code, error_code) {
1437 if ('ok' == code && false !== response && response.hasOwnProperty('data')) {
1438 if (response.data.hasOwnProperty('nonce')) {
1439
1440 var listener_message = '<div class="backup_state">' + udclion.updraftplus.backupstarted + '</div>';
1441
1442 UpdraftCentral.create_dashboard_listener('updraftplus_backup', UpdraftCentral.$site_row, listener_message, { job_id: response.data.nonce }, udclion.updraftplus.upload_backup);
1443
1444 } else {
1445 UpdraftCentral.add_dashboard_notice('<h2>' + UpdraftCentral.$site_row.data('site_description') + '</h2>' + udclion.updraftplus.backup_start_failed, 'error');
1446 }
1447 }
1448 });
1449 } else {
1450 console.log("UDCentral: UpdraftPlus: A upload link was clicked, but the backup ID could not be found");
1451 }
1452 });
1453
1454 UpdraftCentral.register_row_clicker('.updraft_existing_backups_output .updraft-delete-link', function($site_row) {
1455 var hasremote = $(this).data('hasremote').toString();
1456 hasremote = (hasremote === '0') ? false : true;
1457 var nonce = $(this).data('nonce').toString();
1458 var key = $(this).data('key').toString();
1459
1460 delete_action = 'single';
1461 if (nonce) {
1462 if (restored_items.exists(key)) {
1463 updraft_get_existing_backups_panel($site_row);
1464 } else {
1465 updraft_delete(key, nonce, hasremote);
1466 }
1467 } else {
1468 console.log("UDCentral: UpdraftPlus: A delete link was clicked, but the backup ID could not be found");
1469 }
1470 });
1471
1472 UpdraftCentral.register_event_handler('click', '.delete-backup-container input.delete_backup_item', function($site_row) {
1473 var checked = $('.delete-backup-container input.delete_backup_item:checked').length;
1474
1475 if (0 < checked) {
1476 $('button#btn-backup-bulk-delete').removeClass('btn-secondary').addClass('btn-primary');
1477 } else {
1478 $('button#btn-backup-bulk-delete').removeClass('btn-primary').addClass('btn-secondary');
1479 }
1480 });
1481
1482 UpdraftCentral.register_row_clicker('.updraft_existing_backups_output button#btn-backup-bulk-delete', function($site_row) {
1483 var keys = [],
1484 hasremote = false,
1485 nonce,
1486 hasrestored = false;
1487
1488 selected_items.clear();
1489 $('.delete-backup-container input.delete_backup_item:checked').each(function() {
1490 var delete_link = $(this).closest('tr.updraft_existing_backups_row').find('a.updraft-delete-link');
1491 var key = delete_link.data('key');
1492
1493 if ('undefined' !== typeof key && key) {
1494 keys.push(key.toString());
1495 nonce = delete_link.data('nonce');
1496
1497 if (!hasremote) {
1498 hasremote = ('undefined' === typeof delete_link.data('hasremote') || delete_link.data('hasremote') == '0') ? false : true;
1499 }
1500
1501 if (restored_items.exists(key)) hasrestored = true;
1502 selected_items.add(key, $(this).closest('tr.updraft_existing_backups_row').data('nonce'));
1503 }
1504 });
1505
1506 delete_action = 'multiple';
1507 if (keys.length) {
1508 if (hasrestored) {
1509 updraft_get_existing_backups_panel($site_row);
1510 } else {
1511 updraft_delete(keys.join(), nonce, hasremote);
1512 }
1513 } else {
1514 console.log("UDCentral: UpdraftPlus: The bulk delete button was clicked, but none of the backup IDs could be found");
1515 }
1516 });
1517
1518 UpdraftCentral.register_row_clicker('.updraft_existing_backups_output a.updraft_diskspaceused_update', function($site_row) {
1519 var spin_this = this.closest('ul');
1520 UpdraftCentral.send_site_rpc('updraftplus.get_fragment', { fragment: 'disk_usage', data: 'updraft' } , $site_row, function(response, code, error_code) {
1521 if ('ok' == code && response) {
1522 $site_row.find('.updraft_diskspaceused').html(UpdraftCentral_Library.sanitize_html(response.data.output));
1523 }
1524 }, spin_this);
1525 });
1526
1527 UpdraftCentral.register_row_clicker('.updraft_existing_backups_output a.updraft_rescan_local', function($site_row) {
1528 var spin_this = this.closest('ul');
1529 $site_row.find('.updraft_existing_backups').html('<div class="rescanning">'+udclion.updraftplus.rescanning+'</div>');
1530 UpdraftCentral.send_site_rpc('updraftplus.rescan', 'rescan' , $site_row, function(response, code, error_code) {
1531 if ('ok' == code && response) {
1532 $site_row.find('.updraft_existing_backups').html(response.data.t);
1533 $site_row.find('.updraft_existing_backups_output h2').html(response.data.n);
1534
1535 insert_bulk_delete($site_row);
1536 }
1537 }, spin_this);
1538 });
1539
1540 UpdraftCentral.register_row_clicker('.updraft_existing_backups_output a.updraft_rescan_remote', function($site_row) {
1541 var spin_this = this.closest('ul');
1542 $site_row.find('.updraft_existing_backups').html('<div class="rescanning">'+udclion.updraftplus.rescanningremote+'</div>');
1543 UpdraftCentral.send_site_rpc('updraftplus.rescan', 'remotescan' , $site_row, function(response, code, error_code) {
1544 if ('ok' == code && response) {
1545 $site_row.find('.updraft_existing_backups').html(response.data.t);
1546 $site_row.find('.updraft_existing_backups_output h2').html(response.data.n);
1547
1548 insert_bulk_delete($site_row);
1549 }
1550 }, spin_this, 90);
1551 });
1552
1553 UpdraftCentral.register_row_clicker('.updraftcentral_site_backups_manage', function($site_row) {
1554 updraft_get_existing_backups_panel($site_row);
1555 }, true);
1556
1557 UpdraftCentral.register_row_clicker('.updraftcentral_site_backup_settings', function($site_row) {
1558 updraft_get_existing_backup_settings($site_row);
1559 }, true);
1560
1561 UpdraftCentral.register_row_clicker('.updraft_site_settings_output select.updraft_interval, .updraft_site_settings_output select.updraft_interval_database', function() {
1562 updraft_check_same_times();
1563 }, false, 'change');
1564
1565 // Remote method authentication click
1566 UpdraftCentral.register_row_clicker('.updraft_authlink', function($site_row) {
1567 var spin_this = this.closest('ul');
1568 var data = {
1569 remote_method: $(this).data('remote_method'),
1570 instance_id: $(this).data('instance_id')
1571 }
1572
1573 UpdraftCentral.send_site_rpc('updraftplus.auth_remote_method', data, $site_row, function(response, code, error_code) {
1574 if ('ok' == code && false !== response) {
1575 var resp = response.data;
1576 if ('error' == resp.result) {
1577 UpdraftCentral_Library.dialog.alert('<h2>'+udclion.error+'</h2>'+resp.message);
1578 } else if ('success' == resp.result) {
1579 updraft_get_existing_backup_settings($site_row);
1580 }
1581 }
1582 }, spin_this);
1583
1584 }, true);
1585
1586 // Remote method deauthentication click
1587 UpdraftCentral.register_row_clicker('.updraft_deauthlink', function($site_row) {
1588 var spin_this = this.closest('ul');
1589 var data = {
1590 remote_method: $(this).data('remote_method'),
1591 instance_id: $(this).data('instance_id')
1592 }
1593
1594 UpdraftCentral.send_site_rpc('updraftplus.deauth_remote_method', data, $site_row, function(response, code, error_code) {
1595 if ('ok' == code && false !== response) {
1596 var resp = response.data;
1597 if ('error' == resp.result) {
1598 UpdraftCentral_Library.dialog.alert('<h2>'+udclion.error+'</h2>'+resp.message);
1599 } else if ('success' == resp.result) {
1600 updraft_get_existing_backup_settings($site_row);
1601 }
1602 }
1603 }, spin_this);
1604
1605 }, true);
1606
1607 UpdraftCentral.register_row_clicker('.updraft_site_settings_output #updraft_retain_db_addnew', function() {
1608 add_rule('db', 12, 604800, 1, 604800);
1609 });
1610
1611 UpdraftCentral.register_row_clicker('.updraft_site_settings_output #updraft_retain_files_addnew', function() {
1612 add_rule('files', 12, 604800, 1, 604800);
1613 });
1614
1615 UpdraftCentral.register_row_clicker('.updraft_site_settings_output .updraft_retain_rules_delete, .updraft_site_settings_output .updraft_retain_rules_delete', function() {
1616 $(this).parent('.updraft_retain_rules').slideUp(function() {
1617 $(this).remove();
1618 });
1619 });
1620
1621 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output #updraft_report_cell .updraft_reportbox .updraft_reportbox_delete', function() {
1622 $(this).closest('.updraft_reportbox').fadeOut('medium', function() {
1623 $(this).remove();
1624 });
1625 });
1626
1627 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output #updraft_report_cell .updraft_report_another', function() {
1628
1629 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output #updraft_report_cell .updraft_report_another_p').before(template_replace('updraftplus-settings-report-email', {
1630 index: reportbox_index,
1631 send_only_on_warnings: udclion.updraftplus.send_only_on_warnings,
1632 whole_backup: udclion.updraftplus.whole_backup,
1633 email_size_limits: udclion.updraftplus.email_size_limits,
1634 db_backup: udclion.updraftplus.db_backup
1635 }));
1636 $('#updraft_reportbox_'+reportbox_index).fadeIn();
1637 reportbox_index++;
1638
1639 });
1640
1641 UpdraftCentral.register_event_handler('change', '.updraft_report_wholebackup .updraft_report_checkbox', function() {
1642 var reportbox = $(this).closest('.updraft_reportbox').find('.updraft_report_dbbackup');
1643 if ($(this).is(':checked')) {
1644 reportbox.removeClass('updraft_report_disabled').find('.updraft_report_checkbox').prop('disabled', false);
1645 } else {
1646 reportbox.find('.updraft_report_checkbox').prop('checked', false);
1647 reportbox.addClass('updraft_report_disabled').find('.updraft_report_checkbox').prop('disabled', true);
1648 }
1649 });
1650
1651 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output #updraft_include_more', function() {
1652 if ($('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output #updraft_include_more').is(':checked')) {
1653 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output #updraft_include_more_options').slideDown();
1654 } else {
1655 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output #updraft_include_more_options').slideUp();
1656 }
1657 }, false, 'change');
1658
1659 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output #updraft_include_more_paths_another', function() {
1660 updraftplus_morefiles_lastind++;
1661 $(template_replace('updraftplus-settings-more-paths', {
1662 index: updraftplus_morefiles_lastind,
1663 enter_the_directory: udclion.updraftplus.enter_the_directory,
1664 remove: udclion.updraftplus.remove
1665 })).appendTo($('.updraftcentral_row_extracontents .updraft_site_settings_output #updraft_include_more_paths')).slideDown();
1666 });
1667
1668 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output #updraft_include_more_options .updraftplus-morefiles-row-delete', function() {
1669 var prow = $(this).closest('.updraftplus-morefiles-row');
1670 $(prow).slideUp('medium', function() {
1671 $(this).remove();
1672 });
1673 });
1674
1675 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output .updraft_servicecheckbox', function() {
1676 var sclass = $(this).attr('id');
1677 if ('updraft_servicecheckbox_' == sclass.substring(0,24)) {
1678 var serv = sclass.substring(24);
1679 if (null != serv && '' != serv) {
1680 if ($(this).is(':checked')) {
1681 remote_storage_tabs_any_checked++;
1682 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .remote-tab-'+serv).fadeIn();
1683 updraft_remote_storage_tab_activation(serv);
1684 } else {
1685 remote_storage_tabs_any_checked--;
1686 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .remote-tab-'+serv).hide();
1687 // Check if this was the active tab, if yes, switch to another
1688 if ($('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .remote-tab-'+serv).data('active') == true) {
1689 updraft_remote_storage_tab_activation($('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .remote-tab:visible').last().attr('name'));
1690 }
1691 }
1692 }
1693 }
1694
1695 if (remote_storage_tabs_any_checked <= 0) {
1696 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .updraftplusmethod.none').fadeIn();
1697 } else {
1698 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .updraftplusmethod.none').hide();
1699 }
1700 }, false, 'change');
1701
1702 // Changing tabs for the remote storage methods
1703 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output .remote-tab', function() {
1704 var the_method = $(this).attr('name');
1705 updraft_remote_storage_tab_activation(the_method);
1706 });
1707
1708 // For the free version, where only one remote storage choice can be made at a time
1709 UpdraftCentral.register_row_clicker('.updraftcentral_row_extracontents .updraft_site_settings_output .updraft_servicecheckbox:not(.multi)', function() {
1710 var svalue = $(this).attr('value');
1711
1712 if ($(this).is(':not(:checked)')) {
1713 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .updraftplusmethod.'+svalue).hide();
1714 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .updraftplusmethod.none').fadeIn();
1715 } else {
1716 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .updraft_servicecheckbox').not(this).prop('checked', false);
1717 }
1718 }, false, 'change');
1719
1720 // UpdraftVault settings handling
1721 UpdraftCentral.register_row_clicker(settings_css_sub_prefix+'#updraftvault_settings_cell .updraftvault_backtostart', function() {
1722 $(settings_css_prefix+'#updraftvault_settings_showoptions').slideUp();
1723 $(settings_css_prefix+'#updraftvault_settings_connect').slideUp();
1724 $(settings_css_prefix+'#updraftvault_settings_connected').slideUp();
1725 $(settings_css_prefix+'#updraftvault_settings_default').slideDown();
1726 });
1727
1728 // Prevent default event when pressing return in the form
1729 UpdraftCentral.register_row_clicker(settings_css_sub_prefix+'#updraftvault_settings_connect input', function($site_row, site_id, event) {
1730 if (event.which == 13) {
1731 $(settings_css_prefix+'#updraftvault_connect_go').trigger('click');
1732 event.preventDefault();
1733 }
1734 }, false, 'keypress');
1735
1736 UpdraftCentral.register_row_clicker(settings_css_sub_prefix+'#updraftvault_settings_cell #updraftvault_recountquota', function() {
1737 $(settings_css_prefix+'#updraftvault_recountquota').html(udclion.updraftplus.counting);
1738 UpdraftCentral.send_site_rpc('updraftplus.vault_recountquota', { instance_id: $('#updraftvault_settings_connect').data('instance_id') }, UpdraftCentral.$site_row, function(response, code, error_code) {
1739 $(settings_css_prefix+'#updraftvault_recountquota').html(udclion.updraftplus.update_quota_count);
1740 if ('ok' == code && response) {
1741 if (response.hasOwnProperty('data') && response.data.hasOwnProperty('html')) {
1742 $(settings_css_prefix+'#updraftvault_settings_connected').html(response.data.html);
1743 if (response.data.hasOwnProperty('connected')) {
1744 if (response.data.connected) {
1745 $(settings_css_prefix+'#updraftvault_settings_default').hide();
1746 $(settings_css_prefix+'#updraftvault_settings_connected').show();
1747 } else {
1748 $(settings_css_prefix+'#updraftvault_settings_connected').hide();
1749 $(settings_css_prefix+'#updraftvault_settings_default').show();
1750 }
1751 }
1752 }
1753 }
1754 });
1755 });
1756
1757 UpdraftCentral.register_row_clicker(settings_css_sub_prefix+'#updraftvault_settings_cell #updraftvault_disconnect', function() {
1758 $(settings_css_prefix+'#updraftvault_disconnect').html(udclion.updraftplus.disconnecting);
1759 UpdraftCentral.send_site_rpc('updraftplus.vault_disconnect', { instance_id: $('#updraftvault_settings_connect').data('instance_id') }, UpdraftCentral.$site_row, function(response, code, error_code) {
1760 $(settings_css_prefix+'#updraftvault_disconnect').html(udclion.updraftplus.disconnect);
1761
1762 if ('ok' == code && response.hasOwnProperty('data')) {
1763
1764 $(settings_css_prefix+'#updraftvault_disconnect').html(udclion.updraftplus.disconnect);
1765
1766 if (response.data.hasOwnProperty('html')) {
1767 $(settings_css_prefix+'#updraftvault_settings_connected').html(response.data.html).slideUp();
1768 $(settings_css_prefix+'#updraftvault_settings_default').slideDown();
1769 }
1770 }
1771 });
1772 });
1773
1774 UpdraftCentral.register_row_clicker(settings_css_sub_prefix+'#updraftvault_connect', function() {
1775 $(settings_css_prefix+'#updraftvault_settings_default').slideUp();
1776 $(settings_css_prefix+'#updraftvault_settings_connect').slideDown();
1777 });
1778
1779 UpdraftCentral.register_row_clicker(settings_css_sub_prefix+'#updraftvault_showoptions', function() {
1780 $(settings_css_prefix+'#updraftvault_settings_default').slideUp();
1781 $(settings_css_prefix+'#updraftvault_settings_showoptions').slideDown();
1782 });
1783
1784 UpdraftCentral.register_row_clicker(settings_css_sub_prefix+'#updraft_s3_newapiuser', function($site_row) {
1785 var spin_this = this.closest('td');
1786 UpdraftCentral.send_site_rpc('updraftplus.get_fragment', { fragment: 's3_new_api_user_form', data: null } , $site_row, function(response, code, error_code) {
1787 if ('ok' == code && response) {
1788 UpdraftCentral.open_modal(udclion.updraftplus.create_new_iam_user_and_bucket, response.data.output, function() {
1789
1790 // $('#updraftcentral_modal #updraft-s3newapiuser-results').html('<p style="color:green">'+udclion.updraftplus.trying+'</p>');
1791 $('#updraftcentral_modal #updraft-s3newapiuser-results').empty();
1792
1793 var data = {
1794 adminaccesskey: $('#updraftcentral_modal #updraft_s3newapiuser_adminaccesskey').val(),
1795 adminsecret: $('#updraftcentral_modal #updraft_s3newapiuser_adminsecret').val(),
1796 newuser: $('#updraftcentral_modal #updraft_s3newapiuser_newuser').val(),
1797 bucket: $('#updraftcentral_modal #updraft_s3newapiuser_bucket').val(),
1798 region: $('#updraftcentral_modal #updraft_s3newapiuser_region').val(),
1799 useservercerts: $('#updraftcentral_modal #updraft_ssl_useservercerts').val(),
1800 disableverify: $('#updraftcentral_modal #updraft_ssl_disableverify').val(),
1801 nossl: $('#updraftcentral_modal #updraft_ssl_nossl').val(),
1802 allowdelete: $('#updraftcentral_modal #updraft_s3newapiuser_allowdelete').is(':checked') ? 1 : 0,
1803 allowdownload: $('#updraftcentral_modal #updraft_s3newapiuser_allowdownload').is(':checked') ? 1 : 0
1804 };
1805
1806 var spin_this = $('#updraftcentral_modal');
1807
1808 UpdraftCentral.send_site_rpc('updraftplus.s3_newuser', data , $site_row, function(response, code, error_code) {
1809
1810 if ('ok' == code && response) {
1811 if (response.data.e == 1) {
1812 $('#updraftcentral_modal #updraft-s3newapiuser-results').html('<p style="color:red;">'+UpdraftCentral_Library.sanitize_html(response.data.m)+'</p>');
1813 } else if (response.data.e == 0) {
1814 $('#updraftcentral_modal #updraft-s3newapiuser-results').html('<p style="color:green;">'+UpdraftCentral_Library.sanitize_html(response.data.m)+'</p>');
1815 $(settings_css_prefix+'#updraft_s3_apikey').val(response.data.k);
1816 $(settings_css_prefix+'#updraft_s3_apisecret').val(response.data.s);
1817 $(settings_css_prefix+'#updraft_s3_rrs').prop(':checked', response.data.r);
1818 $(settings_css_prefix+'#updraft_s3_path').val(response.data.c);
1819
1820 // Change link to open dialog to reflect that using IAM user
1821 $(settings_css_prefix+'#updraft_s3_newapiuser').html(udclion.updraftplus.now_using_iam);
1822
1823 UpdraftCentral.close_modal();
1824 }
1825 }
1826
1827 }, spin_this);
1828
1829 }, udclion.updraftplus.create);
1830 }
1831 }, spin_this);
1832 });
1833
1834 UpdraftCentral.register_row_clicker(settings_css_sub_prefix+'#updraft_cloudfiles_newapiuser', function($site_row) {
1835 var spin_this = this.closest('td');
1836
1837 UpdraftCentral.send_site_rpc('updraftplus.get_fragment', { fragment: 'cloudfiles_new_api_user_form', data: null }, $site_row, function(response, code, error_code) {
1838 if ('ok' == code) {
1839 var html = UpdraftCentral.template_replace('updraftplus-cloudfiles_new_api_user', response.data.output);
1840
1841 UpdraftCentral.open_modal(udclion.updraftplus.new_api_user, UpdraftCentral_Library.sanitize_html(html), function() {
1842 var $form = $(this).closest('.modal-dialog').find('.form-table'),
1843 new_user = {
1844 'adminuser': $form.find('.adminuser').val(),
1845 'adminapikey': $form.find('.adminapikey').val(),
1846 'newuser': $form.find('.newuser').val(),
1847 'container': $form.find('.container').val(),
1848 'newemail': $form.find('.newemail').val(),
1849 'location': $form.find('.location').val(),
1850 'region': $form.find('.region').val()
1851 };
1852
1853 var spin_this = $('.modal-dialog');
1854
1855 UpdraftCentral.send_site_rpc('updraftplus.cloudfiles_newuser', new_user, $site_row, function(response, code, error_code) {
1856 if ('ok' == code) {
1857 UpdraftCentral.close_modal();
1858
1859 var user = response.data.u;
1860 var key = response.data.k;
1861 var container = response.data.c;
1862
1863 $site_row.find('#updraft_cloudfiles_user').val(user);
1864 $site_row.find('#updraft_cloudfiles_apikey').val(key);
1865 $site_row.find('#updraft_cloudfiles_path').val(container);
1866 } else if (error_code === "error") {
1867 UpdraftCentral_Library.dialog.alert('<h3>'+udclion.error+'</h3>' + response.m);
1868 return true;
1869 }
1870 }, spin_this)
1871 }, udclion.updraftplus.create);
1872 }
1873 }, spin_this)
1874 });
1875
1876 UpdraftCentral.register_row_clicker(settings_css_sub_prefix+'#updraftvault_connect_go', function() {
1877 $(settings_css_prefix+'#updraftvault_connect_go').html(udclion.updraftplus.connecting);
1878
1879 var data = {
1880 email: $(settings_css_prefix+'#updraftvault_email').val(),
1881 pass: $(settings_css_prefix+'#updraftvault_pass').val(),
1882 instance_id: $(settings_css_prefix+'#updraftvault_settings_connect').data('instance_id')
1883 }
1884
1885 UpdraftCentral.send_site_rpc('updraftplus.vault_connect', data, UpdraftCentral.$site_row, function(response, code, error_code) {
1886
1887 $(settings_css_prefix+'#updraftvault_connect_go').html(udclion.updraftplus.connect);
1888
1889 if ('ok' == code && response.hasOwnProperty('data')) {
1890 if (response.data.hasOwnProperty('e')) {
1891 UpdraftCentral_Library.dialog.alert('<h2>'+udclion.error+'</h2><p>'+response.data.e+'</p>');
1892 if (response.data.hasOwnProperty('code') && response.data.code == 'no_quota') {
1893 $(settings_css_prefix+'#updraftvault_settings_connect').slideUp();
1894 $(settings_css_prefix+'#updraftvault_settings_default').slideDown();
1895 }
1896 } else if (response.data.hasOwnProperty('connected') && response.data.connected && response.data.hasOwnProperty('html')) {
1897 $(settings_css_prefix+'#updraftvault_settings_connect').slideUp();
1898 $(settings_css_prefix+'#updraftvault_settings_connected').html(response.data.html).slideDown();
1899 } else {
1900 console.log(response);
1901 UpdraftCentral_Library.dialog.alert('<h2>'+udclion.error+'</h2><p>'+udclion.js_exception_occurred+'</p>');
1902 }
1903 }
1904
1905 });
1906 });
1907
1908 });
1909
1910 /**
1911 * Remote test call back
1912 *
1913 * @callable RemoteTestCallback
1914 * @param {Object} response - the data returned by the RPC call
1915 * @param {string} code - the code returned by the RPC call
1916 * @param {string|null} error_code - the error code returned by the RPC call (if any)
1917 * @param {Object} data - the data that was sent to the remote side (the settings to be tested)
1918 */
1919
1920 /**
1921 * Do a remote storage test based on the indicated button having been pressed, and report the results in a dialog
1922 *
1923 * @param {Object} $method_button - jQuery object for the relevant button
1924 * @param {RemoteTestCallback|false} [result_callback] - optional callable to be invoked with the result
1925 *
1926 * @return {void}
1927 */
1928 function updraft_remote_storage_test($method_button, result_callback) {
1929
1930 var $site_row = $method_button.closest('.updraftcentral_site_row');
1931
1932 var method = $method_button.data('method');
1933 var method_label = $method_button.data('method_label');
1934 var instance_id = $method_button.data('instance_id');
1935 var settings_selector;
1936
1937 if (instance_id) {
1938 settings_selector = '.updraftplusmethod.'+method+'-'+instance_id;
1939 } else {
1940 settings_selector = '.updraftplusmethod.'+method;
1941 }
1942
1943 $method_button.html(sprintf(udclion.updraftplus.testing_settings, method_label));
1944
1945 var data = {
1946 method: method
1947 };
1948
1949 // Add the other items to the data object. The expert mode settings are for the generic SSL options.
1950 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output '+settings_selector+' input[data-updraft_settings_test], #updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .expertmode input[data-updraft_settings_test]').each(function(index, item) {
1951 var item_key = $(item).data('updraft_settings_test');
1952 var input_type = $(item).attr('type');
1953 if (!item_key) { return; }
1954 if (!input_type) {
1955 console.log("UpdraftCentral: UpdraftPlus: settings test input item with no type found");
1956 console.log(item);
1957 // A default
1958 input_type = 'text';
1959 }
1960 var value = null;
1961 if ('checkbox' == input_type) {
1962 value = $(item).is(':checked') ? 1 : 0;
1963 } else if ('text' == input_type || 'password' == input_type) {
1964 value = $(item).val();
1965 } else {
1966 console.log("UpdraftCentral: UpdraftPlus: settings test input item with unrecognised type ("+input_type+") found");
1967 console.log(item);
1968 }
1969 data[item_key] = value;
1970 });
1971 // Data from any text areas or select drop-downs
1972 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output '+settings_selector+' textarea[data-updraft_settings_test], #updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output '+settings_selector+' select[data-updraft_settings_test]').each(function(index, item) {
1973 var item_key = $(item).data('updraft_settings_test');
1974 data[item_key] = $(item).val();
1975 });
1976
1977 if ('webdav' === method && (!data.hasOwnProperty('url') || null === data.url)) {
1978 var url = $('.updraftplusmethod.webdav input[name="updraft_webdav\[settings\]\['+instance_id+'\]\[url\]"]').val();
1979 if ('undefined' !== typeof url && url.length) {
1980 data.url = url;
1981 }
1982 }
1983
1984 UpdraftCentral.send_site_rpc('updraftplus.test_storage_settings', data, $site_row, function(response, code, error_code) {
1985
1986 if ('ok' == code && response) {
1987 $method_button.html(sprintf(udclion.updraftplus.test_settings, method_label));
1988 if ('undefined' !== typeof result_callback && false != result_callback) {
1989 result_callback = result_callback.call(this, response, code, error_code, data);
1990 }
1991 if ('undefined' !== typeof result_callback && false === result_callback) {
1992 UpdraftCentral_Library.dialog.alert('<h2>'+sprintf(udclion.updraftplus.settings_test_result, method_label)+'</h2> '+response.data.output);
1993 }
1994 }
1995
1996 }, $method_button.closest('td'));
1997
1998
1999 }
2000
2001 $('#updraftcentral_notice_container').on('click', '.updraftplus_saved_settings a.updraft_authlink', function(e) {
2002
2003 var href = $(this).attr('href');
2004 if ('undefined' === typeof href) { return; }
2005 var site_id = $(this).closest('.updraftplus_saved_settings').data('site_id');
2006 var $site_row = $('#updraftcentral_dashboard_existingsites .updraftcentral_site_row[data-site_id="'+site_id+'"');
2007
2008 if ($site_row.length < 1) {
2009 console.log("UpdraftCentral: UpdraftPlus: site row not found for the link clicked (site_id="+site_id+")");
2010 return;
2011 }
2012
2013 e.preventDefault();
2014
2015 var spinner_where = $(this).closest('.updraftplus_saved_settings');
2016
2017 UpdraftCentral_Library.open_browser_at($site_row, { module: 'direct_url', url: href }, spinner_where);
2018
2019 });
2020
2021 /**
2022 * Get the "Existing Backups" panel from the remote UpdraftPlus
2023 *
2024 * @param {Object} $site_row - jQuery object for the row of the site for which the information is being requested
2025 *
2026 * @return {void}
2027 */
2028 function updraft_get_existing_backups_panel($site_row) {
2029
2030 $site_row.find('.updraftcentral_row_extracontents').css('opacity', '0.3');
2031
2032 // This just causes an extra informational message to be shown, if set (telling the user to turn off 'Turbo' mode prior to downloading). It does not affect any functionality.
2033 var is_opera = (navigator.userAgent.match(/Opera|OPR\//) ? 1 : 0);
2034 UpdraftCentral.send_site_rpc('updraftplus.get_fragment', {
2035 fragment: 'panel_download_and_restore',
2036 data: {
2037 include_opera_warning: is_opera,
2038 include_uploader: 0,
2039 will_immediately_calculate_disk_space: 0,
2040 include_header: 1
2041 }
2042 }, $site_row, function(response, code, error_code) {
2043 $site_row.find('.updraftcentral_row_extracontents').css('opacity', '1.0');
2044 if ('ok' == code && response) {
2045 $site_row.find('.updraftcentral_row_extracontents').html('<div class="updraft_existing_backups_output"><button class="btn btn-refresh updraftcentral_site_backups_manage"><span class="dashicons dashicons-image-rotate" ></span></button>'+UpdraftCentral_Library.sanitize_html(response.data.output)+'</div>');
2046 insert_bulk_delete($site_row);
2047
2048 if (restored_items.count()) {
2049 var backups_table, backups_checker;
2050 backups_checker = setInterval(function() {
2051 backups_table = $('table.existing-backups-table');
2052 if (backups_table.length) {
2053 clearInterval(backups_checker);
2054
2055 switch (delete_action) {
2056 case 'single':
2057 var items = restored_items.get_items();
2058 restored_items.clear();
2059
2060 if (items.length) {
2061 $('tr.updraft_existing_backups_row[data-nonce="'+items[0]+'"]').find('a.updraft-delete-link').trigger('click');
2062 }
2063 break;
2064 case 'multiple':
2065 var items = selected_items.get_items();
2066 selected_items.clear();
2067 restored_items.clear();
2068
2069 if (items.length) {
2070 for (var i=0; i<items.length; i++) {
2071 $('tr.updraft_existing_backups_row[data-nonce="'+items[i]+'"]').find('input.delete_backup_item').prop('checked', true);
2072 }
2073
2074 $('button#btn-backup-bulk-delete').trigger('click');
2075 }
2076 break;
2077 default:
2078 break;
2079 }
2080 }
2081 }, 1000);
2082 }
2083 }
2084 });
2085 }
2086
2087 /**
2088 * Start a "Backup Now" operation on the specified site
2089 *
2090 * @param {Object} $site_row - the jQuery object for the row of the site to start the backup on
2091 * @param {String} $type - the type of backup e.g new or increment
2092 *
2093 * @return {void}
2094 */
2095 function backup_now($site_row, type) {
2096 UpdraftCentral.send_site_rpc('updraftplus.get_fragment', 'backupnow_modal_contents', $site_row, function(response, code, error_code) {
2097 if ('ok' == code && response) {
2098
2099 var was_error = response.data.output.hasOwnProperty('error') && response.data.output.error;
2100
2101 var action_button = (was_error) ? false : udclion.updraftplus.backupnow;
2102
2103 var impossible_increment_entities;
2104 var incremental_installed = false
2105
2106 if (response.data.output.hasOwnProperty('backupnow_file_entities')) {
2107 impossible_increment_entities = response.data.output.backupnow_file_entities;
2108 }
2109
2110 if (response.data.output.hasOwnProperty('incremental_installed')) {
2111 incremental_installed = response.data.output.incremental_installed;
2112 }
2113
2114 UpdraftCentral.open_modal(udclion.updraftplus.backupnow, response.data.output.html, function() {
2115 var backupnow_nodb = $('#updraftcentral_modal #backupnow_includedb').is(':checked') ? 0 : 1;
2116 var backupnow_nofiles = $('#updraftcentral_modal #backupnow_includefiles').is(':checked') ? 0 : 1;
2117 var backupnow_nocloud = $('#updraftcentral_modal #backupnow_includecloud').is(':checked') ? 0 : 1;
2118 var incremental = ('incremental' == type) ? 1 : 0;
2119
2120 var onlythesefileentities = '';
2121 $('#updraftcentral_modal #backupnow_includefiles_moreoptions input[type="checkbox"]').each(function(index) {
2122 if (!$(this).is(':checked')) { return; }
2123 var name = $(this).attr('name');
2124 if (name.substring(0, 16) != 'updraft_include_') { return; }
2125 var entity = name.substring(16);
2126 if (onlythesefileentities != '') { onlythesefileentities += ','; }
2127 onlythesefileentities += entity;
2128 });
2129
2130 var onlythesetableentities = '';
2131 var send_list = false;
2132 $('#backupnow_database_moreoptions input[type="checkbox"]').each(function(index) {
2133 if (!$(this).is(':checked')) { send_list = true; return; }
2134 });
2135
2136 if (send_list) {
2137 onlythesetableentities = jQuery("input[name^='updraft_include_tables_']").serializeArray();
2138 } else {
2139 onlythesetableentities = true;
2140 }
2141
2142 var send_list_cloud = false;
2143 var onlythesecloudservices = '';
2144 jQuery('#backupnow_includecloud_moreoptions input[type="checkbox"]').each(function(index) {
2145 if (!jQuery(this).is(':checked')) { send_list_cloud = true; return; }
2146 });
2147
2148 if (send_list_cloud) {
2149 onlythesecloudservices = jQuery("input[name^='updraft_include_remote_service_']").serializeArray();
2150 } else {
2151 onlythesecloudservices = true;
2152 }
2153
2154 var always_keep = $('#always_keep').is(':checked') ? 1 : 0;
2155
2156 if ('' == onlythesefileentities && 0 == backupnow_nofiles) {
2157 UpdraftCentral_Library.dialog.alert(udclion.updraftplus.nofileschosen);
2158 return;
2159 }
2160
2161 if ('' == onlythesetableentities && 0 == backupnow_nodb) {
2162 UpdraftCentral_Library.dialog.alert(udclion.updraftplus.notableschosen);
2163 return;
2164 }
2165
2166 if ('' == onlythesecloudservices && 0 == backupnow_nocloud) {
2167 alert(udclion.updraftplus.nocloudserviceschosen);
2168 jQuery('#backupnow_includecloud_moreoptions').show();
2169 return;
2170 }
2171
2172 if (!send_list) {
2173 onlythesetableentities = null;
2174 }
2175
2176 if (!send_list_cloud) {
2177 onlythesecloudservices = null;
2178 }
2179
2180 if (backupnow_nodb && backupnow_nofiles) {
2181 UpdraftCentral_Library.dialog.alert(udclion.updraftplus.excludedeverything);
2182 return;
2183 }
2184
2185 UpdraftCentral.close_modal();
2186
2187 UpdraftCentral_Module_UpdraftPlus.backupnow_go(backupnow_nodb, backupnow_nofiles, backupnow_nocloud, onlythesefileentities, { always_keep: always_keep, incremental: incremental}, $('#updraftcentral_modal #backupnow_label').val(), onlythesetableentities, onlythesecloudservices);
2188 }, action_button, function() {
2189 if (!incremental_installed && 'incremental' == type) {
2190 jQuery('#updraftcentral_modal .incremental-free-only').show();
2191 type = 'new';
2192 } else {
2193 jQuery('#updraftcentral_modal .incremental-backups-only').hide();
2194 }
2195 $('#updraftcentral_modal #backupnow_label').val('');
2196 if ('incremental' == type) {
2197 update_file_entities_checkboxes(true, impossible_increment_entities);
2198 $('#updraftcentral_modal #backupnow_includedb').prop('checked', false);
2199 $('#updraftcentral_modal #backupnow_includefiles').prop('checked', true);
2200 $('#updraftcentral_modal #backupnow_includefiles_label').text(udclion.updraftplus.files_incremental_backup);
2201 $('#updraftcentral_modal .new-backups-only').hide();
2202 $('#updraftcentral_modal .incremental-backups-only').show();
2203 } else {
2204 update_file_entities_checkboxes(false, impossible_increment_entities);
2205 $('#updraftcentral_modal #backupnow_includedb').prop('checked', true);
2206 $('#updraftcentral_modal #backupnow_includefiles_label').text(udclion.updraftplus.files_new_backup);
2207 $('#updraftcentral_modal .new-backups-only').show();
2208 $('#updraftcentral_modal .incremental-backups-only').hide();
2209 }
2210 $('#updraftcentral_modal #backupnow_includefiles_moreoptions').hide();
2211 // Remove the <a> link tab wrapping it, as that goes to the site's WP dashboard
2212 $('#updraftcentral_modal #updraft_backupnow_gotosettings').contents().unwrap();
2213 }, true, 'backup-now');
2214 }
2215 });
2216 }
2217
2218 /**
2219 * This function will enable and disable the file entity options depending on what entities increments can be added to and if this is a new backup or not.
2220 *
2221 * @param {boolean} incremental - a boolean to indicate if this is an incremental backup or not
2222 * @param {array} entities - an array of entities to disable
2223 */
2224 function update_file_entities_checkboxes(incremental, entities) {
2225 if (incremental) {
2226 jQuery(entities).each(function (index, entity) {
2227 jQuery('#updraftcentral_modal #backupnow_files_updraft_include_' + entity).prop('checked', false);
2228 jQuery('#updraftcentral_modal #backupnow_files_updraft_include_' + entity).prop('disabled', true);
2229 });
2230 } else {
2231 jQuery('#updraftcentral_modal #backupnow_includefiles_moreoptions input[type="checkbox"]').each(function (index) {
2232 var name = jQuery(this).attr('name');
2233 if (name.substring(0, 16) != 'updraft_include_') { return; }
2234 var entity = name.substring(16);
2235 jQuery('#updraftcentral_modal #backupnow_files_updraft_include_' + entity).prop('disabled', false);
2236 if (jQuery(this).is(':checked')) {
2237 jQuery('#updraftcentral_modal #backupnow_files_updraft_include_' + entity).prop('checked', true);
2238 }
2239 });
2240 }
2241 }
2242
2243 /**
2244 * Open a modal showing the indicated log file for the indicated site
2245 *
2246 * @param {string} job_id - The UpdraftPlus job identifier string
2247 * @param {Object} $site_row - The jQuery object for the site row that the request is for
2248 *
2249 * @return {void}
2250 */
2251 function updraft_popuplog(job_id, $site_row) {
2252 UpdraftCentral.send_site_rpc('updraftplus.get_log', job_id, $site_row, function(response, code, error_code) {
2253 if ('ok' == code && response) {
2254 UpdraftCentral.open_modal(udclion.updraftplus.logfile, '<pre id="updraft_poppedlog">'+UpdraftCentral_Library.sanitize_html(response.data.log)+'</pre>', function() {
2255 UpdraftCentral_Library.download_inner_html('log.'+job_id+'.txt', 'updraft_poppedlog');
2256 }, udclion.updraftplus.downloadlog, function() {
2257 // Function that gets called after population of modal, before opening
2258 }, null, true, 'modal-lg');
2259 }
2260 });
2261 }
2262
2263 /**
2264 * Open the modal to confirm, and then carry out, deletion of the indicate backup
2265 *
2266 * @param {string} key - A comma-separated list of timestamps of the backups to delete
2267 * @param {string} nonce - the UpdraftPlus job identifier string
2268 * @param {boolean} showremote - whether or not to show the option to also remove the backup from remote storage (if any)
2269 *
2270 * @return {void}
2271 */
2272 function updraft_delete(key, nonce, showremote) {
2273 var delete_question = udclion.updraftplus.delete_areyousure_singular;
2274 if (key.indexOf(',') > -1) {
2275 delete_question = udclion.updraftplus.delete_areyousure_plural;
2276 }
2277
2278 // title, body, action_button_callback, action_button_text, pre_open_callback, sanitize_body
2279 UpdraftCentral.open_modal(
2280 udclion.updraftplus.deletebackupset,
2281 UpdraftCentral.template_replace('updraftplus-deletebackup', {
2282 nonce: nonce,
2283 timestamp: key,
2284 delete_question: delete_question,
2285 also_delete_from_remote: udclion.updraftplus.also_delete_from_remote,
2286 deleting_please_allow_time: udclion.updraftplus.deleting_please_allow_time
2287 }),
2288 function() {
2289 var nonce = $('#updraft_delete_modal_contents').data('nonce').toString();
2290 var timestamps = $('#updraft_delete_modal_contents').data('timestamp').toString();
2291 var delete_remote = 0;
2292 if ($('#updraft_delete_modal_contents #updraft_delete_remote').is(':checked')) {
2293 delete_remote = 1;
2294 }
2295
2296 $('#updraftcentral_modal #updraft-delete-waitwarning').slideDown();
2297
2298 var is_opera = (navigator.userAgent.match(/Opera|OPR\//) ? true : false);
2299
2300 UpdraftCentral.send_site_rpc('updraftplus.deleteset', {
2301 backup_nonce: nonce,
2302 backup_timestamp: timestamps,
2303 delete_remote: delete_remote,
2304 get_history_opts: {
2305 include_opera_warning: is_opera,
2306 include_uploader: false,
2307 will_immediately_calculate_disk_space: false,
2308 include_header: true
2309 }
2310 }, UpdraftCentral.$site_row, function(response, code, error_code) {
2311
2312 $('#updraftcentral_modal #updraft-delete-waitwarning').slideUp();
2313 if ('ok' == code && response) {
2314 var resp = response.data;
2315 if (resp.result != null) {
2316 if (resp.result == 'error') {
2317 UpdraftCentral_Library.dialog.alert('<h2>'+udclion.error+'</h2>'+resp.message);
2318 } else if (resp.result == 'success') {
2319 updraft_get_existing_backups_panel(UpdraftCentral.$site_row);
2320 UpdraftCentral.close_modal();
2321
2322 var message = resp.message;
2323 if ('undefined' === typeof message) {
2324 message = resp.local_message+' '+resp.backup_local;
2325 message += ', '+resp.remote_message+' '+resp.backup_remote;
2326 message += ', '+resp.set_message+' '+resp.backup_sets;
2327 }
2328
2329 UpdraftCentral_Library.dialog.alert('<h2>'+udclion.updraftplus.deleted+'</h2>'+message);
2330 }
2331 }
2332 }
2333
2334 });
2335
2336 },
2337 udclion.updraftplus.delete,
2338 function() {
2339 if (!showremote) {
2340 $('#updraft-delete-remote-section').remove();
2341 } else {
2342 $('#updraft-delete-remote-section, #updraft_delete_remote').prop('disabled', false);
2343 $('#updraft-delete-remote-section, #updraft_delete_remote').show();
2344 }
2345
2346 }
2347 );
2348
2349 }
2350
2351 /**
2352 * Send a command to abort an active backup job_id
2353 *
2354 * @param {string} job_id - the job identifier for the job to be aborted
2355 * @param {Object} $site_row - the jQuery object for the row for the site to send the command to
2356 * @param {Object} site_listener_row - the jQuery object for the listener row associated with the request
2357 *
2358 * @return {void}
2359 */
2360 function updraft_activejobs_delete(job_id, $site_row, site_listener_row) {
2361
2362 UpdraftCentral.send_site_rpc('updraftplus.activejobs_delete', job_id, $site_row, function(response, code, error_code) {
2363 if ('ok' == code && response) {
2364 var msg = '';
2365 if (response.hasOwnProperty('data') && response.data.hasOwnProperty('c')) {
2366 if ('deleted' == response.data.c) {
2367 msg = udclion.updraftplus.delete_deleted;
2368 } else if ('not_found' == response.data.c) {
2369 msg = udclion.updraftplus.delete_not_found;
2370 } else {
2371 console.log("UDCentral: UpdraftPlus: abort job: unknown response");
2372 console.log(response.data);
2373 msg = UpdraftCentral_Library.sanitize_html(response.data.m);
2374 }
2375 } else {
2376 console.log("UDCentral: UpdraftPlus: abort job: unknown response");
2377 console.log(response.data);
2378 msg = udclion.js_exception_occurred;
2379 }
2380 $(site_listener_row).find('.backup_state:first').html(msg);
2381 }
2382 });
2383 }
2384
2385 $('#updraftcentral_notice_container').on('click', '.updraftcentral_listener .updraftplus_downloader_closebutton', function(e) {
2386 e.preventDefault();
2387 var $listener = $(this).closest('.updraftcentral_listener');
2388 $(this).closest('.updraftplus_downloader').fadeOut().remove();
2389 var how_many_downloaders = $listener.find('.updraftplus_downloader').length;
2390 if (how_many_downloaders < 1) {
2391 console.log($listener);
2392 $listener.clearQueue().slideUp('slow', function() {
2393 $(this).remove();
2394 });
2395 }
2396 });
2397
2398 $('#updraftcentral_notice_container').on('click', '.updraftcentral_listener .updraft_downloaded', function(e) {
2399 var site_id = $(this).data('site_id');
2400 var $site_row = $('#updraftcentral_dashboard_existingsites .updraftcentral_site_row[data-site_id="'+site_id+'"');
2401 if ($site_row.length < 1) { return; }
2402 var backup_timestamp = $(this).data('backup_timestamp');
2403 var what = $(this).data('what');
2404 var findex = $(this).data('findex');
2405 UpdraftCentral_Library.open_browser_at($site_row, { module: 'updraftplus', action: 'download_file', data: {
2406 backup_timestamp: backup_timestamp,
2407 what: what,
2408 findex: findex
2409 } }, null);
2410 });
2411
2412 $('#updraftcentral_notice_container').on('click', '.updraftcentral_listener .updraft_delete_downloaded_backup', function(e) {
2413 e.preventDefault();
2414 var delete_button = this;
2415 var site_id = $(this).data('site_id');
2416 var $site_row = $('#updraftcentral_dashboard_existingsites .updraftcentral_site_row[data-site_id="'+site_id+'"');
2417 var findex = $(this).data('findex');
2418 var what = $(this).data('what');
2419 var backup_timestamp = $(this).data('backup_timestamp');
2420 UpdraftCentral.send_site_rpc('updraftplus.delete_downloaded', {
2421 timestamp: backup_timestamp,
2422 site_id: site_id,
2423 type: what,
2424 findex: findex
2425 }, $site_row, function(response, code, error_code) {
2426 if ('ok' == code && false !== response && response.hasOwnProperty('data')) {
2427 $(delete_button).closest('.raw').html(udclion.updraftplus.entity_deleted);
2428 }
2429 });
2430 });
2431
2432 $('#updraftcentral_notice_container, #updraftcentral_dashboard_existingsites').on('click', '.updraftcentral_listener .updraft-log-link, .updraft_existing_backups_output .updraft-log-link', function(e) {
2433 e.preventDefault();
2434 var job_id = $(this).data('jobid');
2435 if (job_id) {
2436 var $site_listener = $(this).closest('.updraftcentral_listener, .updraftcentral_site_row');
2437 var site_id = $site_listener.data('site_id');
2438 var $site_row = $('#updraftcentral_dashboard_existingsites .updraftcentral_site_row[data-site_id="'+site_id+'"');
2439 updraft_popuplog(job_id, $site_row);
2440 } else {
2441 console.log(this);
2442 console.log("UpdraftPlus: A log link was clicked, but the Job ID could not be found");
2443 }
2444 });
2445
2446 $('#updraftcentral_notice_container').on('click', '.updraftcentral_listener .updraft_jobinfo_delete', function(e) {
2447 e.preventDefault();
2448 var job_id = $(this).data('jobid');
2449 if (job_id) {
2450 var $site_listener = $(this).closest('.updraftcentral_listener');
2451 var site_id = $site_listener.data('site_id');
2452 var $site_row = $('#updraftcentral_dashboard_existingsites .updraftcentral_site_row[data-site_id="'+site_id+'"');
2453 updraft_activejobs_delete(job_id, $site_row, $site_listener);
2454 } else {
2455 console.log("UpdraftPlus: A stop job link was clicked, but the Job ID could not be found");
2456 console.log(this);
2457 }
2458 });
2459
2460 /**
2461 * Updates the various bits of widgetry and text associated with the scheduling settings. Suitable for calling when a chosen schedule value (daily/monthly/etc.) changes.
2462 *
2463 * @return {void}
2464 */
2465 function updraft_check_same_times() {
2466 var dbmanual = 0;
2467 var file_interval = $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output .updraft_interval').val();
2468 if (file_interval == 'manual') {
2469 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output .updraft_files_timings').hide();
2470 } else {
2471 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output .updraft_files_timings').show();
2472 }
2473
2474 if ('weekly' == file_interval || 'fortnightly' == file_interval || 'monthly' == file_interval) {
2475 updraft_intervals_monthly_or_not('updraft_startday_files', file_interval);
2476 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output #updraft_startday_files').show();
2477 } else {
2478 $('#updraftcentral_dashboard_existingsites .updraft_monthly_extra_words_updraft_startday_files').remove();
2479 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output #updraft_startday_files').hide();
2480 }
2481
2482 var db_interval = $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output .updraft_interval_database').val();
2483 if (db_interval == 'manual') {
2484 dbmanual = 1;
2485 // $('#updraft_db_timings').css('opacity', '0.25');
2486 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output .updraft_db_timings').hide();
2487 }
2488
2489 if ('weekly' == db_interval || 'fortnightly' == db_interval || 'monthly' == db_interval) {
2490 updraft_intervals_monthly_or_not('updraft_startday_db', db_interval);
2491 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output #updraft_startday_db').show();
2492 } else {
2493 $('#updraftcentral_dashboard_existingsites .updraft_monthly_extra_words_updraft_startday_db').remove();
2494 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output #updraft_startday_db').hide();
2495 }
2496
2497 if (db_interval == file_interval) {
2498 // $('#updraft_db_timings').css('opacity','0.25');
2499 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output .updraft_db_timings').hide();
2500 // $('#updraft_same_schedules_message').show();
2501 if (0 == dbmanual) {
2502 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output .updraft_same_schedules_message').show();
2503 } else {
2504 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output .updraft_same_schedules_message').hide();
2505 }
2506 } else {
2507 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output .updraft_same_schedules_message').hide();
2508 if (0 == dbmanual) {
2509 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output .updraft_db_timings').show();
2510 }
2511 }
2512 }
2513
2514 var updraft_interval_week_val = false;
2515 var updraft_interval_month_val = false;
2516
2517 /**
2518 * This function displays the month-day selector, and adjusts the wording, of the backup scheduling portion of the settings
2519 *
2520 * @param {string} selector_id - the CSS ID to use for finding the element to adjust (according to whether adjusting the files or DB schedule)
2521 * @param {string} now_showing - the currently chosen interval
2522 *
2523 * @return {void}
2524 */
2525 function updraft_intervals_monthly_or_not(selector_id, now_showing) {
2526 var selector = '#updraftcentral_dashboard_existingsites .updraft_site_settings_output #'+selector_id;
2527 var current_length = $(selector+' option').length;
2528 var is_monthly = ('monthly' == now_showing) ? true : false;
2529 var existing_is_monthly = false;
2530 if (current_length > 10) { existing_is_monthly = true; }
2531 if (!is_monthly && !existing_is_monthly) {
2532 return;
2533 }
2534 if (is_monthly && existing_is_monthly) {
2535 if ('monthly' == now_showing) {
2536 // existing_is_monthly does not mean the same as now_showing=='monthly'. existing_is_monthly refers to the drop-down, not whether the drop-down is being displayed. We may need to add these words back.
2537 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output .updraft_monthly_extra_words_'+selector_id).remove();
2538 $(selector).before('<span class="updraft_monthly_extra_words_'+selector_id+'">'+udclion.updraftplus.day+' </span>').after('<span class="updraft_monthly_extra_words_'+selector_id+'"> '+udclion.updraftplus.in_the_month+' </span>');
2539 }
2540 return;
2541 }
2542 $('#updraftcentral_dashboard_existingsites .updraft_site_settings_output .updraft_monthly_extra_words_'+selector_id).remove();
2543 if (is_monthly) {
2544 // Save the old value
2545 updraft_interval_week_val = $(selector+' option:selected').val();
2546 $(selector).html(udclion.updraftplus.mday_selector).before('<span class="updraft_monthly_extra_words_'+selector_id+'">'+udclion.updraftplus.day+' </span>').after('<span class="updraft_monthly_extra_words_'+selector_id+'"> '+udclion.updraftplus.in_the_month+' </span>');
2547 var select_mday = (updraft_interval_month_val === false) ? 1 : updraft_interval_month_val;
2548 // Convert from day of the month (ordinal) to option index (starts at 0)
2549 select_mday = select_mday - 1;
2550 $(selector+" option:eq("+select_mday+")").prop('selected', true);
2551 } else {
2552 // Save the old value
2553 updraft_interval_month_val = $(selector+' option:selected').val();
2554 $(selector).html(udclion.updraftplus.day_selector);
2555 var select_day = (updraft_interval_week_val === false) ? 1 : updraft_interval_week_val;
2556 $(selector+" option:eq("+select_day+")").prop('selected', true);
2557 }
2558 }
2559
2560 var db_index;
2561 var files_index;
2562 /**
2563 * Set up the HTML for the retain rules. This should be called after receiving the settings and rules from the remote end.
2564 *
2565 * @param {array} retain_rules_files - array of retain rules for the files backup
2566 * @param {array} retain_rules_db - array of retain rules for the database backup
2567 *
2568 * @return {void}
2569 */
2570 function setup_retain_rules(retain_rules_files, retain_rules_db) {
2571 // Code for handling the advanced retain rules
2572 db_index = 0;
2573 files_index = 0;
2574 $.each(retain_rules_files, function(index, rule) {
2575 add_rule('files', rule.after_howmany, rule.after_period, rule.every_howmany, rule.every_period);
2576 });
2577
2578 $.each(retain_rules_db, function(index, rule) {
2579 add_rule('db', rule.after_howmany, rule.after_period, rule.every_howmany, rule.every_period);
2580 });
2581 }
2582
2583 /**
2584 * Adds a new advanced retain rule to the relevant section of the settings
2585 *
2586 * @param {string} type - either 'files' or 'db'
2587 * @param {number} howmany_after - how many periods the rule applies after
2588 * @param {number} period_after - the length (in seconds) of the period that the rule applies after
2589 * @param {number} howmany_every - how many periods 1 backup is to be kept for
2590 * @param {number} period_every - the length (in seconds) of the period that 1 backup is to be kept for
2591 *
2592 * @return {void}
2593 */
2594 function add_rule(type, howmany_after, period_after, howmany_every, period_every) {
2595 var selector = 'updraft_retain_'+type+'_rules';
2596 var index;
2597 if ('db' == type) {
2598 db_index++;
2599 index = db_index;
2600 } else {
2601 files_index++;
2602 index = files_index;
2603 }
2604 $('#'+selector).append(
2605 '<div style="float:left; clear:left;" class="updraft_retain_rules '+selector+'_entry">'+
2606 udclion.updraftplus.for_backups_older_than+' '+rule_period_selector(type, index, 'after', howmany_after, period_after)+' keep no more than 1 backup every '+rule_period_selector(type, index, 'every', howmany_every, period_every)+
2607 ' <span title="'+udclion.updraftplus.delete+'" class="updraft_retain_rules_delete"><span class="dashicons dashicons-no"></span></span></div>'
2608 )
2609 }
2610
2611 /**
2612 * Returns the HTML for creating a dropdown <select> widget
2613 *
2614 * @param {string} type - either 'files' or 'db'
2615 * @param {number} index - the rule number, used for constructing the name attribute
2616 * @param {string} which - drop-down type - either 'every' or 'after'
2617 * @param {number} howmany_value - the number of periods of time
2618 * @param {number} period - the length (in seconds) of each period of time
2619 *
2620 * @return {void}
2621 */
2622 function rule_period_selector(type, index, which, howmany_value, period) {
2623 var nameprefix = "updraft_retain_extrarules["+type+"]["+index+"]["+which+"-";
2624 var ret = '<input type="number" min="1" step="1" class="additional-rule-width" name="'+nameprefix+'howmany]" value="'+howmany_value+'"> \
2625 <select name="'+nameprefix+'period]">\
2626 <option value="3600"';
2627 if (period == 3600) { ret += ' selected="selected"'; }
2628 ret += '>'+udclion.updraftplus.hours+'</option>\
2629 <option value="86400"';
2630 if (period == 86400) { ret += ' selected="selected"'; }
2631 ret += '>'+udclion.updraftplus.days+'</option>\
2632 <option value="604800"';
2633 if (period == 604800) { ret += ' selected="selected"'; }
2634 ret += '>'+udclion.updraftplus.weeks+'</option>\
2635 </select>';
2636 return ret;
2637 }
2638
2639 /**
2640 * Set up the status of the 'exclude' field (relevant to backing up uploads, others, WordPress Core)
2641 *
2642 * @param {string} field - the entity type ('uploads', 'others', 'wpcore')
2643 * @param {boolean} instant - whether to simply show/hide, or whether to apply an effect
2644 *
2645 * @return {void}
2646 */
2647 function setup_file_entity_exclude_field(field, instant) {
2648 if ($('.updraftcentral_row_extracontents .updraft_site_settings_output #updraft_include_'+field).is(':checked')) {
2649 if (instant) {
2650 $('.updraftcentral_row_extracontents .updraft_site_settings_output #updraft_include_'+field+'_exclude').show();
2651 } else {
2652 $('.updraftcentral_row_extracontents .updraft_site_settings_output #updraft_include_'+field+'_exclude').slideDown();
2653 }
2654 } else {
2655 if (instant) {
2656 $('.updraftcentral_row_extracontents .updraft_site_settings_output #updraft_include_'+field+'_exclude').hide();
2657 } else {
2658 $('.updraftcentral_row_extracontents .updraft_site_settings_output #updraft_include_'+field+'_exclude').slideUp();
2659 }
2660 }
2661 }
2662
2663 var reportbox_index = 1;
2664
2665 /**
2666 * Inserts remote storage label if its currently not present
2667 *
2668 * @param {string} method The remote storage method whose tab is to be activated. Corresponds to UD's internal method string identifiers (e.g. s3, dropbox, etc.)
2669 * @param {integer} instance_id A unique key/id for a group of form elements created for remote storage entry
2670 *
2671 * @return {void}
2672 */
2673 function maybe_insert_remote_label(method, instance_id) {
2674 var prefix = '#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output';
2675 var default_label = $('#remote-storage-container label[for="updraft_servicecheckbox_'+method+'"] > .labelauty-checked').text();
2676
2677 var attrib = ('undefined' !== typeof instance_id) ? '[data-instance_id="'+instance_id+'"]' : '';
2678 var instance_label = $(prefix+' .updraftplusmethod.'+method).find('h3.updraft_edit_label_instance'+attrib);
2679 if ('undefined' !== typeof instance_label && instance_label) {
2680 var label = instance_label.text().trim();
2681 if ('(' == label.charAt(0) || 0 == label.length) {
2682 instance_label.prepend(default_label+' ');
2683 }
2684 }
2685 }
2686
2687 /**
2688 * Update field description with regard to adding additional paths to backup
2689 *
2690 * @return {void}
2691 */
2692 function update_additional_path_description() {
2693 var field_desc = $('#updraft_include_more_options p.updraft-field-description');
2694 if ('undefined' !== typeof field_desc && field_desc) {
2695 // We currently don't use directory tree (jsTree) selection in UpdraftCentral thus, we
2696 // display an alternative field description for entering additional paths to backup
2697 // since the original text displayed were downloaded as part of the template from the
2698 // remote site where UpdraftPlus was installed therefore, we need to replace it.
2699 field_desc.html(udclion.updraftplus.directory_field_desc);
2700 }
2701 }
2702
2703 /**
2704 * Activate the specified tab within the remote storage section
2705 *
2706 * @param {string} the_method - the remote storage method whose tab is to be activated. Corresponds to UD's internal method string identifiers (e.g. s3, dropbox, etc.)
2707 *
2708 * @return {void}
2709 */
2710 function updraft_remote_storage_tab_activation(the_method) {
2711 var prefix = '#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output';
2712 $(prefix+' .updraftplusmethod').hide();
2713 $(prefix+' .remote-tab').data('active', false);
2714 $(prefix+' .remote-tab').removeClass('nav-tab-active');
2715 $(prefix+' .updraftplusmethod.'+the_method).show();
2716 $(prefix+' .remote-tab-'+the_method).data('active', true);
2717 $(prefix+' .remote-tab-'+the_method).addClass('nav-tab-active');
2718
2719 maybe_insert_remote_label(the_method);
2720 }
2721
2722 var remote_storage_tabs_any_checked = 0;
2723
2724 /**
2725 * Set the initial state of the remote storage options, depending on the currently selected option(s). Includes labelauty setup.
2726 *
2727 * @return {void}
2728 */
2729 function updraft_remote_storage_tabs_setup() {
2730
2731 remote_storage_tabs_any_checked = 0;
2732 var set = $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .updraft_servicecheckbox:checked');
2733
2734 $(set).each(function(ind, obj) {
2735 var ser = $(obj).val();
2736
2737 if ($(obj).attr('id') != 'updraft_servicecheckbox_none') {
2738 remote_storage_tabs_any_checked++;
2739 }
2740
2741 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .remote-tab-'+ser).show();
2742 if (ind == $(set).length-1) {
2743 updraft_remote_storage_tab_activation(ser);
2744 }
2745 });
2746
2747 if (remote_storage_tabs_any_checked > 0) {
2748 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .updraftplusmethod.none').hide();
2749 } else {
2750 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .updraftplusmethod:not(.none)').hide();
2751 $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .updraftplusmethod.none').show();
2752 }
2753
2754 var servicecheckbox = $('#updraftcentral_dashboard_existingsites .updraftcentral_row_extracontents .updraft_site_settings_output .updraft_servicecheckbox');
2755 if (typeof servicecheckbox.labelauty === 'function') { servicecheckbox.labelauty(); }
2756
2757 }
2758
2759 }
2760