Skip to content

Commit

Permalink
Media Library: Implement upload media from URL (#41089)
Browse files Browse the repository at this point in the history
  • Loading branch information
fushar authored and matticbot committed Feb 6, 2025
1 parent 00fe491 commit d8040f5
Show file tree
Hide file tree
Showing 12 changed files with 292 additions and 63 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?php return array('dependencies' => array('react', 'react-dom', 'wp-i18n', 'wp-polyfill'), 'version' => '10268ed3f972a83340f1');

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public static function load_wpcom_user_features() {
require_once __DIR__ . '/features/wpcom-command-palette/wpcom-command-palette.php';
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-media-url-upload.php';
require_once __DIR__ . '/features/wpcom-options-general/options-general.php';
require_once __DIR__ . '/features/wpcom-plugins/wpcom-plugins.php';
require_once __DIR__ . '/features/wpcom-profile-settings/profile-settings-link-to-wpcom.php';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { __ } from '@wordpress/i18n';
import clsx from 'clsx';
import { useState } from 'react';

import './style.scss';

const WpcomMediaUrlUploadForm = ( { ajaxUrl, action, nonce, isEditor } ) => {
const [ url, setUrl ] = useState( '' );

const [ show, setShow ] = useState( false );
const [ isUploading, setIsUploading ] = 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( '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 ) {
const addAttachment = attachmentToAdd => {
( window.wp.media.frame.controller || window.wp.media.frame ).content
.get()
.collection.add( attachmentToAdd );
};

if ( isEditor ) {
const mediaLibraryTab = window.wp.media.frame.state( 'library' );
mediaLibraryTab.trigger( 'open' );

addAttachment( attachment );

const selection = mediaLibraryTab.get( 'selection' );
selection.reset();
selection.add( [ attachment ] );
} else {
addAttachment( attachment );
}

setIsUploading( false );
setUrl( '' );
},
} );
} else {
setIsUploading( false );
window.wp.Uploader.errors.add( { file: { name: url }, message: data[ 0 ].message } );
}

return false;
};

const renderLink = () => {
return (
<button
className="button wpcom-media-url-upload-form__pre-upload-button"
onClick={ () => setShow( true ) }
>
{ __( 'Upload from URL', 'jetpack-mu-wpcom' ) }
</button>
);
};

const renderForm = () => {
let buttonText = __( 'Upload', 'jetpack-mu-wpcom' );
if ( isUploading ) {
buttonText = __( 'Uploading…', 'jetpack-mu-wpcom' );
}
return (
<form onSubmit={ handleSubmit }>
<input
type="url"
value={ url }
onChange={ handleUrlChange }
placeholder={ __( 'Enter media URL', 'jetpack-mu-wpcom' ) }
required
readOnly={ isUploading }
/>
<button
type="submit"
className={ clsx( 'button', 'button-primary', {
'updating-message': isUploading,
} ) }
readOnly={ isUploading }
>
{ buttonText }
</button>
</form>
);
};

return <div className="wpcom-media-url-upload-form">{ show ? renderForm() : renderLink() }</div>;
};

export default WpcomMediaUrlUploadForm;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import WpcomMediaUrlUploadForm from './wpcom-media-url-upload-form';

const props = typeof window === 'object' ? window.JETPACK_MU_WPCOM_MEDIA_URL_UPLOAD : {};

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-upload' );
if ( container ) {
const root = ReactDOM.createRoot( container );
root.render( <WpcomMediaUrlUploadForm { ...props } /> );
}
},
} );
}
} );
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php
/**
* Allows uploading media from URL in Media Library.
*
* @package automattic/jetpack-mu-wpcom
*/

/**
* Appends the wpcom media URL upload form.
*/
function wpcom_media_url_upload() {
global $pagenow;

if ( empty( $_GET['untangling-media'] ) ) { // phpcs:disable WordPress.Security.NonceVerification.Recommended
return;
}

?>
<div id="wpcom-media-url-upload"></div>
<?php

$handle = jetpack_mu_wpcom_enqueue_assets( 'wpcom-media-url-upload', array( 'js', 'css' ) );

$data = wp_json_encode(
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'action' => 'wpcom_media_url_upload',
'nonce' => wp_create_nonce( 'wpcom_media_url_upload' ),
'isEditor' => $pagenow !== 'upload.php',
)
);

wp_add_inline_script(
$handle,
"window.JETPACK_MU_WPCOM_MEDIA_URL_UPLOAD = $data;",
'before'
);
}

/**
* AJAX handler for the wpcom media URL upload.
*/
function wpcom_handle_media_url_upload() {
check_ajax_referer( 'wpcom_media_url_upload' );

if ( ! isset( $_POST['url'] ) ) {
return;
}

$url = esc_url_raw( wp_unslash( $_POST['url'] ) );

$tmp_file = download_url( $url );
if ( is_wp_error( $tmp_file ) ) {
return wp_send_json_error( $tmp_file );
}

if ( is_multisite() ) {
add_filter( 'wp_handle_sideload_prefilter', 'check_upload_size' );
}

$attachment_id = media_handle_sideload(
array(
'name' => basename( wp_parse_url( $url, PHP_URL_PATH ) ),
'tmp_name' => $tmp_file,
)
);

if ( file_exists( $tmp_file ) ) {
wp_delete_file( $tmp_file );
}

if ( is_wp_error( $attachment_id ) ) {
return wp_send_json_error( $attachment_id );
} else {
return wp_send_json_success( array( 'attachment_id' => $attachment_id ) );
}
}

if ( current_user_can( 'upload_files' ) ) {
add_action( 'pre-upload-ui', 'wpcom_media_url_upload', 9 );
add_action( 'wp_ajax_wpcom_media_url_upload', 'wpcom_handle_media_url_upload' );
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ module.exports = [
'./src/features/wpcom-global-styles/wpcom-global-styles-view.js',
'wpcom-documentation-links':
'./src/features/wpcom-documentation-links/wpcom-documentation-links.ts',
'wpcom-media-url-upload': './src/features/wpcom-media/wpcom-media-url-upload.js',
'wpcom-options-general': [
'./src/features/wpcom-options-general/options-general.js',
'./src/features/wpcom-options-general/options-general.scss',
Expand Down
2 changes: 1 addition & 1 deletion jetpack_vendor/i18n-map.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
),
'jetpack-mu-wpcom' => array(
'path' => 'jetpack_vendor/automattic/jetpack-mu-wpcom',
'ver' => '6.2.0-alpha1738744373',
'ver' => '6.2.0-alpha1738809817',
),
'jetpack-password-checker' => array(
'path' => 'jetpack_vendor/automattic/jetpack-password-checker',
Expand Down
Loading

0 comments on commit d8040f5

Please sign in to comment.