to see the whole thing in action.
/*
Snippet Name: FileDownload
Short Desc: Lists files in a folder for downloading.
Created By: Kyle Jaebker
Version: 1.5
Example call: [!FileDownload?getFolder=`assets/js` &chkDesc=`fileinfo` &tplList=`FileDownload` &useHlt=`1` &evenClass=`evenrow` &oddClass=`oddrow`!]
Note: The parameter getFolder is required or you will recieve no results.
For this snippet to work correctly you must have the following files in snippet folder
In a folder named filedownload put the following files:
download.php
filedownload.inc.php
filecount.txt (if you want to use the download counter, this file can be blank to start.)
To use the filetype images you must specify the file types and the associated image in the array imgTypes.
See below for an example already filled in.
My thanks to Robin Stemp <[email protected]> for the template code example and getting the description idea going.
Thanks as well to sottwell for the idea of descriptions in a chunk.
Updated: 03/01/06 - Added template code and ability to get file description from a chunk.
03/02/06 - Added ability to include file images and changed description code for php4.
03/06/06 - Added code to only allow specified user groups to download files. Added sorting capability.
Added ability to show only certain extensions.
Added ability for logged-in user to delete files, you must specify which group.
03/08/06 - Added download counting.
Added ability to use snippet multiple times on a page.
03/22/06 - Added ability to show only one file.
Params:
&getFolder = Folder to use
&getFile = If you would like to get only one file, name it.
&tplList = chunk name to display download list
The chunk is currently split into 3 parts, separated by <hr>
1: Header
2: Each items row, or data
Placeholders to use:
[+filename+] - Displays the filename
[+description+] - Displays the description if included in a chunk
[+sizetext+] - Displays the file size
[+date+] - Displays the modified date
[+link] - Displays the download link
[+image+] - Displays the filetype image if included
[+delete+] - Displays the delete link if allowed
[+counter+] - Displays the number of times downloaded
3: Footer
&chkDesc = Chunk name that contains the file descriptions
The chunk should look like the following example (everything between the *******):
***************************************************
test.pdf|This is a test pdf. It shows report stuff.
options.gif|These are the options available to you.
***************************************************
The filename and description are seperated by a |
Each file needs to be on its own line.
&userSort = Order you would like to sort files (defaults to name): name, date, type, size
&sortOrder = Sort the files in ascending (default) or descending order: asc, desc
&showExt = Show the selected file types, leave blank for all. Default is all types.
Use a list to show multiple types: &showExt=`zip,jpg,png,doc`
&downloadGroups = Allow only certain user groups to download files, the list of files will display but
the user will get a message if they are not in the specified group.
Use a comma-delimited list in your snippet call i.e. &downloadGroups=`group1,group2`
You can change the message the user sees in the variable $loginmsg
&deleteGroups = Allow only certain user groups to delete files
Use a comma-delimited list in your snippet call i.e. &deleteGroups=`group1,group2`
You can change the message the user sees in the variables $delText,$delSuccess,$delError
&downloadCount = If you would like to track download counts set this to 1, you can use the placeholder to display the count.
&useHlt = If you want table row highlighting set to 1.
&oddClass = Set the row class for odd rows.
&evenClass = Set the Row class for the even rows.
$imgLocat = Location of folder for filetype images
Example: assets/templates/coda/images/filetype
&browseDirectories = Allows to browse through directory structure (defaults to false)
*/
/*
***************************************************
Parameters
***************************************************
*/
// Folder to get the file list from. Can be set from snippet call
$getFolder = isset($getFolder)? $getFolder : 'No Folder Specified';
// If you only want one file to be outputed. Set in snippet call
$getFile = isset($getFile)? $getFile : '';
// Template chunk for displaying list of downloads
$tplList = isset($tplList)? $tplList : '';
// Chunk for file descriptions
$chkDesc = isset($chkDesc)? $chkDesc : '';
// Sort order for files. Choices are: name, date, type, size
$userSort = isset($userSort)? $userSort : 'name';
// Sort ascending or descending. Choices are: asc, desc
$sortOrder = isset($sortOrder)? $sortOrder : 'asc';
// Show only selected filtypes. Use a comma-delimited list. i.e. `zip,jpg,txt`
$showExt = isset($showExt)? $showExt : '';
// Allow only certain groups to download files, use a comma seperated list in your snippet call, leave blank for all
$downloadGroups = isset($downloadGroups)? $downloadGroups : '';
// Allow only certain groups to delete files, use a comma seperated list in your snippet call, leave blank for none
$deleteGroups = isset($deleteGroups)? $deleteGroups : '';
// Set to 1 if you want to count the number of downloads. Use placeholder [+counter+] to show.
$downloadCount = isset($downloadCount)? $downloadCount : 0;
// Use even/Odd row highlighting? pass in 1 if you want to use the row highlighting.
$useHlt = isset($useHlt)? $useHlt : '0';
// Odd Row Class
$oddClass = isset($oddClass)? $oddClass : '';
// Even Row Class
$evenClass = isset($evenClass)? $evenClass : '';
// Location of images to use - leave blank if you do not want images
$imgLocat = isset($imgLocat)? $imgLocat : '';
// Array to set image to use for different file types
$imgTypes = array(
'jpg' => 'page_white_picture-trans.png',
'gif' => 'page_white_picture-trans.png',
'png' => 'page_white_picture-trans.png',
'pdf' => 'page_white_acrobat-trans.png',
'mp3' => 'sound-trans.png',
'txt' => 'page_white_text-trans.png',
'zip' => 'page_white_zip-trans.png',
'sit' => 'page_white_zip-trans.png',
'rar' => 'page_white_zip-trans.png',
'dmg' => 'page_white_zip-trans.png',
'folder' => 'folder-trans.png',
'parent' => 'arrow_up-trans.png',
'default' => 'page_white-trans.png'
);
// Allows to browse through directory structure
$browseDirectories = isset($browseDirectories)? $browseDirectories : FALSE;
/*
***************************************************
Language variables - you can set these to whatever you want
***************************************************
*/
$loginmsg = 'You must login to download this file.';
$delText = 'Delete'; //This can be an image as well. It will be placed inside of the delete href. Just type the whole image tag in the quotes, i.e. <img src='images/del.png' alt='Delete File'/>
$delSuccess = 'Deleted file: ';
$delError = 'There was an error deleting the file: ';
//******************************************************************************
// Do not modify below this line
//******************************************************************************
// initialize the output
$output = '';
$snippetPath = $modx->config['base_path'] . "assets/snippets/";
include_once $snippetPath."filedownload/filedownload.inc.php";
$download = "assets/snippets/filedownload/download.php";
$fileCount = "assets/snippets/filedownload/filecount.txt";
$dwnPath = base64_encode($getFolder);
if ($browseDirectories) {
$relPath = urldecode($_GET['relPath']);
// Just for safety, directory traversal should not be possible
$relPath = strtr($relPath, '../', '');
$dwnPath .= $relPath;
$currentpageid = $modx->documentObject['id'];
}
if (isset($_GET['act']) && isset($_GET['name'])) {
if ($_GET['act'] == 'del') {
$delFiles = getFiles($getFolder,$userSort,$sortOrder,$showExt);
foreach ($delFiles as $dFile) {
if ($dFile['delete'] == $_GET['name']) {
$dfilename = "{$getFolder}/{$dFile['name']}";
$delReturn = unlink($dfilename);
if ($delReturn) {
$output .= "<p>{$delSuccess}{$dFile['name']}</p>";
} else {
$output .= "<p>{$delError}{$dFile['name']}</p>";
}
break;
}
}
}
}
/*
***************************************************
Create the Output
***************************************************
*/
// Prepare the template for displaying
if ($tplList=='') {
$tpl = getTemplateArray(getDownloadListTpl());
} else {
$tpl = getTemplateArray($modx->getChunk($tplList));
}
$files = getFiles($getFolder.$relPath,$userSort,$sortOrder,$showExt,$getFile);
// Add the header from the template
if ($browseDirectories) {
$tpl['header'] = str_replace('[+path+]', ($relPath ? $relPath : '/'), $tpl['header']);
}
$strTpl = $tpl['header'];
if (is_array($files)) {
// Get the description information if a chunk is specified.
if ($chkDesc !== '') {
$descrip = $modx->getChunk($chkDesc);
$aDesc = explode("\n", $descrip);
foreach ($aDesc as $fileDesc) {
$fileInfo = explode("|", $fileDesc);
foreach ( array_keys($files) as $key ) {
$myFile =& $files[$key];
if ($myFile['name'] == $fileInfo[0]) {
$myFile['description'] = $fileInfo[1];
break;
}
}
}
}
// Add the count information if specified.
if ($downloadCount) {
if(!$handle = fopen($fileCount,'r+')) {
return "file open failed: $fileCount";
} else {
$i = 0;
while ((list($fname,$count) = fgetcsv($handle, 1000)) !== FALSE) {
$arCount[$i]['name'] = $fname;
$arCount[$i]['count'] = $count;
$i++;
}
fclose($handle);
}
foreach ( $arCount as $fCount ) {
foreach ( array_keys($files) as $key ) {
$myFile =& $files[$key];
if ($myFile['name'] == $fCount['name']) {
$myFile['count'] = $fCount['count'];
break;
}
}
}
}
// Add the file images if specified
if ($imgLocat !== '') {
foreach ( array_keys($files) as $key ) {
$myFile =& $files[$key];
$extension = substr($myFile['name'], -(strrpos('.',$myFile['name'])));
foreach ($imgTypes as $imgtype => $image) {
if (stristr($extension,$imgtype)) {
$myFile['image'] = $image;
break;
} else {
$myFile['image'] = $imgTypes['default'];
}
}
}
}
$canDownload = $downloadGroups=='' || $modx->isMemberOfWebGroup(explode(",", $downloadGroups));
$canDelete = $modx->isMemberOfWebGroup(explode(",", $deleteGroups));
$i = 0;
$fields = array('[+filename+]','[+sizetext+]','[+description+]','[+date+]','[+image+]','[+link+]','[+counter+]');
// Create link to parent directory
if ($relPath) {
$tpl2 = $tpl['row'];
if ($useHlt) {
if ($i++ & 1) {
$tpl2 = str_replace("<tr>","<tr class='$oddClass'>",$tpl2);
} else {
$tpl2 = str_replace("<tr>","<tr class='$evenClass'>",$tpl2);
}
}
$date = date('Y-m-d H:i', filemtime($_SERVER['DOCUMENT_ROOT'] . '/' . $getFolder.$relPath));
$relPathParts = explode('/', $relPath);
array_pop($relPathParts);
$fileImage = "<img src='{$imgLocat}/{$imgTypes['parent']}' alt='' />";
$fileLink = '[~' . $currentpageid . '~]' . (count($relPathParts)>1 ? '?relPath=' . implode('/', $relPathParts) : '');
$values = array('../','-','',$date,$fileImage,$fileLink,'');
$tpl2 = str_replace($fields, $values, $tpl2);
$strTpl .= $tpl2;
}
// Create each files output.
foreach ($files as $file) {
$tpl2 = $tpl['row'];
if ($useHlt) {
if ($i++ & 1) {
$tpl2 = str_replace("<tr>","<tr class='$oddClass'>",$tpl2);
} else {
$tpl2 = str_replace("<tr>","<tr class='$evenClass'>",$tpl2);
}
}
$fileImage = "<img src='{$imgLocat}/{$file['image']}' alt='' />";
if ($canDownload) {
if ($downloadCount) {
$fileLink = "{$download}?path={$dwnPath}&fileName={$file['name']}";
} else {
if (!is_dir($_SERVER['DOCUMENT_ROOT'] . '/' . $getFolder.$relPath . '/' . $file['name'])) {
$fullPath = $getFolder.$relPath;
$fileLink = "{$fullPath}/{$file['name']}";
} else {
$fileLink = '[~' . $currentpageid . '~]' . '?relPath=' . $relPath . '/' .
urlencode($file['name']);
$fileImage = "<img src='{$imgLocat}/{$imgTypes['folder']}' alt='' />";
$file['sizetext'] = '-';
$file['name'] = '<em>' . $file['name'] . '</em>';
}
}
} else {
$fileLink = "javascript:alert('$loginmsg')";
}
$values = array($file['name'],$file['sizetext'],$file['description'],$file['date'],$fileImage,$fileLink,$file['count']);
$tpl2 = str_replace($fields, $values, $tpl2);
if ($canDelete) {
$tpl2 = str_replace("[+delete+]","<a href='[~[*id*]~]?act=del&name={$file['delete']}'>{$delText}</a>",$tpl2);
} else {
$tpl2 = str_replace("[+delete+]","",$tpl2);
}
$strTpl .= $tpl2;
}
} else {
$tpl2 = $tpl['row'];
$tpl2 = str_replace("[+filename+]",$files,$tpl2);
$strTpl .= $tpl2;
}
// Add the footer from the template
$strTpl .= $tpl['footer'];
$output .= $strTpl;
/*
***************************************************
Output file list
***************************************************
*/
return $output;