• Skip to main content
  • Skip to primary sidebar
  • Skip to footer

nSiteful Web Builders

Building a Better Web - One Site at a Time.

  • Home
  • About
    • Testimonials
    • Resources
  • Web Sites
  • Online Marketing
  • WordPress Support
    • Customized WordPress Training
    • 60-for-60 Sessions
  • Web Applications
  • Blog
    • Archive Listing Minimalistic
    • Blog Articles Grouped by Category
    • Case Studies
    • General
    • Portfolio
    • Reviews
    • Snippets
    • Techniques
  • Contact Jeff
    • Purchase Retainer Consulting Hours
    • About Retainer Consulting Hours

By Jeff Cohan, April 2, 2019

I Built a WordPress Plugin for Downloadable Files

If you’ve ever embedded a PDF file or other downloadable file in WordPress posts or pages using the standard “Add Media” button, you probably know what a pain it can be if and when — but most likely when — that file needs to be updated.

You can’t just upload the newly updated file to the Media Library and expect “voila” to happen.

Even if the updated file has the same filename as the original, WordPress will rename it on upload rather than replace the old one with the new one. (I’ve tried a plugin that offers this replacement functionality, but it wasn’t user-friendly and fell short in other ways.)

What you’ll have to do to replace the file is:

  1. remember all the places you embedded it
  2. remove the old embed in all those places
  3. add the new embed in all those places

Not the end of the earth, but not the best use of anyone’s time, either. Especially if there are lots of documents that get updated or some documents that get updated a lot or some combination of the two.

So I created my own plugin — “Downloads” — for replacing downloadable files.

(Note: This is a plugin with a small “p”. More work is needed before it can be submitted for inclusion in the WordPress repository.)

A Web site for a private school was the inspiration.

The project that inspired this solution was a Web-site redesign for a private school. This school — like many, I suppose — offers a whole lot of documents, most of them in PDF format, for students and parents, both actual and prospective.

Lots of downloadable documents.

There are:

  • school-year calendars for each of three academic programs
  • application forms
  • forms for requesting transcripts
  • field trip permission forms
  • handbooks
  • course descriptions
  • event flyers
  • and more.

In the rest of this article I’ll describe the basic features, elements and operation of the plugin, without getting too much into the weeds. If you’re interested in learning more, let me know in the comments.

Features of the Plugin

Feature #1. Insert Documents by Shortcode

One of the main components of the plugin is a custom shortcode used to embed each Download (more on the shortcode below).

Feature #2. Conditional Display

Each downloadable document can have either a “Start Showing On…” date and/or a “Stop Showing After…” date. Wherever a Download is embedded in a page or post (or widget, for that matter), the plugin “knows” whether to display the link based on those dates and the current date.

This means two things:

  • You can embed a Download on a page or post even before you want it to appear on the front end of the site. This is almost exactly like post-dating a blog post to schedule it to appear in the future.
  • Conversely, the plugin will automatically hide any Download that should not appear after a specific date. (For example, you might want to remove a field trip application form after the field trip occurs.) You needn’t edit the page(s) or post(s) to manually remove the embed, as long as you specified the proper date parameters.

Feature #3. Automatic Inclusion on Front End

screen shot of Academic Calendars page
Click image to enlarge
The site has a dedicated page for Academic Calendars. As I mentioned earlier, there are calendars for each of the three main programs the school offers. In addition, at any given time of year, the calendars for multiple school years for any given program might be displayed. For example, in the spring of the 2018-2019 school year, both the current school year calendar (2018-2019) and the next school year calendar (2019-2020, if available) for the K-12 will be displayed.

I made a custom template for this page. The template’s code automatically displays the link for every downloadable document whose type (custom taxonomy) is “Calendar” as long as the current date is on or after the designated “Start Showing On…” date and on or before the “Stop Showing After…” date.

Feature #4. Automatic Replacement

This is the feature that drove me to create the plugin in the first place.

Invariably, Downloads need to be replaced from time to time, due either to errors or actual changes.

Because each downloadable document is identified by its post ID — rather than by its filename — you can just replace the obsolete document with the new one in the Downloads administrative panel, and voila!

First click the “Remove” icon…
Remove file screen shot

Then add the new file.
Replace file screen shot

There are five main elements of this plugin:

  1. a custom post type for downloadable documents (“Downloads”)
  2. custom fields (using the Advanced Custom Fields plugin for specifying metadata for each document)
  3. a custom taxonomy
  4. a shortcode for displaying the download links where needed
  5. a custom page template for displaying calendars

Element #1. The Custom Post Type

