Skip to main content

WordPress Media Library

Duration: 40 minutes|Module 4: Session 3.4

Learning Objectives

  • Navigate and use the WordPress Media Library interface
  • Upload and organize various media file types
  • Edit and optimize images directly in WordPress
  • Understand image sizes and responsive images
  • Manage media programmatically with PHP
  • Implement media security and permissions
  • Optimize media for performance
  • Work with audio, video, and document files

Introduction to the Media Library

The WordPress Media Library is your central repository for all uploaded files including images, videos, audio files, and documents. It provides tools for organizing, editing, and optimizing media assets for your website.

Media Library Interface

The Media Library provides two views: Grid View for visual browsing and List View for detailed information.

Uploading Media

Programmatic Media Upload

<?php
// Handle file upload
if (!function_exists('wp_handle_upload')) {
    require_once(ABSPATH . 'wp-admin/includes/file.php');
}

$uploadedfile = $_FILES['file'];
$upload_overrides = array(
    'test_form' => false,
    'mimes' => array(
        'jpg|jpeg|jpe' => 'image/jpeg',
        'gif' => 'image/gif',
        'png' => 'image/png',
        'pdf' => 'application/pdf',
        'mp4|m4v' => 'video/mp4',
        'mp3' => 'audio/mpeg'
    )
);

$movefile = wp_handle_upload($uploadedfile, $upload_overrides);

if ($movefile && !isset($movefile['error'])) {
    // File uploaded successfully
    $filename = $movefile['file'];
    $filetype = wp_check_filetype(basename($filename), null);
    $wp_upload_dir = wp_upload_dir();
    
    // Prepare attachment data
    $attachment = array(
        'guid'           => $wp_upload_dir['url'] . '/' . basename($filename),
        'post_mime_type' => $filetype['type'],
        'post_title'     => preg_replace('/\.[^.]+$/', '', basename($filename)),
        'post_content'   => '',
        'post_status'    => 'inherit'
    );
    
    // Insert attachment
    $attach_id = wp_insert_attachment($attachment, $filename);
    
    // Generate metadata
    require_once(ABSPATH . 'wp-admin/includes/image.php');
    $attach_data = wp_generate_attachment_metadata($attach_id, $filename);
    wp_update_attachment_metadata($attach_id, $attach_data);
    
    // Set as featured image if needed
    if ($post_id) {
        set_post_thumbnail($post_id, $attach_id);
    }
}

// Upload from URL
function upload_image_from_url($url, $post_id = 0) {
    $tmp = download_url($url);
    
    if (is_wp_error($tmp)) {
        return $tmp;
    }
    
    $file_array = array(
        'name' => basename($url),
        'tmp_name' => $tmp
    );
    
    $id = media_handle_sideload($file_array, $post_id);
    
    if (is_wp_error($id)) {
        @unlink($file_array['tmp_name']);
        return $id;
    }
    
    return $id;
}
?>

Attachment Details & Metadata

Working with Attachment Metadata

<?php
// Get attachment metadata
$attachment_id = 123;
$metadata = wp_get_attachment_metadata($attachment_id);

echo 'Width: ' . $metadata['width'] . 'px';
echo 'Height: ' . $metadata['height'] . 'px';
echo 'File: ' . $metadata['file'];

// Available image sizes
foreach ($metadata['sizes'] as $size => $data) {
    echo $size . ': ' . $data['width'] . 'x' . $data['height'];
}

// Update attachment metadata
update_post_meta($attachment_id, '_wp_attachment_image_alt', 'Alt text here');

// Get attachment information
$attachment_url = wp_get_attachment_url($attachment_id);
$attachment_path = get_attached_file($attachment_id);
$attachment_title = get_the_title($attachment_id);
$attachment_caption = wp_get_attachment_caption($attachment_id);
$attachment_description = get_post_field('post_content', $attachment_id);

// Get image at specific size
$image = wp_get_attachment_image_src($attachment_id, 'large');
$image_url = $image[0];
$image_width = $image[1];
$image_height = $image[2];

// Check if attachment is image
if (wp_attachment_is_image($attachment_id)) {
    // Process image
}

// Get attached post
$parent_post_id = wp_get_post_parent_id($attachment_id);
?>

Image Sizes in WordPress

WordPress automatically creates multiple sizes of each uploaded image:

  • Thumbnail:150 × 150 (hard crop)
  • Medium:300 × 300 (proportional)
  • Medium Large:768 × 0 (proportional)
  • Large:1024 × 1024 (proportional)
  • Full:Original size

