wp_prepare_attachment_for_js

The timeline below displays how wordpress function wp_prepare_attachment_for_js has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.5

/**
 * 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 (str_contains($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, '.svg'), '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 = wp_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, '.svg');
            $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 {@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);
}

WordPress Version: 6.4

/**
 * 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 (str_contains($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 = wp_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 {@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);
}

WordPress Version: 6.3

/**
 * 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 (str_contains($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 = wp_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);
}

WordPress Version: 6.1

/**
 * 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 = wp_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);
}

WordPress Version: 5.6

/**
 * 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);
}

WordPress Version: 5.4

/**
 * 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.
 */
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()) {
        $response['authorName'] = html_entity_decode($author->display_name, ENT_QUOTES, get_bloginfo('charset'));
    } else {
        $response['authorName'] = __('(no author)');
    }
    if ($attachment->post_parent) {
        $post_parent = get_post($attachment->post_parent);
    } else {
        $post_parent = false;
    }
    if ($post_parent) {
        $parent_type = get_post_type_object($post_parent->post_type);
        if ($parent_type && $parent_type->show_ui && current_user_can('edit_post', $attachment->post_parent)) {
            $response['uploadedToLink'] = get_edit_post_link($attachment->post_parent, 'raw');
        }
        if ($parent_type && current_user_can('read_post', $attachment->post_parent)) {
            $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __('(no title)');
        }
    }
    $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));
    }
    /**
     * Filters the attachment data prepared for JavaScript.
     *
     * @since 3.5.0
     *
     * @param array       $response   Array of prepared attachment data.
     * @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);
}

WordPress Version: 5.3

/**
 * 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.
 */
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()) {
        $response['authorName'] = html_entity_decode($author->display_name, ENT_QUOTES, get_bloginfo('charset'));
    } else {
        $response['authorName'] = __('(no author)');
    }
    if ($attachment->post_parent) {
        $post_parent = get_post($attachment->post_parent);
    } else {
        $post_parent = false;
    }
    if ($post_parent) {
        $parent_type = get_post_type_object($post_parent->post_type);
        if ($parent_type && $parent_type->show_ui && current_user_can('edit_post', $attachment->post_parent)) {
            $response['uploadedToLink'] = get_edit_post_link($attachment->post_parent, 'raw');
        }
        if ($parent_type && current_user_can('read_post', $attachment->post_parent)) {
            $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __('(no title)');
        }
    }
    $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) {
            $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));
    }
    /**
     * Filters the attachment data prepared for JavaScript.
     *
     * @since 3.5.0
     *
     * @param array       $response   Array of prepared attachment data.
     * @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);
}

WordPress Version: 5.1

/**
 * 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.
 */
function wp_prepare_attachment_for_js($attachment)
{
    if (!$attachment = get_post($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()) {
        $response['authorName'] = html_entity_decode($author->display_name, ENT_QUOTES, get_bloginfo('charset'));
    } else {
        $response['authorName'] = __('(no author)');
    }
    if ($attachment->post_parent) {
        $post_parent = get_post($attachment->post_parent);
    } else {
        $post_parent = false;
    }
    if ($post_parent) {
        $parent_type = get_post_type_object($post_parent->post_type);
        if ($parent_type && $parent_type->show_ui && current_user_can('edit_post', $attachment->post_parent)) {
            $response['uploadedToLink'] = get_edit_post_link($attachment->post_parent, 'raw');
        }
        if ($parent_type && current_user_can('read_post', $attachment->post_parent)) {
            $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __('(no title)');
        }
    }
    $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 */
            if ($downsize = apply_filters('image_downsize', false, $attachment->ID, $size)) {
                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) {
            $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));
    }
    /**
     * Filters the attachment data prepared for JavaScript.
     *
     * @since 3.5.0
     *
     * @param array       $response   Array of prepared attachment data.
     * @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);
}

WordPress Version: 4.9

/**
 * 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 mixed $attachment Attachment ID or object.
 * @return array|void Array of attachment details.
 */