The Custom Post Type itself is very simple. This new post type (named “Download”) supports only the ‘title’ and “page-attributes” features of WordPress’ post edit screen. The ‘title’ is the internal (for office use only) name for the download. Enabling page attributes permits assigning order values, for the purpose of sorting, where desired.

Element #2. Custom Fields

This is where the meaty stuff of the plugin happens.

Here’s a screen shot of the ACF Field Group for downloads:

screen shot of custom fields admin screen
Click image to enlarge

The fields:

  • Title (required, internal use only)
  • Academic Program (optional; e.g., “K-12”, “Independent Study”, etc.)
  • Front-End Document Title (required)
  • Document Description (optional and hidden on front end by default)
  • Document File (required)
  • Start Showing On… date (optional, supports date-picker)
  • Stop Showing After… date (optional, supports date-picker)

Element #3. Custom Taxonomy

screen shot of download categories boxI registered a custom taxonomy called “download_cat” and associated it with the Downloads custom post type. As of this writing, the only download_cat value that has any special power is “Calendar”. As I mentioned above, the template’s code automatically displays the HTML for every downloadable document whose type (download_cat) is “Calendar” as long as the current date is on or after the designated “Start Showing On…” date and on or before the “Stop Showing After…” date.

Element #4. The Downloads Shortcode

Format for Shortcode:

The format for the shortcode that embeds a Download into a page or post is as follows. The only required attribute is the id. Where I show optional values for attributes (e.g., “true|false”), the first element is the default.

[ea_download id="nnn" block="true|false" show_description="false|true" href_only="false|true"]

Shortcode Function:

Here’s the actual code for generating the HTML from the shortcode. If you’re interested in a description of how it works, let me know.

function nwb_shortcode_download($atts) {
	global $post;
	$atts = shortcode_atts( array(
		'id' => '',
		'block' => 'true',
		'show_description' => 'false',
		'href_only' => 'false',
	), $atts, 'ea_download' );
	if ( empty($atts['id']) ) {
		return;
	}
	$doc_id = $atts['id'];
	$data = get_post_custom($doc_id);
	$program 		=	$data['program'][0];
	$title 			= 	$data['document_title'][0];
	$description 	= 	$data['document_description'][0];
	$show_from 		= 	$data['show_from'][0];
	$show_through 	= 	$data['show_through'][0];
	$file 			=	$data['document_file'][0];
	
	// Test from and to dates
	$today = date('Y-m-d');
	if ( !empty($show_from) && $today < $show_from ) {
		return;
	}
	if ( !empty($show_through) && $today > $show_through ) {
		return;
	}
	$file_url 		= 	wp_get_attachment_url($file);
	$href_start = '<a target="_blank" href="' . $file_url . '">';
	$href_end = '</a>';
	

	/* To return only the link */
	if ( 'true' == $atts['href_only']) {
		$output = $file_url; 
		return $output;
	}
	if ( 'true' == $atts['block']) {
		$output = '<div class="download">';
		$output .= '<div class="name">' . $href_start . $title . $href_end . '</div>';
		if ( $atts['show_description'] == 'true' && !empty($description)) {
			$output .= '<div class="description">' . $description . '</div>';
		}
		$output .= '</div>';
	} else {
		$output = '<span class="name">' . $href_start . $title . $href_end . '</span>';
	}
	return $output;
}
add_shortcode('ea_download', 'nwb_shortcode_download');

Element #5. The Custom Page Template for Academic Calendars

Here are pertient blocks of code from the custom page template for grabbing and diplaying academic calendars. Again, if anyone is interested in more information, please let me know.

Custom Query:

global $post;
$args = array(
	'post_type' => 'download',
	'order' => 'ASC',
	'orderby' => 'menu_order',
	'tax_query' => array(
		array(
			'taxonomy' => 'download_cat',
			'field' => 'slug',
			'terms' => 'calendar',
		),
	),
	'posts_per_page' => -1,
);
$cal_query = new WP_Query($args);

Rendering the HTML on the page:

<?php if ( $cal_query->have_posts() ) : while ( $cal_query->have_posts() ) : $cal_query->the_post(); ?>
	<?php 
		$doc_id = $post->ID;
		$data = get_post_custom($doc_id);
		$program 		=	$data['program'][0];
		$title 			= 	$data['document_title'][0];
		$description 	= 	$data['document_description'][0];
		$show_from 		= 	$data['show_from'][0];
		$show_through 	= 	$data['show_through'][0];
		$file 			=	$data['document_file'][0];
		// Test from and to dates
		$today = date('Y-m-d');
		if ( !empty($show_from) && $today < $show_from ) {
			continue;
		}
		if ( !empty($show_through) && $today > $show_through ) {
			continue;
		}
		$file_url 		= 	wp_get_attachment_url($file);
		$href_start = '<a target="_blank" href="' . $file_url . '">';
		$href_end = '</a>';
		/* Assemble the output */
		$output = '<section>';
		$output .= '<div class="download">';
		$output .= '<div class="name">' . $href_start . $title . $href_end . '</div>';
		if ( $atts['show_description'] == 'true' && !empty($description)) {
			$output .= '<div class="description">' . $description . '</div>';
		}
		$output .= '</div>';
		$output .= '</section>';
		echo $output; 
	?>
