CreateIT
CreateIT
BLOG

Zip files and download all

ACF files

Zip files and download all

SHARE

CHALLENGE:
add a “Download All” button that will archive all ACF files
SOLUTION:
use the WordPress Ajax function and ZipArchive library

Advanced Custom Fields (ACF Pro) is a powerful plugin, which has the ability to define custom meta data. In our WordPress Extranet system, we have Events defined as custom post type. Attached documents are added via ACF fields. The field with the name ‘documents’ is registered as ‘repeater’ with sub_fields named ‘file’.

<?php
if( function_exists('acf_add_local_field_group') ):
acf_add_local_field_group(array(
   'key' => 'group_5ae0745f59812',
   'title' => 'Events',
   'fields' => array(
      array(
         'key' => 'field_5bc66b2ef45c1',
         'label' => 'Documents',
         'name' => 'documents',
         'type' => 'repeater',
         'sub_fields' => array(
            array(
               'key' => 'field_5bc56b94f45d4',
               'label' => 'File',
               'name' => 'file',
               'type' => 'file',
            ),
         ),
      ),
   ),
   'location' => array(
      array(
         array(
            'param' => 'post_type',
            'operator' => '==',
            'value' => 'tribe_events',
         ),
      ),
   ),
   'active' => 1,
));
endif;

Display document files

Documents can be added via the WordPress Admin Panel, after upload – the file will be added to the Media Library and saved as a serialized array in the wp_postmeta table. This PHP function displays documents attached to a particular Event:

function ct_render_downloads_acf($documents_files)
{
    // 3 per row
    $doc_rows = array();
    if (!empty($documents_files)) {
        $doc_rows = array_chunk($documents_files, 3);
    }
    if (!empty($doc_rows)):
        foreach ($doc_rows as $one_row): ?>
            <div class="row posts">
                <?php foreach ($one_row as $file): ?>
                    <?php if (!empty($file)):
                        if (is_array($file)) {
                            $file = reset($file);
                        }
                        ?>
                        <div class="thumb-wrapper col-md-4 col-xs-12">
                            <span class="date"><?php echo date('d/m/Y', strtotime($file["modified"])); ?></span>
                            <h3 class="title"><a href="<?php echo $file["url"]; ?>"
                                                 target="_blank"><?php echo $file["title"]; ?></a></h3>
                            <div class="content"><?php echo $file["description"]; ?></div>
                            <a href="<?php echo $file["url"]; ?>" class="post-link" download>Download document</a>
                        </div>
                    <?php endif; ?>
                <?php endforeach; ?>
            </div>
            <!-- / row posts -->
        <?php endforeach; ?>
    <?php else: ?>
        <div class="row posts">
            <div class="thumb-wrapper col-md-offset-4 col-md-4 col-xs-12 text-center">
                <div class="content"><p>There are no results.</p></div>
            </div>
        </div>
    <?php endif; ?>
    <?php
}
/**
 * Usage
 */
$documents_files = get_field('documents');
ct_render_downloads_acf($documents_files);

Download All button

It’s difficult to download files one by one when you have a lot of them. We’re going to add an additional button – ‘Download All’, which will find all the files defined in post meta, zip them as one archive, save to wp-content/uploads/ and trigger the downloading process in the browser.

<div class="text-center download-all-button">
  <a href="javascript:void(0);" class='btn btn-primary js-btn-download-all' data-ct_event_id="<?php echo get_the_ID(); ?>">Download All</a>
</div>

Our jQuery function will trigger the WordPress AJAX function with backend logic.

(function ($) {
   $(document).ready(function ($) {
      $('.js-btn-download-all').on('click', function (e) {
         e.preventDefault();
         var eventid = $(this).attr('data-ct_event_id');
         if (eventid) {
            $.ajax({
               url: my_ajax_object.ajax_url, type: 'POST', context: document.body, cache: false, dataType: 'text', data: {
                  action: 'ct_download_documents', event_postid: eventid
               }, success: function (data) {
                  window.location = data;
               }, error: function (e) {
                  console.log(e);
               }
            });
         }
      });
   });
})(jQuery);

PHP function to zip the files

PHP function requires the ZipArchive Library to be installed on the server. Advanced Custom Fields plugin stores all file urls as post_meta with the key ‘documents’. Those will be opened and saved as one Zip file.

/**
 * Zip all documents and trigger download
 */
add_action('wp_ajax_ct_download_documents', 'ct_download_documents');
add_action('wp_ajax_nopriv_ct_download_documents', 'ct_download_documents');
function ct_download_documents()
{
    if (isset($_POST['event_postid'])) {
        $eventID = $_POST['event_postid'];
        $files_to_zip = array();
        $event_documents = get_field('documents', $eventID);
        foreach ($event_documents as $document):
            if (!isset($document['file']['url'])) {
                continue;
            }
            $files_to_zip[] .= $document['file']['url'];
        endforeach;
        $zip = new ZipArchive();
        $destination = wp_upload_dir();
        $destination_path = $destination['basedir'];
        $DelFilePath = "document_{$eventID}.zip";
        $zip_destination_path = $destination_path . "/" . $DelFilePath;
        if (file_exists($zip_destination_path)) {
            unlink($zip_destination_path);
        }
        if ($zip->open($zip_destination_path, ZIPARCHIVE::CREATE) != TRUE) {
            die ("Could not open archive");
        }
        if ($files_to_zip) {
            foreach ($files_to_zip as $row):
                $explode = explode('uploads', $row);
                $explodes = end($explode);
                $index_files = array($destination_path, $explodes);
                $index_file = implode("", $index_files);
                $new_index_file = basename($index_file);
                $zip->addFile($index_file, $new_index_file);
            endforeach;
        }
        $zip->close();
        if (file_exists($zip_destination_path)) {
            $zip_destination_paths = explode('wp-content', $zip_destination_path);
            echo get_site_url() . "/wp-content" . end($zip_destination_paths);
        }
    }
    die();
}

That’s it, make sure to follow us for other useful tips and guidelines.

Need help?

  • Looking for support from experienced programmers?

  • Need to fix a bug in the code?

  • Want to customize your webste/application?

ADD COMMENT

Your email address will not be published.

createIT Contact