diff --git a/assets/src/admin/media-sharing/components/browser-uploader.js b/assets/src/admin/media-sharing/components/browser-uploader.js index 824527f..65dee65 100644 --- a/assets/src/admin/media-sharing/components/browser-uploader.js +++ b/assets/src/admin/media-sharing/components/browser-uploader.js @@ -9,12 +9,12 @@ import { useState, useRef } from '@wordpress/element'; * Internal dependencies */ import { uploadMedia, updateExistingAttachment, checkIfAllSitesConnected, isSyncAttachment as isSyncAttachmentApi } from '../../../components/api'; -import { getFrameProperty, showSnackbarNotice } from '../../../js/utils'; +import { getAllowedMimeTypeExtensions, getFrameProperty, getAllowedMimeTypes, restrictMediaFrameUploadTypes, showSnackbarNotice } from '../../../js/utils'; // const UPLOAD_NONCE = window.OneMediaMediaFrame?.uploadNonce || ''; -const ALLOWED_MIME_TYPES = window.OneMediaMediaFrame?.allowedMimeTypes !== 'undefined' - ? Object.values( window.OneMediaMediaFrame?.allowedMimeTypes ) +const ALLOWED_MIME_TYPES_MAP = typeof window.OneMediaMediaFrame?.allowedMimeTypesMap !== 'undefined' + ? window.OneMediaMediaFrame?.allowedMimeTypesMap : []; const BrowserUploaderButton = ( { @@ -108,10 +108,13 @@ const BrowserUploaderButton = ( { }, multiple: false, library: { - type: ALLOWED_MIME_TYPES, + type: getAllowedMimeTypes( ALLOWED_MIME_TYPES_MAP ), + is_onemedia_sync: false, }, } ); + restrictMediaFrameUploadTypes( frame, getAllowedMimeTypeExtensions( ALLOWED_MIME_TYPES_MAP ).join( ',' ) ); + frame.on( 'open', () => { const frameEl = frame.el; if ( frameEl ) { @@ -191,10 +194,13 @@ const BrowserUploaderButton = ( { }, multiple: false, library: { - type: ALLOWED_MIME_TYPES, + type: getAllowedMimeTypes( ALLOWED_MIME_TYPES_MAP ), + is_onemedia_sync: false, }, } ); + restrictMediaFrameUploadTypes( frame, getAllowedMimeTypeExtensions( ALLOWED_MIME_TYPES_MAP ).join( ',' ) ); + frame.on( 'open', () => { const frameEl = frame.el; if ( frameEl ) { @@ -252,8 +258,10 @@ const BrowserUploaderButton = ( { return; } + const mimeTypes = getAllowedMimeTypes( ALLOWED_MIME_TYPES_MAP ); + // Validate file type. - if ( ! ALLOWED_MIME_TYPES.length > 0 || ! ALLOWED_MIME_TYPES.includes( file.type ) ) { + if ( ! mimeTypes.length > 0 || ! mimeTypes.includes( file.type ) ) { setNotice( { type: 'error', message: __( 'Please select a valid image file.', 'onemedia' ), @@ -346,7 +354,7 @@ const BrowserUploaderButton = ( { diff --git a/assets/src/admin/media-sharing/index.js b/assets/src/admin/media-sharing/index.js index c4ae2c3..59145d5 100644 --- a/assets/src/admin/media-sharing/index.js +++ b/assets/src/admin/media-sharing/index.js @@ -32,13 +32,16 @@ import BrowserUploaderButton from './components/browser-uploader'; import ShareMediaModal from './components/ShareMediaModal'; import VersionModal from './components/VersionModal'; import { fetchSyncedSites as fetchSyncedSitesApi, fetchMediaItems as fetchMediaItemsApi, fetchBrandSites as fetchBrandSitesApi, shareMedia as shareMediaApi, uploadMedia } from '../../components/api'; -import { getNoticeClass, trimTitle, debounce, getFrameProperty } from '../../js/utils'; +import { getNoticeClass, trimTitle, debounce, getFrameProperty, restrictMediaFrameUploadTypes, getAllowedMimeTypeExtensions } from '../../js/utils'; import fallbackImage from '../../images/fallback-image.svg'; const MEDIA_PER_PAGE = 12; const ONEMEDIA_PLUGIN_TAXONOMY_TERM = 'onemedia'; const UPLOAD_NONCE = window.OneMediaMediaSharing?.uploadNonce || ''; const ONEMEDIA_MEDIA_SHARING = window.OneMediaMediaSharing || {}; +const ALLOWED_MIME_TYPES_MAP = typeof window.OneMediaMediaFrame?.allowedMimeTypesMap !== 'undefined' + ? window.OneMediaMediaFrame?.allowedMimeTypesMap + : []; const MediaSharingApp = ( { imageType = '', @@ -199,7 +202,7 @@ const MediaSharingApp = ( { } }; - const handleEditMedia = ( mediaId, currentImageType ) => { + const handleEditMedia = ( mediaId ) => { if ( getFrameProperty( 'wp.media' ) ) { // Create edit media frame. const editFrame = window.wp.media( { @@ -210,11 +213,12 @@ const MediaSharingApp = ( { multiple: false, library: { type: 'image', - onemedia_sync_media_filter: - ONEMEDIA_PLUGIN_TAXONOMY_TERM === currentImageType ? true : false, + is_onemedia_sync: true, }, } ); + restrictMediaFrameUploadTypes( editFrame, getAllowedMimeTypeExtensions( ALLOWED_MIME_TYPES_MAP ).join( ',' ), true ); + editFrame.on( 'open', function() { // Reset the selection state. editFrame.state().get( 'selection' ).reset(); @@ -516,7 +520,6 @@ const MediaSharingApp = ( { e.stopPropagation(); handleEditMedia( media.id, - imageType, ); } } title={ __( 'Edit Media', 'onemedia' ) } diff --git a/assets/src/css/main.scss b/assets/src/css/main.scss index b62df76..88a99b8 100644 --- a/assets/src/css/main.scss +++ b/assets/src/css/main.scss @@ -251,27 +251,18 @@ } } -.onemedia_page_onemedia-media-sharing, -.media_page_onemedia-media-sharing { +.toplevel_page_onemedia { .components-tooltip { white-space: pre-line; } .media-toolbar:not(:has(.media-button-select)) { - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - - .media-toolbar-primary, - .media-toolbar-secondary { - float: none; - } + height: fit-content; .media-toolbar-secondary .attachment-filters { - width: 100%; - max-width: 100%; + width: 100% !important; + max-width: 100% !important; } } } @@ -502,23 +493,9 @@ } } -.onemedia-selec-sync-media-frame{ - - .onemedia-synced-media{ - pointer-events: none; - } -} - -.onemedia-select-non-sync-media-frame { +.onemedia-selec-sync-media-frame { .onemedia-synced-media { - display: none; - } -} - -.onemedia-edit-media-frame { - - .onemedia-non-synced-media { - display: none; + pointer-events: none; } } diff --git a/assets/src/js/media-frame.js b/assets/src/js/media-frame.js index a966abe..2c3243a 100644 --- a/assets/src/js/media-frame.js +++ b/assets/src/js/media-frame.js @@ -36,7 +36,7 @@ function isSyncAttachment( attachmentOrElement ) { // Handle Backbone model if ( typeof attachmentOrElement.get === 'function' ) { - return isSyncValue( attachmentOrElement.get( 'is_sync_attachment' ) ); + return isSyncValue( attachmentOrElement.get( 'is_onemedia_sync' ) ); } // Not a DOM element @@ -55,7 +55,7 @@ function isSyncAttachment( attachmentOrElement ) { if ( wpMedia && wpMedia.attachment ) { const attachment = wpMedia.attachment( attachmentId ); if ( attachment && attachment.get ) { - return isSyncValue( attachment.get( 'is_sync_attachment' ) ); + return isSyncValue( attachment.get( 'is_onemedia_sync' ) ); } } @@ -80,7 +80,7 @@ function customizeSyncMediaFrame() { originalAttachmentRender.apply( this, arguments ); // Add custom class if synced. - if ( this.model.get( 'is_sync_attachment' ) === true ) { + if ( this.model.get( 'is_onemedia_sync' ) === true ) { // this.el is the native DOM element const element = this.el; diff --git a/assets/src/js/utils.ts b/assets/src/js/utils.ts index 3bf441a..06f9670 100644 --- a/assets/src/js/utils.ts +++ b/assets/src/js/utils.ts @@ -4,6 +4,46 @@ import type { NoticeType } from '../admin/settings/page'; +declare global { + interface Window { + wp: { + Uploader: { + queue: unknown; + }; + media: { + attachment( id: number ): { + get( key: string ): unknown; + } | undefined; + }; + }; + } +} + +type WPMediaUploader = { + settings: { + multipart_params: Record; + } + setOption( + key: 'filters' | 'multi_selection' | string, + value: string | object | boolean, + ): void; +}; + +type WPMediaFrame = { + once( event: 'uploader:ready' | string, cb: () => void ): void; + uploader: { + uploader: { + uploader: WPMediaUploader; + }; + }; + on( event: 'ready' | string, cb: () => void ): void; + state(): { + get( key: 'library' | string ): { + observe( queue: unknown ): void; + } | undefined; + }; +}; + /** * Helper function to validate if a string is a well-formed URL. * @@ -194,6 +234,76 @@ const showSnackbarNotice = ( detail: NoticeType ): void => { document.dispatchEvent( event ); }; +/** + * Restrict upload types in a WordPress media frame. + * + * @param {WPMediaFrame} frame - The WordPress media frame to restrict. + * @param {string} allowedTypes - Comma-separated list of allowed file extensions. + * @param {boolean} is_sync - Whether the upload is for sync (default false). + * + * @return {void} + */ +const restrictMediaFrameUploadTypes = ( frame : WPMediaFrame, allowedTypes: string, is_sync:boolean = false ) => { + /** + * Using mime_type will restrict the upload types in media modal, + * Which we don't want as we only need to restrict for OneMedia uploader frame. + * + * @see https://wordpress.stackexchange.com/questions/343320/restrict-file-types-in-the-uploader-of-a-wp-media-frame + */ + frame.once( 'uploader:ready', () => { + const uploader = frame.uploader.uploader.uploader; + + // Get existing multipart_params first + const existingParams = uploader.settings.multipart_params || {}; + + uploader.setOption( 'filters', + { + mime_types: [ + { extensions: allowedTypes }, + ], + }, + ); + + // Trick to re-init field + uploader.setOption( 'multi_selection', false ); + + // Set is_onemedia_sync param + uploader.setOption( 'multipart_params', { + ...existingParams, + is_onemedia_sync: is_sync, + } ); + } ); + + /** + * Observe the library to link with uploader queue. + * + * @see https://core.trac.wordpress.org/ticket/34465 + */ + frame.on( 'ready', function() { + const library = frame.state().get( 'library' ); + if ( library && window.wp.Uploader && window.wp.Uploader.queue ) { + library.observe( window.wp.Uploader.queue ); + } + } ); +}; + +/** + * Get MIME types from a MIME map. + * @param {Object} mimeMap + */ +function getAllowedMimeTypes( mimeMap : Object ) : string[]|undefined { + return [ ...new Set( Object.values( mimeMap ) ) ]; +} + +/** + * Get extensions from a MIME map. + * @param {Object} mimeMap + */ +function getAllowedMimeTypeExtensions( mimeMap : Object ) : string[] { + return Object.keys( mimeMap ) + .flatMap( ( key ) => key.split( '|' ) ); +} + export { isURL, isValidUrl, @@ -204,4 +314,7 @@ export { observeElement, getFrameProperty, showSnackbarNotice, + restrictMediaFrameUploadTypes, + getAllowedMimeTypes, + getAllowedMimeTypeExtensions, }; diff --git a/inc/Modules/Core/Assets.php b/inc/Modules/Core/Assets.php index 43ba043..fd81fa6 100644 --- a/inc/Modules/Core/Assets.php +++ b/inc/Modules/Core/Assets.php @@ -68,21 +68,21 @@ final class Assets implements Registrable { public static function get_localized_data(): array { if ( empty( self::$localized_data ) ) { self::$localized_data = [ - 'restUrl' => esc_url( home_url( '/wp-json' ) ), - 'restNonce' => wp_create_nonce( 'wp_rest' ), - 'apiKey' => Settings::get_api_key(), - 'settingsLink' => esc_url( admin_url( 'admin.php?page=onemedia-settings' ) ), - 'siteType' => Settings::get_site_type(), - 'siteName' => get_bloginfo( 'name' ), - 'ajaxUrl' => admin_url( 'admin-ajax.php' ), - 'uploadNonce' => wp_create_nonce( 'onemedia_upload_media' ), - 'allowedMimeTypes' => Utils::get_supported_mime_types(), - 'mediaSyncNonce' => wp_create_nonce( 'onemedia_check_sync_status' ), - 'allLabel' => __( 'All media', 'onemedia' ), - 'syncLabel' => __( 'Synced', 'onemedia' ), - 'notSyncLabel' => __( 'Not Synced', 'onemedia' ), - 'filterLabel' => __( 'Sync Status', 'onemedia' ), - 'syncStatus' => Attachment::SYNC_STATUS_POSTMETA_KEY, + 'restUrl' => esc_url( home_url( '/wp-json' ) ), + 'restNonce' => wp_create_nonce( 'wp_rest' ), + 'apiKey' => Settings::get_api_key(), + 'settingsLink' => esc_url( admin_url( 'admin.php?page=onemedia-settings' ) ), + 'siteType' => Settings::get_site_type(), + 'siteName' => get_bloginfo( 'name' ), + 'ajaxUrl' => admin_url( 'admin-ajax.php' ), + 'uploadNonce' => wp_create_nonce( 'onemedia_upload_media' ), + 'allowedMimeTypesMap' => Utils::get_supported_mime_types(), + 'mediaSyncNonce' => wp_create_nonce( 'onemedia_check_sync_status' ), + 'allLabel' => __( 'All media', 'onemedia' ), + 'syncLabel' => __( 'Synced', 'onemedia' ), + 'notSyncLabel' => __( 'Not Synced', 'onemedia' ), + 'filterLabel' => __( 'Sync Status', 'onemedia' ), + 'syncStatus' => Attachment::SYNC_STATUS_POSTMETA_KEY, ]; } diff --git a/inc/Modules/MediaLibrary/Admin.php b/inc/Modules/MediaLibrary/Admin.php index f4ff0b1..bb27129 100644 --- a/inc/Modules/MediaLibrary/Admin.php +++ b/inc/Modules/MediaLibrary/Admin.php @@ -11,7 +11,6 @@ use OneMedia\Modules\Core\Assets; use OneMedia\Modules\MediaSharing\Attachment; use OneMedia\Modules\Settings\Settings; -use OneMedia\Modules\Taxonomies\Media; /** * Class Admin @@ -26,7 +25,6 @@ public function register_hooks(): void { add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ], 20 ); add_filter( 'ajax_query_attachments_args', [ $this,'filter_ajax_query_attachments_args' ] ); - add_filter( 'ajax_query_attachments_args', [ $this,'filter_ajax_query_attachments' ] ); } /** @@ -122,63 +120,32 @@ public function filter_ajax_query_attachments_args( array $query ): array { } } - return $query; - } - - /** - * Filter the AJAX query for attachments to include or exclude onemedia_sync based on the onemedia_sync_media_filter parameter. - * - * @param array $query The current query arguments. - * - * @return array Modified query arguments. - */ - public function filter_ajax_query_attachments( array $query ): array { - // Return early if not an AJAX request. - if ( ! wp_doing_ajax() ) { - return $query; - } - - // Nonce verification for AJAX requests. - $nonce = filter_input( INPUT_POST, '_ajax_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); - $nonce = sanitize_text_field( wp_unslash( $nonce ) ); - if ( ! wp_verify_nonce( $nonce, 'onemedia_check_sync_status' ) ) { - return $query; - } - - // Check if this is an AJAX request for attachments. - $post_action = filter_input( INPUT_POST, 'action', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); - - if ( ! isset( $post_action ) || empty( $post_action ) || 'query-attachments' !== $post_action ) { - return $query; - } - - $post_query = isset( $_POST['query'] ) && is_array( $_POST['query'] ) ? array_map( 'sanitize_text_field', $_POST['query'] ) : []; - if ( empty( $post_query['onemedia_sync_media_filter'] ) ) { - return $query; - } + // check for is_onemedia_sync meta filter. + if ( ! empty( $request_query['is_onemedia_sync'] ) ) { + $is_onemedia_sync = filter_var( $request_query['is_onemedia_sync'], FILTER_VALIDATE_BOOLEAN ); - $onemedia_sync_media_filter = sanitize_text_field( wp_unslash( $post_query['onemedia_sync_media_filter'] ) ); - - if ( 'true' === $onemedia_sync_media_filter ) { - $query['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query - [ - 'taxonomy' => Media::TAXONOMY, - 'field' => 'slug', - 'terms' => Media::TAXONOMY_TERM, - ], - ]; - } - - // If onemedia_sync_media_filter: false then exclude onemedia. - if ( 'false' === $onemedia_sync_media_filter ) { - $query['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query - [ - 'taxonomy' => Media::TAXONOMY, - 'field' => 'slug', - 'terms' => Media::TAXONOMY_TERM, - 'operator' => 'NOT IN', - ], - ]; + if ( true === $is_onemedia_sync ) { + $query['meta_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query + [ + 'key' => Attachment::IS_SYNC_POSTMETA_KEY, + 'value' => '1', + 'compare' => '=', + ], + ]; + } else { + $query['meta_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query + 'relation' => 'OR', + [ + 'key' => Attachment::IS_SYNC_POSTMETA_KEY, + 'value' => '0', + 'compare' => '=', + ], + [ + 'key' => Attachment::IS_SYNC_POSTMETA_KEY, + 'compare' => 'NOT EXISTS', + ], + ]; + } } return $query; diff --git a/inc/Modules/MediaSharing/Attachment.php b/inc/Modules/MediaSharing/Attachment.php index 4426359..df98519 100644 --- a/inc/Modules/MediaSharing/Attachment.php +++ b/inc/Modules/MediaSharing/Attachment.php @@ -63,6 +63,17 @@ public function register_hooks(): void { */ public function register_attachment_post_meta(): void { $post_meta = [ + self::IS_SYNC_POSTMETA_KEY => [ + 'show_in_rest' => true, + 'single' => true, + 'type' => 'boolean', + 'default' => false, + 'revisions_enabled' => false, + 'description' => __( 'Indicates if the attachment is synced to brand site or not.', 'onemedia' ), + 'auth_callback' => static function (): bool { + return current_user_can( 'edit_posts' ); + }, + ], self::SYNC_STATUS_POSTMETA_KEY => [ 'show_in_rest' => [ 'schema' => [ diff --git a/inc/Modules/MediaSharing/MediaActions.php b/inc/Modules/MediaSharing/MediaActions.php index cbe136b..12208e7 100644 --- a/inc/Modules/MediaSharing/MediaActions.php +++ b/inc/Modules/MediaSharing/MediaActions.php @@ -874,7 +874,7 @@ public function add_sync_meta( $response, $attachment ) { } // Add sync status to the response. - $response['is_sync_attachment'] = Attachment::is_sync_attachment( $attachment->ID ); + $response['is_onemedia_sync'] = Attachment::is_sync_attachment( $attachment->ID ); return $response; } diff --git a/inc/Modules/MediaSharing/MediaProtection.php b/inc/Modules/MediaSharing/MediaProtection.php index d6adcb4..9c4ef1f 100644 --- a/inc/Modules/MediaSharing/MediaProtection.php +++ b/inc/Modules/MediaSharing/MediaProtection.php @@ -20,7 +20,6 @@ class MediaProtection implements Registrable { * {@inheritDoc} */ public function register_hooks(): void { - add_filter( 'delete_attachment', [ $this, 'maybe_block_media_delete' ], 10, 1 ); add_action( 'admin_notices', [ $this, 'show_deletion_notice' ] ); add_action( 'add_attachment', [ $this, 'add_term_to_attachment' ] ); @@ -38,42 +37,28 @@ public function register_hooks(): void { * @return void */ public function add_term_to_attachment( int $attachment_id ): void { - $is_onemedia_attachment = metadata_exists( 'post', $attachment_id, Attachment::IS_SYNC_POSTMETA_KEY ); - if ( ! $attachment_id || ! taxonomy_exists( Media::TAXONOMY ) || ! $is_onemedia_attachment ) { + if ( ! wp_doing_ajax() ) { return; } - // Assign the 'onemedia' term to the attachment. - $success = wp_set_object_terms( $attachment_id, Media::TAXONOMY_TERM, Media::TAXONOMY, true ); + if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( $_POST['_wpnonce'] ), 'media-form' ) ) { + return; + } - if ( ! is_wp_error( $success ) ) { + if ( ! isset( $_REQUEST['action'] ) || 'upload-attachment' !== sanitize_text_field( $_REQUEST['action'] ) ) { return; } - wp_send_json_error( [ 'message' => __( 'Failed to assign taxonomy term to attachment.', 'onemedia' ) ], 500 ); - } + // Handle boolean strings (e.g. 'false'). + $is_onemedia_sync = isset( $_POST['is_onemedia_sync'] ) && filter_var( wp_unslash( $_POST['is_onemedia_sync'] ), FILTER_VALIDATE_BOOLEAN ); - /** - * Block deletion of media attachments assigned to the 'onemedia' term. - * - * This method prevents the deletion of media attachments that are assigned to the 'onemedia' term, - * ensuring that important media cannot be removed unintentionally. - * - * @param int $attachment_id The ID of the attachment being deleted. - * - * @return int|\WP_Error The attachment ID if deletion is allowed, or a WP_Error if blocked. - */ - public function maybe_block_media_delete( int $attachment_id ): int|\WP_Error { - $terms = Attachment::get_post_terms( $attachment_id, [ 'fields' => 'slugs' ] ); - if ( ! empty( $terms ) && isset( array_flip( $terms )[ Media::TAXONOMY_TERM ] ) ) { - // Set a transient to show a notice on the next admin page load. - set_transient( 'onemedia_delete_notice', true, 30 ); - // Redirect back to prevent deletion. - $redirect_url = admin_url( 'upload.php' ); - wp_safe_redirect( $redirect_url ); - exit; + update_post_meta( $attachment_id, Attachment::IS_SYNC_POSTMETA_KEY, $is_onemedia_sync ? 1 : 0 ); + + if ( true !== $is_onemedia_sync ) { + return; } - return $attachment_id; + + wp_set_object_terms( $attachment_id, Media::TAXONOMY_TERM, Media::TAXONOMY, true ); } /** @@ -102,10 +87,10 @@ public function show_deletion_notice(): void { /** * Prevent editing or deleting of synced media attachments on brand sites. * - * @param array $caps Current user's capabilities. - * @param string $cap Capability being checked. + * @param array $caps Current user's capabilities. + * @param string $cap Capability being checked. * @param int $user_id User ID. - * @param array $args Arguments for the capability check. + * @param array $args Arguments for the capability check. * * @return array|string[] */ diff --git a/inc/Modules/MediaSharing/UserInterface.php b/inc/Modules/MediaSharing/UserInterface.php index e2724a0..02b9402 100644 --- a/inc/Modules/MediaSharing/UserInterface.php +++ b/inc/Modules/MediaSharing/UserInterface.php @@ -49,20 +49,9 @@ public function display_media_column_content( string $column_name, int $attachme return; } - $terms = Attachment::get_post_terms( $attachment_id, [ 'fields' => 'names' ] ); - $classes = 'onemedia-media-term-label'; - - // Build the labels and css classes. - if ( empty( $terms ) ) { - $label = __( 'Not assigned', 'onemedia' ); - $classes .= ' empty'; - } else { - $labels = []; - foreach ( $terms as $term ) { - $labels[] = Media::TAXONOMY_TERM === $term ? Media::TERM_NAME : esc_html( $term ); - } - $label = implode( ', ', $labels ); - } + $is_sync = Attachment::is_sync_attachment( $attachment_id ); + $label = $is_sync ? __( 'OneMedia', 'onemedia' ) : __( 'Not Assigned', 'onemedia' ); + $classes = $is_sync ? 'onemedia-media-term-label' : 'onemedia-media-term-label empty'; printf( /* translators: %1$s is the class attribute, %2$s is the label text. */ diff --git a/inc/Modules/Rest/Media_Sharing_Controller.php b/inc/Modules/Rest/Media_Sharing_Controller.php index c4d26e9..9c79809 100644 --- a/inc/Modules/Rest/Media_Sharing_Controller.php +++ b/inc/Modules/Rest/Media_Sharing_Controller.php @@ -585,6 +585,9 @@ public function get_media_files( \WP_REST_Request $request ): \WP_Error|\WP_REST $args['s'] = sanitize_text_field( $search_term ); } + /** + * @todo => This taxonomy approach is complete overkill we can do it using meta so need to remove this in future. + */ // If image_type is provided, filter by onemedia_media_type taxonomy. if ( ! empty( $image_type ) ) { $args['tax_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query diff --git a/inc/Modules/Settings/Admin.php b/inc/Modules/Settings/Admin.php index 0cd1652..50391d7 100644 --- a/inc/Modules/Settings/Admin.php +++ b/inc/Modules/Settings/Admin.php @@ -114,10 +114,8 @@ public function enqueue_scripts( string $hook ): void { return; } - if ( ( 'plugins.php' === $hook || str_contains( $hook, 'plugins' ) || str_contains( $hook, 'onemedia' ) ) ) { - // Enqueue the onboarding modal. - $this->enqueue_onboarding_scripts(); - } + // Enqueue the onboarding modal. + $this->enqueue_onboarding_scripts(); if ( strpos( $hook, 'onemedia-settings' ) !== false ) { $this->enqueue_settings_scripts(); @@ -130,8 +128,7 @@ public function enqueue_scripts( string $hook ): void { * Inject site selection modal into the admin footer. */ public function inject_site_selection_modal(): void { - $current_screen = get_current_screen(); - if ( ! $current_screen || 'plugins' !== $current_screen->base ) { + if ( ! $this->should_display_site_selection_modal() ) { return; } @@ -208,8 +205,7 @@ public function enqueue_settings_scripts(): void { * Enqueue scripts and styles for the onboarding modal. */ private function enqueue_onboarding_scripts(): void { - // Bail if the site type is already set. - if ( ! empty( Settings::get_site_type() ) ) { + if ( ! $this->should_display_site_selection_modal() ) { return; } @@ -234,7 +230,7 @@ private function enqueue_onboarding_scripts(): void { * @param \WP_Screen $current_screen Current screen object. */ private function add_body_class_for_modal( string $classes, \WP_Screen $current_screen ): string { - if ( 'plugins' !== $current_screen->base ) { + if ( ! $this->should_display_site_selection_modal() ) { return $classes; } @@ -252,7 +248,7 @@ private function add_body_class_for_modal( string $classes, \WP_Screen $current_ /** * Add body class for missing sites. * - * @param string $classes Existing body classes. + * @param string $classes Existing body classes. */ private function add_body_class_for_missing_sites( string $classes ): string { // Bail if the shared sites are already set. @@ -265,4 +261,17 @@ private function add_body_class_for_missing_sites( string $classes ): string { return $classes; } + + /** + * Whether to display the site selection modal. + */ + private function should_display_site_selection_modal(): bool { + $current_screen = get_current_screen(); + if ( ! $current_screen || ( 'plugins' !== $current_screen->base && ! str_contains( $current_screen->id, self::MENU_SLUG ) ) ) { + return false; + } + + // Bail if the site type is already set. + return empty( Settings::get_site_type() ); + } } diff --git a/inc/Utils.php b/inc/Utils.php index 1635364..081e837 100644 --- a/inc/Utils.php +++ b/inc/Utils.php @@ -5,7 +5,7 @@ * @package OneMedia */ -declare( strict_types = 1 ); +declare( strict_types=1 ); namespace OneMedia; @@ -27,13 +27,13 @@ final class Utils { * @var array */ private const ALLOWED_MIME_TYPES = [ - 'image/jpg', - 'image/jpeg', - 'image/png', - 'image/gif', - 'image/webp', - 'image/bmp', - 'image/svg+xml', + 'jpg|jpeg|jpe' => 'image/jpeg', + 'png' => 'image/png', + 'gif' => 'image/gif', + 'bmp' => 'image/bmp', + 'webp' => 'image/webp', + 'svg' => 'image/svg+xml', + 'svgz' => 'image/svg+xml', ]; /** @@ -53,13 +53,15 @@ public static function decode_filename( string $filename ): string { * @return array Array of supported mime types by the server. */ public static function get_supported_mime_types(): array { - $allowed_types = self::ALLOWED_MIME_TYPES; - - // Remove any types that are not supported by the server. - $supported_types = array_values( get_allowed_mime_types() ); - $allowed_types = array_intersect( $allowed_types, $supported_types ); - - return $allowed_types; + $wp_mimes = get_allowed_mime_types(); + + /** + * Filter WordPress mime list by allowed mime values. + */ + return array_intersect_key( + $wp_mimes, + self::ALLOWED_MIME_TYPES + ); } /**