<?php endwhile; ?>
<?php wp_reset_postdata(); ?>
<?php endif; ?>

Tying it Up

Here are screen shots of the “Forms & Downloads” page followed by the code that makes it happen.

Screen shots

screen shot of forms/downloads page, top
Click image to enlarge
screen shot of forms/downloads page, bottom
Click image to enlarge

The code entered into the page:

<h2 id="orientation">Orientation, Handbooks &amp; General Forms</h2>

[ea_download id="4709"]
[ea_download id="5099"]
[ea_download id="4785"]

<h2 id="distance-learning">Distance Learning</h2>

[ea_download id="4787"]
[ea_download id="4788"]
[ea_download id="4790"]

<h2 id="summer-school">Summer School</h2>

[ea_download id="4792" show_description='true']
[ea_download id="4791" show_description='true']

<h2 id="other-forms">Other Forms &amp; Downloads</h2>

[ea_download id="5473" show_description="true"]
[ea_download id="4786"]
[ea_download id="4771" show_description='true']
[ea_download id="5550" show_description='true']
[ea_download id="5553" show_description='true']

Comments Welcome

I guess I ended up covering a lot of ground after all. But if you have questions or are interested in knowing more, please let me know in the comments below.

Related Posts

  1. Add Dynamic Table of Contents to a Series of WordPress Posts
  2. Custom extensible PHP shortcode function for non-WordPress Web sites
  3. Dive Into WordPress Custom Post Types – Part 2
  4. FooGallery Plugin for WordPress: First Look
  5. Tipsy WordPress Plugin from iThemes
  • Choose the best match.

Written by Jeff Cohan · Categorized: Case Studies · Tagged: Plugins, WordPress

  • Choose the best match.

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

mailchimp signup

Subscribe to get notified when new articles are published. Unsubscribe any time. No spam. I promise. Check out my newsletter archives.

social

Twitter Facebook LinkedIn

Recent Articles

  • Create a Custom Shortcode to Display a MemberPress Membership Price ANYWHERE on Your Website February 5, 2023
  • Avoid Direct Styling; Use CSS Instead September 21, 2022
  • Blog Tags: What They Are (and What They’re Not) August 5, 2022
  • How to Create a Simple Custom Events Plugin May 24, 2022
  • Make your Web Site the Heart & Hub of your Online Marketing Strategy March 24, 2022

Filter By Category/Tag

Categories

  • Case Studies (7)
  • General (61)
  • Portfolio (5)
  • Reviews (12)
  • Snippets (16)
  • Techniques (37)

Popular Tags

Advanced Custom Fields Blogging Child Themes Content Marketing CSS CSS Grid Customer Service Custom Fields Custom Post Types Diagnostics Facebook FooGallery Genesis Gutenberg HTML Images iPhone Libra Live Chat Marketing Media MemberPress MemberPress Courses mu-plugins MySQL Photo Gallery php Pinterest Plugins Post Formats Pricing Project Management Security SEO Seth Godin Shortcodes Social Networking Surveys Taxonomies Trello Twitter Video Web design Web forms WordPress

siteground wp hosting

Web Hosting

wp101

EasyWordPresstutorialvideosforbeginners.
MemberPress CTA

Footer

Background

Web Sites | WordPress Support | Web Applications.

Formally trained in liberal arts and education (I have a B.A. in Government from Harvard and studied Secondary Education at Rutgers Graduate School), I have honed my skills in the communication arts and sciences as a teacher, trainer, instructional designer, writer, photographer, calligrapher, helpdesk manager, database programmer, and multimedia developer.

(I've also been a group counselor, waiter, bartender, bicycle messenger boy, computer salesman, carpenter's helper, financial analyst, and school board president.)

Tech

Systems since 1983.
Web sites since 1994.
PHP since 2001.
WordPress since 2007.

Contact

770-772-5134
Email Jeff
Send Money
All Ways

Copyright 2023, nSiteful Web Builders, Inc.

 

Subscribe

Pardon the interruption. I know popups can be annoying. But I’d love to have you as a subscriber.

Sign up to be notified when new articles are published. Unsubscribe any time.

* indicates required

Powered by MailChimp

×