How to Build a Downloads Gallery WordPress Plugin


By

Plugins extend WordPress’ functionality and let you do almost anything with your existing site. In this tutorial, we create a downloads gallery WordPress plugin, keeping it plain and simple and focusing more on WordPress core instead of PHP logic.

  1. Firstly, we will set up the admin area functionality, including uploading, listing and deleting files.
  2. Secondly, we will list the uploaded files on the actual site for others to download them.

Note: You can easily turn this plugin into a full-featured Downloads system, but as of now, we will focus more on how to work with WordPress to setup a working plugin.


How to Build a Downloads Gallery WordPress Plugin

Functionality

We will set up a Downloads Gallery for your WordPress website, where we need our users to download all the files uploaded by admin. In brief, we need a page to upload files to WordPress and a page to download the requested files.

File Structure

FileStructure

The above screenshot shows the required files and folder to help us set up our plugin. Let’s first understand the file structure:

  1. secure_files: This folder will store our download files.
  2. downloads.php: This file will let the end-user download the file by clicking on a link.
  3. style.css: You can write a separate design for your Downloads Gallery under this file.
  4. tutlage_file_manager.php This file will store the logic for the front-end view (website page to download files).
  5. tutlage_file_manager_admin.php This file will store the logics for the admin page.

These are the required files to set up our WordPress plugin. We will be creating functions to manage uploads and downloads. You will need to have a working knowledge of PHP basics for this purpose.

Getting Started

Create a new folder named tutlage_file_manager under wp-content->plugins, with a new file called tutlage_file_manager.php inside it. Now open that file with your favorite text editor and paste the following code inside it:

<!--?php
/*
Plugin Name: Tutlage File Manager
Plugin URI: https://www.speckyboy.com
Description: Plugin to set up a simple downloads gallery for your WordPress website
Author: Aman Virk
Version: 1.0
Author URI: https://www.thetutlage.com
*/
?-->

Login to the WordPress dashboard and navigate to Plugins->Installed Plugins. Now, you will be able to find a new plugin listed there. In our case, it shows Tutlage File Manager

WordPressPlugin Dashboard

You can activate the plugin by clicking the Activate link next to the plugin name, but it will not make any changes to WordPress because we have not yet written any code for our plugin.

Working with Action Hooks

Action Hooks are designated points in WordPress that give you a chance to run your code before executing any described function. Let’s say you wish to add something to WordPress’s footer. You can hook your function with the wp_footer function. See the given example. Check out list of available hooks in WordPress.

<?php
function your_function() {
    echo '<p>This is inserted at the bottom</p>';
}
add_action('wp_footer', 'your_function');
?>

Now, if you have the plugin activated, just go to the website, and you will be able to see the above text at the bottom of the page. As we have nothing to do with footer, just remove the above code so that we can write the action hook to show our plugin inside the WordPress Settings tab.

function tutlage_file_manager_callback(){
    //Here goes our callback function
}
 
function tutlage_admin_setup(){
    add_options_page("Tutlage File Manager", "Tutlage File Manager", 1, "tutlage_file_manager", "tutlage_file_manager_callback");
}
add_action('admin_menu',tutlage_admin_setup);

Copy the above code inside your tutlage_file_manager.php file and refresh the Dashboard page. Now you will be able to see a link inside the settings tab.

FunctionReference-addoptionspageWordPressCodex

Understanding the Above Code

What we have done so far is called the add_options_page function to list our plugin inside the Settings tab. You can read more about add_options_page here.

As of now, we are able to see our plugin link and a blank page. We can move forward to create an Upload button for our plugin. We will keep the logic for our admin page inside a different file. Let’s create a new file tutlage_file_manager_admin.php.

WordPress, by default, listens to the main plugin file, which in our case is tutlage_file_manager.php. So we will include the tutlage_file_manager_admin.php file under this file.

function tutlage_file_manager_callback(){
    include_once( 'tutlage_file_manager_admin.php' );
}