function wp_prepare_attachment_for_js($attachment)
{
    if (!$attachment = get_post($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()) {
        $response['authorName'] = html_entity_decode($author->display_name, ENT_QUOTES, get_bloginfo('charset'));
    } else {
        $response['authorName'] = __('(no author)');
    }
    if ($attachment->post_parent) {
        $post_parent = get_post($attachment->post_parent);
    } else {
        $post_parent = false;
    }
    if ($post_parent) {
        $parent_type = get_post_type_object($post_parent->post_type);
        if ($parent_type && $parent_type->show_ui && current_user_can('edit_post', $attachment->post_parent)) {
            $response['uploadedToLink'] = get_edit_post_link($attachment->post_parent, 'raw');
        }
        if ($parent_type && current_user_can('read_post', $attachment->post_parent)) {
            $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __('(no title)');
        }
    }
    $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 */
            if ($downsize = apply_filters('image_downsize', false, $attachment->ID, $size)) {
                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) {
            $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['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));
    }
    /**
     * Filters the attachment data prepared for JavaScript.
     *
     * @since 3.5.0
     *
     * @param array      $response   Array of prepared attachment data.
     * @param int|object $attachment Attachment ID or object.
     * @param array      $meta       Array of attachment meta data.
     */
    return apply_filters('wp_prepare_attachment_for_js', $response, $attachment, $meta);
}

WordPress Version: 4.8

/**
 * 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 mixed $attachment Attachment ID or object.
 * @return array|void Array of attachment details.
 */
function wp_prepare_attachment_for_js($attachment)
{
    if (!$attachment = get_post($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()) {
        $response['authorName'] = html_entity_decode($author->display_name, ENT_QUOTES, get_bloginfo('charset'));
    } else {
        $response['authorName'] = __('(no author)');
    }
    if ($attachment->post_parent) {
        $post_parent = get_post($attachment->post_parent);
    } else {
        $post_parent = false;
    }
    if ($post_parent) {
        $parent_type = get_post_type_object($post_parent->post_type);
        if ($parent_type && $parent_type->show_ui && current_user_can('edit_post', $attachment->post_parent)) {
            $response['uploadedToLink'] = get_edit_post_link($attachment->post_parent, 'raw');
        }
        if ($parent_type && current_user_can('read_post', $attachment->post_parent)) {
            $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __('(no title)');
        }
    }
    $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);
    }
    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 */
            if ($downsize = apply_filters('image_downsize', false, $attachment->ID, $size)) {
                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) {
            $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['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));
    }
    /**
     * Filters the attachment data prepared for JavaScript.
     *
     * @since 3.5.0
     *
     * @param array      $response   Array of prepared attachment data.
     * @param int|object $attachment Attachment ID or object.
     * @param array      $meta       Array of attachment meta data.
     */
    return apply_filters('wp_prepare_attachment_for_js', $response, $attachment, $meta);
}

WordPress Version: 7.1

/**
 * 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 mixed $attachment Attachment ID or object.
 * @return array|void Array of attachment details.
 */
function wp_prepare_attachment_for_js($attachment)
{
    if (!$attachment = get_post($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);
    $response['authorName'] = $author->display_name;
    if ($attachment->post_parent) {
        $post_parent = get_post($attachment->post_parent);
    } else {
        $post_parent = false;
    }
    if ($post_parent) {
        $parent_type = get_post_type_object($post_parent->post_type);
        if ($parent_type && $parent_type->show_ui && current_user_can('edit_post', $attachment->post_parent)) {
            $response['uploadedToLink'] = get_edit_post_link($attachment->post_parent, 'raw');
        }
        if ($parent_type && current_user_can('read_post', $attachment->post_parent)) {
            $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __('(no title)');
        }
    }
    $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);
    }
    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 */
            if ($downsize = apply_filters('image_downsize', false, $attachment->ID, $size)) {
                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) {
            $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['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));
    }
    /**
     * Filters the attachment data prepared for JavaScript.
     *
     * @since 3.5.0
     *
     * @param array      $response   Array of prepared attachment data.
     * @param int|object $attachment Attachment ID or object.
     * @param array      $meta       Array of attachment meta data.
     */
    return apply_filters('wp_prepare_attachment_for_js', $response, $attachment, $meta);
}

WordPress Version: 4.7

/**
 * 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 mixed $attachment Attachment ID or object.
 * @return array|void Array of attachment details.
 */
function wp_prepare_attachment_for_js($attachment)
{
    if (!$attachment = get_post($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);
    $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);
    $response['authorName'] = $author->display_name;
    if ($attachment->post_parent) {
        $post_parent = get_post($attachment->post_parent);
    } else {
        $post_parent = false;
    }
    if ($post_parent) {
        $parent_type = get_post_type_object($post_parent->post_type);
        if ($parent_type && $parent_type->show_ui && current_user_can('edit_post', $attachment->post_parent)) {
            $response['uploadedToLink'] = get_edit_post_link($attachment->post_parent, 'raw');
        }
        if ($parent_type && current_user_can('read_post', $attachment->post_parent)) {
            $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __('(no title)');
        }
    }
    $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);
    }
    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 */
            if ($downsize = apply_filters('image_downsize', false, $attachment->ID, $size)) {
                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])) {
                if (!isset($base_url)) {
                    $base_url = str_replace(wp_basename($attachment_url), '', $attachment_url);
                }
                // 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) {
            $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['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));
    }
    /**
     * Filters the attachment data prepared for JavaScript.
     *
     * @since 3.5.0
     *
     * @param array      $response   Array of prepared attachment data.
     * @param int|object $attachment Attachment ID or object.
     * @param array      $meta       Array of attachment meta data.
     */
    return apply_filters('wp_prepare_attachment_for_js', $response, $attachment, $meta);
}

