wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file ) );
* Outputs the iframe to display the media upload page.
* @since 5.3.0 Formalized the existing and already documented `...$args` parameter
* by adding it to the function signature.
* @param callable $content_func Function that outputs the content.
* @param mixed ...$args Optional additional parameters to pass to the callback function when it's called.
function wp_iframe( $content_func, ...$args ) {
<title><?php bloginfo( 'name' ); ?> › <?php _e( 'Uploads' ); ?> — <?php _e( 'WordPress' ); ?></title>
wp_enqueue_style( 'colors' );
// Check callback name for 'media'.
( is_array( $content_func ) && ! empty( $content_func[1] ) && 0 === strpos( (string) $content_func[1], 'media' ) ) ||
( ! is_array( $content_func ) && 0 === strpos( $content_func, 'media' ) )
wp_enqueue_style( 'deprecated-media' );
<script type="text/javascript">
addLoadEvent = function(func){if(typeof jQuery!="undefined")jQuery(document).ready(func);else if(typeof wpOnload!='function'){wpOnload=func;}else{var oldonload=wpOnload;wpOnload=function(){oldonload();func();}}};
var ajaxurl = '<?php echo esc_js( admin_url( 'admin-ajax.php', 'relative' ) ); ?>', pagenow = 'media-upload-popup', adminpage = 'media-upload-popup',
isRtl = <?php echo (int) is_rtl(); ?>;
/** This action is documented in wp-admin/admin-header.php */
do_action( 'admin_enqueue_scripts', 'media-upload-popup' );
* Fires when admin styles enqueued for the legacy (pre-3.5.0) media upload popup are printed.
do_action( 'admin_print_styles-media-upload-popup' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
/** This action is documented in wp-admin/admin-header.php */
do_action( 'admin_print_styles' );
* Fires when admin scripts enqueued for the legacy (pre-3.5.0) media upload popup are printed.
do_action( 'admin_print_scripts-media-upload-popup' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
/** This action is documented in wp-admin/admin-header.php */
do_action( 'admin_print_scripts' );
* Fires when scripts enqueued for the admin header for the legacy (pre-3.5.0)
* media upload popup are printed.
do_action( 'admin_head-media-upload-popup' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
/** This action is documented in wp-admin/admin-header.php */
do_action( 'admin_head' );
if ( is_string( $content_func ) ) {
* Fires in the admin header for each specific form tab in the legacy
* (pre-3.5.0) media upload popup.
* The dynamic portion of the hook, `$content_func`, refers to the form
* callback for the media upload type. Possible values include
* 'media_upload_type_form', 'media_upload_type_url_form', and
* 'media_upload_library_form'.
do_action( "admin_head_{$content_func}" );
if ( isset( $GLOBALS['body_id'] ) ) {
$body_id_attr = ' id="' . $GLOBALS['body_id'] . '"';
<body<?php echo $body_id_attr; ?> class="wp-core-ui no-js">
<script type="text/javascript">
document.body.className = document.body.className.replace('no-js', 'js');
call_user_func_array( $content_func, $args );
/** This action is documented in wp-admin/admin-footer.php */
do_action( 'admin_print_footer_scripts' );
<script type="text/javascript">if(typeof wpOnload=='function')wpOnload();</script>
* Adds the media button to the editor
* @param string $editor_id
function media_buttons( $editor_id = 'content' ) {
if ( ! $post && ! empty( $GLOBALS['post_ID'] ) ) {
$post = $GLOBALS['post_ID'];
wp_enqueue_media( array( 'post' => $post ) );
$img = '<span class="wp-media-buttons-icon"></span> ';
$id_attribute = 1 === $instance ? ' id="insert-media-button"' : '';
'<button type="button"%s class="button insert-media add_media" data-editor="%s">%s</button>',
* Filters the legacy (pre-3.5.0) media buttons.
* Use {@see 'media_buttons'} action instead.
* @deprecated 3.5.0 Use {@see 'media_buttons'} action instead.
* @param string $string Media buttons context. Default empty.
$legacy_filter = apply_filters_deprecated( 'media_buttons_context', array( '' ), '3.5.0', 'media_buttons' );
// #WP22559. Close <a> if a plugin started by closing <a> to open their own <a> tag.
if ( 0 === stripos( trim( $legacy_filter ), '</a>' ) ) {
$legacy_filter .= '</a>';
function get_upload_iframe_src( $type = null, $post_id = null, $tab = null ) {
if ( empty( $post_id ) ) {
$upload_iframe_src = add_query_arg( 'post_id', (int) $post_id, admin_url( 'media-upload.php' ) );
if ( $type && 'media' !== $type ) {
$upload_iframe_src = add_query_arg( 'type', $type, $upload_iframe_src );
$upload_iframe_src = add_query_arg( 'tab', $tab, $upload_iframe_src );
* Filters the upload iframe source URL for a specific media type.
* The dynamic portion of the hook name, `$type`, refers to the type
* @param string $upload_iframe_src The upload iframe source URL by type.
$upload_iframe_src = apply_filters( "{$type}_upload_iframe_src", $upload_iframe_src );
return add_query_arg( 'TB_iframe', true, $upload_iframe_src );
* Handles form submissions for the legacy media uploader.
* @return mixed void|object WP_Error on failure
function media_upload_form_handler() {
check_admin_referer( 'media-form' );
if ( isset( $_POST['send'] ) ) {
$keys = array_keys( $_POST['send'] );
$send_id = (int) reset( $keys );
if ( ! empty( $_POST['attachments'] ) ) {
foreach ( $_POST['attachments'] as $attachment_id => $attachment ) {
$post = get_post( $attachment_id, ARRAY_A );
if ( ! current_user_can( 'edit_post', $attachment_id ) ) {
if ( isset( $attachment['post_content'] ) ) {
$post['post_content'] = $attachment['post_content'];
if ( isset( $attachment['post_title'] ) ) {
$post['post_title'] = $attachment['post_title'];
if ( isset( $attachment['post_excerpt'] ) ) {
$post['post_excerpt'] = $attachment['post_excerpt'];
if ( isset( $attachment['menu_order'] ) ) {
$post['menu_order'] = $attachment['menu_order'];
if ( isset( $send_id ) && $attachment_id == $send_id ) {
if ( isset( $attachment['post_parent'] ) ) {
$post['post_parent'] = $attachment['post_parent'];
* Filters the attachment fields to be saved.
* @see wp_get_attachment_metadata()
* @param array $post An array of post data.
* @param array $attachment An array of attachment metadata.
$post = apply_filters( 'attachment_fields_to_save', $post, $attachment );
if ( isset( $attachment['image_alt'] ) ) {
$image_alt = wp_unslash( $attachment['image_alt'] );
if ( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) !== $image_alt ) {
$image_alt = wp_strip_all_tags( $image_alt, true );
// update_post_meta() expects slashed.
update_post_meta( $attachment_id, '_wp_attachment_image_alt', wp_slash( $image_alt ) );
if ( isset( $post['errors'] ) ) {
$errors[ $attachment_id ] = $post['errors'];
unset( $post['errors'] );
foreach ( get_attachment_taxonomies( $post ) as $t ) {
if ( isset( $attachment[ $t ] ) ) {
wp_set_object_terms( $attachment_id, array_map( 'trim', preg_split( '/,+/', $attachment[ $t ] ) ), $t, false );
if ( isset( $_POST['insert-gallery'] ) || isset( $_POST['update-gallery'] ) ) {
<script type="text/javascript">
var win = window.dialogArguments || opener || parent || top;
if ( isset( $send_id ) ) {
$attachment = wp_unslash( $_POST['attachments'][ $send_id ] );
$html = isset( $attachment['post_title'] ) ? $attachment['post_title'] : '';
if ( ! empty( $attachment['url'] ) ) {
if ( strpos( $attachment['url'], 'attachment_id' ) || get_attachment_link( $send_id ) == $attachment['url'] ) {
$rel = " rel='attachment wp-att-" . esc_attr( $send_id ) . "'";
$html = "<a href='{$attachment['url']}'$rel>$html</a>";
* Filters the HTML markup for a media item sent to the editor.
* @see wp_get_attachment_metadata()
* @param string $html HTML markup for a media item sent to the editor.
* @param int $send_id The first key from the $_POST['send'] data.
* @param array $attachment Array of attachment metadata.
$html = apply_filters( 'media_send_to_editor', $html, $send_id, $attachment );
return media_send_to_editor( $html );
* Handles the process of uploading media.
function wp_media_upload_handler() {
if ( isset( $_POST['html-upload'] ) && ! empty( $_FILES ) ) {
check_admin_referer( 'media-form' );
// Upload File button was clicked.
$id = media_handle_upload( 'async-upload', $_REQUEST['post_id'] );
if ( is_wp_error( $id ) ) {
$errors['upload_error'] = $id;
if ( ! empty( $_POST['insertonlybutton'] ) ) {
if ( ! empty( $src ) && ! strpos( $src, '://' ) ) {
if ( isset( $_POST['media_type'] ) && 'image' !== $_POST['media_type'] ) {
$title = esc_html( wp_unslash( $_POST['title'] ) );
$title = esc_html( wp_basename( $src ) );
$html = "<a href='" . esc_url( $src ) . "'>$title</a>";
$ext = preg_replace( '/^.+?\.([^.]+)$/', '$1', $src );
$ext_type = wp_ext2type( $ext );
if ( 'audio' === $ext_type || 'video' === $ext_type ) {
* Filters the URL sent to the editor for a specific media type.
* The dynamic portion of the hook name, `$type`, refers to the type
* @param string $html HTML markup sent to the editor.
* @param string $src Media source URL.
* @param string $title Media title.
$html = apply_filters( "{$type}_send_to_editor_url", $html, esc_url_raw( $src ), $title );
$alt = esc_attr( wp_unslash( $_POST['alt'] ) );
if ( isset( $_POST['align'] ) ) {
$align = esc_attr( wp_unslash( $_POST['align'] ) );
$class = " class='align$align'";
$html = "<img src='" . esc_url( $src ) . "' alt='$alt'$class />";
* Filters the image URL sent to the editor.
* @param string $html HTML markup sent to the editor for an image.
* @param string $src Image source URL.
* @param string $alt Image alternate, or alt, text.
* @param string $align The image alignment. Default 'alignnone'. Possible values include
* 'alignleft', 'aligncenter', 'alignright', 'alignnone'.
$html = apply_filters( 'image_send_to_editor_url', $html, esc_url_raw( $src ), $alt, $align );
return media_send_to_editor( $html );
if ( isset( $_POST['save'] ) ) {
$errors['upload_notice'] = __( 'Saved.' );
wp_enqueue_script( 'admin-gallery' );
return wp_iframe( 'media_upload_gallery_form', $errors );
} elseif ( ! empty( $_POST ) ) {
$return = media_upload_form_handler();
if ( is_string( $return ) ) {
if ( is_array( $return ) ) {
if ( isset( $_GET['tab'] ) && 'type_url' === $_GET['tab'] ) {
if ( isset( $_GET['type'] ) && in_array( $_GET['type'], array( 'video', 'audio', 'file' ), true ) ) {
return wp_iframe( 'media_upload_type_url_form', $type, $errors, $id );
return wp_iframe( 'media_upload_type_form', 'image', $errors, $id );
* Downloads an image from the specified URL, saves it as an attachment, and optionally attaches it to a post.
* @since 4.2.0 Introduced the `$return` parameter.
* @since 4.8.0 Introduced the 'id' option for the `$return` parameter.
* @since 5.3.0 The `$post_id` parameter was made optional.
* @since 5.4.0 The original URL of the attachment is stored in the `_source_url`
* @param string $file The URL of the image to download.
* @param int $post_id Optional. The post ID the media is to be associated with.
* @param string $desc Optional. Description of the image.
* @param string $return Optional. Accepts 'html' (image tag html) or 'src' (URL),
* or 'id' (attachment ID). Default 'html'.
* @return string|int|WP_Error Populated HTML img tag, attachment ID, or attachment source
* on success, WP_Error object otherwise.
function media_sideload_image( $file, $post_id = 0, $desc = null, $return = 'html' ) {
if ( ! empty( $file ) ) {
$allowed_extensions = array( 'jpg', 'jpeg', 'jpe', 'png', 'gif' );
* Filters the list of allowed file extensions when sideloading an image from a URL.
* The default allowed extensions are:
* @param string[] $allowed_extensions Array of allowed file extensions.