Custom Image Sizes

<?php
// Register custom image sizes
add_action('after_setup_theme', function() {
    // Hard crop to exact dimensions
    add_image_size('hero-banner', 1920, 600, true);
    
    // Proportional resize (max width 800)
    add_image_size('blog-featured', 800, 0, false);
    
    // Crop from specific position
    add_image_size('square-thumb', 300, 300, array('center', 'top'));
    
    // Make custom sizes available in media library
    add_filter('image_size_names_choose', function($sizes) {
        return array_merge($sizes, array(
            'hero-banner' => 'Hero Banner',
            'blog-featured' => 'Blog Featured',
            'square-thumb' => 'Square Thumbnail'
        ));
    });
});

// Regenerate thumbnails for existing images
function regenerate_all_thumbnails() {
    $attachments = get_posts(array(
        'post_type' => 'attachment',
        'post_mime_type' => 'image',
        'posts_per_page' => -1
    ));
    
    foreach ($attachments as $attachment) {
        $file = get_attached_file($attachment->ID);
        $metadata = wp_generate_attachment_metadata($attachment->ID, $file);
        wp_update_attachment_metadata($attachment->ID, $metadata);
    }
}

// Get srcset for responsive images
$attachment_id = 123;
$img_srcset = wp_get_attachment_image_srcset($attachment_id, 'large');
$img_sizes = wp_get_attachment_image_sizes($attachment_id, 'large');

echo '<img src="' . wp_get_attachment_image_url($attachment_id, 'large') . '" 
      srcset="' . $img_srcset . '" 
      sizes="' . $img_sizes . '">';
?>

WordPress Image Editor

Programmatic Image Editing

<?php
// Load image editor
$image_path = get_attached_file($attachment_id);
$image_editor = wp_get_image_editor($image_path);

if (!is_wp_error($image_editor)) {
    // Resize image
    $image_editor->resize(800, 600, true);
    
    // Rotate image
    $image_editor->rotate(90);
    
    // Flip image
    $image_editor->flip(true, false); // horizontal, vertical
    
    // Crop image
    $image_editor->crop(0, 0, 500, 500);
    
    // Save edited image
    $saved = $image_editor->save();
    
    if (!is_wp_error($saved)) {
        // Update attachment metadata
        $new_file = $saved['file'];
        update_attached_file($attachment_id, $new_file);
        
        // Generate new metadata
        $metadata = wp_generate_attachment_metadata($attachment_id, $new_file);
        wp_update_attachment_metadata($attachment_id, $metadata);
    }
}

// Create image from scratch
$image = imagecreatetruecolor(400, 300);
$bg_color = imagecolorallocate($image, 255, 255, 255);
$text_color = imagecolorallocate($image, 0, 0, 0);
imagefill($image, 0, 0, $bg_color);
imagestring($image, 5, 150, 140, 'Custom Image', $text_color);

// Save to uploads directory
$upload_dir = wp_upload_dir();
$filename = $upload_dir['path'] . '/custom-image.png';
imagepng($image, $filename);
imagedestroy($image);

// Create attachment for the image
$attachment = array(
    'post_mime_type' => 'image/png',
    'post_title' => 'Custom Generated Image',
    'post_content' => '',
    'post_status' => 'inherit'
);

$attach_id = wp_insert_attachment($attachment, $filename);
$attach_data = wp_generate_attachment_metadata($attach_id, $filename);
wp_update_attachment_metadata($attach_id, $attach_data);
?>

Organizing Media

Media Categories and Tags

<?php
// Enable categories and tags for attachments
function add_media_taxonomies() {
    register_taxonomy_for_object_type('category', 'attachment');
    register_taxonomy_for_object_type('post_tag', 'attachment');
    
    // Create custom taxonomy for media
    register_taxonomy('media_category', 'attachment', array(
        'labels' => array(
            'name' => 'Media Categories',
            'singular_name' => 'Media Category'
        ),
        'hierarchical' => true,
        'show_admin_column' => true,
        'show_in_rest' => true
    ));
}
add_action('init', 'add_media_taxonomies');

// Organize uploads by category
add_filter('upload_dir', function($uploads) {
    // Organize by year/month/category
    if (isset($_POST['media_category'])) {
        $category = sanitize_title($_POST['media_category']);
        $uploads['path'] .= '/' . $category;
        $uploads['url'] .= '/' . $category;
    }
    return $uploads;
});