WordPress Version: 4.6

/**
 * 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 mixed $attachment Attachment ID or object.
 * @return array|void Array of attachment details.
 */
function wp_prepare_attachment_for_js($attachment)
{
    if (!$attachment = get_post($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);
    $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);
    $response['authorName'] = $author->display_name;
    if ($attachment->post_parent) {
        $post_parent = get_post($attachment->post_parent);
    } else {
        $post_parent = false;
    }
    if ($post_parent) {
        $parent_type = get_post_type_object($post_parent->post_type);
        if ($parent_type && $parent_type->show_ui && current_user_can('edit_post', $attachment->post_parent)) {
            $response['uploadedToLink'] = get_edit_post_link($attachment->post_parent, 'raw');
        }
        if ($parent_type && current_user_can('read_post', $attachment->post_parent)) {
            $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __('(no title)');
        }
    }
    $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);
    }
    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) {
        $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 */
            if ($downsize = apply_filters('image_downsize', false, $attachment->ID, $size)) {
                if (!$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])) {
                if (!isset($base_url)) {
                    $base_url = str_replace(wp_basename($attachment_url), '', $attachment_url);
                }
                // 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');
            }
        }
        $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, array('sizes' => $sizes), $sizes['full']);
    } elseif ($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['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));
    }
    /**
     * Filters the attachment data prepared for JavaScript.
     *
     * @since 3.5.0
     *
     * @param array      $response   Array of prepared attachment data.
     * @param int|object $attachment Attachment ID or object.
     * @param array      $meta       Array of attachment meta data.
     */
    return apply_filters('wp_prepare_attachment_for_js', $response, $attachment, $meta);
}

WordPress Version: 4.5

/**
 * 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 mixed $attachment Attachment ID or object.
 * @return array|void Array of attachment details.
 */
