Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editor: Make mime type config less confusing #10709

Merged
merged 58 commits into from
Mar 10, 2022
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
bba80b3
Remove lots of mime properties.
spacedmonkey Feb 24, 2022
6b94fe0
useMemo.
spacedmonkey Feb 24, 2022
8d99e78
Fix keys.
spacedmonkey Feb 25, 2022
3506908
Remove unused method.
spacedmonkey Feb 25, 2022
132328c
More usememos.
spacedmonkey Feb 25, 2022
34459e0
Add new `getExtensionsFromMimeType` function (#10718)
swissspidy Feb 25, 2022
51dd3bf
Break vector into it's own group.
spacedmonkey Feb 25, 2022
a94862e
Handle mime types in one place.
spacedmonkey Feb 25, 2022
106614f
Don't allow audio and text to hotlinked.
spacedmonkey Feb 25, 2022
5703004
Fix lints
spacedmonkey Feb 28, 2022
8aade45
Merge branch 'main' into try/mime-type-tidy-up
spacedmonkey Feb 28, 2022
09b5008
Improved php logic and fixed tests.
spacedmonkey Feb 28, 2022
fe5cf19
Tidy up php logic of test.
spacedmonkey Feb 28, 2022
a7cbb41
Add unit tests for multisite.
spacedmonkey Feb 28, 2022
ef7b182
Fixes for js unit tests.
spacedmonkey Feb 28, 2022
643de93
Add vector to allowed list.
spacedmonkey Feb 28, 2022
c16e3a8
Update fixtures
spacedmonkey Feb 28, 2022
49b8d54
Fix lints.
spacedmonkey Feb 28, 2022
f4785bf
Remove lots of mime properties.
spacedmonkey Feb 24, 2022
df44baf
useMemo.
spacedmonkey Feb 24, 2022
1828e27
Fix keys.
spacedmonkey Feb 25, 2022
6cf2a97
Remove unused method.
spacedmonkey Feb 25, 2022
7e091fd
More usememos.
spacedmonkey Feb 25, 2022
46aebb2
Add new `getExtensionsFromMimeType` function (#10718)
swissspidy Feb 25, 2022
ff4d401
Break vector into it's own group.
spacedmonkey Feb 25, 2022
110ce68
Handle mime types in one place.
spacedmonkey Feb 25, 2022
49a8236
Don't allow audio and text to hotlinked.
spacedmonkey Feb 25, 2022
9e5aec7
Fix lints
spacedmonkey Feb 28, 2022
ef44774
Improved php logic and fixed tests.
spacedmonkey Feb 28, 2022
367706b
Tidy up php logic of test.
spacedmonkey Feb 28, 2022
0977b59
Add unit tests for multisite.
spacedmonkey Feb 28, 2022
80f9dfe
Fixes for js unit tests.
spacedmonkey Feb 28, 2022
2d4c5d4
Add vector to allowed list.
spacedmonkey Feb 28, 2022
7dd5ab6
Update fixtures
spacedmonkey Feb 28, 2022
186e0db
Fix lints.
spacedmonkey Feb 28, 2022
e0df21e
Merge branch 'try/mime-type-tidy-up' of github.com:google/web-stories…
spacedmonkey Feb 28, 2022
7249292
Merge branch 'main' into try/mime-type-tidy-up
spacedmonkey Mar 2, 2022
0c8cf44
Merge branch 'try/mime-type-tidy-up' of github.com:google/web-stories…
spacedmonkey Mar 2, 2022
59fc07b
Change method name.
spacedmonkey Mar 2, 2022
29f363e
Skip test on multisite.
spacedmonkey Mar 2, 2022
64b3f2c
Change text to caption.
spacedmonkey Mar 2, 2022
60b1307
Unused variable.
spacedmonkey Mar 2, 2022
ae6bd56
Rename variables.
spacedmonkey Mar 2, 2022
0c3ca6c
Merge branch 'main' into try/mime-type-tidy-up
spacedmonkey Mar 3, 2022
69f603a
Update includes/REST_API/Hotlinking_Controller.php
spacedmonkey Mar 4, 2022
71e1eb7
Change variable name.
spacedmonkey Mar 4, 2022
e515290
Space and tabs.
spacedmonkey Mar 4, 2022
6a50936
Space and tabs again.
spacedmonkey Mar 4, 2022
1aeff8d
Merge branch 'main' into try/mime-type-tidy-up
spacedmonkey Mar 4, 2022
949c998
Merge branch 'main' into try/mime-type-tidy-up
swissspidy Mar 9, 2022
44c6aaf
Use tabs
swissspidy Mar 9, 2022
ce22739
Apply suggestions from code review
spacedmonkey Mar 9, 2022
d9657bc
Tweak logic.
spacedmonkey Mar 9, 2022
d1cb9c6
Default to empty array.
spacedmonkey Mar 9, 2022
300025f
Merge branch 'main' into try/mime-type-tidy-up
spacedmonkey Mar 9, 2022
5259e55
Update fixtures.
spacedmonkey Mar 9, 2022
c5835ed
Merge remote-tracking branch 'origin/try/mime-type-tidy-up' into try/…
spacedmonkey Mar 9, 2022
b95b4e4
Fix karma tests.
spacedmonkey Mar 9, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion includes/Admin/Dashboard.php
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,8 @@ public function get_dashboard_settings(): array {
if ( ! $max_upload_size ) {
$max_upload_size = 0;
}
$mime_types = $this->types->get_allowed_mime_types();
$allowed_image_mime_types = $mime_types['image'];

$settings = [
'isRTL' => is_rtl(),
Expand All @@ -419,7 +421,7 @@ public function get_dashboard_settings(): array {
'archiveURL' => $this->story_post_type->get_archive_link(),
'defaultArchiveURL' => $this->story_post_type->get_archive_link( true ),
'cdnURL' => trailingslashit( WEBSTORIES_CDN_URL ),
'allowedImageMimeTypes' => $this->types->get_allowed_image_mime_types(),
'allowedImageMimeTypes' => $allowed_image_mime_types,
'version' => WEBSTORIES_VERSION,
'encodeMarkup' => $this->decoder->supports_decoding(),
'api' => [
Expand Down
10 changes: 1 addition & 9 deletions includes/Admin/Editor.php
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,6 @@ public function get_editor_settings(): array {
/** This filter is documented in wp-admin/includes/post.php */
$show_locked_dialog = apply_filters( 'show_post_locked_dialog', true, $post, $user );
$nonce = wp_create_nonce( 'wp_rest' );
$mime_types = $this->types->get_allowed_mime_types();
$image_mime_types = $this->types->get_allowed_image_mime_types();
$audio_mime_types = $this->types->get_allowed_audio_mime_types();

$story = new Story();
$story->load_from_post( $post );
Expand All @@ -357,12 +354,7 @@ public function get_editor_settings(): array {
'autoSaveInterval' => \defined( 'AUTOSAVE_INTERVAL' ) ? AUTOSAVE_INTERVAL : null,
'isRTL' => is_rtl(),
'locale' => $this->locale->get_locale_settings(),
'allowedFileTypes' => $this->types->get_allowed_file_types(),
'allowedImageFileTypes' => $this->types->get_file_type_exts( $image_mime_types ),
'allowedImageMimeTypes' => $image_mime_types,
'allowedAudioFileTypes' => $this->types->get_file_type_exts( $audio_mime_types ),
'allowedAudioMimeTypes' => $audio_mime_types,
'allowedMimeTypes' => $mime_types,
'allowedMimeTypes' => $this->types->get_allowed_mime_types(),
'postType' => $this->story_post_type->get_slug(),
'storyId' => $story_id,
'dashboardLink' => $dashboard_url,
Expand Down
2 changes: 1 addition & 1 deletion includes/Media/SVG.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public function mime_types_add_svg( array $mime_types ): array {
* @return array
*/
public function web_stories_allowed_mime_types( array $mime_types ): array {
$mime_types['image'][] = self::MIME_TYPE;
$mime_types['vector'][] = self::MIME_TYPE;

return $mime_types;
}
Expand Down
86 changes: 10 additions & 76 deletions includes/Media/Types.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,27 +30,6 @@
* Class Types
*/
class Types {
/**
* Returns a list of allowed file types.
*
* @since 1.0.0
*
* @return array List of allowed file types.
*/
public function get_allowed_file_types(): array {
$allowed_mime_types = $this->get_allowed_mime_types();
$mime_types = [];

foreach ( $allowed_mime_types as $mimes ) {
// Otherwise this throws a warning on PHP < 7.3.
if ( ! empty( $mimes ) ) {
array_push( $mime_types, ...$mimes );
}
}

return $this->get_file_type_exts( $mime_types );
}

/**
* Returns a list of allowed file types.
*
Expand Down Expand Up @@ -82,16 +61,22 @@ public function get_file_type_exts( array $mime_types = [] ): array {
*/
public function get_allowed_mime_types(): array {
$default_allowed_mime_types = [
'image' => [
'image' => [
'image/webp',
'image/png',
'image/jpeg',
'image/jpg',
'image/gif',
],
// TODO: Update once audio elements are supported.
'audio' => [],
'video' => [
'audio' => [
'audio/mpeg',
'audio/aac',
'audio/wav',
'audio/ogg',
],
'caption' => [ 'text/vtt' ],
'vector' => [],
'video' => [
'video/mp4',
'video/webm',
],
Expand Down Expand Up @@ -120,55 +105,4 @@ public function get_allowed_mime_types(): array {

return $allowed_mime_types;
}

/**
* Returns a list of image mime types.
*
* @since 1.4.0
*
* @return array List of allowed mime types.
*/
public function get_allowed_image_mime_types(): array {
$mime_type = $this->get_allowed_mime_types();
$allowed_mime_type = $mime_type['image'];
$image_mime_type = [
'image/webp',
'image/png',
'image/jpeg',
'image/jpg',
'image/gif',
];

/**
* Filter list of allowed poster image mime types.
*
* @since 1.4.0
*
* @param array $image_mime_type List of allowed mime types. Defaults to 'image/png', 'image/jpeg', 'image/jpg','image/gif'.
* @param array $allowed_mime_type Allowed mime types from get_allowed_mime_types.
*/
$image_mime_type = apply_filters( 'web_stories_allowed_image_mime_types', $image_mime_type, $allowed_mime_type );

return array_values( array_intersect( $allowed_mime_type, $image_mime_type ) );
}

/**
* Returns a list of audio mime types.
*
* Used for the allowlist when adding background audio.
*
* @since 1.11.0
*
* @return array List of allowed mime types.
*/
public function get_allowed_audio_mime_types(): array {
$allowed_mime_types = [
'audio/mpeg',
'audio/aac',
'audio/wav',
'audio/ogg',
];

return array_values( array_intersect( $allowed_mime_types, get_allowed_mime_types() ) );
}
}
23 changes: 21 additions & 2 deletions includes/REST_API/Hotlinking_Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ public function parse_url( $request ) {
$ext = end( $exts );
}

$allowed_mime_types = $this->types->get_allowed_mime_types();
$allowed_mime_types = $this->get_allowed_mime_types();
$type = '';
foreach ( $allowed_mime_types as $key => $mime_types ) {
if ( \in_array( $mime_type, $mime_types, true ) ) {
Expand Down Expand Up @@ -429,7 +429,7 @@ public function get_item_schema(): array {
return $this->add_additional_fields_schema( $this->schema );
}

$allowed_mime_types = $this->types->get_allowed_mime_types();
$allowed_mime_types = $this->get_allowed_mime_types();
$types = array_keys( $allowed_mime_types );
$allowed_mime_types = array_merge( ...array_values( $allowed_mime_types ) );
$exts = $this->types->get_file_type_exts( $allowed_mime_types );
Expand Down Expand Up @@ -570,4 +570,23 @@ public function stream_headers( $handle, $header ): int {

return \strlen( $header );
}

/**
* Returns a list of allowed mime types per media type (image, audio, video).
*
* @since 1.19.0
*
* @return array<string, array> List of allowed mime types.
*/
protected function get_allowed_mime_types(): array {
$mime_type = $this->types->get_allowed_mime_types();
// TODO: Update once audio elements are supported.
$mime_type['audio'] = [];
// TODO: Add support hotlinking vvt files.
spacedmonkey marked this conversation as resolved.
Show resolved Hide resolved
unset( $mime_type['caption'] );
// Do not support hotlinking SVGs for security reasons.
unset( $mime_type['vector'] );

return $mime_type;
}
}
7 changes: 6 additions & 1 deletion includes/REST_API/Stories_Media_Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,11 @@ public function get_item_schema(): array {
* @return array Array of supported media types.
*/
protected function get_media_types(): array {
return $this->types->get_allowed_mime_types();
$mime_type = $this->types->get_allowed_mime_types();
// TODO: Update once audio elements are supported.
$mime_type['audio'] = [];
unset( $mime_type['caption'] );

return $mime_type;
}
}
30 changes: 0 additions & 30 deletions packages/media/src/getExtensionFromMimeType.js

This file was deleted.

2 changes: 1 addition & 1 deletion packages/media/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export { default as formatMsToHMS } from './formatMsToHMS';
export { default as generateVideoStrip } from './generateVideoStrip';
export { default as getFileNameFromUrl } from './getFileNameFromUrl';
export { default as getFileNameWithExt } from './getFileNameWithExt';
export { default as getExtensionFromMimeType } from './getExtensionFromMimeType';
export * from './mimeTypes';
export { default as getFirstFrameOfVideo } from './getFirstFrameOfVideo';
export { default as getImageDimensions } from './getImageDimensions';
export { default as getMsFromHMS } from './getMsFromHMS';
Expand Down
60 changes: 60 additions & 0 deletions packages/media/src/mimeTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* External dependencies
*/
import mime from 'mime/lite';

/**
* Get the file extension for a given mime type.
*
* @param {string} mimeType Mime type.
* @return {string} File extension.
*/
export function getExtensionFromMimeType(mimeType) {
return mime.getExtension(mimeType);
}

/**
* Get all possible file extensions for a given mime type.
*
* Some mime types can map to multiple file extensions, but
* the mime package does not offer a way to retrieve all of them.
*
* Since this is only needed for user-facing error messages
* (e.g. "You can upload jpeg, png, mp4, ..."), this function
* contains a simple, opinionated, hardcoded list of extensions for the
* most relevant mime types as used in the story editor.
*
* @see https://github.com/broofa/mime/issues/254
* @param {string} mimeType Mime type.
* @return {string[]} File extension.
*/
export function getExtensionsFromMimeType(mimeType) {
switch (mimeType) {
case 'audio/mpeg':
return ['mp3', 'm3a'];
case 'audio/aac':
return ['aac'];
case 'audio/ogg':
return ['oga', 'ogg'];
case 'image/jpeg':
return ['jpg', 'jpeg'];
default:
return [getExtensionFromMimeType(mimeType)].filter(Boolean);
}
}
37 changes: 37 additions & 0 deletions packages/media/src/test/mimeTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Internal dependencies
*/
import { getExtensionsFromMimeType } from '../mimeTypes';

describe('getExtensionsFromMimeType', () => {
it('returns an array of file extensions', () => {
expect(getExtensionsFromMimeType('audio/mpeg')).toStrictEqual([
'mp3',
'm3a',
]);
expect(getExtensionsFromMimeType('audio/mp3')).toStrictEqual(['mp3']);
expect(getExtensionsFromMimeType('audio/aac')).toStrictEqual(['aac']);
expect(getExtensionsFromMimeType('audio/ogg')).toStrictEqual([
'oga',
'ogg',
]);
expect(getExtensionsFromMimeType('video/mp4')).toStrictEqual(['mp4']);
expect(getExtensionsFromMimeType('invalid/type')).toStrictEqual([]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -363,9 +363,9 @@ describe('useQuickActions', () => {
useStoryTriggersDispatch.mockReturnValue(mockDispatchStoryEvent);

mockUseConfig.mockReturnValue({
allowedFileTypes: [],
allowedMimeTypes: {
image: [],
vector: [],
video: [],
},
capabilities: { hasUploadMediaAction: true },
Expand Down Expand Up @@ -1004,9 +1004,9 @@ describe('MediaPicker', () => {
});

mockUseConfig.mockReturnValue({
allowedFileTypes: ['pepperoni', 'cheese'],
allowedMimeTypes: {
image: ['image/gif'],
vector: [],
video: ['muted'],
},
capabilities: { hasUploadMediaAction: true },
Expand Down
Loading