DEV: Fix uploadHandler impl. in composer-upload-uppy mixin (#15105)

In f6528afa01 I added parity support
for composer upload handlers to the uppy-ized composer. However the
way I assumed that it was only possible to handle a single file
upload at a time was false; it only appeared this way in the old
jQuery file upload composer because jQuery file upload sent through
files one at a time even if multiple were added at once. This caused
issues in certain plugins and themes by third parties.

This commit fixes the issue by making the uppy upload handler work
the same as the old one, by capturing all of the added files that
have matching handlers then going through them one by one and passing
them to the handler function.
This commit is contained in:
Martin Brennan 2021-11-29 08:32:06 +10:00 committed by GitHub
parent 7c572d0472
commit e464958333
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 29 additions and 14 deletions

View File

@ -140,24 +140,36 @@ export default Mixin.create(ExtendableUploader, UppyS3Multipart, {
},
onBeforeUpload: (files) => {
const fileCount = Object.keys(files).length;
const maxFiles = this.siteSettings.simultaneous_uploads;
// Look for a matching file upload handler contributed from a plugin.
// It is not ideal that this only works for single file uploads, but
// at this time it is all we need. In future we may want to devise a
// nicer way of doing this. Uppy plugins are out of the question because
// there is no way to define which uploader plugin handles which file
// extensions at this time.
if (fileCount === 1) {
const file = Object.values(files)[0];
// In future we may want to devise a nicer way of doing this.
// Uppy plugins are out of the question because there is no way to
// define which uploader plugin handles which file extensions at this time.
const uploadHandlerFiles = [];
const unhandledFiles = {};
for (const [fileId, file] of Object.entries(files)) {
const matchingHandler = this._findMatchingUploadHandler(file.name);
if (matchingHandler && !matchingHandler.method(file.data, this)) {
return this._abortAndReset();
if (matchingHandler) {
uploadHandlerFiles.push([file, matchingHandler]);
} else {
unhandledFiles[fileId] = { ...files[fileId] };
}
}
// Limit the number of simultaneous uploads
// This replicates what the old composer upload handler did; because
// jQuery file uploader passed through a single file at a time to
// the upload handlers.
uploadHandlerFiles.forEach((fileWithHandler) => {
const [file, matchingHandler] = fileWithHandler;
if (matchingHandler && !matchingHandler.method(file.data, this)) {
return this._abortAndReset();
}
});
// Limit the number of simultaneous uploads, for files which have
// _not_ been handled by an upload handler.
const fileCount = Object.keys(unhandledFiles).length;
if (maxFiles > 0 && fileCount > maxFiles) {
bootbox.alert(
I18n.t("post.errors.too_many_dragged_and_dropped_files", {
@ -166,6 +178,9 @@ export default Mixin.create(ExtendableUploader, UppyS3Multipart, {
);
return this._abortAndReset();
}
// uppy uses this new object to track progress of remaining files
return unhandledFiles;
},
});
@ -196,14 +211,14 @@ export default Mixin.create(ExtendableUploader, UppyS3Multipart, {
});
this._uppyInstance.on("file-removed", (file, reason) => {
file.meta.cancelled = true;
// we handle the cancel-all event specifically, so no need
// to do anything here
// to do anything here. this event is also fired when some files
// are handled by an upload handler
if (reason === "cancel-all") {
return;
}
file.meta.cancelled = true;
this._removeInProgressUpload(file.id);
this._resetUpload(file, { removePlaceholder: true });
if (this.inProgressUploads.length === 0) {