function wp_prepare_attachment_for_js($attachment)
{
    if (!$attachment = get_post($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);
    $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);
    $response['authorName'] = $author->display_name;
    if ($attachment->post_parent) {
        $post_parent = get_post($attachment->post_parent);
    } else {
        $post_parent = false;
    }
    if ($post_parent) {
        $parent_type = get_post_type_object($post_parent->post_type);
        if ($parent_type && $parent_type->show_ui && current_user_can('edit_post', $attachment->post_parent)) {
            $response['uploadedToLink'] = get_edit_post_link($attachment->post_parent, 'raw');
        }
        $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __('(no title)');
    }
    $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);
    }
    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) {
        $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 */
            if ($downsize = apply_filters('image_downsize', false, $attachment->ID, $size)) {
                if (!$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])) {
                if (!isset($base_url)) {
                    $base_url = str_replace(wp_basename($attachment_url), '', $attachment_url);
                }
                // 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');
            }
        }
        $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, array('sizes' => $sizes), $sizes['full']);
    } elseif ($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['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));
    }
    /**
     * Filter the attachment data prepared for JavaScript.
     *
     * @since 3.5.0
     *
     * @param array      $response   Array of prepared attachment data.
     * @param int|object $attachment Attachment ID or object.
     * @param array      $meta       Array of attachment meta data.
     */
    return apply_filters('wp_prepare_attachment_for_js', $response, $attachment, $meta);
}

WordPress Version: 4.4

/**
 * 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 mixed $attachment Attachment ID or object.
 * @return array|void Array of attachment details.
 */
function wp_prepare_attachment_for_js($attachment)
{
    if (!$attachment = get_post($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);
    $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(get_option('date_format'), $attachment->post_date), 'nonces' => array('update' => false, 'delete' => false, 'edit' => false), 'editLink' => false, 'meta' => false);
    $author = new WP_User($attachment->post_author);
    $response['authorName'] = $author->display_name;
    if ($attachment->post_parent) {
        $post_parent = get_post($attachment->post_parent);
    } else {
        $post_parent = false;
    }
    if ($post_parent) {
        $parent_type = get_post_type_object($post_parent->post_type);
        if ($parent_type && $parent_type->show_ui && current_user_can('edit_post', $attachment->post_parent)) {
            $response['uploadedToLink'] = get_edit_post_link($attachment->post_parent, 'raw');
        }
        $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __('(no title)');
    }
    $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);
    }
    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) {
        $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 */
            if ($downsize = apply_filters('image_downsize', false, $attachment->ID, $size)) {
                if (!$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])) {
                if (!isset($base_url)) {
                    $base_url = str_replace(wp_basename($attachment_url), '', $attachment_url);
                }
                // 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');
            }
        }
        $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, array('sizes' => $sizes), $sizes['full']);
    } elseif ($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['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));
    }
    /**
     * Filter the attachment data prepared for JavaScript.
     *
     * @since 3.5.0
     *
     * @param array      $response   Array of prepared attachment data.
     * @param int|object $attachment Attachment ID or object.
     * @param array      $meta       Array of attachment meta data.
     */
    return apply_filters('wp_prepare_attachment_for_js', $response, $attachment, $meta);
}

WordPress Version: 4.3

/**
 * 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 mixed $attachment Attachment ID or object.
 * @return array|void Array of attachment details.
 */
