1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-02-27 13:32:33 +01:00
Marc Alexander c810f1934e [ticket/11916] Remove files from hidden attach list after deletion
The hidden attachment_data list needs to be updated if a file got removed.
This was not done until now and caused a general error after submitting a
post if a file was removed after uploading it.

PHPBB3-11916
2013-10-23 11:50:41 +02:00

305 lines
8.6 KiB
JavaScript

plupload.addI18n(phpbb.plupload.i18n);
plupload.attachment_data = [];
/**
* Returns the index of the plupload.attachment_data array where the given
* attach id appears
*
* @param int id The attachment id of the file
*
* @return bool Returns false if the id cannot be found
* @return int Returns the index in the main array where the attachment id
* was found
*/
function phpbb_plupload_find_attachment_idx(id) {
var data = plupload.attachment_data;
for (var i = 0; i < data.length; i++) {
if (data[i].attach_id == id) {
return i;
}
}
return false;
}
/**
* Converts an array of objects into an object that PHP would expect as POST
* data
*
* @return object An object in the form 'attachment_data[i][key]': value as
* expected by the server
*/
function phpbb_plupload_attachment_data_serialize() {
var obj = {};
for (var i = 0; i < plupload.attachment_data.length; i++) {
var datum = plupload.attachment_data[i];
for (var key in datum) {
if (!datum.hasOwnProperty(key)) {
continue;
}
obj['attachment_data[' + i + '][' + key + ']'] = datum[key];
}
}
return obj;
}
/**
* Unsets all elements in an object whose keys begin with 'attachment_data['
*
* @param object The object to be cleared
*
* @return undefined
*/
function phpbb_plupload_clear_params(obj) {
for (var key in obj) {
if (!obj.hasOwnProperty(key) || key.indexOf('attachment_data[') !== 0) {
continue;
}
delete obj[key];
}
}
/**
* Update hidden attachment inputs in posting form
* Pre-existing hidden inputs will be removed by comparing the old attachment
* data (old_data) to the new attachment data (data) that has been sent back
* by plupload.
*
* @param object form Posting form
* @param object data Current attachment_data
* @param object old_date Previous attachment_data (before submission)
*
* @return void
*/
phpbb.update_hidden_attachment_inputs = function(form, data, old_data) {
// Update already existing hidden inputs
for (var i = 0; i < form.length; i++) {
if (data.hasOwnProperty(form[i].name)) {
form[i].value = data[form[i].name];
delete data[form[i].name];
} else if (typeof old_data !== 'undefined' && old_data.hasOwnProperty(form[i].name)) {
var inputRegex = /\b^[a-z_]+[+[0-9]+]/;
var inputName = inputRegex.exec(form[i].name);
if (typeof inputName !== 'undefined' && inputName[0] !== '') {
$("input[type='hidden'][name^='" + inputName[0] + "']").remove();
}
}
}
// Append new inputs
for (var key in data) {
if (!data.hasOwnProperty(key)) {
continue;
}
var input = $('<input />')
.attr('type', 'hidden')
.attr('name', key)
.attr('value', data[key]);
$(form).append(input);
}
}
jQuery(function($) {
$(phpbb.plupload.config.element_hook).pluploadQueue(phpbb.plupload.config);
var uploader = $(phpbb.plupload.config.element_hook).pluploadQueue();
// Check the page for already-existing attachment data and add it to the
// array
var form = $(phpbb.plupload.config.form_hook)[0];
for (var i = 0; i < form.length; i++) {
if (form[i].name.indexOf('attachment_data[') !== 0) {
continue;
}
var matches = form[i].name.match(/\[(\d+)\]\[([^\]]+)\]/);
var index = matches[1];
var property = matches[2];
if (!plupload.attachment_data[index]) {
plupload.attachment_data[index] = {};
}
plupload.attachment_data[index][property] = form[i].value;
uploader.settings.multipart_params[form[i].name] = form[i].value;
}
/**
* Fires before a given file is about to be uploaded. This allows us to
* send the real filename along with the chunk. This is necessary because
* for some reason the filename is set to 'blob' whenever a file is chunked
*
* @param object up The plupload.Uploader object
* @param object file The plupload.File object that is about to be
* uploaded
*
* @return undefined
*/
uploader.bind('BeforeUpload', function(up, file) {
up.settings.multipart_params = $.extend(
up.settings.multipart_params,
{'real_filename': file.name}
);
});
/**
* Fired when a single chunk of any given file is uploaded. This parses the
* response from the server and checks for an error. If an error occurs it
* is reported to the user and the upload of this particular file is halted
*
* @param object up The plupload.Uploader object
* @param object file The plupload.File object whose chunk has just
* been uploaded
* @param object response The response object from the server
*
* @return undefined
*/
uploader.bind('ChunkUploaded', function(up, file, response) {
if (response.chunk >= response.chunks - 1) {
return;
}
var json = {};
try {
json = $.parseJSON(response.response);
} catch (e) {
file.status = plupload.FAILED;
up.trigger('FileUploaded', file, {
response: JSON.stringify({
error: {
message: 'Error parsing server response.'
}
})
});
}
if (json.error) {
file.status = plupload.FAILED;
up.trigger('FileUploaded', file, {
response: JSON.stringify({
error: {
message: json.error.message
}
})
});
}
});
/**
* Fires when an entire file has been uploaded. It checks for errors
* returned by the server otherwise parses the list of attachment data and
* appends it to the next file upload so that the server can maintain state
* with regards to the attachments in a given post
*
* @param object up The plupload.Uploader object
* @param object file The plupload.File object that has just been
* uploaded
* @param string response The response string from the server
*
* @return undefined
*/
uploader.bind('FileUploaded', function(up, file, response) {
var json = {};
try {
json = $.parseJSON(response.response);
} catch (e) {
file.status = plupload.FAILED;
file.error = 'Error parsing server response.'
}
if (json.error) {
file.status = plupload.FAILED;
file.error = json.error.message;
} else if (file.status === plupload.DONE) {
plupload.attachment_data = json;
file.attachment_data = json[0];
up.settings.multipart_params = $.extend(
up.settings.multipart_params,
phpbb_plupload_attachment_data_serialize()
);
}
});
/**
* Fires when the entire queue of files have been uploaded. It resets the
* 'add files' button to allow more files to be uploaded and also attaches
* several events to each row of the currently-uploaded files to facilitate
* deleting any one of the files.
*
* Deleting a file removes it from the queue and fires an ajax event to the
* server to tell it to remove the temporary attachment. The server
* responds with the updated attachment data list so that any future
* uploads can maintain state with the server
*
* @param object up The plupload.Uploader object
* @param array files An array of plupload.File objects that have just
* been uploaded as part of a queue
*
* @return undefined
*/
uploader.bind('UploadComplete', function(up, files) {
$('.plupload_upload_status').css('display', 'none');
$('.plupload_buttons').css('display', 'block');
// Insert a bunch of hidden input elements containing the attachment
// data so that the save/preview/submit buttons work as expected.
var form = $(phpbb.plupload.config.form_hook)[0];
var data = phpbb_plupload_attachment_data_serialize();
phpbb.update_hidden_attachment_inputs(form, data);
files.forEach(function(file) {
if (file.status !== plupload.DONE) {
var click = function(evt) {
alert(file.error);
}
$('#' + file.id).attr('title', file.error);
$('#' + file.id).click(click);
return;
}
var click = function(evt) {
$(evt.target).find('a').addClass('working');
// The index is always found because file.attachment_data is
// just an element of plupload.attachment_data
var idx = phpbb_plupload_find_attachment_idx(file.attachment_data.attach_id);
var fields = {};
fields['delete_file[' + idx + ']'] = 1;
var always = function() {
$(evt.target).find('a').removeClass('working');
};
var done = function(response) {
up.removeFile(file);
plupload.attachment_data = response;
phpbb.update_hidden_attachment_inputs(form, phpbb_plupload_attachment_data_serialize(), data);
phpbb_plupload_clear_params(up.settings.multipart_params);
up.settings.multipart_params = $.extend(
up.settings.multipart_params,
phpbb_plupload_attachment_data_serialize()
);
};
$.ajax(phpbb.plupload.config.url, {
type: 'POST',
data: $.extend(fields, phpbb_plupload_attachment_data_serialize()),
headers: {'X-PHPBB-USING-PLUPLOAD': '1'}
})
.always(always)
.done(done);
};
$('#' + file.id)
.addClass('can_delete')
.click(click);
});
});
});