The default WordPress post editor declares a simple form that does not have an encoding type defined and, therefore, can only accept regular text input. Fortunately, we have access to an action hook to register a callback function that will output additional code when the form gets created, allowing us to upload files. This callback is implemented in the first part of this recipe.
The next code section registers a meta box, as we have seen in many recipes so far, to display a new editor section that will display a link to an attached file if present, a file selection box to upload a new file, and a button to request for the attachment to be deleted.
Moving on to the function responsible for processing the post data, the recipe's code first checks whether the user requested to delete a file associated with a post. If that is the case, it will proceed with the deletion of the file and remove the associated post metadata. In other circumstances, if the item's post type is a post or page, the plugin will proceed to search for a file uploaded by the user within the PHP global $_FILES array. This array contains information on any uploads that have been processed as part of a form's post data. If an entry is found, we will use the wp_check_filetype function to retrieve information about the file type and proceed to convert the resulting extension to a lowercase string to make comparisons easier.
As this example only expects to receive PDF files, the code then checks to see whether the file extension is correct to decide whether it will display an error message using the wp_die function or move the file from the web server's temp directory to the wp-content/uploads directory in WordPress, using the wp_upload_bits function. In the latter case, it also stores the resulting file's path and URL in the post custom field table.
Once this is done, this recipe implements a filter function for the_content to display a link to associated PDF attachments under posts and pages.