function wp_prepare_attachment_for_js($attachment)
{
    if (!$attachment = get_post($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);
    $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(get_option('date_format'), $attachment->post_date), 'nonces' => array('update' => false, 'delete' => false, 'edit' => false), 'editLink' => false, 'meta' => false);
    $author = new WP_User($attachment->post_author);
    $response['authorName'] = $author->display_name;
    if ($attachment->post_parent) {
        $post_parent = get_post($attachment->post_parent);
    } else {
        $post_parent = false;
    }
    if ($post_parent) {
        $parent_type = get_post_type_object($post_parent->post_type);
        if ($parent_type && $parent_type->show_ui && current_user_can('edit_post', $attachment->post_parent)) {
            $response['uploadedToLink'] = get_edit_post_link($attachment->post_parent, 'raw');
        }
        $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __('(no title)');
    }
    $attached_file = get_attached_file($attachment->ID);
    if (file_exists($attached_file)) {
        $bytes = filesize($attached_file);
        $response['filesizeInBytes'] = $bytes;
        $response['filesizeHumanReadable'] = size_format($bytes);
    }
    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) {
        $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 */
            if ($downsize = apply_filters('image_downsize', false, $attachment->ID, $size)) {
                if (!$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])) {
                if (!isset($base_url)) {
                    $base_url = str_replace(wp_basename($attachment_url), '', $attachment_url);
                }
                // 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');
            }
        }
        $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, array('sizes' => $sizes), $sizes['full']);
    } elseif ($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['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));
    }
    /**
     * Filter the attachment data prepared for JavaScript.
     *
     * @since 3.5.0
     *
     * @param array      $response   Array of prepared attachment data.
     * @param int|object $attachment Attachment ID or object.
     * @param array      $meta       Array of attachment meta data.
     */
    return apply_filters('wp_prepare_attachment_for_js', $response, $attachment, $meta);
}

WordPress Version: 0.1

/**
 * 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 mixed $attachment Attachment ID or object.
 * @return array Array of attachment details.
 */
function wp_prepare_attachment_for_js($attachment)
{
    if (!$attachment = get_post($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);
    $response = array('id' => $attachment->ID, 'title' => $attachment->post_title, 'filename' => wp_basename($attachment->guid), '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(get_option('date_format'), $attachment->post_date), 'nonces' => array('update' => false, 'delete' => false, 'edit' => false), 'editLink' => false, 'meta' => false);
    $author = new WP_User($attachment->post_author);
    $response['authorName'] = $author->display_name;
    if ($attachment->post_parent) {
        $post_parent = get_post($attachment->post_parent);
    } else {
        $post_parent = false;
    }
    if ($post_parent) {
        $parent_type = get_post_type_object($post_parent->post_type);
        if ($parent_type && $parent_type->show_ui && current_user_can('edit_post', $attachment->post_parent)) {
            $response['uploadedToLink'] = get_edit_post_link($attachment->post_parent, 'raw');
        }
        $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __('(no title)');
    }
    $attached_file = get_attached_file($attachment->ID);
    if (file_exists($attached_file)) {
        $bytes = filesize($attached_file);
        $response['filesizeInBytes'] = $bytes;
        $response['filesizeHumanReadable'] = size_format($bytes);
    }
    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) {
        $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 */
            if ($downsize = apply_filters('image_downsize', false, $attachment->ID, $size)) {
                if (!$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])) {
                if (!isset($base_url)) {
                    $base_url = str_replace(wp_basename($attachment_url), '', $attachment_url);
                }
                // 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');
            }
        }
        $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, array('sizes' => $sizes), $sizes['full']);
    } elseif ($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['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));
    }
    /**
     * Filter the attachment data prepared for JavaScript.
     *
     * @since 3.5.0
     *
     * @param array      $response   Array of prepared attachment data.
     * @param int|object $attachment Attachment ID or object.
     * @param array      $meta       Array of attachment meta data.
     */
    return apply_filters('wp_prepare_attachment_for_js', $response, $attachment, $meta);
}

WordPress Version: 4.0

/**
 * 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 mixed $attachment Attachment ID or object.
 * @return array Array of attachment details.
 */