// Bulk organize existing media
function organize_media_library() {
    $attachments = get_posts(array(
        'post_type' => 'attachment',
        'posts_per_page' => -1,
        'post_status' => 'inherit'
    ));
    
    foreach ($attachments as $attachment) {
        $file_type = wp_check_filetype($attachment->guid);
        $type = explode('/', $file_type['type'])[0];
        
        // Assign category based on file type
        switch ($type) {
            case 'image':
                wp_set_object_terms($attachment->ID, 'images', 'media_category');
                break;
            case 'video':
                wp_set_object_terms($attachment->ID, 'videos', 'media_category');
                break;
            case 'audio':
                wp_set_object_terms($attachment->ID, 'audio', 'media_category');
                break;
            default:
                wp_set_object_terms($attachment->ID, 'documents', 'media_category');
        }
    }
}
?>

Media Search and Filtering

<?php
// Search media by various criteria
$args = array(
    'post_type' => 'attachment',
    'post_status' => 'inherit',
    'posts_per_page' => 20,
    'post_mime_type' => 'image',
    's' => 'banner', // Search term
    'meta_query' => array(
        array(
            'key' => '_wp_attachment_image_alt',
            'value' => 'hero',
            'compare' => 'LIKE'
        )
    ),
    'tax_query' => array(
        array(
            'taxonomy' => 'media_category',
            'field' => 'slug',
            'terms' => 'headers'
        )
    )
);

$media_query = new WP_Query($args);

// Get unattached media
$unattached = get_posts(array(
    'post_type' => 'attachment',
    'post_parent' => 0,
    'posts_per_page' => -1
));

// Get media by date range
$recent_media = get_posts(array(
    'post_type' => 'attachment',
    'date_query' => array(
        array(
            'after' => '1 week ago'
        )
    )
));
?>

Supported File Types

WordPress supports various file types by default:

  • Images:jpg, jpeg, png, gif, webp, ico, svg
  • Video:mp4, m4v, mov, wmv, avi, mpg, ogv, webm
  • Audio:mp3, m4a, ogg, wav, wma
  • Documents:pdf, doc, docx, ppt, pptx, xls, xlsx, odt
  • Archives:zip, rar, 7z, tar, gz

Custom MIME Types

<?php
// Allow additional file types
add_filter('upload_mimes', function($mimes) {
    // Add new MIME types
    $mimes['svg'] = 'image/svg+xml';
    $mimes['webp'] = 'image/webp';
    $mimes['json'] = 'application/json';
    $mimes['xml'] = 'text/xml';
    
    // Remove unwanted types
    unset($mimes['exe']);
    
    return $mimes;
});

// Custom upload validation
add_filter('wp_check_filetype_and_ext', function($data, $file, $filename, $mimes) {
    $filetype = wp_check_filetype($filename, $mimes);
    
    // Additional security check for SVG files
    if ($filetype['ext'] === 'svg') {
        $svg_content = file_get_contents($file);
        
        // Check for malicious content
        if (strpos($svg_content, '<script') !== false) {
            $data['ext'] = false;
            $data['type'] = false;
        }
    }
    
    return $data;
}, 10, 4);

// Set upload size limits by file type
add_filter('upload_size_limit', function($size) {
    if (isset($_FILES['async-upload'])) {
        $type = $_FILES['async-upload']['type'];
        
        if (strpos($type, 'video') !== false) {
            return 100 * 1024 * 1024; // 100MB for videos
        } elseif (strpos($type, 'image') !== false) {
            return 5 * 1024 * 1024; // 5MB for images
        }
    }
    
    return $size;
});
?>

Media Security and Permissions

<?php
// Restrict media access based on user role
add_filter('ajax_query_attachments_args', function($query) {
    $user = wp_get_current_user();
    
    // Authors can only see their own uploads
    if (in_array('author', $user->roles)) {
        $query['author'] = $user->ID;
    }
    
    return $query;
});

// Protect uploads directory
function protect_uploads_directory() {
    $upload_dir = wp_upload_dir();
    $htaccess = $upload_dir['basedir'] . '/.htaccess';
    
    $rules = "# Protect uploads
<FilesMatch '\.(php|php\d|phtml)$'>
    Order Allow,Deny
    Deny from all
</FilesMatch>

# Prevent script execution
Options -ExecCGI
AddHandler cgi-script .php .pl .py .jsp .asp .sh .cgi";
    
    file_put_contents($htaccess, $rules);
}

