diff --git a/packages/block-editor/src/components/background-image-control/index.js b/packages/block-editor/src/components/background-image-control/index.js index 3411d7d3ee8a9..62bffb54218c5 100644 --- a/packages/block-editor/src/components/background-image-control/index.js +++ b/packages/block-editor/src/components/background-image-control/index.js @@ -313,12 +313,6 @@ function BackgroundImageControls( { // Drag and drop callback, restricting image to one. const onFilesDrop = ( filesList ) => { - if ( filesList?.length > 1 ) { - onUploadError( - __( 'Only one image can be used as a background image.' ) - ); - return; - } getSettings().mediaUpload( { allowedTypes: [ IMAGE_BACKGROUND_TYPE ], filesList, @@ -326,6 +320,7 @@ function BackgroundImageControls( { onSelectMedia( image ); }, onError: onUploadError, + multiple: false, } ); }; diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index e19e350f959b2..3d6578dcd39c2 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -227,6 +227,7 @@ export function MediaPlaceholder( { filesList: files, onFileChange: setMedia, onError, + multiple, } ); }; diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index d2d2327736fd7..f1ba371bfb35e 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -499,11 +499,6 @@ export default function LogoEdit( { }; const onFilesDrop = ( filesList ) => { - if ( filesList?.length > 1 ) { - onUploadError( __( 'Only one image can be used as a site logo.' ) ); - return; - } - getSettings().mediaUpload( { allowedTypes: ALLOWED_MEDIA_TYPES, filesList, @@ -515,6 +510,7 @@ export default function LogoEdit( { onInitialSelectLogo( image ); }, onError: onUploadError, + multiple: false, } ); }; diff --git a/packages/editor/README.md b/packages/editor/README.md index bbea89105419c..d0140df088845 100644 --- a/packages/editor/README.md +++ b/packages/editor/README.md @@ -501,6 +501,7 @@ _Parameters_ - _$0.onError_ `Function`: Function called when an error happens. - _$0.onFileChange_ `Function`: Function called each time a file or a temporary representation of the file is available. - _$0.onSuccess_ `Function`: Function called after the final representation of the file is available. +- _$0.multiple_ `boolean`: Whether to allow multiple files to be uploaded. ### MediaUploadCheck diff --git a/packages/editor/src/components/post-featured-image/index.js b/packages/editor/src/components/post-featured-image/index.js index acf366506cc41..cf7ba1664b8ba 100644 --- a/packages/editor/src/components/post-featured-image/index.js +++ b/packages/editor/src/components/post-featured-image/index.js @@ -125,6 +125,7 @@ function PostFeaturedImage( { noticeOperations.removeAllNotices(); noticeOperations.createErrorNotice( message ); }, + multiple: false, } ); } @@ -345,6 +346,7 @@ const applyWithDispatch = withDispatch( noticeOperations.removeAllNotices(); noticeOperations.createErrorNotice( message ); }, + multiple: false, } ); }, onRemoveImage() { diff --git a/packages/editor/src/utils/media-upload/index.js b/packages/editor/src/utils/media-upload/index.js index 0d970d91ce745..02b2a039330d6 100644 --- a/packages/editor/src/utils/media-upload/index.js +++ b/packages/editor/src/utils/media-upload/index.js @@ -28,6 +28,7 @@ const noop = () => {}; * @param {Function} $0.onError Function called when an error happens. * @param {Function} $0.onFileChange Function called each time a file or a temporary representation of the file is available. * @param {Function} $0.onSuccess Function called after the final representation of the file is available. + * @param {boolean} $0.multiple Whether to allow multiple files to be uploaded. */ export default function mediaUpload( { additionalData = {}, @@ -37,6 +38,7 @@ export default function mediaUpload( { onError = noop, onFileChange, onSuccess, + multiple = true, } ) { const { getCurrentPost, getEditorSettings } = select( editorStore ); const { @@ -92,5 +94,6 @@ export default function mediaUpload( { onError( message ); }, wpAllowedMimeTypes, + multiple, } ); } diff --git a/packages/media-utils/README.md b/packages/media-utils/README.md index ddf18efb28833..a87aaf89618d9 100644 --- a/packages/media-utils/README.md +++ b/packages/media-utils/README.md @@ -56,6 +56,7 @@ _Parameters_ - _$0.onFileChange_ `UploadMediaArgs[ 'onFileChange' ]`: Function called each time a file or a temporary representation of the file is available. - _$0.wpAllowedMimeTypes_ `UploadMediaArgs[ 'wpAllowedMimeTypes' ]`: List of allowed mime types and file extensions. - _$0.signal_ `UploadMediaArgs[ 'signal' ]`: Abort signal. +- _$0.multiple_ `UploadMediaArgs[ 'multiple' ]`: Whether to allow multiple files to be uploaded. ### validateFileSize diff --git a/packages/media-utils/src/utils/test/upload-media.ts b/packages/media-utils/src/utils/test/upload-media.ts index b5075255ad4c8..ee6276557ed79 100644 --- a/packages/media-utils/src/utils/test/upload-media.ts +++ b/packages/media-utils/src/utils/test/upload-media.ts @@ -196,4 +196,18 @@ describe( 'uploadMedia', () => { ); expect( uploadToServer ).not.toHaveBeenCalled(); } ); + + it( 'should throw error when multiple files are selected in single file upload mode', async () => { + const onError = jest.fn(); + await uploadMedia( { + filesList: [ imageFile, xmlFile ], + onError, + multiple: false, + } ); + + expect( onError ).toHaveBeenCalledWith( + new Error( 'Only one file can be used here.' ) + ); + expect( uploadToServer ).not.toHaveBeenCalled(); + } ); } ); diff --git a/packages/media-utils/src/utils/upload-media.ts b/packages/media-utils/src/utils/upload-media.ts index ff3f718076512..4b600f983c571 100644 --- a/packages/media-utils/src/utils/upload-media.ts +++ b/packages/media-utils/src/utils/upload-media.ts @@ -42,6 +42,8 @@ interface UploadMediaArgs { wpAllowedMimeTypes?: Record< string, string > | null; // Abort signal. signal?: AbortSignal; + // Whether to allow multiple files to be uploaded. + multiple?: boolean; } /** @@ -57,6 +59,7 @@ interface UploadMediaArgs { * @param $0.onFileChange Function called each time a file or a temporary representation of the file is available. * @param $0.wpAllowedMimeTypes List of allowed mime types and file extensions. * @param $0.signal Abort signal. + * @param $0.multiple Whether to allow multiple files to be uploaded. */ export function uploadMedia( { wpAllowedMimeTypes, @@ -67,7 +70,13 @@ export function uploadMedia( { onError, onFileChange, signal, + multiple = true, }: UploadMediaArgs ) { + if ( ! multiple && filesList.length > 1 ) { + onError?.( new Error( __( 'Only one file can be used here.' ) ) ); + return; + } + const validFiles = []; const filesSet: Array< Partial< Attachment > | null > = [];