function wp_prepare_attachment_for_js($attachment)
{
    if (!$attachment = get_post($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);
    $response = array('id' => $attachment->ID, 'title' => $attachment->post_title, 'filename' => wp_basename($attachment->guid), '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(get_option('date_format'), $attachment->post_date), 'nonces' => array('update' => false, 'delete' => false, 'edit' => false), 'editLink' => false, 'meta' => false);
    $author = new WP_User($attachment->post_author);
    $response['authorName'] = $author->display_name;
    if ($attachment->post_parent) {
        $post_parent = get_post($attachment->post_parent);
        $parent_type = get_post_type_object($post_parent->post_type);
        if ($parent_type && $parent_type->show_ui && current_user_can('edit_post', $attachment->post_parent)) {
            $response['uploadedToLink'] = get_edit_post_link($attachment->post_parent, 'raw');
        }
        $response['uploadedToTitle'] = $post_parent->post_title ? $post_parent->post_title : __('(no title)');
    }
    $attached_file = get_attached_file($attachment->ID);
    if (file_exists($attached_file)) {
        $bytes = filesize($attached_file);
        $response['filesizeInBytes'] = $bytes;
        $response['filesizeHumanReadable'] = size_format($bytes);
    }
    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) {
        $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 */
            if ($downsize = apply_filters('image_downsize', false, $attachment->ID, $size)) {
                if (!$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])) {
                if (!isset($base_url)) {
                    $base_url = str_replace(wp_basename($attachment_url), '', $attachment_url);
                }
                // 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');
            }
        }
        $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, array('sizes' => $sizes), $sizes['full']);
    } elseif ($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['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));
    }
    /**
     * Filter the attachment data prepared for JavaScript.
     *
     * @since 3.5.0
     *
     * @param array      $response   Array of prepared attachment data.
     * @param int|object $attachment Attachment ID or object.
     * @param array      $meta       Array of attachment meta data.
     */
    return apply_filters('wp_prepare_attachment_for_js', $response, $attachment, $meta);
}

WordPress Version: 3.9

/**
 * 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 mixed $attachment Attachment ID or object.
 * @return array Array of attachment details.
 */
function wp_prepare_attachment_for_js($attachment)
{
    if (!$attachment = get_post($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);
    $response = array('id' => $attachment->ID, 'title' => $attachment->post_title, 'filename' => wp_basename($attachment->guid), '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(get_option('date_format'), $attachment->post_date), 'nonces' => array('update' => false, 'delete' => false, 'edit' => false), 'editLink' => false);
    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) {
        $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 */
            if ($downsize = apply_filters('image_downsize', false, $attachment->ID, $size)) {
                if (!$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])) {
                if (!isset($base_url)) {
                    $base_url = str_replace(wp_basename($attachment_url), '', $attachment_url);
                }
                // 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');
            }
        }
        $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, array('sizes' => $sizes), $sizes['full']);
    } elseif ($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['meta'] = array();
        foreach (wp_get_attachment_id3_keys($attachment) as $key => $label) {
            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));
    }
    /**
     * Filter the attachment data prepared for JavaScript.
     *
     * @since 3.5.0
     *
     * @param array      $response   Array of prepared attachment data.
     * @param int|object $attachment Attachment ID or object.
     * @param array      $meta       Array of attachment meta data.
     */
    return apply_filters('wp_prepare_attachment_for_js', $response, $attachment, $meta);
}

WordPress Version: 3.7

/**
 * 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 mixed $attachment Attachment ID or object.
 * @return array Array of attachment details.
 */
function wp_prepare_attachment_for_js($attachment)
{
    if (!$attachment = get_post($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);
    $response = array('id' => $attachment->ID, 'title' => $attachment->post_title, 'filename' => wp_basename($attachment->guid), '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(get_option('date_format'), $attachment->post_date), 'nonces' => array('update' => false, 'delete' => false), 'editLink' => false);
    if (current_user_can('edit_post', $attachment->ID)) {
        $response['nonces']['update'] = wp_create_nonce('update-post_' . $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) {
        $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) {
            if ($downsize = apply_filters('image_downsize', false, $attachment->ID, $size)) {
                if (!$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])) {
                if (!isset($base_url)) {
                    $base_url = str_replace(wp_basename($attachment_url), '', $attachment_url);
                }
                // 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');
            }
        }
        $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, array('sizes' => $sizes), $sizes['full']);
    } elseif ($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'];
        }
    }
    if (function_exists('get_compat_media_markup')) {
        $response['compat'] = get_compat_media_markup($attachment->ID, array('in_modal' => true));
    }
    return apply_filters('wp_prepare_attachment_for_js', $response, $attachment, $meta);
}