Created
February 1, 2016 19:33
-
-
Save soderlind/92593c6fb6d1c633fdb9 to your computer and use it in GitHub Desktop.
DropzoneJS & WordPress REST API with Custom Endpoint
This file contains 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
About: | |
The plugin provides drag’n’drop file uploads and uses the wp rest api to upload the file. | |
This version adds a custom endpoint, has code for handling the upload and uploads the file to uploads/yyyy/mm without | |
adding the file to the media library. | |
Installation: | |
Save dropzonejs-wp-rest-api-custom-endpoint.php in wp-content/plugins/dropzonejs-wp-rest-api-custom-endpoint/ | |
Save dropzonejs-wp-rest-api-custom-endpoint.js in wp-content/plugins/dropzonejs-wp-rest-api-custom-endpoint/js/ | |
Use: | |
After activating the plugin, add the [dropzonerest] shortcode to a post | |
Credits: | |
http://www.dropzonejs.com/ | |
https://github.com/WP-API/WP-API, I learned a lot reading the wp-api source | |
Copyright: | |
The plugin is copyright Per Soderlind - [email protected] | |
License: GPL, please feel free to modify the plugin as long as you make it GPL |
This file contains 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
// dropzoneWordpressRestApiForm is the configuration for the element that has an id attribute | |
// with the value dropzone-wordpress-rest-api-form (or dropzoneWordpressRestApiForm) | |
Dropzone.options.dropzoneWordpressRestApiForm = { | |
//acceptedFiles: "image/*", // all image mime types | |
acceptedFiles: ".jpg", // only .jpg files | |
maxFiles: 1, | |
uploadMultiple: false, | |
maxFilesize: 5, // 5 MB | |
init: function() { | |
console.group('dropzonejs-wp-rest-api:'); | |
var myDropzone = this; // closure | |
myDropzone.on("sending", function(file, xhr, data) { | |
console.log("file: %O", file); | |
//add nonce, from: http://v2.wp-api.org/guide/authentication/ | |
xhr.setRequestHeader('X-WP-Nonce', WP_API_Settings.nonce); | |
}); | |
// myDropzone.on("processing", function(file) { | |
// this.options.url = WP_API_Settings.root + 'wp/v2/media/'; | |
// }); | |
myDropzone.on("error", function(file, error, xhr) { | |
console.error("ERROR: %o", error); | |
console.groupEnd(); | |
}); | |
myDropzone.on("success", function(file, response) { | |
console.log("success: %o", response); | |
// etc | |
}); | |
} | |
}; |
This file contains 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 | |
/* | |
Plugin Name: DropzoneJS & WordPress REST API with Custom Endpoint | |
Version: 0.0.1 | |
Description: Demos how to upload files using DropzoneJS and the WordPress REST API (wp-api v2) | |
Author: Per Soderlind | |
Author URI: https://soderlind.no | |
Plugin URI: https://gist.github.com/soderlind/ | |
License: GPL | |
*/ | |
define( 'DROPZONEJS_WP_REST_API_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); | |
define( 'DROPZONEJS_WP_REST_API_PLUGIN_VERSION', '0.0.1' ); | |
define( 'DROPZONEJS_WP_REST_API_NAMESPACE', 'dropzonejs/v' . DROPZONEJS_WP_REST_API_PLUGIN_VERSION ); | |
define( 'DROPZONEJS_WP_REST_API_BASE', 'upload' ); | |
add_action( 'plugins_loaded', 'dropzonejs_wp_rest_api_init' ); | |
function dropzonejs_wp_rest_api_init() { | |
add_action( 'wp_enqueue_scripts', 'dropzonejs_wp_rest_api_enqueue_scripts' ); | |
add_shortcode( 'dropzonerest', 'dropzonejs_wp_rest_api_shortcode' ); | |
} | |
function dropzonejs_wp_rest_api_enqueue_scripts() { | |
wp_enqueue_script( | |
'dropzonejs', | |
'https://cdnjs.cloudflare.com/ajax/libs/dropzone/4.2.0/min/dropzone.min.js', | |
array(), | |
DROPZONEJS_WP_REST_API_PLUGIN_VERSION | |
); | |
// Load custom dropzone javascript | |
wp_enqueue_script( | |
'dropzone-wp-rest', | |
DROPZONEJS_WP_REST_API_PLUGIN_URL . '/js/dropzonejs-wp-rest-api-custom-endpoint.js', | |
array( 'wp-api', 'dropzonejs' ), | |
DROPZONEJS_WP_REST_API_PLUGIN_VERSION | |
); | |
wp_enqueue_style( | |
'dropzonecss', | |
'https://cdnjs.cloudflare.com/ajax/libs/dropzone/4.2.0/min/dropzone.min.css', | |
array(), | |
DROPZONEJS_WP_REST_API_PLUGIN_VERSION | |
); | |
// from: http://v2.wp-api.org/guide/authentication/ | |
wp_enqueue_script( 'wp-api' ); | |
wp_localize_script( | |
'wp-api', | |
'WP_API_Settings', | |
array( | |
'root' => esc_url_raw( rest_url() ), | |
'nonce' => wp_create_nonce( 'wp_rest' ), | |
'title' => 'Media Title', | |
'description' => 'Media Description', | |
'alt_text' => 'Media Alt Text', | |
'caption' => 'Media Caption' | |
) | |
); | |
} | |
// Add Shortcode | |
function dropzonejs_wp_rest_api_shortcode( $atts ) { | |
//user can ? | |
if ( ! is_user_logged_in() || !current_user_can( 'upload_files' ) ) { | |
return; | |
} | |
$url = rest_url() . DROPZONEJS_WP_REST_API_NAMESPACE . '/' . DROPZONEJS_WP_REST_API_BASE; | |
return <<<ENDFORM | |
<div id="dropzone-wordpress-rest-api"><form action="$url" class="dropzone needsclick dz-clickable" id="dropzone-wordpress-rest-api-form"> | |
<div class="dz-message needsclick"> | |
Drop files here or click to upload.<br> | |
<span class="note needsclick">(Files are uploaded to uploads/yyyy/mm)</span> | |
</div> | |
<input type='hidden' name='action' value='submit_dropzonejs'> | |
</form></div> | |
ENDFORM; | |
} | |
/** | |
* register custom endpoint, see http://v2.wp-api.org/extending/adding/ | |
*/ | |
add_action( 'rest_api_init', function () { | |
register_rest_route( DROPZONEJS_WP_REST_API_NAMESPACE, '/' . DROPZONEJS_WP_REST_API_BASE , array( | |
'methods' => 'POST', | |
'callback' => 'dropzonejs_upload', | |
'permission_callback' => function () { | |
return current_user_can( 'upload_files' ); | |
} | |
) ); | |
} ); | |
/** | |
* dropzonejs_upload hadles the upload, code from https://github.com/WP-API/WP-API/blob/47491996f08a3f51883dbae6f6fd0c94ade90c9f/lib/endpoints/class-wp-rest-attachments-controller.php#L56 | |
* | |
* @param WP_REST_Request $request The request object has the multipart file parameters and the given header from the request. | |
* @return WP_HTTP_Response The response has the name, file type and url of the uploaded file | |
*/ | |
function dropzonejs_upload( WP_REST_Request $request ) { | |
// Get the file via $_FILES (raw data ignored) | |
$files = $request->get_file_params(); | |
$headers = $request->get_headers(); | |
$file = dropzonejs_upload_file( $files, $headers ); | |
if ( is_wp_error( $file ) ) { | |
return $file; | |
} | |
// Wrap the data in a response object | |
$data = array(); | |
$data['name'] = basename( $file['file'] ); | |
$data['url'] = $file['url']; | |
$data['type'] = $file['type']; | |
$response = rest_ensure_response( $data ); | |
$response->set_status( 201 ); | |
return $response; | |
} | |
/** | |
* dropzonejs_upload_file does the actual upload, it's a strip down version of https://github.com/WP-API/WP-API/blob/47491996f08a3f51883dbae6f6fd0c94ade90c9f/lib/endpoints/class-wp-rest-attachments-controller.php#L451 | |
* | |
* @param array $files Data from $_FILES | |
* @param array $headers HTTP headers from the request | |
* @return array|WP_Error Data from {@see wp_handle_upload()} | |
*/ | |
function dropzonejs_upload_file( $files, $headers ) { | |
if ( empty( $files ) ) { | |
return new WP_Error( 'rest_upload_no_data', __( 'No data supplied' ), array( 'status' => 400 ) ); | |
} | |
// Verify hash, if given | |
if ( ! empty( $headers['content_md5'] ) ) { | |
$content_md5 = array_shift( $headers['content_md5'] ); | |
$expected = trim( $content_md5 ); | |
$actual = md5_file( $files['file']['tmp_name'] ); | |
if ( $expected !== $actual ) { | |
return new WP_Error( 'rest_upload_hash_mismatch', __( 'Content hash did not match expected' ), array( 'status' => 412 ) ); | |
} | |
} | |
// Pass off to WP to handle the actual upload | |
$overrides = array( | |
'test_form' => false, | |
); | |
// Bypasses is_uploaded_file() when running unit tests | |
if ( defined( 'DIR_TESTDATA' ) && DIR_TESTDATA ) { | |
$overrides['action'] = 'wp_handle_mock_upload'; | |
} | |
/** Include admin functions to get access to wp_handle_upload() */ | |
require_once ABSPATH . 'wp-admin/includes/admin.php'; | |
$file = wp_handle_upload( $files['file'], $overrides ); | |
if ( isset( $file['error'] ) ) { | |
return new WP_Error( 'rest_upload_unknown_error', $file['error'], array( 'status' => 500 ) ); | |
} | |
return $file; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment