s Default Plupload parameters array. */ $params = apply_filters( 'plupload_default_params', $params ); $params['_wpnonce'] = wp_create_nonce( 'media-form' ); $defaults['multipart_params'] = $params; $settings = array( 'defaults' => $defaults, 'browser' => array( 'mobile' => wp_is_mobile(), 'supported' => _device_can_upload(), ), 'limitExceeded' => is_multisite() && ! is_upload_space_available(), ); $script = 'var _wpPluploadSettings = ' . wp_json_encode( $settings ) . ';'; if ( $data ) { $script = "$data\n$script"; } $wp_scripts->add_data( 'wp-plupload', 'data', $script ); } /** * Prepares an attachment post object for JS, where it is expected * to be JSON-encoded and fit into an Attachment model. * * @since 3.5.0 * * @param int|WP_Post $attachment Attachment ID or object. * @return array|void { * Array of attachment details, or void if the parameter does not correspond to an attachment. * * @type string $alt Alt text of the attachment. * @type string $author ID of the attachment author, as a string. * @type string $authorName Name of the attachment author. * @type string $caption Caption for the attachment. * @type array $compat Containing item and meta. * @type string $context Context, whether it's used as the site icon for example. * @type int $date Uploaded date, timestamp in milliseconds. * @type string $dateFormatted Formatted date (e.g. June 29, 2018). * @type string $description Description of the attachment. * @type string $editLink URL to the edit page for the attachment. * @type string $filename File name of the attachment. * @type string $filesizeHumanReadable Filesize of the attachment in human readable format (e.g. 1 MB). * @type int $filesizeInBytes Filesize of the attachment in bytes. * @type int $height If the attachment is an image, represents the height of the image in pixels. * @type string $icon Icon URL of the attachment (e.g. /wp-includes/images/media/archive.png). * @type int $id ID of the attachment. * @type string $link URL to the attachment. * @type int $menuOrder Menu order of the attachment post. * @type array $meta Meta data for the attachment. * @type string $mime Mime type of the attachment (e.g. image/jpeg or application/zip). * @type int $modified Last modified, timestamp in milliseconds. * @type string $name Name, same as title of the attachment. * @type array $nonces Nonces for update, delete and edit. * @type string $orientation If the attachment is an image, represents the image orientation * (landscape or portrait). * @type array $sizes If the attachment is an image, contains an array of arrays * for the images sizes: thumbnail, medium, large, and full. * @type string $status Post status of the attachment (usually 'inherit'). * @type string $subtype Mime subtype of the attachment (usually the last part, e.g. jpeg or zip). * @type string $title Title of the attachment (usually slugified file name without the extension). * @type string $type Type of the attachment (usually first part of the mime type, e.g. image). * @type int $uploadedTo Parent post to which the attachment was uploaded. * @type string $uploadedToLink URL to the edit page of the parent post of the attachment. * @type string $uploadedToTitle Post title of the parent of the attachment. * @type string $url Direct URL to the attachment file (from wp-content). * @type int $width If the attachment is an image, represents the width of the image in pixels. * } * */ function wp_prepare_attachment_for_js( $attachment ) { $attachment = get_post( $attachment ); if ( ! $attachment ) { return; } if ( 'attachment' !== $attachment->post_type ) { return; } $meta = wp_get_attachment_metadata( $attachment->ID ); if ( false !== strpos( $attachment->post_mime_type, '/' ) ) { list( $type, $subtype ) = explode( '/', $attachment->post_mime_type ); } else { list( $type, $subtype ) = array( $attachment->post_mime_type, '' ); } $attachment_url = wp_get_attachment_url( $attachment->ID ); $base_url = str_replace( wp_basename( $attachment_url ), '', $attachment_url ); $response = array( 'id' => $attachment->ID, 'title' => $attachment->post_title, 'filename' => wp_basename( get_attached_file( $attachment->ID ) ), 'url' => $attachment_url, 'link' => get_attachment_link( $attachment->ID ), 'alt' => get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ), 'author' => $attachment->post_author, 'description' => $attachment->post_content, 'caption' => $attachment->post_excerpt, 'name' => $attachment->post_name, 'status' => $attachment->post_status, 'uploadedTo' => $attachment->post_parent, 'date' => strtotime( $attachment->post_date_gmt ) * 1000, 'modified' => strtotime( $attachment->post_modified_gmt ) * 1000, 'menuOrder' => $attachment->menu_order, 'mime' => $attachment->post_mime_type, 'type' => $type, 'subtype' => $subtype, 'icon' => wp_mime_type_icon( $attachment->ID ), 'dateFormatted' => mysql2date( __( 'F j, Y' ), $attachment->post_date ), 'nonces' => array( 'update' => false, 'delete' => false, 'edit' => false, ), 'editLink' => false, 'meta' => false, ); $author = new WP_User( $attachment->post_author ); if ( $author->exists() ) { $author_name = $author->display_name ? $author->display_name : $author->nickname; $response['authorName'] = html_entity_decode( $author_name, ENT_QUOTES, get_bloginfo( 'charset' ) ); $response['authorLink'] = get_edit_user_link( $author->ID ); } else { $response['authorName'] = __( '(no author)' ); } if ( $attachment->post_parent ) { $post_parent = get_post( $attachment->post_parent ); if ( $post_parent ) { $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __( '(no title)' ); $response['uploadedToLink'] = get_edit_post_link( $attachment->post_parent, 'raw' ); } } $attached_file = get_attached_file( $attachment->ID ); if ( isset( $meta['filesize'] ) ) { $bytes = $meta['filesize']; } elseif ( file_exists( $attached_file ) ) { $bytes = filesize( $attached_file ); } else { $bytes = ''; } if ( $bytes ) { $response['filesizeInBytes'] = $bytes; $response['filesizeHumanReadable'] = size_format( $bytes ); } $context = get_post_meta( $attachment->ID, '_wp_attachment_context', true ); $response['context'] = ( $context ) ? $context : ''; if ( current_user_can( 'edit_post', $attachment->ID ) ) { $response['nonces']['update'] = wp_create_nonce( 'update-post_' . $attachment->ID ); $response['nonces']['edit'] = wp_create_nonce( 'image_editor-' . $attachment->ID ); $response['editLink'] = get_edit_post_link( $attachment->ID, 'raw' ); } if ( current_user_can( 'delete_post', $attachment->ID ) ) { $response['nonces']['delete'] = wp_create_nonce( 'delete-post_' . $attachment->ID ); } if ( $meta && ( 'image' === $type || ! empty( $meta['sizes'] ) ) ) { $sizes = array(); /** This filter is documented in wp-admin/includes/media.php */ $possible_sizes = apply_filters( 'image_size_names_choose', array( 'thumbnail' => __( 'Thumbnail' ), 'medium' => __( 'Medium' ), 'large' => __( 'Large' ), 'full' => __( 'Full Size' ), ) ); unset( $possible_sizes['full'] ); /* * Loop through all potential sizes that may be chosen. Try to do this with some efficiency. * First: run the image_downsize filter. If it returns something, we can use its data. * If the filter does not return something, then image_downsize() is just an expensive way * to check the image metadata, which we do second. */ foreach ( $possible_sizes as $size => $label ) { /** This filter is documented in wp-includes/media.php */ $downsize = apply_filters( 'image_downsize', false, $attachment->ID, $size ); if ( $downsize ) { if ( empty( $downsize[3] ) ) { continue; } $sizes[ $size ] = array( 'height' => $downsize[2], 'width' => $downsize[1], 'url' => $downsize[0], 'orientation' => $downsize[2] > $downsize[1] ? 'portrait' : 'landscape', ); } elseif ( isset( $meta['sizes'][ $size ] ) ) { // Nothing from the filter, so consult image metadata if we have it. $size_meta = $meta['sizes'][ $size ]; // We have the actual image size, but might need to further constrain it if content_width is narrower. // Thumbnail, medium, and full sizes are also checked against the site's height/width options. list( $width, $height ) = image_constrain_size_for_editor( $size_meta['width'], $size_meta['height'], $size, 'edit' ); $sizes[ $size ] = array( 'height' => $height, 'width' => $width, 'url' => $base_url . $size_meta['file'], 'orientation' => $height > $width ? 'portrait' : 'landscape', ); } } if ( 'image' === $type ) { if ( ! empty( $meta['original_image'] ) ) { $response['originalImageURL'] = wp_get_original_image_url( $attachment->ID ); $response['originalImageName'] = wp_basename( wp_get_original_image_path( $attachment->ID ) ); } $sizes['full'] = array( 'url' => $attachment_url ); if ( isset( $meta['height'], $meta['width'] ) ) { $sizes['full']['height'] = $meta['height']; $sizes['full']['width'] = $meta['width']; $sizes['full']['orientation'] = $meta['height'] > $meta['width'] ? 'portrait' : 'landscape'; } $response = array_merge( $response, $sizes['full'] ); } elseif ( $meta['sizes']['full']['file'] ) { $sizes['full'] = array( 'url' => $base_url . $meta['sizes']['full']['file'], 'height' => $meta['sizes']['full']['height'], 'width' => $meta['sizes']['full']['width'], 'orientation' => $meta['sizes']['full']['height'] > $meta['sizes']['full']['width'] ? 'portrait' : 'landscape', ); } $response = array_merge( $response, array( 'sizes' => $sizes ) ); } if ( $meta && 'video' === $type ) { if ( isset( $meta['width'] ) ) { $response['width'] = (int) $meta['width']; } if ( isset( $meta['height'] ) ) { $response['height'] = (int) $meta['height']; } } if ( $meta && ( 'audio' === $type || 'video' === $type ) ) { if ( isset( $meta['length_formatted'] ) ) { $response['fileLength'] = $meta['length_formatted']; $response['fileLengthHumanReadable'] = human_readable_duration( $meta['length_formatted'] ); } $response['meta'] = array(); foreach ( wp_get_attachment_id3_keys( $attachment, 'js' ) as $key => $label ) { $response['meta'][ $key ] = false; if ( ! empty( $meta[ $key ] ) ) { $response['meta'][ $key ] = $meta[ $key ]; } } $id = get_post_thumbnail_id( $attachment->ID ); if ( ! empty( $id ) ) { list( $src, $width, $height ) = wp_get_attachment_image_src( $id, 'full' ); $response['image'] = compact( 'src', 'width', 'height' ); list( $src, $width, $height ) = wp_get_attachment_image_src( $id, 'thumbnail' ); $response['thumb'] = compact( 'src', 'width', 'height' ); } else { $src = wp_mime_type_icon( $attachment->ID ); $width = 48; $height = 64; $response['image'] = compact( 'src', 'width', 'height' ); $response['thumb'] = compact( 'src', 'width', 'height' ); } } if ( function_exists( 'get_compat_media_markup' ) ) { $response['compat'] = get_compat_media_markup( $attachment->ID, array( 'in_modal' => true ) ); } if ( function_exists( 'get_media_states' ) ) { $media_states = get_media_states( $attachment ); if ( ! empty( $media_states ) ) { $response['mediaStates'] = implode( ', ', $media_states ); } } /** * Filters the attachment data prepared for JavaScript. * * @since 3.5.0 * * @param array $response Array of prepared attachment data. @see wp_prepare_attachment_for_js(). * @param WP_Post $attachment Attachment object. * @param array|false $meta Array of attachment meta data, or false if there is none. */ return apply_filters( 'wp_prepare_attachment_for_js', $response, $attachment, $meta ); } /** * Enqueues all scripts, styles, settings, and templates necessary to use * all media JS APIs. * * @since 3.5.0 * * @global int $content_width * @global wpdb $wpdb WordPress database abstraction object. * @global WP_Locale $wp_locale WordPress date and time locale object. * * @param array $args { * Arguments for enqueuing media scripts. * * @type int|WP_Post A post object or ID. * } */ function wp_enqueue_media( $args = array() ) { // Enqueue me just once per page, please. if ( did_action( 'wp_enqueue_media' ) ) { return; } global $content_width, $wpdb, $wp_locale; $defaults = array( 'post' => null, ); $args = wp_parse_args( $args, $defaults ); // We're going to pass the old thickbox media tabs to `media_upload_tabs` // to ensure plugins will work. We will then unset those tabs. $tabs = array( // handler action suffix => tab label 'type' => '', 'type_url' => '', 'gallery' => '', 'library' => '', ); /** This filter is documented in wp-admin/includes/media.php */ $tabs = apply_filters( 'media_upload_tabs', $tabs ); unset( $tabs['type'], $tabs['type_url'], $tabs['gallery'], $tabs['library'] ); $props = array( 'link' => get_option( 'image_default_link_type' ), // DB default is 'file'. 'align' => get_option( 'image_default_align' ), // Empty default. 'size' => get_option( 'image_default_size' ), // Empty default. ); $exts = array_merge( wp_get_audio_extensions(), wp_get_video_extensions() ); $mimes = get_allowed_mime_types(); $ext_mimes = array(); foreach ( $exts as $ext ) { foreach ( $mimes as $ext_preg => $mime_match ) { if ( preg_match( '#' . $ext . '#i', $ext_preg ) ) { $ext_mimes[ $ext ] = $mime_match; break; } } } /** * Allows showing or hiding the "Create Audio Playlist" button in the media library. * * By default, the "Create Audio Playlist" button will always be shown in * the media library. If this filter returns `null`, a query will be run * to determine whether the media library contains any audio items. This * was the default behavior prior to version 4.8.0, but this query is * expensive for large media libraries. * * @since 4.7.4 * @since 4.8.0 The filter's default value is `true` rather than `null`. * * @link https://core.trac.wordpress.org/ticket/31071 * * @param bool|null $show Whether to show the button, or `null` to decide based * on whether any audio files exist in the media library. */ $show_audio_playlist = apply_filters( 'media_library_show_audio_playlist', true ); if ( null === $show_audio_playlist ) { $show_audio_playlist = $wpdb->get_var( " SELECT ID FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type LIKE 'audio%' LIMIT 1 " ); } /** * Allows showing or hiding the "Create Video Playlist" button in the media library. * * By default, the "Create Video Playlist" button will always be shown in * the media library. If this filter returns `null`, a query will be run * to determine whether the media library contains any video items. This * was the default behavior prior to version 4.8.0, but this query is * expensive for large media libraries. * * @since 4.7.4 * @since 4.8.0 The filter's default value is `true` rather than `null`. * * @link https://core.trac.wordpress.org/ticket/31071 * * @param bool|null $show Whether to show the button, or `null` to decide based * on whether any video files exist in the media library. */ $show_video_playlist = apply_filters( 'media_library_show_video_playlist', true ); if ( null === $show_video_playlist ) { $show_video_playlist = $wpdb->get_var( " SELECT ID FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type LIKE 'video%' LIMIT 1 " ); } /** * Allows overriding the list of months displayed in the media library. * * By default (if this filter does not return an array), a query will be * run to determine the months that have media items. This query can be * expensive for large media libraries, so it may be desirable for sites to * override this behavior. * * @since 4.7.4 * * @link https://core.trac.wordpress.org/ticket/31071 * * @param array|null $months An array of objects with `month` and `year` * properties, or `null` (or any other non-array value) * for default behavior. */ $months = apply_filters( 'media_library_months_with_files', null ); if ( ! is_array( $months ) ) { $months = $wpdb->get_results( $wpdb->prepare( " SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month FROM $wpdb->posts WHERE post_type = %s ORDER BY post_date DESC ", 'attachment' ) ); } foreach ( $months as $month_year ) { $month_year->text = sprintf( /* translators: 1: Month, 2: Year. */ __( '%1$s %2$d' ), $wp_locale->get_month( $month_year->month ), $month_year->year ); } $settings = array( 'tabs' => $tabs, 'tabUrl' => add_query_arg( array( 'chromeless' => true ), admin_url( 'media-upload.php' ) ), 'mimeTypes' => wp_list_pluck( get_post_mime_types(), 0 ), /** This filter is documented in wp-admin/includes/media.php */ 'captions' => ! apply_filters( 'disable_captions', '' ), 'nonce' => array( 'sendToEditor' => wp_create_nonce( 'media-send-to-editor' ), 'setAttachmentThumbnail' => wp_create_nonce( 'set-attachment-thumbnail' ), ), 'post' => array( 'id' => 0, ), 'defaultProps' => $props, 'attachmentCounts' => array( 'audio' => ( $show_audio_playlist ) ? 1 : 0, 'video' => ( $show_video_playlist ) ? 1 : 0, ), 'oEmbedProxyUrl' => rest_url( 'oembed/1.0/proxy' ), 'embedExts' => $exts, 'embedMimes' => $ext_mimes, 'contentWidth' => $content_width, 'months' => $months, 'mediaTrash' => MEDIA_TRASH ? 1 : 0, ); $post = null; if ( isset( $args['post'] ) ) { $post = get_post( $args['post'] ); $settings['post'] = array( 'id' => $post->ID, 'nonce' => wp_create_nonce( 'update-post_' . $post->ID ), ); $thumbnail_support = current_theme_supports( 'post-thumbnails', $post->post_type ) && post_type_supports( $post->post_type, 'thumbnail' ); if ( ! $thumbnail_support && 'attachment' === $post->post_type && $post->post_mime_type ) { if ( wp_attachment_is( 'audio', $post ) ) { $thumbnail_support = post_type_supports( 'attachment:audio', 'thumbnail' ) || current_theme_supports( 'post-thumbnails', 'attachment:audio' ); } elseif ( wp_attachment_is( 'video', $post ) ) { $thumbnail_support = post_type_supports( 'attachment:video', 'thumbnail' ) || current_theme_supports( 'post-thumbnails', 'attachment:video' ); } } if ( $thumbnail_support ) { $featured_image_id = get_post_meta( $post->ID, '_thumbnail_id', true ); $settings['post']['featuredImageId'] = $featured_image_id ? $featured_image_id : -1; } } if ( $post ) { $post_type_object = get_post_type_object( $post->post_type ); } else { $post_type_object = get_post_type_object( 'post' ); } $strings = array( // Generic. 'mediaFrameDefaultTitle' => __( 'Media' ), 'url' => __( 'URL' ), 'addMedia' => __( 'Add media' ), 'search' => __( 'Search' ), 'select' => __( 'Select' ), 'cancel' => __( 'Cancel' ), 'update' => __( 'Update' ), 'replace' => __( 'Replace' ), 'remove' => __( 'Remove' ), 'back' => __( 'Back' ), /* * translators: This is a would-be plural string used in the media manager. * If there is not a word you can use in your language to avoid issues with the * lack of plural support here, turn it into "selected: %d" then translate it. */ 'selected' => __( '%d selected' ), 'dragInfo' => __( 'Drag and drop to reorder media files.' ), // Upload. 'uploadFilesTitle' => __( 'Upload files' ), 'uploadImagesTitle' => __( 'Upload images' ), // Library. 'mediaLibraryTitle' => __( 'Media Library' ), 'insertMediaTitle' => __( 'Add media' ), 'createNewGallery' => __( 'Create a new gallery' ), 'createNewPlaylist' => __( 'Create a new playlist' ), 'createNewVideoPlaylist' => __( 'Create a new video playlist' ), 'returnToLibrary' => __( '← Go to library' ), 'allMediaItems' => __( 'All media items' ), 'allDates' => __( 'All dates' ), 'noItemsFound' => __( 'No items found.' ), 'insertIntoPost' => $post_type_object->labels->insert_into_item, 'unattached' => __( 'Unattached' ), 'mine' => _x( 'Mine', 'media items' ), 'trash' => _x( 'Trash', 'noun' ), 'uploadedToThisPost' => $post_type_object->labels->uploaded_to_this_item, 'warnDelete' => __( "You are about to permanently delete this item from your site.\nThis action cannot be undone.\n 'Cancel' to stop, 'OK' to delete." ), 'warnBulkDelete' => __( "You are about to permanently delete these items from your site.\nThis action cannot be undone.\n 'Cancel' to stop, 'OK' to delete." ), 'warnBulkTrash' => __( "You are about to trash these items.\n 'Cancel' to stop, 'OK' to delete." ), 'bulkSelect' => __( 'Bulk select' ), 'trashSelected' => __( 'Move to Trash' ), 'restoreSelected' => __( 'Restore from Trash' ), 'deletePermanently' => __( 'Delete permanently' ), 'apply' => __( 'Apply' ), 'filterByDate' => __( 'Filter by date' ), 'filterByType' => __( 'Filter by type' ), 'searchLabel' => __( 'Search' ), 'searchMediaLabel' => __( 'Search media' ), // Backward compatibility pre-5.3. 'searchMediaPlaceholder' => __( 'Search media items...' ), // Placeholder (no ellipsis), backward compatibility pre-5.3. 'mediaFound' => __( 'Number of media items found: %d' ), 'mediaFoundHasMoreResults' => __( 'Number of media items displayed: %d. Scroll the page for more results.' ), 'noMedia' => __( 'No media items found.' ), 'noMediaTryNewSearch' => __( 'No media items found. Try a different search.' ), // Library Details. 'attachmentDetails' => __( 'Attachment details' ), // From URL. 'insertFromUrlTitle' => __( 'Insert from URL' ), // Featured Images. 'setFeaturedImageTitle' => $post_type_object->labels->featured_image, 'setFeaturedImage' => $post_type_object->labels->set_featured_image, // Gallery. 'createGalleryTitle' => __( 'Create gallery' ), 'editGalleryTitle' => __( 'Edit gallery' ), 'cancelGalleryTitle' => __( '← Cancel gallery' ), 'insertGallery' => __( 'Insert gallery' ), 'updateGallery' => __( 'Update gallery' ), 'addToGallery' => __( 'Add to gallery' ), 'addToGalleryTitle' => __( 'Add to gallery' ), 'reverseOrder' => __( 'Reverse order' ), // Edit Image. 'imageDetailsTitle' => __( 'Image details' ), 'imageReplaceTitle' => __( 'Replace image' ), 'imageDetailsCancel' => __( 'Cancel edit' ), 'editImage' => __( 'Edit image' ), // Crop Image. 'chooseImage' => __( 'Choose image' ), 'selectAndCrop' => __( 'Select and crop' ), 'skipCropping' => __( 'Skip cropping' ), 'cropImage' => __( 'Crop image' ), 'cropYourImage' => __( 'Crop your image' ), 'cropping' => __( 'Cropping…' ), /* translators: 1: Suggested width number, 2: Suggested height number. */ 'suggestedDimensions' => __( 'Suggested image dimensions: %1$s by %2$s pixels.' ), 'cropError' => __( 'There has been an error cropping your image.' ), // Edit Audio. 'audioDetailsTitle' => __( 'Audio details' ), 'audioReplaceTitle' => __( 'Replace audio' ), 'audioAddSourceTitle' => __( 'Add audio source' ), 'audioDetailsCancel' => __( 'Cancel edit' ), // Edit Video. 'videoDetailsTitle' => __( 'Video details' ), 'videoReplaceTitle' => __( 'Replace video' ), 'videoAddSourceTitle' => __( 'Add video source' ), 'videoDetailsCancel' => __( 'Cancel edit' ), 'videoSelectPosterImageTitle' => __( 'Select poster image' ), 'videoAddTrackTitle' => __( 'Add subtitles' ), // Playlist. 'playlistDragInfo' => __( 'Drag and drop to reorder tracks.' ), 'createPlaylistTitle' => __( 'Create audio playlist' ), 'editPlaylistTitle' => __( 'Edit audio playlist' ), 'cancelPlaylistTitle' => __( '← Cancel audio playlist' ), 'insertPlaylist' => __( 'Insert audio playlist' ), 'updatePlaylist' => __( 'Update audio playlist' ), 'addToPlaylist' => __( 'Add to audio playlist' ), 'addToPlaylistTitle' => __( 'Add to Audio Playlist' ), // Video Playlist. 'videoPlaylistDragInfo' => __( 'Drag and drop to reorder videos.' ), 'createVideoPlaylistTitle' => __( 'Create video playlist' ), 'editVideoPlaylistTitle' => __( 'Edit video playlist' ), 'cancelVideoPlaylistTitle' => __( '← Cancel video playlist' ), 'insertVideoPlaylist' => __( 'Insert video playlist' ), 'updateVideoPlaylist' => __( 'Update video playlist' ), 'addToVideoPlaylist' => __( 'Add to video playlist' ), 'addToVideoPlaylistTitle' => __( 'Add to video Playlist' ), // Headings. 'filterAttachments' => __( 'Filter media' ), 'attachmentsList' => __( 'Media list' ), ); /** * Filters the media view settings. * * @since 3.5.0 * * @param array $settings List of media view settings. * @param WP_Post $post Post object. */ $settings = apply_filters( 'media_view_settings', $settings, $post ); /** * Filters the media view strings. * * @since 3.5.0 * * @param string[] $strings Array of media view strings keyed by the name they'll be referenced by in JavaScript. * @param WP_Post $post Post object. */ $strings = apply_filters( 'media_view_strings', $strings, $post ); $strings['settings'] = $settings; // Ensure we enqueue media-editor first, that way media-views // is registered internally before we try to localize it. See #24724. wp_enqueue_script( 'media-editor' ); wp_localize_script( 'media-views', '_wpMediaViewsL10n', $strings ); wp_enqueue_script( 'media-audiovideo' ); wp_enqueue_style( 'media-views' ); if ( is_admin() ) { wp_enqueue_script( 'mce-view' ); wp_enqueue_script( 'image-edit' ); } wp_enqueue_style( 'imgareaselect' ); wp_plupload_default_settings(); require_once ABSPATH . WPINC . '/media-template.php'; add_action( 'admin_footer', 'wp_print_media_templates' ); add_action( 'wp_footer', 'wp_print_media_templates' ); add_action( 'customize_controls_print_footer_scripts', 'wp_print_media_templates' ); /** * Fires at the conclusion of wp_enqueue_media(). * * @since 3.5.0 */ do_action( 'wp_enqueue_media' ); } /** * Retrieves media attached to the passed post. * * @since 3.6.0 * * @param string $type Mime type. * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. * @return WP_Post[] Array of media attached to the given post. */ function get_attached_media( $type, $post = 0 ) { $post = get_post( $post ); if ( ! $post ) { return array(); } $args = array( 'post_parent' => $post->ID, 'post_type' => 'attachment', 'post_mime_type' => $type, 'posts_per_page' => -1, 'orderby' => 'menu_order', 'order' => 'ASC', ); /** * Filters arguments used to retrieve media attached to the given post. * * @since 3.6.0 * * @param array $args Post query arguments. * @param string $type Mime type of the desired media. * @param WP_Post $post Post object. */ $args = apply_filters( 'get_attached_media_args', $args, $type, $post ); $children = get_children( $args ); /** * Filters the list of media attached to the given post. * * @since 3.6.0 * * @param WP_Post[] $children Array of media attached to the given post. * @param string $type Mime type of the media desired. * @param WP_Post $post Post object. */ return (array) apply_filters( 'get_attached_media', $children, $type, $post ); } /** * Check the content HTML for a audio, video, object, embed, or iframe tags. * * @since 3.6.0 * * @param string $content A string of HTML which might contain media elements. * @param string[] $types An array of media types: 'audio', 'video', 'object', 'embed', or 'iframe'. * @return string[] Array of found HTML media elements. */ function get_media_embedded_in_content( $content, $types = null ) { $html = array(); /** * Filters the embedded media types that are allowed to be returned from the content blob. * * @since 4.2.0 * * @param string[] $allowed_media_types An array of allowed media types. Default media types are * 'audio', 'video', 'object', 'embed', and 'iframe'. */ $allowed_media_types = apply_filters( 'media_embedded_in_content_allowed_types', array( 'audio', 'video', 'object', 'embed', 'iframe' ) ); if ( ! empty( $types ) ) { if ( ! is_array( $types ) ) { $types = array( $types ); } $allowed_media_types = array_intersect( $allowed_media_types, $types ); } $tags = implode( '|', $allowed_media_types ); if ( preg_match_all( '#<(?P' . $tags . ')[^<]*?(?:>[\s\S]*?<\/(?P=tag)>|\s*\/>)#', $content, $matches ) ) { foreach ( $matches[0] as $match ) { $html[] = $match; } } return $html; } /** * Retrieves galleries from the passed post's content. * * @since 3.6.0 * * @param int|WP_Post $post Post ID or object. * @param bool $html Optional. Whether to return HTML or data in the array. Default true. * @return array A list of arrays, each containing gallery data and srcs parsed * from the expanded shortcode. */ function get_post_galleries( $post, $html = true ) { $post = get_post( $post ); if ( ! $post ) { return array(); } if ( ! has_shortcode( $post->post_content, 'gallery' ) ) { return array(); } $galleries = array(); if ( preg_match_all( '/' . get_shortcode_regex() . '/s', $post->post_content, $matches, PREG_SET_ORDER ) ) { foreach ( $matches as $shortcode ) { if ( 'gallery' === $shortcode[2] ) { $srcs = array(); $shortcode_attrs = shortcode_parse_atts( $shortcode[3] ); if ( ! is_array( $shortcode_attrs ) ) { $shortcode_attrs = array(); } // Specify the post ID of the gallery we're viewing if the shortcode doesn't reference another post already. if ( ! isset( $shortcode_attrs['id'] ) ) { $shortcode[3] .= ' id="' . (int) $post->ID . '"'; } $gallery = do_shortcode_tag( $shortcode ); if ( $html ) { $galleries[] = $gallery; } else { preg_match_all( '#src=([\'"])(.+?)\1#is', $gallery, $src, PREG_SET_ORDER ); if ( ! empty( $src ) ) { foreach ( $src as $s ) { $srcs[] = $s[2]; } } $galleries[] = array_merge( $shortcode_attrs, array( 'src' => array_values( array_unique( $srcs ) ), ) ); } } } } /** * Filters the list of all found galleries in the given post. * * @since 3.6.0 * * @param array $galleries Associative array of all found post galleries. * @param WP_Post $post Post object. */ return apply_filters( 'get_post_galleries', $galleries, $post ); } /** * Check a specified post's content for gallery and, if present, return the first * * @since 3.6.0 * * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. * @param bool $html Optional. Whether to return HTML or data. Default is true. * @return string|array Gallery data and srcs parsed from the expanded shortcode. */ function get_post_gallery( $post = 0, $html = true ) { $galleries = get_post_galleries( $post, $html ); $gallery = reset( $galleries ); /** * Filters the first-found post gallery. * * @since 3.6.0 * * @param array $gallery The first-found post gallery. * @param int|WP_Post $post Post ID or object. * @param array $galleries Associative array of all found post galleries. */ return apply_filters( 'get_post_gallery', $gallery, $post, $galleries ); } /** * Retrieve the image srcs from galleries from a post's content, if present * * @since 3.6.0 * * @see get_post_galleries() * * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global `$post`. * @return array A list of lists, each containing image srcs parsed. * from an expanded shortcode */ function get_post_galleries_images( $post = 0 ) { $galleries = get_post_galleries( $post, false ); return wp_list_pluck( $galleries, 'src' ); } /** * Checks a post's content for galleries and return the image srcs for the first found gallery * * @since 3.6.0 * * @see get_post_gallery() * * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global `$post`. * @return string[] A list of a gallery's image srcs in order. */ function get_post_gallery_images( $post = 0 ) { $gallery = get_post_gallery( $post, false ); return empty( $gallery['src'] ) ? array() : $gallery['src']; } /** * Maybe attempts to generate attachment metadata, if missing. * * @since 3.9.0 * * @param WP_Post $attachment Attachment object. */ function wp_maybe_generate_attachment_metadata( $attachment ) { if ( empty( $attachment ) || empty( $attachment->ID ) ) { return; } $attachment_id = (int) $attachment->ID; $file = get_attached_file( $attachment_id ); $meta = wp_get_attachment_metadata( $attachment_id ); if ( empty( $meta ) && file_exists( $file ) ) { $_meta = get_post_meta( $attachment_id ); $_lock = 'wp_generating_att_' . $attachment_id; if ( ! array_key_exists( '_wp_attachment_metadata', $_meta ) && ! get_transient( $_lock ) ) { set_transient( $_lock, $file ); wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file ) ); delete_transient( $_lock ); } } } /** * Tries to convert an attachment URL into a post ID. * * @since 4.0.0 * * @global wpdb $wpdb WordPress database abstraction object. * * @param string $url The URL to resolve. * @return int The found post ID, or 0 on failure. */ function attachment_url_to_postid( $url ) { global $wpdb; $dir = wp_get_upload_dir(); $path = $url; $site_url = parse_url( $dir['url'] ); $image_path = parse_url( $path ); // Force the protocols to match if needed. if ( isset( $image_path['scheme'] ) && ( $image_path['scheme'] !== $site_url['scheme'] ) ) { $path = str_replace( $image_path['scheme'], $site_url['scheme'], $path ); } if ( 0 === strpos( $path, $dir['baseurl'] . '/' ) ) { $path = substr( $path, strlen( $dir['baseurl'] . '/' ) ); } $sql = $wpdb->prepare( "SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = '_wp_attached_file' AND meta_value = %s", $path ); $results = $wpdb->get_results( $sql ); $post_id = null; if ( $results ) { // Use the first available result, but prefer a case-sensitive match, if exists. $post_id = reset( $results )->post_id; if ( count( $results ) > 1 ) { foreach ( $results as $result ) { if ( $path === $result->meta_value ) { $post_id = $result->post_id; break; } } } } /** * Filters an attachment ID found by URL. * * @since 4.2.0 * * @param int|null $post_id The post_id (if any) found by the function. * @param string $url The URL being looked up. */ return (int) apply_filters( 'attachment_url_to_postid', $post_id, $url ); } /** * Returns the URLs for CSS files used in an iframe-sandbox'd TinyMCE media view. * * @since 4.0.0 * * @return string[] The relevant CSS file URLs. */ function wpview_media_sandbox_styles() { $version = 'ver=' . get_bloginfo( 'version' ); $mediaelement = includes_url( "js/mediaelement/mediaelementplayer-legacy.min.css?$version" ); $wpmediaelement = includes_url( "js/mediaelement/wp-mediaelement.css?$version" ); return array( $mediaelement, $wpmediaelement ); } /** * Registers the personal data exporter for media. * * @param array[] $exporters An array of personal data exporters, keyed by their ID. * @return array[] Updated array of personal data exporters. */ function wp_register_media_personal_data_exporter( $exporters ) { $exporters['wordpress-media'] = array( 'exporter_friendly_name' => __( 'WordPress Media' ), 'callback' => 'wp_media_personal_data_exporter', ); return $exporters; } /** * Finds and exports attachments associated with an email address. * * @since 4.9.6 * * @param string $email_address The attachment owner email address. * @param int $page Attachment page. * @return array An array of personal data. */ function wp_media_personal_data_exporter( $email_address, $page = 1 ) { // Limit us to 50 attachments at a time to avoid timing out. $number = 50; $page = (int) $page; $data_to_export = array(); $user = get_user_by( 'email', $email_address ); if ( false === $user ) { return array( 'data' => $data_to_export, 'done' => true, ); } $post_query = new WP_Query( array( 'author' => $user->ID, 'posts_per_page' => $number, 'paged' => $page, 'post_type' => 'attachment', 'post_status' => 'any', 'orderby' => 'ID', 'order' => 'ASC', ) ); foreach ( (array) $post_query->posts as $post ) { $attachment_url = wp_get_attachment_url( $post->ID ); if ( $attachment_url ) { $post_data_to_export = array( array( 'name' => __( 'URL' ), 'value' => $attachment_url, ), ); $data_to_export[] = array( 'group_id' => 'media', 'group_label' => __( 'Media' ), 'group_description' => __( 'User’s media data.' ), 'item_id' => "post-{$post->ID}", 'data' => $post_data_to_export, ); } } $done = $post_query->max_num_pages <= $page; return array( 'data' => $data_to_export, 'done' => $done, ); } /** * Add additional default image sub-sizes. * * These sizes are meant to enhance the way WordPress displays images on the front-end on larger, * high-density devices. They make it possible to generate more suitable `srcset` and `sizes` attributes * when the users upload large images. * * The sizes can be changed or removed by themes and plugins but that is not recommended. * The size "names" reflect the image dimensions, so changing the sizes would be quite misleading. * * @since 5.3.0 * @access private */ function _wp_add_additional_image_sizes() { // 2x medium_large size. add_image_size( '1536x1536', 1536, 1536 ); // 2x large size. add_image_size( '2048x2048', 2048, 2048 ); } /** * Callback to enable showing of the user error when uploading .heic images. * * @since 5.5.0 * * @param array[] $plupload_settings The settings for Plupload.js. * @return array[] Modified settings for Plupload.js. */ function wp_show_heic_upload_error( $plupload_settings ) { $plupload_settings['heic_upload_error'] = true; return $plupload_settings; } /** * Allows PHP's getimagesize() to be debuggable when necessary. * * @since 5.7.0 * * @param string $filename The file path. * @param array $image_info Optional. Extended image information (passed by reference). * @return array|false Array of image information or false on failure. */ function wp_getimagesize( $filename, array &$image_info = null ) { if ( // Skip when running unit tests. ! defined( 'WP_RUN_CORE_TESTS' ) && // Return without silencing errors when in debug mode. defined( 'WP_DEBUG' ) && WP_DEBUG ) { if ( 2 === func_num_args() ) { return getimagesize( $filename, $image_info ); } else { return getimagesize( $filename ); } } /* * Silencing notice and warning is intentional. * * getimagesize() has a tendency to generate errors, such as * "corrupt JPEG data: 7191 extraneous bytes before marker", * even when it's able to provide image size information. * * See https://core.trac.wordpress.org/ticket/42480 */ if ( 2 === func_num_args() ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors return @getimagesize( $filename, $image_info ); } else { // phpcs:ignore WordPress.PHP.NoSilencedErrors return @getimagesize( $filename ); } }