We have edited our tutlage_file_manager_callback() function which will now include the tutlage_file_manager_admin.php file. Let’s do ‘Hello World‘ to check if we are on the correct path. Paste the below code inside tutlage_file_manager_admin.php and refresh the page to see ‘Hello World’ printed on your screen:

<?php
    echo '<p>Hello world</p>';
?>

WordPressActionHooks

If you do see ‘Hello World’ then we can proceed…

Setting up the Upload Form

Paste the below code inside tutlage_file_manager_admin.php file and refresh the page; you will be able to see the upload form:

<div class="wrap">
    <h3>Uploading Files</h3>
    <form method="post" action="<?php echo str_replace( '%7E', '~', $_SERVER['REQUEST_URI']); ?>" enctype="multipart/form-data">
        <p><label for="Upload File">Upload File: </label><input type="file" name="tutlage_file_upload" /></p>
        <p class="submit"><input type="submit" name="Upload" value="Upload" /></p>
    </form>
</div>

This form will not do anything as of now because we have not written any code for it. We need to find out whether the Download directory, which in our case is secure_files, exists or not. Paste the code below to the top of your file.

<?php
$folder_path = ABSPATH.'wp-content/plugins/tutlage_file_manager/secure_files';
function createDirectory($folder_path){
    if(!is_dir($folder_path))
    {
        mkdir($folder_path);
    }
}
createDirectory($folder_path);
?>
  1. First, we have defined the base path for our Downloads directory.
  2. Next, we have created the function which will check whether the above directory exists or not. If not, it will make a new directory.
  3. Finally, we are calling the function.

Now, we can move forward and write the function to add the uploaded files under this directory. Add the below code after the createDirectory() function.:

