diff --git a/utils/mediaupload.js b/utils/mediaupload.js index 59b726b6b083c..abea32723927d 100644 --- a/utils/mediaupload.js +++ b/utils/mediaupload.js @@ -1,7 +1,7 @@ /** * External Dependencies */ -import { compact, forEach, get, includes, noop, startsWith } from 'lodash'; +import { compact, flatMap, forEach, get, includes, map, noop, startsWith } from 'lodash'; /** * WordPress dependencies @@ -13,6 +13,30 @@ import { __, sprintf } from '@wordpress/i18n'; */ import apiRequest from '@wordpress/api-request'; +/** + * Browsers may use unexpected mime types, and they differ from browser to browser. + * This function computes a flexible array of mime types from the mime type structured provided by the server. + * Converts { jpg|jpeg|jpe: "image/jpeg" } into [ "image/jpeg", "image/jpg", "image/jpeg", "image/jpe" ] + * The computation of this array instead of directly using the object, + * solves the problem in chrome where mp3 files have audio/mp3 as mime type instead of audio/mpeg. + * https://bugs.chromium.org/p/chromium/issues/detail?id=227004 + * + * @param {?Object} wpMimeTypesObject Mime type object received from the server. + * Extensions are keys separated by '|' and values are mime types associated with an extension. + * + * @return {?Array} Media Object Promise. + */ +export function getMimeTypesArray( wpMimeTypesObject ) { + if ( ! wpMimeTypesObject ) { + return wpMimeTypesObject; + } + return flatMap( wpMimeTypesObject, ( mime, extensionsString ) => { + const [ type ] = mime.split( '/' ); + const extensions = extensionsString.split( '|' ); + return [ mime, ...map( extensions, ( extension ) => `${ type }/${ extension }` ) ]; + } ); +} + /** * Media Upload is used by audio, image, gallery and video blocks to handle uploading a media file * when a file upload button is activated. @@ -48,7 +72,7 @@ export function mediaUpload( { const isAllowedType = ( fileType ) => startsWith( fileType, `${ allowedType }/` ); // Allowed types for the current WP_User - const allowedMimeTypesForUser = get( window, [ '_wpMediaSettings', 'allowedMimeTypes' ] ); + const allowedMimeTypesForUser = getMimeTypesArray( get( window, [ '_wpMediaSettings', 'allowedMimeTypes' ] ) ); const isAllowedMimeTypeForUser = ( fileType ) => { return includes( allowedMimeTypesForUser, fileType ); }; diff --git a/utils/test/mediaupload.js b/utils/test/mediaupload.js index 4f779acf9c365..35dca2906e249 100644 --- a/utils/test/mediaupload.js +++ b/utils/test/mediaupload.js @@ -3,7 +3,7 @@ /** * Internal dependencies */ -import { mediaUpload } from '../mediaupload'; +import { mediaUpload, getMimeTypesArray } from '../mediaupload'; // mediaUpload is passed the onImagesChange function // so we can stub that out have it pass the data to @@ -79,3 +79,50 @@ describe( 'mediaUpload', () => { } ); } ); } ); + +describe( 'getMimeTypesArray', () => { + it( 'should return the parameter passed if it is "falsy" e.g: undefined or null', () => { + expect( getMimeTypesArray( null ) ).toEqual( null ); + expect( getMimeTypesArray( undefined ) ).toEqual( undefined ); + } ); + + it( 'should return an empty array if an empty object is passed', () => { + expect( getMimeTypesArray( {} ) ).toEqual( [] ); + } ); + + it( 'should return the type plus a new mime type with type and subtype with the extension if a type is passed', () => { + expect( + getMimeTypesArray( { ext: 'chicken' } ) + ).toEqual( + [ 'chicken', 'chicken/ext' ] + ); + } ); + + it( 'should return the mime type passed and a new mime type with type and the extension as subtype', () => { + expect( + getMimeTypesArray( { ext: 'chicken/ribs' } ) + ).toEqual( + [ 'chicken/ribs', 'chicken/ext' ] + ); + } ); + + it( 'should return the mime type passed and an additional mime type per extension supported', () => { + expect( + getMimeTypesArray( { 'jpg|jpeg|jpe': 'image/jpeg' } ) + ).toEqual( + [ 'image/jpeg', 'image/jpg', 'image/jpeg', 'image/jpe' ] + ); + } ); + + it( 'should handle multiple mime types', () => { + expect( + getMimeTypesArray( { 'ext|aaa': 'chicken/ribs', aaa: 'bbb' } ) + ).toEqual( [ + 'chicken/ribs', + 'chicken/ext', + 'chicken/aaa', + 'bbb', + 'bbb/aaa', + ] ); + } ); +} );