Skip to content

Instantly share code, notes, and snippets.

@undfine
Created September 23, 2024 20:40
Show Gist options
  • Select an option

  • Save undfine/4c4dbd193e1a9efaa368ccecea1e6ecc to your computer and use it in GitHub Desktop.

Select an option

Save undfine/4c4dbd193e1a9efaa368ccecea1e6ecc to your computer and use it in GitHub Desktop.
Uploads Handler for Wordpress to alter the directory based on Post type and/or Filetype (extension)
<?php
/**
* Filters the uploads directory to use a custom structure for select post types
*/
class Custom_Uploads_Handler {
public function __construct() {
// initialize upload filters
add_filter('wp_handle_upload_prefilter', [$this,'upload_prefilter'], 10, 1);
add_filter('wp_handle_upload', [$this,'upload_postfilter'], 10, 1);
}
private function get_directory_by_posttype() {
//Define the post types and their respective folders
return array([
'type' => '', // 'property'
'folder' => '', // 'properties',
'use_subdir' => false // false overrides year/month format
]);
}
private function get_directory_by_filetype() {
//Define the post types and their respective folders
return array([
'type' => 'pdf', //the extension
'folder' => 'documents', //the folder
'use_subdir' => false // false overrides year/month format
]);
}
private function format_upload_by_type($upload, $type, $filter_array) {
if (!is_array($filter_array) || empty($type) || empty($filter_array)) return $upload;
// loop through each node in the array and check if it matches the type (posttype or extension)
foreach ($filter_array as $node){
// Check the post type of the current post (and parent)
if( $node['type'] === $type ){
// rewrite the subdirectory
$folder = isset($node['folder']) ? '/'. $node['folder'] : '';
// rewrite the subdirectory if use_subdir is false, otherwise use default (year/month)
$upload['subdir'] = ( isset($node['use_subdir']) && $node['use_subdir'] === false ) ? $folder : $folder . $upload['subdir'];
// add the folder to the path
$fullpath = $upload['basedir'] . $upload['subdir'];
$upload['path'] = $fullpath;
$upload['url'] = $fullpath;
// exit loop and return the upload path and filename
return $upload;
}
}
// return original upload if no match
return $upload;
}
public function upload_prefilter($file){
add_filter('upload_dir', [$this,'filter_uploads_dir'], 10, 1);
return $file;
}
public function upload_postfilter($fileinfo){
remove_filter('upload_dir', [$this,'filter_uploads_dir'], 10, 1);
return $fileinfo;
}
public function filter_uploads_dir( $upload ) {
// Exit early
if (!empty($upload['error']) ) return $upload;
// Define the filetypes and posttypes with their respective folders
$file_types = $this->get_directory_by_filetype();
$file_types = apply_filters('custom_upload_directories_by_filetype', $file_types);
$post_types = $this->get_directory_by_posttype();
$post_types = apply_filters('custom_upload_directories_by_posttype', $post_types);
// Get the extension for 'pdf', change dir and exit
if ( isset($_POST['name'])){
//trim the
$extension = substr(strrchr($_POST['name'],'.'),1);
// Check if this matches a filtered extension
$upload = $this->format_upload_by_type($upload, $extension, $file_types);
}
global $post;
// Get the ID and Posttype of the current post
// NOTE: use $_REQUEST to catch both GET and POST requests
if ( !empty($post) ) {
$id = $post->ID;
$post_type = get_post_type( $post);
} else {
$id = isset($_REQUEST['post']) ? $_REQUEST['post'] : '';
$id = isset($_REQUEST['post_id']) ? $_REQUEST['post_id'] : $id;
$post_type = isset($_REQUEST['post_type']) ? $_REQUEST['post_type'] : get_post_type( $id );
}
// Check if this matches a filtered posttype
if (isset($post_type) && !empty($post_type)){
$upload = $this->format_upload_by_type($upload, $post_type, $post_types);
}
// output debug info to Query Monitory (if active)
do_action( 'qm/debug', $upload );
return $upload;
}
}
add_action('init', function(){
// Initialize the Class
$customUploadsHandler = new Custom_Uploads_Handler();
});
@undfine
Copy link
Author

undfine commented Sep 23, 2024

This defaults to putting PDFs in a "documents" folder.

Includes 2 hooks to modify these outside the class:

$file_types = apply_filters('custom_upload_directories_by_filetype', $file_types);
$post_types = apply_filters('custom_upload_directories_by_posttype', $post_types);

Both callbacks should return an array like this:

return array([
            'type' => 'property'
            'folder' => 'properties',
            'use_subdir' => false
        ]);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment