2nd Aug '22
/
4 comments

Download Area with HappyFiles

Download Area with HappyFiles

Aside from the series I’m currently writing on how to create custom galleries and sliders with HappyFiles, Metabox and Bricks, I have developed a snippet to output all subfolders of a specific folder. This one is very useful if you want to create a custom “Download Area” for example. You can manage all your downloadable files from your WP Media section and don’t have to manually update that page every time a document/image changes, gets removed or a new one gets added!

What’s included in the snippet?

The snippet takes care of the following things:

  • Icon generation
  • The possibility to output it with or without CSS rules applied!
  • Automatically group the files/images by their folder
  • Filter to add custom Links

What you should do

Basically, all you have to do is create the folder structure and upload your files. You need to take care that all folders you want to include are the child of one parent folder. And the files inside the parent folder don’t get included in my script. So it is only targeting the child folders! A possible setup could look like this:

Although I have some files here in my parent folder they don’t get included in the output (as seen in the image on top of that post). That’s one thing you should keep in mind!

Full Source Code

Here you can find the full source code of the snippet. I’m gonna explain the steps to take later on:

<?php
function get_happyfile_childFolders($parentSlug)
{
    $happyfile_terms = get_terms([
        "taxonomy" => HAPPYFILES_TAXONOMY,
        "hide_empty" => false,
    ]);
    
    $parentID = false;
    // GET THE ID OF THE PARENT FOLDER
    foreach ($happyfile_terms as $term) {
        if ($term->slug == $parentSlug || $term->name == $parentSlug || $term->term_id == $parentSlug) {
            $parentID = $term->term_id;
        }
    }
    
    if (!$parentID){
        return false;
    }

    $folders = [];
    foreach ($happyfile_terms as $term) {
        if ($term->parent == $parentID) {
            $term = json_decode(json_encode($term), true);
            $folders[$term["slug"]] = $term;
        }
    }
    return $folders;
}

function outputFiles($folderSlug)
{
    global $wpdb;
    $folders = get_happyfile_childFolders($folderSlug);
    
    if (!$folders){
        echo 'No Folder found, please check the passed Parameter!';
        return;
    }
    echo '<div class="downloads">';
    


    foreach ($folders as $folder) {
        $files = $wpdb->get_results(
            "SELECT * FROM {$wpdb->prefix}term_relationships WHERE term_taxonomy_id = {$folder["term_id"]}",
            OBJECT
        );
       
       // ADD CUSTOM CONTENT TO THE SPECIFIED FOLDER (via Filter)
       $customContent = [];
       $customContent = apply_filters('foldersCustomContent', $customContent, $folder['name']);
       

        echo '<div class="folder">';
        echo '<div class="folder-heading">';
        echo "<h2>{$folder["name"]}</h2>";
        echo "</div>";

        echo '<div class="folder-content">';
        foreach ($files as $file) {
            $url = wp_get_attachment_url($file->object_id);
            $title = get_the_title($file->object_id);

            echo '<div class="file">';
            echo '<i class="ti-file"></i>';

            echo "<a href='{$url}' target='_blank'>{$title}</a>";

            echo "</div>";
        }
        
        // OUTPUT CUSTOM CONTENT AFTER HAPPY-FILES FILES:
       if ( count($customContent) != 0 ) {
        foreach ($customContent as $title=>$file) {

            echo '<div class="file">';
            echo '<i class="ti-file"></i>';

            echo "<a href='{$file}' target='_blank'>{$title}</a>";

            echo "</div>";
        }           
       }        
        
        

        echo "</div></div>";
    }
    echo "</div>";
}

function outputDefaultStyles()
{
    ?>
<style>
@media only screen and (min-width: 0px) {
    :root{
      --folders-primary: #004f9e;
      --folders-textOnPrimary: white;
      --folders-linkColor: #004f9e;
      --folders-iconColor: #e1e1e1;
    }
    .downloads{
        width: 100%;
        display: flex;
        gap: 40px;
        flex-wrap: wrap;
    }
    
    /* FOLDER-WRAPPER */
    .folder{
        max-width: 100%;
        width: 100%;
        box-shadow: 0 0 20px 0 rgba(0,0,0,0.1);
        background-color: white;
    }
    .folder-heading{
        min-height: 48px;
        display: flex;
        flex-direction: column;
        justify-content: center;
        background-color: var(--folders-primary);
        padding: 0 12px;
    }
    .folder-content{
        padding: 24px;
        padding-top: 8px;
    }
    
    .folder-heading h2{
        font-size: 22px;
        color: var(--folders-textOnPrimary);
    }
    
    /* DATEIEN */
    .file{
        margin-bottom: 8px;
    }
    .file > i{
        margin-right: 5px;
        font-size: 26px;
    }
    
    .file > a{
        font-size: 18px;
        margin-left: 30px;
        position: relative;
        color: var(--folders-linkColor);
    }
    .file a:before{
        content: "";
        width: 25px;
        height: 25px;
        position: absolute;
        top: 0px;
        left: -35px;
        background-color: var(--folders-iconColor);
        -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3C!-- Font Awesome Pro 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --%3E%3Cpath d='M216 0h80c13.3 0 24 10.7 24 24v168h87.7c17.8 0 26.7 21.5 14.1 34.1L269.7 378.3c-7.5 7.5-19.8 7.5-27.3 0L90.1 226.1c-12.6-12.6-3.7-34.1 14.1-34.1H192V24c0-13.3 10.7-24 24-24zm296 376v112c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V376c0-13.3 10.7-24 24-24h146.7l49 49c20.1 20.1 52.5 20.1 72.6 0l49-49H488c13.3 0 24 10.7 24 24zm-124 88c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20zm64 0c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20z'/%3E%3C/svg%3E");
        mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3C!-- Font Awesome Pro 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --%3E%3Cpath d='M216 0h80c13.3 0 24 10.7 24 24v168h87.7c17.8 0 26.7 21.5 14.1 34.1L269.7 378.3c-7.5 7.5-19.8 7.5-27.3 0L90.1 226.1c-12.6-12.6-3.7-34.1 14.1-34.1H192V24c0-13.3 10.7-24 24-24zm296 376v112c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V376c0-13.3 10.7-24 24-24h146.7l49 49c20.1 20.1 52.5 20.1 72.6 0l49-49H488c13.3 0 24 10.7 24 24zm-124 88c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20zm64 0c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20z'/%3E%3C/svg%3E");       
    }
}


@media only screen and (min-width: 800px) {
    .folder{
        width: calc(50% - 20px);
    }
}
</style>

<?php
}

?>

How to use that snippet?

Copy that code above to your child theme’s functions.php or code execution tool of your choice.

Create a page in WordPress and open it with Bricks. Inside Bricks, you would need to use the Code element: There are two possibilities to output the files, with or without CSS styles:

With CSS styles you need to call it the following way:

outputDefaultStyles();
outputFiles( 'SLUG/NAME/ID' ); // pass the slug, name or ID of your happyfiles-parentfolder here

Updated

You can now use either the SLUG, NAME, or the ID of your HappyFiles Folder as Argument for the function “outputFiles()” as described above!

Without CSS styles you just leave out the first function outputDefaultstyles(). Then you can write your own CSS Styles to it. But I’ve provided a pre-styled possibility where you can also change the color output inside the CSS variables at the beginning of the function outputDefaultStyles();

How to adapt the Icon?

You can manually change the Icon in front of each file, all you need to do is download an Icon from FontAwesome, Bootstrap Icons or anything else and URL encode the SVG content of that file. You could use a tool like this one here: https://yoksel.github.io/url-encoder/

