View source
<?php
function filetree_init() {
drupal_add_css(drupal_get_path('module', 'filetree') . '/filetree.css');
drupal_add_js(drupal_get_path('module', 'filetree') . '/filetree.js');
}
function filetree_theme() {
return array(
'filetree' => array(
'arguments' => array(
'files' => array(),
'params' => array(),
),
),
);
}
function filetree_filter($op, $delta = 0, $format = -1, $text = '', $cache_id = 0) {
switch ($op) {
case 'list':
return array(
0 => t('File tree'),
);
case 'description':
return t('Replaces [filetree dir="some-directory"] with an inline list of files.');
case 'settings':
$form['filetree'] = array(
'#type' => 'fieldset',
'#title' => t('File tree'),
'#collapsible' => TRUE,
);
$form['filetree']['filetree_folders_' . $format] = array(
'#type' => 'textarea',
'#title' => t('Allowed folder paths'),
'#description' => t('Enter one folder per line as paths which are allowed to be rendered as a list of files (relative to your <a href="@url">file system path</a>). The "*" character is a wildcard. Example paths are "*", "some-folder", and "some-folder/*".', array(
'@url' => url('admin/settings/file-system'),
)),
'#default_value' => variable_get('filetree_folders_' . $format, '*'),
);
return $form;
case 'prepare':
return $text;
case 'process':
$text = _filetree_process($text, $format);
return $text;
}
}
function filetree_token_values($type, $object = NULL, $options = array()) {
$values = array();
if ($type == 'filetree') {
$pathinfo = pathinfo($object);
$values['filename'] = $pathinfo['basename'];
$values['basename'] = defined('PATHINFO_FILENAME') ? $pathinfo['filename'] : substr($object, 0, strrpos($object, '.'));
$values['extension'] = $pathinfo['extension'];
}
return $values;
}
function filetree_filter_tips($delta, $format, $long = FALSE) {
$output = t('You may use [filetree dir="some-directory"] to display a list of files inline.');
if ($long) {
$output = '<p>' . $output . '</p>';
$output .= '<p>' . t('Additional options include "multi", "controls", "absolute", "exclude", "dirname", "dirtitle", "filename", and "filetitle". For example:') . '</p>';
$output .= '<blockquote>[filetree dir="some-directory" multi="false" controls="false" absolute="false" exclude="CVS; directory1; directory2" dirname="%basename" dirtitle="Click to toggle this folder." filename="%basename" filetitle="Click to download this %extension file."]</blockquote>';
$output .= '<p>' . t('Available tokens for use within the "dirname", "dirtitle", "filename", and "filetitle" options include:') . '</p>';
$output .= theme('item_list', array(
'%filename: ' . t("The file's name and extension."),
'%basename: ' . t("The file's name, without extension."),
'%extension: ' . t("The file's extension."),
));
$output .= '<p>' . t('You can also read a <a href="http://drupal.org/project/filetree">detailed explanation of these options</a>.') . '</p>';
}
return $output;
}
function _filetree_process($text, $format) {
if (!preg_match_all('/(?:<p>)?\\[filetree\\s*(.*?)\\](?:<\\/p>)?/s', $text, $matches)) {
return $text;
}
$default_params = array(
'dir' => NULL,
'multi' => TRUE,
'controls' => TRUE,
'absolute' => TRUE,
'exclude' => array(
'CVS',
),
'dirname' => '%filename',
'dirtitle' => '%filename',
'filename' => '%filename',
'filetitle' => '%filename',
);
foreach ($matches[1] as $key => $passed_params) {
$params[$key] = $default_params;
preg_match_all('/(\\w*)=(?:\\"|")(.*?)(?:\\"|")/', $passed_params, $matches2[$key]);
foreach ($matches2[$key][1] as $param_key => $param_name) {
if (in_array($param_name, array_keys($default_params))) {
if (is_bool($default_params[$param_name])) {
$params[$key][$param_name] = $matches2[$key][2][$param_key] == "false" ? FALSE : (bool) $matches2[$key][2][$param_key];
}
else {
if ($param_name == 'exclude') {
$params[$key][$param_name] = array_filter(array_map('trim', explode(';', $matches2[$key][2][$param_key])));
}
else {
$params[$key][$param_name] = $matches2[$key][2][$param_key];
}
}
}
}
if (!$params[$key]['dir'] or !($dir = file_create_path($params[$key]['dir'])) or !drupal_match_path($params[$key]['dir'], variable_get('filetree_folders_' . $format, '*'))) {
continue;
}
$params[$key]['exclude'] = implode("\n", $params[$key]['exclude']);
foreach (array(
'dirname',
'dirtitle',
'filename',
'filetitle',
) as $token_param) {
$params[$key][$token_param] = preg_replace('/%(\\w+)/', '[$1]', $params[$key][$token_param]);
}
$files = _filetree_list_files($dir, $params[$key]);
$rendered = theme('filetree', $files, $params[$key]);
$text = str_replace($matches[0][$key], $rendered, $text);
}
return $text;
}
function _filetree_list_files($dir, $params) {
$list = array();
if (is_dir($dir) && ($handle = opendir($dir))) {
$folders = $files = array();
$descriptions = _filetree_parse_description($dir);
while (FALSE !== ($file = readdir($handle))) {
if ($file[0] != '.' and !drupal_match_path($file, $params['exclude'])) {
$filename = "{$dir}/{$file}";
if (is_dir($filename)) {
$folders[$file] = array(
'data' => isset($descriptions[$file]) ? $descriptions[$file] : token_replace($params['dirname'], 'filetree', $file),
'children' => _filetree_list_files($filename, $params),
'title' => token_replace($params['dirtitle'], 'filetree', $file),
'class' => 'folder',
);
}
else {
$name = isset($descriptions[$file]) ? $descriptions[$file] : token_replace($params['filename'], 'filetree', $file);
$url = $params['absolute'] ? file_create_url($filename) : substr(file_create_url($filename), strlen($GLOBALS['base_url'] . '/'));
$files[$file] = array(
'data' => l($name, $url),
'title' => token_replace($params['filetitle'], $file),
'class' => _filetree_icon(pathinfo($file, PATHINFO_EXTENSION)),
);
}
}
}
closedir($handle);
asort($folders);
asort($files);
$list += $folders;
$list += $files;
}
return $list;
}
function _filetree_parse_description($dir) {
$descriptions = array();
if (is_readable("{$dir}/.descript.ion") && ($file = file("{$dir}/.descript.ion"))) {
foreach ($file as $line) {
$line = trim($line);
if ($line == '' || strpos($line, '#') === 0) {
continue;
}
$matches = array();
if (strpos($line, '"') === 0) {
preg_match('/^"([^"]+)"\\s+(.*)$/', $line, $matches);
}
else {
preg_match('/^(\\S+)\\s+(.*)$/', $line, $matches);
}
list(, $name, $description) = $matches;
if (isset($descriptions[$name])) {
$descriptions[$name] .= ' ' . trim($description);
}
else {
$descriptions[$name] = trim($description);
}
}
}
return $descriptions;
}
function _filetree_icon($extension) {
$extension = strtolower($extension);
$icon = 'file';
$map = array(
'application' => array(
'exe',
),
'css' => array(
'css',
),
'db' => array(
'sql',
),
'doc' => array(
'doc',
'docx',
),
'film' => array(
'avi',
'mov',
),
'flash' => array(
'flv',
'swf',
),
'html' => array(
'htm',
'html',
),
'music' => array(
'mp3',
'aac',
),
'pdf' => array(
'pdf',
),
'php' => array(
'php',
),
'image' => array(
'jpg',
'jpeg',
'gif',
'png',
'bmp',
),
'ppt' => array(
'ppt',
),
'psd' => array(
'psd',
),
'script' => array(
'asp',
),
'txt' => array(
'txt',
),
'xls' => array(
'xls',
'xlsx',
),
'zip' => array(
'zip',
),
);
foreach ($map as $key => $values) {
foreach ($values as $value) {
if ($extension == $value) {
$icon = $key;
}
}
}
return $icon;
}
function theme_filetree($files, $params) {
$output = '';
if ($params['multi'] and $params['controls']) {
$has_folder = FALSE;
foreach ($files as $file) {
if (isset($file['children'])) {
$has_folder = TRUE;
break;
}
}
if ($has_folder) {
$controls = array(
'<a href="#" class="expand">' . t('expand all') . '</a>',
'<a href="#" class="collapse">' . t('collapse all') . '</a>',
);
$output .= theme('item_list', $controls, NULL, 'ul', array(
'class' => 'controls',
));
}
}
$output .= theme('item_list', $files, NULL, 'ul', array(
'class' => 'files',
));
$id = form_clean_id(uniqid('filetree-'));
$classes = array(
'filetree',
);
if ($params['multi']) {
$classes[] = 'multi';
}
return '<div id="' . $id . '" class="' . implode(' ', $classes) . '">' . $output . '</div>';
}