function uploadFiles($directory,$file_name,$file_tmp_name){
    if(move_uploaded_file($file_tmp_name,$directory.'/'.$file_name))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

We are simply uploading the files to the given directory under this function. Now, we will write the code that gets executed every time the Upload button is clicked. Add the below code inside the same file ( tutlage_file_manager_admin.php ):

if(isset($_POST['Upload']))
{
    $file_name = strtotime("now").$_FILES['tutlage_file_upload']['name'];
    $upload = uploadFiles($folder_path,$file_name,$_FILES['tutlage_file_upload']['tmp_name']);
    if($upload == 1)
    {
        echo '<div class="updated"><p><strong>File Uploaded Successfully <a href="'.str_replace('%7E','~',$_SERVER['REQUEST_URI']).'">Return Back</a></strong></p></div>';
    }
    else
    {
        echo '<div class="error"><p><strong> Error Uploading File <a href="'.str_replace('%7E','~',$_SERVER['REQUEST_URI']).'">Return Back</a></strong></p></div>';
    }
}

WordPressFileUpload [image]

  1. We have created a variable $file_name, which will add the current time (in milliseconds) in front of the filename. It will make sure we are not overriding the existing file with the current one if they both have the same name.
  2. Every time we click the Upload button, we run the function uploadFiles() with the required parameters.
  3. First, we will pass the folder path.
  4. Next, we will pass the actual file name.
  5. Lastly, we will pass the temporary file name.
  6. If the upload was successful, we will show a success message. Otherwise, we will send an error message.

Check the secure_files folder to find out whether files are saved there or not. At this point, we are able to save files; now, we need a way to retrieve all files from the secure_files directory and list them on our plugin’s page.

The below function will return an array of data containing uploaded file information. It is a good practice to keep all of your functions in one place, so paste the code below where your last function ends.

 
function getUploadedFiles($directory){
    $folder = opendir($directory);
    while ($file = readdir($folder)) {
        if($file !== '.' && $file !== '..')
        {
            $filename = $directory.'/'.$file;
            $file_size = filesize($filename);
            $last_date = date("F d Y H:i:s", filectime($filename));
            $file_array[] = array('filename' => $file,'filesize' => $file_size,'lastdate' => $last_date);
        }
    }
    return $file_array;
}

The above function will list all the files from a specific directory.

Earlier, we created an if statement to upload the files; now, we will create an else statement just next to it to list all files.

 
else
{
    $list_files = getUploadedFiles($folder_path);
 
    $output = ' <table class="wp-list-table widefat fixed posts" cellspacing="0">
    <thead>
        <tr>
            <th id="title" class="manage-column column-title sortable desc" style="" scope="col">
                <a href=""><span>Title</span></a>
            </th>
            <th id="title" class="manage-column column-title sortable desc" style="" scope="col">
                <a href=""><span>File Size</span></a>
            </th>
            <th id="title" class="manage-column column-title sortable desc" style="" scope="col">
                <a href=""><span>Upload Date</span></a>
            </th>
            <th id="title" class="manage-column column-title sortable desc" style="" scope="col">
                <a href=""><span>Actions</span></a>
            </th>
        </tr>
    </thead><h3> Uploaded Files </h3>
    <tbody>';
    if(!empty($list_files))
    {
        foreach($list_files as $key => $value)
        {
            $output .= '<tr>
                <td class="post-title page-title column-title">
                    <strong>'.$value['filename'].'</strong>
                </td>
                <td class="post-title page-title column-title">
                    <strong>'.$value['filesize'].' Bytes </strong>
                </td>
                <td class="post-title page-title column-title">
                    <strong>'.$value['lastdate'].'</strong>
                </td>
                <td class="post-title page-title column-title">
                    <a href="'.str_replace( '%7E', '~', $_SERVER['REQUEST_URI']).'&&file='.$value['filename'].'&&action=delete"> Delete </a>
                </td>
            </tr>';
        }
    }
    else
    {
        $output .= '<tr><td> No files have been found </td></tr>';
    }
    $output .= '</tbody></table>';
}

It does seem like a lot of code, but most of it is HTML.

  1. First, we have called the function getUploadedFiles(), which will get all files from a directory and return us the array of data.
  2. Next, we have created a table and defined ID and class attributes to make sure our table looks quite similar to the native WordPress table structure.
  3. We have also stored the output inside a variable called $output.
  4. All we need to do now is to echo the above variable.

Place the below code next to the form we created, and we are done!

 
<div class="clear"></div>
<?php if(isset($output)) { echo $output; } ?>

WordPressFileUploading [image]

If everything has gone right, you will now be able to find a Delete button with every file listed on a table. So, why not write one more function to delete the selected file?

 
function deleteFiles($file_path){
    if(is_file($file_path))
    {
        unlink($file_path);
    }
    else
    {
        rmdir($file_path);
    }
    return true;
}

The above function is quite simple as it will check if the selected filename is a file. Then, we can use the unlink method to delete else; we will also use the rmdir method, which will remove the directory.

Now, where should we write the code that will run after hitting that Delete button? Do you remember that we created if and else statements earlier? Let’s add else if inside them, and this else if will be the one to delete the file.

 
elseif(isset($_GET['action']) && $_GET['action'] == 'delete')
{
    $file_path = $folder_path.'/'.$_GET['file'];
    if(deleteFiles($file_path))
    {
        echo '<div class="updated"><p><strong>File Deleted Successfully <a href="'.str_replace('%7E','~',$_SERVER['PHP_SELF']).'?page=tutlage_file_manager">Return Back</a></strong></p></div>';
    }
}

Let’s have a quick recap of what we have done so far. We’ve learned how to add a link to our plugin inside the WordPress Settings menu, figured out how WordPress hooks work, and created the functionality to upload and list files from the admin’s Dashboard.

Now, we will work with the front-end logic where a user can download all the listed files from our website. Let’s break it down to find what we need to make it work.

  1. Create a dynamic page where all files will be listed.
  2. Grab all files from our secure_files directory and list them on the above page.
  3. Add functionality to download files with an onclick event.

Let’s get started with it. Open file tutlage_file_manager.php and paste the following code inside it.

function thetutlage_add_share_page()
{
    if (!get_page_by_title('Downloads Gallery'))
    {
        $post = array(
            'post_content'  => '',
            'post_name'     =>  'Downloads Gallery',
            'post_status'   => 'publish',
            'post_title'    => 'Downloads Gallery',
            'post_type'     => 'page',
            'post_parent'   => 0,
            'menu_order'    => 0,
        );
        wp_insert_post($post);
    }
}
thetutlage_add_share_page();

The above function will check whether a page with the title Downloads Gallery exists or not. If our Downloads Gallery exists already, then we will not create a new page else. We will create one and name it Downloads Gallery.

Now go back to your actual website, and you will find a blank page with a title Downloads Gallery. With that done, we now need to write a function to grab all files from the secure_files directory and list them on this page.

Copy function getUploadedFiles() from tutlage_file_manager_admin.php and paste it to tutlage_file_manager.php and rename the function to getDownloadFiles().

This function will do the same thing: it will grab all the files from a given directory and return them in an array. Now we need to call this function, break the array, and list them on the page with the title Downloads Gallery.

We need to list files only where the page title is Downloads Gallery, and in order to do that, we can use a handy WordPress is_page function:

function list_downloads($content) {
    $page = get_page_by_title( 'Downloads Gallery' );
    if(is_page($page->ID))
    {
        $folder_path = ABSPATH.'wp-content/plugins/tutlage_file_manager/secure_files';
        $files = getDownloadFiles($folder_path);
        if(!empty($files))
        {
            $output = '<table id="tutlage_file_manager">
                <tbody><tr>
                    <th>File Name</th>
                    <th>File Size</th>
                    <th>Download</th>
                </tr>';
            foreach($files as $value)
            {
                $output .= '<tr><td>'.$value['filename'].'</td><td>'.$value['filesize'].' Bytes</td><td><a href="'.get_option('siteurl').'/wp-content/plugins/tutlage_file_manager/downloads.php?file='.$value['filename'].'"> Download </a></td></tr>';
            }
            $output .= '</tbody></table>';
        }
        else
        {
            $output = '<h3> No files found </h3>';
        }
        return $output;
    }
}

Understanding the Above Code

Most of the above code is HTML, which will let us display our files inside a table. There will be a link next to every item, which will allow the user to download it.

  1. First we will get a page where the title is Downloads Gallery
  2. Next, we will check whether that page exists or not using is_page function.
  3. If it exists than we will call the above function getDownloadFiles(), which will return files as an array.
  4. Finally, we will break the array and list the items inside a table.

Now, if you refresh the page, you will see no change. It is because, so far, we have only created the function. We still need to attach this function to WordPress so that every time the content is loaded, our function runs as well.

add_filter( 'the_content', 'list_downloads' );

Just paste the above code in the same file tutlage_file_manager.php and now refresh the page. You will see all the files listed there. Now, all we are left with is the downloads.php file. Make a new file inside the plugin directory and name it downloads.php.:

<?php
    $files = $_GET['file'];
 
    $filepath = 'secure_files/'.$files;
 
    header('Content-Description: File Transfer');
    header("Content-Disposition: attachment; filename=\"$files\"");
    header('Content-Type: application/octet-stream');
    header('Content-Transfer-Encoding: binary');
    header('Content-Length: ' . filesize($filepath));
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Expires: 0');
    readfile($filepath);
?>

downloads.php does not have much work to do: it will get the file name from the URL and will use a method to read the file back to the user. Now, you can easily test the entire plugin right from uploading to downloading files.

Is There Anything Left?

Yes. As of now, we have not created any stylesheet, so let’s take care of that too. Create a new file named style.css.

This file will let you write styles for your actual Downloads page on the website. We just have to link the stylesheet to our existing function called list_downloads(). Open tutlage_file_manager.php.

wp_enqueue_style( 'myprefix-style', plugins_url('style.css', __FILE__) );

Paste the above code inside if statement of list_downloads() function. You can now write any style for your Downloads Gallery.

All done!


Top
This page may contain affiliate links. At no extra cost to you, we may earn a commission from any purchase via the links on our site. You can read our Disclosure Policy at any time.