WordPress Media Library
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
- Upload 10 different media files (images, PDF, video)
- Edit image metadata (alt text, caption, description)
- Create custom image sizes for your theme
- Organize media with categories
- Implement image optimization on upload
- Create a gallery with multiple images
- Set up lazy loading for images
- Build a media management plugin