Dorokhov.codes

17. Working with media

WordPress is a web application like many others. It means that we can use standard approaches to work with media files: we can send files using the POST method, receive them from the $_FILES array, store them anywhere and so on.

But let’s see what WordPress offers us.

Media library

The Media Library in WordPress is a central hub for managing all media files (images, videos, audio files, documents) that have been uploaded to the website. It provides a convenient interface where users can upload, view, edit, and organize their media content.

Key Features of the WordPress Media Library:

  • We can upload files directly from the computer by dragging and dropping them into the media library or by selecting files from your device.
  • Media files are stored in a directory structure based on the date they were uploaded (e.g., wp-content/uploads/yyyy/mm/).
  • The library allows us to view all the media in either a grid or list format.
  • We can click on individual media files to view their details, edit file information (such as title, alt text, and description), and make basic modifications like cropping, resizing, or rotating images.
  • We can easily insert images, videos, and other media files into posts or pages using the “Add Media” button in the post editor.
  • When inserting media, we can select from various image sizes (thumbnail, medium, large, full size) based on what’s been automatically generated during the upload process.

Attachment Post Type

Each media file uploaded to the Media Library is stored as an attachment post type in the WordPress database, and it is treated similarly to a post with its own metadata and attributes.

Attachments are stored as posts in the wp_posts table, with the post_type set to attachment.

Each attachment post stores essential metadata about the file, such as file path, file type, date uploaded, and author.

Relationship to Parent Post

  • Attachments can be associated with other post types like posts or pages. For example, when you upload an image directly while editing a post, that image attachment is “attached” to that post.
  • You can view this relationship in the Media Library by seeing which post or page the attachment is associated with.

Image Sizes

When you upload an image to the Media Library, WordPress creates several sizes for this image (thumbnail, medium, large, full-size). Information about these files is stored as metadata associated with the attachment post and can be accessed and used throughout the website.

Attachments and Custom Fields

Just like regular posts, attachments can have custom fields. This makes it possible to extend the data stored for an attachment, adding fields like copyright information, author credits, or any other custom metadata relevant to your needs.

Attachment API

Developers can programmatically interact with attachments using WordPress functions:

  • wp_get_attachment_image_src( $attachment_id, 'full' ): gets an image source. Note that it returns an array.
  • wp_get_attachment_image( $attachment_id, 'thumbnail' ): gets an HTML img element representing an image attachment.
  • wp_get_attachment_url( $attachment_id ): get a file URL. It works with any file, not only images.

Featured images are typically used as the main image for a post or page and help visually communicate the theme or subject of the content. They are widely used in themes, especially in blog layouts, to give users a visual cue about the content before they read it.

In the WordPress block editor (Gutenberg), there is a Featured Image section in the sidebar where you can upload or choose an existing image from the media library.

Once a featured image is set, it will be associated with that specific post or page.

Theme Support

Not all WordPress themes support featured images out of the box, but most modern themes do. If a theme supports featured images, the feature will be enabled by default.

Developers can add support for featured images in their custom themes by adding this line of code in the functions.php file:

add_theme_support('post-thumbnails');

Once enabled, developers can display featured images in templates using the_post_thumbnail(). Example:

<?php if ( has_post_thumbnail() ) : ?>
    <div class="post-thumbnail">
        <?php the_post_thumbnail('large'); // or 'thumbnail', 'medium', 'full' ?>
    </div>
<?php endif; ?>

wp_upload_bits()

The wp_upload_bits function in WordPress is used to handle the uploading of files to the WordPress media library.

Note that wp_upload_bits() is useful when you already have the file content and want to upload it directly without relying on a form submission.

// You can use only file name (not path). The function will make it unique.
$upload = wp_upload_bits($file_name, null, $file_content);

This function only uploads the file and returns the file info. Nothing is stored in the DB.

Returns array:

[
	'file'  => '/var/www/wp-content/uploads/2010/03/example.pdf',
	'url'   => 'http://example.com/wp-content/uploads/2010/03/example.pdf',
	'type'  => 'application/pdf',
	'error' => false,
]

media_handle_upload()

Saves a file submitted from a POST request and create an attachment post for it.

This function uses the below functions:

  • wp_handle_upload().
  • wp_insert_attachment().
  • wp_update_attachment_metadata().

wp_insert_attachment()

Creates a post type (attachment) record based on the passing parameters. This functions is like wp_insert_post().

// Insert the attachment.
$attach_id = wp_insert_attachment( $attachment, $filename, $parent_post_id );

No files are added. It’s just created a record in the DB.

First parameter should contain the necessary fields:

[
    'guid'           => $file_path, // We can pass the file path.
    'post_mime_type' => $filetype['type'],
    'post_title'     => 'My picture',
    'post_content'   => '', // We pass an empty string.
    'post_status'    => 'inherit'
]

Usually after this function we call wp_generate_attachment_metadata() to generates attachment meta data and create image sub-sizes for images.

$attachment_data = wp_generate_attachment_metadata( $attachment_id, $uploaded_file_data[ 'file' ] );

wp_update_attachment_metadata( $attachment_id, $attachment_data );

wp_handle_upload()

This function is used by WordPress core and is not intended for use by plugin or theme developers.

Helpers

wp_upload_dir() - returns an array containing the current upload directory’s path and URL.

$upload_dir = wp_upload_dir();

$upload_path = $upload_dir['path'];

wp_unique_filename() - gets a filename that is sanitized and unique for the given directory.

If the filename is not unique, then a number will be added to the filename before the extension, and will continue adding numbers until the filename is unique.

$file_name = wp_unique_filename($upload_path, 'file.txt');

wp_check_filetype() - retrieves the file type from the file name.

$filetype = wp_check_filetype('image.jpg');

echo $filetype['ext']; // will output "jpg"
echo $filetype['type']; // will output "image/jpeg"

My function for uploading images

/**
 * Upload an image.
 *
 * @param $image_url
 * @param $name
 * @param $parent_post_id
 * @return bool
 */
public static function upload_image( $image_url, $name, $parent_post_id )
{
    $file_info = wp_check_filetype( $image_url );

    $file_extension = $file_info[ 'ext' ];
    $file_mime_type = $file_info[ 'type' ];

    if ( ! $file_extension || ! $file_mime_type ) {

        $file_headers = get_headers( $image_url, true );

        if ( ! $file_headers ) {
            return false;
        }

        if ( ! isset( $file_headers[ 'Content-Type' ] ) ) {
            return false;
        }

        $file_mime_type = $file_headers[ 'Content-Type' ];
        $file_extension = wp_get_default_extension_for_mime_type( $file_mime_type );

        if ( ! $file_mime_type || ! $file_extension ) {
            return false;
        }
    }

    $file_name = uniqid() . '.' . $file_extension;

    $image_data = file_get_contents( $image_url );

    if ( ! $image_data ) {
        return false;
    }

    $uploaded_file_data = wp_upload_bits( $file_name, null, $image_data );

    if ( $uploaded_file_data[ 'error' ] ) {
        return false;
    }

    $attachment_id = wp_insert_attachment( [
        'guid'           => $uploaded_file_data[ 'file' ],
        'post_mime_type' => $file_mime_type,
        'post_title'     => $name,
        'post_content'   => '', // We pass an empty string.
        'post_status'    => 'inherit'
    ], $uploaded_file_data[ 'file' ], $parent_post_id );

    $attachment_data = wp_generate_attachment_metadata( $attachment_id, $uploaded_file_data[ 'file' ] );

    wp_update_attachment_metadata( $attachment_id, $attachment_data );

    return true;
}