You can use the great wordpress media manager. I’ve prepared a plugin to attach PDF files to noraml posts. You can download it here.
The php:
<?php
/*
Plugin Name: PDF Metabox
Plugin URI: https://github.com/CybMeta/cyb-pdf-metabox
Description: Displays a metabox to attach a PDF file to current post.
Author: Juan Padial
Version: 1.0.2
Author URI: http://cybmeta.com
*/
class PDF_Metabox
{
/**
* This is our constructor
*
* @return PDF_Metabox
*/
public function __construct() {
add_action( 'post_mime_types', array( $this, 'pdf_mime_type' ) );
add_action( 'add_meta_boxes', array( $this, 'admin_scripts' ), 5 );
add_action( 'add_meta_boxes', array( $this, 'metabox_add' ) );
add_action( 'save_post', array( $this, 'pdf_save_postdata') );
add_action( 'wp_ajax_refresh_pdf', array( $this, 'refresh_pdf' ) );
}
public function pdf_mime_type() {
$post_mime_types['application/pdf'] = array( __( 'PDFs' ), __( 'Manage PDFs' ), _n_noop( 'PDF <span class="count">(%s)</span>', 'PDFs <span class="count">(%s)</span>' ) );
return $post_mime_types;
}
public function admin_scripts() {
wp_register_script( 'pdf-metabox-js', plugins_url( '/lib/js/pdf-metabox.js', __FILE__ ) , array( 'jquery' ), '1.0.2', true );
}
public function metabox_add() {
// Filterable metabox settings.
$post_types = array( 'post');
$context="normal";
$priority = 'low';
// Loop through all post types
foreach( $post_types as $post_type ) {
// Add Metabox
add_meta_box( 'pdf_metabox', __( 'PDF', 'pdf-metabox' ), array( $this, 'pdf_metabox' ), $post_type, $context, $priority );
// Add Necessary Scripts and Styles
wp_enqueue_media();
wp_enqueue_script( 'pdf-metabox-js' );
}
}
public function pdf_metabox( $post ) {
$original_post = $post;
echo $this->pdf_metabox_html( $post->ID );
$post = $original_post;
}
public function pdf_item( $id ) {
if(!$id) return;
$pdf_url = esc_url_raw(wp_get_attachment_url($id));
$pdf="<object data="".$pdf_url.'" type="application/pdf" height="580" width="100%">
<iframe src="https://docs.google.com/viewer?url=".$pdf_url."&embedded=true" width="100%" height="580" frameborder="0"></iframe>
<p><a href="'.$pdf_url.'">'.get_the_title($id).'</a></p>
</object>';
return $pdf;
}
public function pdf_metabox_html( $post_id ) {
$current_value="";
$post_meta = get_post_custom($post_id);
if( isset($post_meta['pdf-id'][0] ) ) $current_value = $post_meta['pdf-id'][0];
$return = '';
//Nonce for verification
wp_nonce_field( plugin_basename( __FILE__ ), 'pdf_noncename' );
$return .= '<p>';
$return .= '<a title="'.__( 'PDF', 'pdf-metabox' ).'" class="button button-primary insert-pdf-button" id="insert-pdf-button" href="#" style="float:left">'.__( 'Upload PDF', 'pdf-metabox' ).'</a><span id="pdf-spinner" class="spinner" style="float:left"></span></p>';
$return .= '<div style="clear:both"></div>';
$return .= '<input type="hidden" name="pdf-id" id="pdf-id" value="'.$current_value.'">';
$return .= '<div style="clear:both"></div>';
$return .= '<div id="pdf-wrapper">';
$pdf = $this->pdf_item( $current_value );
if( empty( $pdf ) ) {
$return .= '<p>No pdf.</p>';
} else {
$return .= $pdf;
}
$return .= '</div>';
return $return;
}
public function pdf_save_postdata($post_id){
// First we need to check if the current user is authorised to do this action.
//Currently capabilities of property post type is the same as normal post type
if ( isset($_POST['post_type']) && 'post' == $_POST['post_type'] ) {
if ( !current_user_can( 'edit_post', $post_id ) ) return;
}
// Secondly we need to check if the user intended to change this value.
if ( !isset( $_POST['pdf_noncename'] ) || ! wp_verify_nonce( $_POST['pdf_noncename'], plugin_basename( __FILE__ ) ) )
return;
// Thirdly we can save the value to the database
if(isset($_POST['pdf-id']) ):
//Don't forget sanitize
update_post_meta($post_id, 'pdf-id', sanitize_text_field( $_POST['pdf-id'] ) );
else:
if (isset($post_id)) {
delete_post_meta($post_id, 'pdf-id');
}
endif;
}
public function refresh_pdf() {
if(isset($_POST['id'])){
$item = $_POST['id'];
if($item != '' && $item !=0){
$pdf = $this->pdf_item( $item );
$ret = array();
if( !empty( $pdf ) ) {
$ret['success'] = true;
$ret['pdf'] = $pdf;
} else {
$ret['success'] = false;
}
} else {
//Is success but the $_POST['ids'] is empty, maybe deleting deattiching files so:
$ret['success'] = true;
$ret['pdf'] = '';
}
} else {
$ret['success'] = false;
}
echo json_encode( $ret );
die();
}
}
// Instantiate our class
$PDF_Metabox = new PDF_Metabox();
?>
The javascript:
// **************************************************************
// Refresh pdf function - fired when a new pdf is selectd
// **************************************************************
function Refresh_PDF(the_ids){
jQuery('#pdf-spinner').css('display','inline');
var data = {
action: 'refresh_pdf',
id: the_ids
};
jQuery.post(ajaxurl, data, function(response) {
var obj;
try {
obj = jQuery.parseJSON(response);
}
catch(e) { // bad JSON catch
// add some error messaging ?
}
if(obj.success === true) { // it worked. AS IT SHOULD.
if( obj.pdf != '' ) {
jQuery('div#pdf-wrapper').html(obj.pdf);
} else {
jQuery('div#pdf-wrapper').html('');
}
jQuery('#pdf-spinner').css('display','none');
// add some success messaging ?
}
else { // something else went wrong
// add some error messaging ?
}
});
}
// **************************************************************
// now start the engine
// **************************************************************
jQuery(document).ready( function($) {
jQuery('#insert-pdf-button').click(function(e) {
e.preventDefault();
var frame = wp.media({
title : 'Pick the PDF to attach to this entry',
frame: 'select',
multiple : false,
library : {
type : 'application/pdf'
},
button : { text : 'Insert' }
});
frame.on('close',function() {
// get selections and save to hidden input plus other AJAX stuff etc.
var selection = frame.state().get('selection');
var pdf_ids = new Array();
var my_index = 0;
selection.each(function(attachment) {
pdf_ids[my_index] = attachment['id'];
my_index++;
});
var ids = pdf_ids.join(",");
jQuery('#pdf-id').val(ids);
Refresh_PDF(ids);
});
frame.on('open',function() {
var selection = frame.state().get('selection');
ids = jQuery('#pdf-id').val().split(',');
ids.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
});
frame.on('toolbar:create:select',function() {
frame.state().set('filterable', 'uploaded');
});
frame.open();
})
});
The plugin stores the ID of the attached PDF file in the meta field “pdf-id”. To get it in the front end you can use different ways. For example, if you are inside the loop you can use:
<?php
$post_meta = get_post_custom(get_the_ID());
$pdf_id = $post_meta['pdf-id'][0];
$pdf_url = wp_get_attachment_url($pdf_id);
echo $pdf_url;
?>