// Sanitize file names
add_filter('sanitize_file_name', function($filename) {
    // Remove special characters
    $filename = preg_replace('/[^a-zA-Z0-9-_\.]/', '', $filename);
    
    // Add timestamp to prevent duplicates
    $info = pathinfo($filename);
    $name = $info['filename'];
    $ext = $info['extension'];
    
    return $name . '_' . time() . '.' . $ext;
}, 10, 1);

// Scan uploads for malware
add_filter('wp_handle_upload_prefilter', function($file) {
    // Check for PHP code in images
    $content = file_get_contents($file['tmp_name']);
    
    if (preg_match('/<\?php/i', $content)) {
        $file['error'] = 'Security threat detected in file.';
    }
    
    return $file;
});
?>

Media Performance Optimization

<?php
// Auto-optimize images on upload
add_filter('wp_handle_upload', function($upload) {
    if ($upload['type'] === 'image/jpeg' || $upload['type'] === 'image/jpg') {
        $image = imagecreatefromjpeg($upload['file']);
        imagejpeg($image, $upload['file'], 85); // 85% quality
        imagedestroy($image);
    } elseif ($upload['type'] === 'image/png') {
        $image = imagecreatefrompng($upload['file']);
        imagepng($image, $upload['file'], 7); // Compression level 7
        imagedestroy($image);
    }
    
    return $upload;
});

// Implement lazy loading
add_filter('wp_get_attachment_image_attributes', function($attr, $attachment, $size) {
    $attr['loading'] = 'lazy';
    $attr['decoding'] = 'async';
    return $attr;
}, 10, 3);

// Convert images to WebP
function convert_to_webp($attachment_id) {
    $file = get_attached_file($attachment_id);
    $image = wp_get_image_editor($file);
    
    if (!is_wp_error($image)) {
        $webp_file = str_replace(
            array('.jpg', '.jpeg', '.png'),
            '.webp',
            $file
        );
        
        $image->save($webp_file, 'image/webp');
        
        // Store WebP version reference
        update_post_meta($attachment_id, '_webp_file', $webp_file);
    }
}

// Serve WebP images when supported
add_filter('wp_get_attachment_url', function($url, $attachment_id) {
    // Check if browser supports WebP
    if (isset($_SERVER['HTTP_ACCEPT']) && 
        strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') !== false) {
        
        $webp_file = get_post_meta($attachment_id, '_webp_file', true);
        
        if ($webp_file && file_exists($webp_file)) {
            $upload_dir = wp_upload_dir();
            $webp_url = str_replace(
                $upload_dir['basedir'],
                $upload_dir['baseurl'],
                $webp_file
            );
            return $webp_url;
        }
    }
    
    return $url;
}, 10, 2);
?>

Creating and Managing Galleries

<?php
// Create gallery shortcode
$gallery = '[gallery ids="1,2,3,4,5" columns="3" size="medium" link="file"]';

// Create gallery programmatically
function create_gallery($image_ids, $columns = 3) {
    $gallery_html = '<div class="gallery gallery-columns-' . $columns . '">';
    
    foreach ($image_ids as $id) {
        $image = wp_get_attachment_image($id, 'medium');
        $link = wp_get_attachment_url($id);
        
        $gallery_html .= '<figure class="gallery-item">';
        $gallery_html .= '<a href="' . $link . '" data-lightbox="gallery">';
        $gallery_html .= $image;
        $gallery_html .= '</a>';
        $gallery_html .= '</figure>';
    }
    
    $gallery_html .= '</div>';
    
    return $gallery_html;
}

// Custom gallery output
add_filter('post_gallery', function($output, $attr) {
    // Custom gallery markup
    $ids = explode(',', $attr['ids']);
    $columns = isset($attr['columns']) ? $attr['columns'] : 3;
    $size = isset($attr['size']) ? $attr['size'] : 'thumbnail';
    
    $output = '<div class="custom-gallery" data-columns="' . $columns . '">';
    
    foreach ($ids as $id) {
        $image = wp_get_attachment_image_src($id, $size);
        $full = wp_get_attachment_image_src($id, 'full');
        
        $output .= '<div class="gallery-item">';
        $output .= '<img src="' . $image[0] . '" data-full="' . $full[0] . '">';
        $output .= '</div>';
    }
    
    $output .= '</div>';
    
    return $output;
}, 10, 2);
?>

Practice Exercise

Hands-On Practice

  1. Upload 10 different media files (images, PDF, video)
  2. Edit image metadata (alt text, caption, description)
  3. Create custom image sizes for your theme
  4. Organize media with categories
  5. Implement image optimization on upload
  6. Create a gallery with multiple images
  7. Set up lazy loading for images
  8. Build a media management plugin

Additional Resources