Once you have that URL encoded SVG you need to change that code in the provided source code. I think it’s pretty easy to localize where to change that, but just in case: inside the outputDefaultStyles() function you need to localize the line where it says .file a:before {. Then find the line with -webkit-mask-image: url( and replace the content with your icon!

Filter to add custom Content

The filter adds the possibility to add custom links inside any subfolder!

Want to have an entire Section with custom Links?

Since that filter is running inside the loop through all subfolders you would need to create an empty subfolder to create a Section with only custom links. Of course, you could also add something inside that folder, then your custom links get mixed with your folder contents!

You can call the filter inside of your code block by doing so:

add_filter( 'foldersCustomContent', function( $links, $name ) {

	// Here you can specify the foldername to which you want to add custom links.
	if ( $name != 'THE_NAME_OF_THE_FOLDER_YOU_WANT_TO_ADD_SOMETHING' ) {
		return $links;
	}
	
	$links['NAME OF THE LINK'] = 'https://example.com';
	$links['NAME OF ANOTHER LINK'] = 'https://example.com';

	return $links;
}, 10, 2);

You have access to two variables inside that function

  1. $links which is an array holding all the links of the current looped folder. Here you can add any links or even external files by doing it like I did in the example.
  2. $name which is the NAME (not the slug) of the folder you want to target. So it’s the pretty name you defined inside of HappyFiles!

That’s it. Now you’ve added custom links to your folder loop!

Downside:

The query itself could be optimized, although I didn’t recognize any performance issues you could achieve the same with wp_query instead of $wpdb!

Summary

This is definitely not a beginners article, but it should also work for beginners if you copy & paste the snippets and play around with the CSS only. I know it’s not as visual as using a page-builder, but it does its job pretty well and it saves a lot of time in managing download areas on any website. It’s super cool to use because you have to upload your files any way and with that snippets, you don’t need to think about all the different locations you need to add your uploads because that’s handled by the script! Hope you like it! 😉

Get access to all 610 Bricks code tutorials with BricksLabs Pro

4 comments

  • Marcel Bütgenbach

    Hi Wolfgang,

    an chance you happen to know if we can change or manipulate the desired order of the downloads? Not even sure, if you are still available here :)

    Othen than that, this tutorial still works pretty good <3

  • Michael Kokott

    I have set this up with wpcodebox2, but all i get on the frontpage is:

    outputDefaultStyles(); outputFiles( 'PDFs' ); // pass the slug, name or ID of your happyfiles-parentfolder here

    The code should be executed as a simple output is executed.

    Any Idea?

    Thanks

  • Amanda Lucas

    Is there a way to change the order of how things are ordered. I have the order changed in the media folder but its not outputting that way in the front end.

    • Was wondering the same. If there was a ordering mechanism, this would be very helpfull. But this tutorial itself is already awesome! Trying it out on a brand new project im just starting to work on =)

Leave a Reply to Amanda Lucas (Cancel Reply)

 

Related Tutorials..

Plain HTML pages in Bricks

Plain HTML pages in Bricks

How to output only raw HTML on the page with no other WordPress/Bricks (or any other active child/parent theme)/plugins baggage.
Pro
Oxygen’s Focus Section in Bricks

Oxygen’s Focus Section in Bricks

These are the steps to implement Focus Section, an Oxygen’s composite element, in Bricks.
Categories:
HappyFiles Bricks Query Loop

HappyFiles Bricks Query Loop

This tutorial explores different ways in which images from WordPress Media Library organized via HappyFiles can be pulled and shown in Bricks using query loop(s).…
Categories:
How to create filters with IsotopeJS in Bricks (Part 3): apply multiple filters

How to create filters with IsotopeJS in Bricks (Part 3): apply multiple filters

This tutorial will review how to apply multiple filters to an isotope container using the IsotopeJS library‘s features in Bricks.
Floats in Bricks for Wrapping Text Around Images

Floats in Bricks for Wrapping Text Around Images

In the Bricks Facebook group a user asks: Float, left or right? Just a quick question. Am I going crazy or can't I specify a…
Categories:
Tags:
Pro
Stacking Post Cards in Bricks

Stacking Post Cards in Bricks

How we can stack posts in a query loop so they stick on top of the previous one when scrolling.
Categories:
Tags:
Pro
Filtering Masonry-layout Posts by Categories in Bricks using Isotope

Filtering Masonry-layout Posts by Categories in Bricks using Isotope

Step by step on how to use Isotope in Bricks for filtering posts by categories.
Categories:
Pro
Floating Bottom Div when Scrolling Down in Bricks

Floating Bottom Div when Scrolling Down in Bricks

Creating a floating call to action element that reveals only as the user scrolls down.
Categories:
Tags: