RSFormPro.Backup = { forms: [], submissionsCount: {}, // Request limiting variables formsPerRequest: 5, submissionsPerRequest: 100, // Progress variables progressUnit: 0, progressCount: 0, // Request key key: '', requestTimeOut: { Seconds : 0, Milliseconds: function(){ return RSFormPro.Backup.requestTimeOut.Seconds * 1000; } }, parseJSON: function(data) { if (typeof data != 'object') { // parse invalid data: var match = data.match(/{.*}/); if (match) { return jQuery.parseJSON(match[0]); } else { var serverError = ''; var matchedError = data.match(/error.*/); if (matchedError) { serverError = matchedError[0].replace(/(<([^>]+)>)/ig, '').substring(0, 255); } RSFormPro.Backup.showError(Joomla.JText._('RSFP_JSON_DECODING_ERROR').replace('%s', serverError)); return false; } } return jQuery.parseJSON(data); }, // Shows an error message if something goes wrong and stops the backup process. showError: function(message) { RSFormPro.Backup.clearError(); jQuery('.progressBar').css('background', '#b94a48'); return jQuery('.progressWrapper').after('<div class="alert alert-error"><strong>' + Joomla.JText._('RSFP_ERROR') + '</strong> ' + message + '</div>'); }, clearError: function() { jQuery('.alert').remove(); }, // Shows the current status (text) of the backup progress showStatus: function(message) { jQuery('.alert').remove(); return jQuery('.progressWrapper').after('<div class="alert alert-info"><strong>' + Joomla.JText._('RSFP_STATUS') + '</strong> ' + message + '</div>'); }, // Helper to parse the JSON response based on several conditions parseResponse: function(data, textStatus, jqXHR){ if (data.status == 'error') { RSFormPro.Backup.showError(data.message); } else if (data.status == 'ok') { RSFormPro.Backup.progress(); // If key has been supplied, store it. if (data.key) { RSFormPro.Backup.key = data.key; } switch (data.step) { // Continue requesting form structure to be saved. case 'forms': RSFormPro.Backup.sendRequest('storeForms', { 'forms': RSFormPro.Backup.forms.splice(0, RSFormPro.Backup.formsPerRequest), // Keep splicing the array until there's nothing left }); RSFormPro.Backup.showStatus(Joomla.JText._('RSFP_STATUS_BACKING_UP_FORM_STRUCTURE_LEFT').replace('%d', RSFormPro.Backup.forms.length)); break; // Continue requesting submissions to be saved. case 'prepare-submissions': case 'next-form-submissions': case 'submissions': if (jQuery('#jform_submissions1').prop('checked') ? 1 : 0) { // This is done as a first step so that we can populate the forms array once. // Submissions are done per form at this point. if (data.step == 'prepare-submissions') { RSFormPro.Backup.grabSelectedForms(); } // Grab the next (or first) form var form; if (data.step == 'next-form-submissions' || data.step == 'prepare-submissions') { var nextForm = RSFormPro.Backup.forms.splice(0, 1); if (nextForm.length > 0) { form = nextForm[0]; } } else { // Still working on current form form = data.form; } if (form) { RSFormPro.Backup.sendRequest('storeSubmissions', { 'limit': RSFormPro.Backup.submissionsPerRequest, 'start': data.start ? data.start : 0, 'header': data.header ? data.header : 0, 'form': form }); var submissionsLeft = RSFormPro.Backup.submissionsCount[form] - parseFloat(data.start ? data.start : 0); if (submissionsLeft < 0) { submissionsLeft = 0; } if (submissionsLeft) { RSFormPro.Backup.showStatus(Joomla.JText._('RSFP_STATUS_BACKING_UP_FORM_SUBMISSIONS_LEFT').replace('%d', form).replace('%d', submissionsLeft)); } else { RSFormPro.Backup.showStatus(Joomla.JText._('RSFP_STATUS_FINISHING_UP_SUBMISSIONS_FOR_FORM').replace('%d', form)); } } else { RSFormPro.Backup.sendRequest('prepareGzip'); } } else { RSFormPro.Backup.sendRequest('prepareGzip'); } break; // Continue adding files to the GZIP archive. case 'prepare-gzip': case 'compress-gzip': RSFormPro.Backup.showStatus(Joomla.JText._('RSFP_STATUS_COMPRESSING_FILES')); if (data.step == 'prepare-gzip') { // Let's see how many steps are needed RSFormPro.Backup.progressUnit = 100 / parseFloat(data.chunks); // Reset to 0% RSFormPro.Backup.progress(true); } RSFormPro.Backup.sendRequest('compressGzip', { 'seek': data.seek ? data.seek : 0, }); break; case 'done': RSFormPro.Backup.toggle(); document.getElementById('backupKey').value = RSFormPro.Backup.key; Joomla.submitbutton('backup.download'); break; } } }, // Helper - sends a task request to index.php?option=com_rsform&controller=backup and passes the response to the parseResponse() function. sendRequest: function(task, data) { if (!data) { data = {}; } data['option'] = 'com_rsform'; data['controller'] = 'backup'; data['task'] = task; if (RSFormPro.Backup.key.length > 0) { data['key'] = RSFormPro.Backup.key; } if (RSFormPro.Backup.requestTimeOut.Seconds != 0 && task !='start') { setTimeout(function(){RSFormPro.Backup.ajaxRequest(data)}, RSFormPro.Backup.requestTimeOut.Milliseconds()); } else { RSFormPro.Backup.ajaxRequest(data); } }, ajaxRequest : function(data) { jQuery.ajax({ converters: { "text json": RSFormPro.Backup.parseJSON }, type: "POST", url: 'index.php?option=com_rsform', data: data, success: RSFormPro.Backup.parseResponse, dataType: 'json' }); }, // Helper function to adjust the progress by a unit. progress: function(reset) { var bar = jQuery('.progressBar'); var current = RSFormPro.Backup.progressCount += RSFormPro.Backup.progressUnit; if (reset) { current = 0; RSFormPro.Backup.progressCount = 0; } if (current > 100) { current = 100; } bar.animate({'width': current + '%'}, { 'duration': 'fast', 'step': function(now, tween) { bar.html(Math.round(now) + '%'); } }); }, // Helper function that populates the this.forms array grabSelectedForms: function() { RSFormPro.Backup.forms = []; jQuery(document.getElementsByName('cid[]')).each(function(index, el){ if (jQuery(el).prop('checked')) { RSFormPro.Backup.forms.push(jQuery(el).val()); } }); }, // Starts the backup process start: function() { RSFormPro.Backup.toggle(); RSFormPro.Backup.grabSelectedForms(); // Time to calculate the number of steps so that we can show a nice progress bar. var steps = 0; // +1 from the start() request. steps++; // + number of forms steps += Math.ceil(RSFormPro.Backup.forms.length / RSFormPro.Backup.formsPerRequest); // +1 from the empty forms AJAX request (when the forms array is empty) steps++; if (jQuery('#jform_submissions1').prop('checked')) { for (var i = 0; i < RSFormPro.Backup.forms.length; i++) { steps += Math.ceil(RSFormPro.Backup.submissionsCount[RSFormPro.Backup.forms[i]] / RSFormPro.Backup.submissionsPerRequest); // +1 from the "next-form-submissions" step (when there are no more submissions to load from the db) steps++; } } RSFormPro.Backup.progressUnit = 100 / steps; RSFormPro.Backup.sendRequest('start', { 'forms': RSFormPro.Backup.forms, 'submissions': jQuery('#jform_submissions1').prop('checked') ? 1 : 0, }); }, // Toggles the display and availability of controls toggle: function() { var progress = jQuery('.progressWrapper'); var button = jQuery('#backupButton'); var forms = jQuery('#formsList'); // If the progress wrapper is shown, then we have to hide it and re-enable elements var shown = progress.is(':visible'); shown ? progress.fadeOut() : progress.fadeIn(); shown ? button.show() : button.hide(); shown ? forms.show() : forms.hide(); // If we're re-enabling elements we must clear the error as well. if (shown) { RSFormPro.Backup.clearError(); RSFormPro.Backup.forms = []; RSFormPro.Backup.progressUnit = 0; RSFormPro.Backup.progressCount = 0; RSFormPro.Backup.progress(true); } } } Joomla.submitbutton = function(task) { if (task === 'backup.start') { return RSFormPro.Backup.start(); } Joomla.submitform(task); }