From ba05597962c018bcc444d4abef693a755a756e79 Mon Sep 17 00:00:00 2001 From: Ashar Fuadi Date: Wed, 15 Jan 2025 23:31:08 +0700 Subject: [PATCH 1/2] Implement media import via URL -- list view --- .../jetpack-mu-wpcom/.phan/baseline.php | 5 +- .../changelog/wpcom-media-url-import | 4 + .../src/class-jetpack-mu-wpcom.php | 1 + .../wpcom-media-url-import-form/index.jsx | 109 ++++++++++++++++++ .../wpcom-media-url-import-form/style.scss | 7 ++ .../wpcom-media/wpcom-media-url-import.js | 23 ++++ .../wpcom-media/wpcom-media-url-import.php | 65 +++++++++++ .../jetpack-mu-wpcom/webpack.config.js | 1 + 8 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 projects/packages/jetpack-mu-wpcom/changelog/wpcom-media-url-import create mode 100644 projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import-form/index.jsx create mode 100644 projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import-form/style.scss create mode 100644 projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import.js create mode 100644 projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import.php diff --git a/projects/packages/jetpack-mu-wpcom/.phan/baseline.php b/projects/packages/jetpack-mu-wpcom/.phan/baseline.php index 6865fcfd0af51..93e7c19ab865c 100644 --- a/projects/packages/jetpack-mu-wpcom/.phan/baseline.php +++ b/projects/packages/jetpack-mu-wpcom/.phan/baseline.php @@ -17,9 +17,9 @@ // PhanNoopNew : 5 occurrences // PhanTypeMismatchArgumentInternal : 4 occurrences // PhanTypeMismatchReturnProbablyReal : 4 occurrences + // PhanParamTooMany : 3 occurrences // PhanTypePossiblyInvalidDimOffset : 3 occurrences // PhanEmptyFQSENInCallable : 2 occurrences - // PhanParamTooMany : 2 occurrences // PhanTypeArraySuspicious : 2 occurrences // PhanTypeArraySuspiciousNullable : 2 occurrences // PhanTypeMismatchDefault : 2 occurrences @@ -37,6 +37,8 @@ // PhanTypeMismatchReturnNullable : 1 occurrence // PhanTypeNonVarPassByRef : 1 occurrence // PhanTypeVoidArgument : 1 occurrence + // PhanUndeclaredExtendedClass : 1 occurrence + // PhanUndeclaredMethod : 1 occurrence // Currently, file_suppressions and directory_suppressions are the only supported suppressions 'file_suppressions' => [ @@ -57,6 +59,7 @@ 'src/features/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-launchpad.php' => ['PhanPluginDuplicateConditionalNullCoalescing'], 'src/features/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-site-migration-migrate-guru-key.php' => ['PhanUndeclaredClassMethod'], 'src/features/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-site-migration-wpcom-migration-key.php' => ['PhanUndeclaredClassMethod'], + 'src/features/wpcom-media/wpcom-media-url-import.php' => ['PhanParamTooMany', 'PhanUndeclaredExtendedClass', 'PhanUndeclaredMethod'], 'tests/lib/functions-wordpress.php' => ['PhanRedefineFunction'], 'tests/php/features/block-patterns/class-wpcom-block-patterns-from-api-test.php' => ['PhanDeprecatedFunction'], 'tests/php/features/coming-soon/class-coming-soon-test.php' => ['PhanTypeMismatchArgument', 'PhanTypeMismatchArgumentProbablyReal'], diff --git a/projects/packages/jetpack-mu-wpcom/changelog/wpcom-media-url-import b/projects/packages/jetpack-mu-wpcom/changelog/wpcom-media-url-import new file mode 100644 index 0000000000000..27db5a6914fdc --- /dev/null +++ b/projects/packages/jetpack-mu-wpcom/changelog/wpcom-media-url-import @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Implement media import via URL diff --git a/projects/packages/jetpack-mu-wpcom/src/class-jetpack-mu-wpcom.php b/projects/packages/jetpack-mu-wpcom/src/class-jetpack-mu-wpcom.php index ec3435b3fbc18..4bc2a39096518 100644 --- a/projects/packages/jetpack-mu-wpcom/src/class-jetpack-mu-wpcom.php +++ b/projects/packages/jetpack-mu-wpcom/src/class-jetpack-mu-wpcom.php @@ -152,6 +152,7 @@ public static function load_wpcom_user_features() { require_once __DIR__ . '/features/wpcom-dashboard-widgets/wpcom-dashboard-widgets.php'; require_once __DIR__ . '/features/wpcom-locale/sync-locale-from-calypso-to-atomic.php'; require_once __DIR__ . '/features/wpcom-media/wpcom-external-media-import.php'; + require_once __DIR__ . '/features/wpcom-media/wpcom-media-url-import.php'; require_once __DIR__ . '/features/wpcom-plugins/wpcom-plugins.php'; require_once __DIR__ . '/features/wpcom-profile-settings/profile-settings-link-to-wpcom.php'; require_once __DIR__ . '/features/wpcom-profile-settings/profile-settings-notices.php'; diff --git a/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import-form/index.jsx b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import-form/index.jsx new file mode 100644 index 0000000000000..571144b698c67 --- /dev/null +++ b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import-form/index.jsx @@ -0,0 +1,109 @@ +import { __ } from '@wordpress/i18n'; +import clsx from 'clsx'; +import { useState } from 'react'; + +import './style.scss'; + +const WpcomMediaUrlImportForm = ( { ajaxUrl, action, nonce } ) => { + const [ url, setUrl ] = useState( '' ); + + const [ show, setShow ] = useState( false ); + const [ isUploading, setIsUploading ] = useState( false ); + const [ isUploaded, setIsUploaded ] = useState( false ); + + const handleUrlChange = e => { + setUrl( e.target.value ); + }; + + const handleSubmit = async e => { + if ( isUploading ) { + return false; + } + try { + new URL( url ); // eslint-disable-line no-new + } catch { + return false; + } + e.preventDefault(); + + const formData = new FormData(); + formData.append( 'action', action ); + formData.append( 'image_url', url ); + formData.append( '_ajax_nonce', nonce ); + + setIsUploading( true ); + + const response = await fetch( ajaxUrl, { + method: 'POST', + body: formData, + } ); + + const { success, data } = await response.json(); + + if ( success ) { + window.wp.media.model.Attachment.get( data.attachment_id ).fetch( { + success: function ( attachment ) { + window.wp.media.frame.content.get().collection.add( attachment ); + + setIsUploading( false ); + + setIsUploaded( true ); + setTimeout( () => { + setIsUploaded( false ); + setUrl( '' ); + }, 2000 ); + }, + } ); + } else { + setIsUploading( false ); + // window.alert( data[ 0 ].message ); + } + + return false; + }; + + const renderLink = () => { + return ( + setShow( true ) }> + { __( 'Upload from URL', 'jetpack-mu-wpcom' ) } + + ); + }; + + const renderForm = () => { + let buttonText = __( 'Upload', 'jetpack-mu-wpcom' ); + if ( isUploaded ) { + buttonText = __( 'Uploaded!', 'jetpack-mu-wpcom' ); + } else if ( isUploading ) { + buttonText = __( 'Uploading…', 'jetpack-mu-wpcom' ); + } + + return ( +
+ + +
+ ); + }; + + return
{ show ? renderForm() : renderLink() }
; +}; + +export default WpcomMediaUrlImportForm; diff --git a/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import-form/style.scss b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import-form/style.scss new file mode 100644 index 0000000000000..67d6bc15312e5 --- /dev/null +++ b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import-form/style.scss @@ -0,0 +1,7 @@ +.wpcom-media-url-import-form { + input { + width: 100%; + max-width: 600px; + margin-bottom: 5px; + } +} diff --git a/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import.js b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import.js new file mode 100644 index 0000000000000..c5baf4519bb8d --- /dev/null +++ b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import.js @@ -0,0 +1,23 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import WpcomMediaUrlImportForm from './wpcom-media-url-import-form'; + +const props = typeof window === 'object' ? window.JETPACK_MU_WPCOM_MEDIA_URL_IMPORT : {}; + +document.addEventListener( 'DOMContentLoaded', function () { + if ( window.wp?.media?.view?.UploaderInline ) { + const originalUploaderInline = window.wp.media.view.UploaderInline; + + window.wp.media.view.UploaderInline = originalUploaderInline.extend( { + ready: function () { + originalUploaderInline.prototype.ready.apply( this, arguments ); + + const container = document.getElementById( 'wpcom-media-url-import' ); + if ( container ) { + const root = ReactDOM.createRoot( container ); + root.render( ); + } + }, + } ); + } +} ); diff --git a/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import.php b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import.php new file mode 100644 index 0000000000000..49eee993e3d2b --- /dev/null +++ b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import.php @@ -0,0 +1,65 @@ + +
+ admin_url( 'admin-ajax.php' ), + 'action' => 'wpcom_media_url_import', + 'nonce' => wp_create_nonce( 'wpcom_media_url_import' ), + ) + ); + + wp_add_inline_script( + $handle, + "window.JETPACK_MU_WPCOM_MEDIA_URL_IMPORT = $data;", + 'before' + ); +} + +/** + * AJAX handler for the wpcom media URL import. + */ +function wpcom_handle_media_url_import() { + check_ajax_referer( 'wpcom_media_url_import' ); + + if ( ! isset( $_POST['image_url'] ) ) { + return; + } + $image_url = esc_url_raw( wp_unslash( $_POST['image_url'] ) ); + + require_once JETPACK__PLUGIN_DIR . 'class.json-api-endpoints.php'; + $endpoint = new class( array() ) extends WPCOM_JSON_API_Endpoint { + // phpcs:ignore Squiz.Commenting.FunctionComment.Missing, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable + public function callback( $path = '', $blog_id = 0 ) {} + }; + + $result = $endpoint->handle_media_creation_v1_1( array(), array( $image_url ) ); + + if ( count( $result['media_ids'] ) > 0 ) { + $attachment_id = $result['media_ids'][0]; + return wp_send_json_success( array( 'attachment_id' => $attachment_id ) ); + } + if ( count( $result['errors'] ) > 0 ) { + $error = $result['errors'][0]; + return wp_send_json_error( new WP_Error( $error['error'], $error['message'] ) ); + } +} + +if ( current_user_can( 'upload_files' ) ) { + add_action( 'post-plupload-upload-ui', 'wpcom_media_url_import', 20 ); + add_action( 'wp_ajax_wpcom_media_url_import', 'wpcom_handle_media_url_import' ); +} diff --git a/projects/packages/jetpack-mu-wpcom/webpack.config.js b/projects/packages/jetpack-mu-wpcom/webpack.config.js index 1329b074d4b9d..b4883c2857302 100644 --- a/projects/packages/jetpack-mu-wpcom/webpack.config.js +++ b/projects/packages/jetpack-mu-wpcom/webpack.config.js @@ -47,6 +47,7 @@ module.exports = [ './src/features/wpcom-documentation-links/wpcom-documentation-links.ts', 'wpcom-external-media-import-page': './src/features/wpcom-media/wpcom-external-media-import.js', + 'wpcom-media-url-import': './src/features/wpcom-media/wpcom-media-url-import.js', 'wpcom-plugins-banner': './src/features/wpcom-plugins/js/banner.js', 'wpcom-plugins-banner-style': './src/features/wpcom-plugins/css/banner.css', 'wpcom-profile-settings-link-to-wpcom': From 3acc4613fd85669953c1087b9ea731dcdbfd9059 Mon Sep 17 00:00:00 2001 From: Ashar Fuadi Date: Mon, 20 Jan 2025 23:19:00 +0700 Subject: [PATCH 2/2] Support in site editor --- .../wpcom-media-url-import-form/index.jsx | 18 +++++++++++++++--- .../wpcom-media/wpcom-media-url-import.php | 9 ++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import-form/index.jsx b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import-form/index.jsx index 571144b698c67..078c3c3af0436 100644 --- a/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import-form/index.jsx +++ b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import-form/index.jsx @@ -4,7 +4,7 @@ import { useState } from 'react'; import './style.scss'; -const WpcomMediaUrlImportForm = ( { ajaxUrl, action, nonce } ) => { +const WpcomMediaUrlImportForm = ( { ajaxUrl, action, nonce, isSiteEditor } ) => { const [ url, setUrl ] = useState( '' ); const [ show, setShow ] = useState( false ); @@ -43,14 +43,26 @@ const WpcomMediaUrlImportForm = ( { ajaxUrl, action, nonce } ) => { if ( success ) { window.wp.media.model.Attachment.get( data.attachment_id ).fetch( { success: function ( attachment ) { - window.wp.media.frame.content.get().collection.add( attachment ); + if ( ! isSiteEditor ) { + window.wp.media.frame.content.get().collection.add( attachment ); + } setIsUploading( false ); - setIsUploaded( true ); + setTimeout( () => { setIsUploaded( false ); setUrl( '' ); + + if ( isSiteEditor ) { + const mediaLibraryTab = window.wp.media.frame.state( 'library' ); + mediaLibraryTab.collection.add( attachment ); + mediaLibraryTab.trigger( 'open' ); + const selection = mediaLibraryTab.get( 'selection' ); + selection.reset(); + selection.add( [ attachment ] ); + mediaLibraryTab.trigger( 'open' ); + } }, 2000 ); }, } ); diff --git a/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import.php b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import.php index 49eee993e3d2b..a64423a13eee0 100644 --- a/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import.php +++ b/projects/packages/jetpack-mu-wpcom/src/features/wpcom-media/wpcom-media-url-import.php @@ -9,6 +9,8 @@ * Appends the wpcom media UL import form. */ function wpcom_media_url_import() { + global $pagenow; + ?>
admin_url( 'admin-ajax.php' ), - 'action' => 'wpcom_media_url_import', - 'nonce' => wp_create_nonce( 'wpcom_media_url_import' ), + 'ajaxUrl' => admin_url( 'admin-ajax.php' ), + 'action' => 'wpcom_media_url_import', + 'nonce' => wp_create_nonce( 'wpcom_media_url_import' ), + 'isSiteEditor' => $pagenow === 'site-editor.php', ) );