Last active
May 18, 2018 19:23
-
-
Save RalfAlbert/5521518 to your computer and use it in GitHub Desktop.
WordPress: Simple class to handle file uploads to the wp-content directory and creating an attachment post
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class File_Upload | |
{ | |
/** | |
* Index key from upload form | |
* @var string | |
*/ | |
public $index_key = ''; | |
/** | |
* Copy of superglobal array $_FILES | |
* @var array | |
*/ | |
public $files = array(); | |
/** | |
* Array with url, filepath and mimetype after uploading | |
* @var array | |
*/ | |
public $filedata = array(); | |
/** | |
* Error object containing errors as WP_Error | |
* @var onject | |
*/ | |
public $errors = null; | |
/** | |
* Constructor | |
* Setup files array and guess index key | |
*/ | |
public function __construct(){ | |
if ( isset( $_FILES ) && ! empty( $_FILES ) ) { | |
$this->files = $_FILES; | |
$this->guess_index_key(); | |
} | |
} | |
/** | |
* Set/overwrites the index key | |
* Converts $name with type casting (string) | |
* | |
* @param string $name Name of the index key | |
* @return string ::name Name of the stored index key | |
*/ | |
public function set_field_name_for_file( $name = '' ) { | |
$this->index_key = ( ! empty( $name ) ) ? (string) $name : ''; | |
return $this->index_key; | |
} | |
/** | |
* Converts uploaded file into WordPress attachment | |
* | |
* @return boolean Whether if the attachment was created (true) or not (false) | |
*/ | |
public function create_attachment(){ | |
// move the uploaded file from temp folder and create basic data | |
$this->filedata = $this->handle_uploaded_file(); | |
// if moving fails, stop here | |
if ( empty( $this->filedata ) || is_wp_error( $this->filedata ) ) { | |
$code = 'createerror'; | |
$msg = 'Could not create attachment'; | |
if ( is_wp_error( $this->filedata ) ) { | |
$this->errors = $this->filedata; | |
$this->filedata = array(); | |
$this->errors->add( $code, $msg ); | |
} else { | |
$this->errors = new WP_Error( $code, $msg ); | |
} | |
return $this->errors; | |
} | |
/* | |
* For Production | |
* Check if $imagedata contains the expected (and needed) | |
* values. Every method could fail and return malicious data!! | |
*/ | |
extract( $this->filedata ); | |
// create the attachment data array | |
$attachment = array( | |
'guid' => $url, | |
'post_mime_type' => $type, | |
'post_title' => sanitize_key( basename( $file ) ), | |
'post_content' => '', | |
'post_status' => 'inherit' | |
); | |
// insert attachment (posttype attachment) | |
$attach_id = wp_insert_attachment( $attachment, $file ); | |
// you must first include the image.php file | |
// for the function wp_generate_attachment_metadata() to work | |
require_once( ABSPATH . 'wp-admin/includes/image.php' ); | |
/* | |
* For Production | |
* Check $attach_data, wp_generate_attachment_metadata() could fail | |
* Check if wp_update_attachment_metadata() fails (returns false), | |
* return an error object with WP_Error() | |
*/ | |
$attach_data = wp_generate_attachment_metadata( $attach_id, $file ); | |
wp_update_attachment_metadata( $attach_id, $attach_data ); | |
return $attach_id; | |
} | |
/** | |
* Handles the upload | |
* | |
* @return array|object $return_data Array with informations about the uploaded file on success. WP_Error object on failure | |
*/ | |
protected function handle_uploaded_file() { | |
// stop if something went wrong | |
if ( ! isset( $this->files[$this->index_key]['tmp_name'] ) || empty( $this->files[$this->index_key]['tmp_name'] ) ) { | |
$code = ( isset( $this->files[$this->index_key]['error'] ) ) ? | |
$this->files[$this->index_key]['error'] : 0; | |
$msg = $this->guess_upload_error( $code ); | |
return new WP_Error( 'uploaderror', 'Upload failed with message: ' . $msg ); | |
} | |
/* | |
* For Production | |
* You should really, really check the file extension and filetype ($movedfile['type']) | |
* on EVERY upload. If you do not, it is possible to upload EVERY kind of | |
* file including malicious code. | |
* | |
*/ | |
if ( ! function_exists( 'wp_handle_upload' ) ) | |
require_once( ABSPATH . 'wp-admin/includes/file.php' ); | |
$movedfile = wp_handle_upload( $this->files[$this->index_key], array( 'test_form' => false ) ); | |
return $movedfile; | |
} | |
/** | |
* Try to fetch the first index from $_FILES | |
* | |
* @return boolean Whether if a key was found or not | |
*/ | |
protected function guess_index_key() { | |
$keys = array_keys( $_FILES ); | |
if ( ! empty( $keys ) ) { | |
$this->index_key = $keys[0]; | |
return true; | |
} | |
return false; | |
} | |
protected function guess_upload_error( $err = 0 ) { | |
$errcodes = array( | |
'Unknown error', | |
'The uploaded file exceeds the upload_max_filesize directive in php.ini.', | |
'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', | |
'The uploaded file was only partially uploaded.', | |
'No file was uploaded.', | |
'Missing a temporary folder.', | |
'Failed to write file to disk.', | |
'A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help.' | |
); | |
return ( isset( $errcodes[$err] ) ) ? | |
$errcodes[$err] : 'Unknown error'; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
if ( empty ( $_FILES ) ) { | |
global $pagenow; | |
$url = admin_url( $pagenow ); | |
?> | |
<!-- The data encoding type, enctype, MUST be specified as below --> | |
<form enctype="multipart/form-data" action="<?php echo $url; ?>" method="POST"> | |
<!-- MAX_FILE_SIZE must precede the file input field --> | |
<input type="hidden" name="MAX_FILE_SIZE" value="30000" /> | |
<!-- Name of input element determines name in $_FILES array --> | |
Send this file: <input name="userfile" type="file" /> | |
<input type="submit" value="Send File" /> | |
</form> | |
<?php | |
} else { | |
$imageupload = new File_Upload(); | |
$attachment_id = $imageupload->create_attachment(); | |
if ( is_wp_error( $attachment_id ) ) { | |
echo '<ol>'; | |
foreach ( $attachment_id->get_error_messages() as $err ) | |
printf( '<li>%s</li>', $err ); | |
echo '</ol>'; | |
} else { | |
// check if the upload was successfull | |
$attachment = get_post( $attachment_id ); | |
$image_url = $attachment->guid; | |
printf( '<p><img src="%s"></p>', $image_url ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Good job, thank you!
And I also added multiple files support in fork https://gist.github.com/antongorodezkiy/10be9f726d827f920aaa