View source
<?php
include_once drupal_get_path('module', 'filefield') . '/field_file.inc';
include_once drupal_get_path('module', 'filefield') . '/filefield.widget.inc';
function filefield_menu() {
$items = array();
$items['filefield/js/upload/%/%/%'] = array(
'page callback' => 'filefield_js',
'page arguments' => array(
3,
4,
5,
'filefield_file_upload_js',
),
'access callback' => 'filefield_edit_access',
'access arguments' => array(
3,
),
'type' => MENU_CALLBACK,
'file' => 'filefield.widget.inc',
);
$items['filefield/js/delete/%/%/%'] = array(
'page callback' => 'filefield_js',
'page arguments' => array(
3,
4,
5,
'filefield_file_edit_delete_js',
),
'access callback' => 'filefield_edit_access',
'access arguments' => array(
3,
),
'type' => MENU_CALLBACK,
'file' => 'filefield.widget.inc',
);
return $items;
}
function filefield_edit_access($field_name) {
if (module_exists('content_permissions')) {
return user_access('edit ' . $field_name);
}
return user_access('access content');
}
function filefield_view_access($field_name) {
if (module_exists('content_permissions')) {
return user_access('view ' . $field_name);
}
return user_access('access content');
}
function filefield_elements() {
$elements = array();
$elements['filefield_file_upload'] = array(
'#input' => TRUE,
'#process' => array(
'filefield_file_upload_process',
),
'#element_validate' => array(),
'#value_callback' => 'filefield_file_upload_value',
'#replaced_file' => NULL,
);
$elements['filefield_file_edit'] = array(
'#input' => TRUE,
'#process' => array(
'filefield_file_edit_process',
),
'#value_callback' => 'filefield_file_edit_value',
);
$elements['filefield_generic_edit'] = array(
'#input' => TRUE,
'#process' => array(
'filefield_generic_edit_process',
),
);
return $elements;
}
function filefield_theme() {
return array(
'filefield_draggable_settings_table' => array(
'arguments' => array(
'element' => NULL,
),
'file' => 'filefield.theme.inc',
),
'filefield_container_item' => array(
'arguments' => array(
'element' => NULL,
),
'file' => 'filefield.theme.inc',
),
'filefield_icon' => array(
'arguments' => array(
'file' => NULL,
),
'file' => 'filefield.theme.inc',
),
'filefield_file_upload' => array(
'arguments' => array(
'element' => NULL,
),
'file' => 'filefield.widget.inc',
),
'filefield_file_edit' => array(
'arguments' => array(
'element' => NULL,
),
'file' => 'filefield.widget.inc',
),
'filefield_generic_edit' => array(
'arguments' => array(
'element' => NULL,
),
),
'filefield_formatter_default' => array(
'arguments' => array(
'element' => NULL,
),
'file' => 'filefield.formatter.inc',
),
'filefield_unguarded' => array(
'arguments' => array(
'file' => NULL,
'field' => NULL,
),
'file' => 'filefield.formatter.inc',
),
'filefield' => array(
'arguments' => array(
'file' => NULL,
'field' => NULL,
),
'file' => 'filefield.formatter.inc',
),
'filefield_file_formatter_generic' => array(
'arguments' => array(
'file' => NULL,
'field' => NULL,
'file_formatter_settings' => NULL,
),
'file' => 'filefield.formatter.inc',
),
);
}
function filefield_icon_url($file) {
include_once drupal_get_path('module', 'filefield') . '/filefield.theme.inc';
return _filefield_icon_url($file);
}
function filefield_file_references($file) {
$references = 0;
foreach (content_fields() as $field) {
if ($field['type'] != 'file') {
continue;
}
$references += field_file_references($file, $field);
}
return array(
'filefield' => $references,
);
}
function filefield_field_info() {
return array(
'file' => array(
'label' => 'File',
'description' => t('Store an arbitrary file.'),
),
);
}
function filefield_field_settings($op, $field) {
switch ($op) {
case 'form':
$form = array();
$form['force_list'] = array(
'#type' => 'checkbox',
'#title' => t('Always list files'),
'#default_value' => isset($field['force_list']) ? $field['force_list'] : 0,
'#description' => t('If enabled, the "List" checkbox will be hidden and files are always shown. Otherwise, the user can choose for each file whether it should be listed or not.'),
);
$form['file_formatters'] = array(
'#title' => t('File display'),
'#description' => t('Control how files may be displayed in the node view and other views for this field. If no formatters are enabled or are able to handle a file then that specific file will not be displayed. You can also reorder the formatters to specify their priority: the top-most enabled formatter always gets to display the files that it supports, whereas the bottom-most enabled formatter only gets to handle them if the file is not supported by any other other one.'),
'#weight' => 5,
'#settings_type' => 'formatters',
);
$file_formatter_info = _filefield_file_formatter_info($field);
$form['file_formatters'] = _filefield_draggable_settings_table($form['file_formatters'], $file_formatter_info, $field['file_formatters'], 'file_formatter_settings');
return $form;
case 'validate':
$file_formatter_info = _filefield_file_formatter_info($field);
foreach ($file_formatter_info as $file_formatter => $info) {
$file_formatter_settings = isset($field['file_formatters'][$file_formatter]) ? $field['file_formatters'][$file_formatter] : array();
module_invoke($info['module'], 'file_formatter_settings_' . $info['name'], 'validate', $file_formatter_settings);
}
break;
case 'save':
return array(
'force_list',
'file_formatters',
);
case 'database columns':
$columns = array(
'fid' => array(
'type' => 'int',
'not null' => FALSE,
),
'description' => array(
'type' => 'varchar',
'length' => 255,
'not null' => FALSE,
'sortable' => TRUE,
),
'list' => array(
'type' => 'int',
'size' => 'tiny',
'not null' => FALSE,
),
'data' => array(
'type' => 'text',
'serialize' => true,
),
);
return $columns;
case 'views data':
$data = content_views_field_views_data($field);
$db_info = content_database_info($field);
$table_alias = content_views_tablename($field);
unset($data[$table_alias][$field['field_name'] . '_fid']['filter']);
$data[$table_alias][$field['field_name'] . '_fid']['relationship'] = array(
'base' => 'files',
'field' => $db_info['columns']['fid']['column'],
'handler' => 'views_handler_relationship',
);
return $data;
}
}
function filefield_content_is_empty($item, $field) {
if (empty($item['fid'])) {
return TRUE;
}
return FALSE;
}
function filefield_field($op, $node, $field, &$items, $teaser, $page) {
$field_name = $field['field_name'];
switch ($op) {
case 'load':
if (empty($items)) {
return array();
}
foreach ($items as $delta => $item) {
if (empty($item['fid']) || !($file = field_file_load($item['fid']))) {
unset($items[$delta]);
}
else {
$items[$delta] = array_merge($item, $file);
}
}
$items = array_values($items);
return array(
$field_name => $items,
);
case 'insert':
case 'update':
foreach ($items as $delta => $item) {
$items[$delta] = field_file_save($node, $item);
if (empty($items[$delta])) {
unset($items[$delta]);
}
}
$items = array_values($items);
break;
case 'presave':
foreach ($items as $delta => $item) {
if (!empty($item['replaced_file'])) {
$items[] = $item['replaced_file'];
}
}
break;
case 'delete revision':
foreach ($items as $delta => $item) {
$item['field_name'] = $field['field_name'];
if (field_file_delete($item)) {
unset($items[$delta]);
}
}
$items = array_values($items);
break;
case 'delete':
foreach ($items as $delta => $item) {
$item['field_name'] = $field['field_name'];
field_file_delete($item);
}
break;
case 'sanitize':
foreach ($items as $delta => $item) {
if (empty($item['fid']) || !empty($item['delete'])) {
unset($items[$delta]);
}
else {
if (!empty($item['fid']) && empty($item['filepath'])) {
$items[$delta] = array_merge($item, field_file_load($item['fid']));
}
$items[$delta]['nid'] = $node->nid;
}
}
break;
}
}
function filefield_field_formatter_info() {
return array(
'default' => array(
'label' => t('Dynamic file formatters'),
'field types' => array(
'file',
),
'multiple values' => CONTENT_HANDLE_CORE,
),
);
}
function filefield_widget_info() {
return array(
'filefield_combo' => array(
'label' => 'File',
'field types' => array(
'file',
),
'multiple values' => CONTENT_HANDLE_CORE,
'callbacks' => array(
'default value' => CONTENT_CALLBACK_CUSTOM,
),
),
);
}
function filefield_widget_settings($op, $widget) {
switch ($op) {
case 'form':
$form = array();
$form['file_extensions'] = array(
'#type' => 'textfield',
'#title' => t('Permitted upload file extensions'),
'#default_value' => is_string($widget['file_extensions']) ? $widget['file_extensions'] : 'txt',
'#size' => 64,
'#description' => t('Extensions a user can upload to this field. Separate extensions with a space and do not include the leading dot. Leaving this blank will allow users to upload a file with any extension.'),
);
$form['file_path'] = array(
'#type' => 'textfield',
'#title' => t('File path'),
'#default_value' => is_string($widget['file_path']) ? $widget['file_path'] : '',
'#description' => t('Optional subdirectory within the "%dir" directory where files will be stored. Do not include trailing slash.', array(
'%dir' => variable_get('file_directory_path', 'files'),
)),
'#element_validate' => array(
'_filefield_widget_settings_file_path_validate',
),
);
if (module_exists('token')) {
$form['file_path']['#suffix'] = theme('token_help', 'user');
}
$form['max_filesize'] = array(
'#type' => 'fieldset',
'#title' => t('File size restrictions'),
'#description' => t('Limits for the size of files that a user can upload. Note that these settings only apply to newly uploaded files, whereas existing files are not affected.'),
'#weight' => 3,
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['max_filesize']['max_filesize_per_file'] = array(
'#type' => 'textfield',
'#title' => t('Maximum upload size per file'),
'#default_value' => is_string($widget['max_filesize_per_file']) ? $widget['max_filesize_per_file'] : '',
'#description' => t('Specify the size limit that applies to each file separately. Enter a value like "512" (bytes), "80K" (kilobytes) or "50M" (megabytes) in order to restrict the allowed file size. If you leave this this empty the file sizes will be limited only by PHP\'s maximum post and file upload sizes.'),
'#element_validate' => array(
'_filefield_widget_settings_max_filesize_per_file_validate',
),
);
$form['max_filesize']['max_filesize_per_node'] = array(
'#type' => 'textfield',
'#title' => t('Maximum upload size per node'),
'#default_value' => is_string($widget['max_filesize_per_node']) ? $widget['max_filesize_per_node'] : '',
'#description' => t('Specify the total size limit for all files in field on a given node. Enter a value like "512" (bytes), "80K" (kilobytes) or "50M" (megabytes) in order to restrict the total size of a node. Leave this empty if there should be no size restriction.'),
'#element_validate' => array(
'_filefield_widget_settings_max_filesize_per_node_validate',
),
);
$form['file_widgets'] = array(
'#title' => t('File widgets'),
'#description' => t('Control which kinds of files may be uploaded to the edit form for this field, by specifying the widgets that can handle the desired file types. You can also reorder the widgets to specify their priority: the top-most enabled widget always gets to handle the files that it supports, whereas the bottom-most enabled widget only gets to handle them if the file is not supported by any other other one.'),
'#required' => TRUE,
'#weight' => 5,
'#settings_type' => 'widgets',
);
$file_widget_info = _filefield_file_widget_info($widget);
$form['file_widgets'] = _filefield_draggable_settings_table($form['file_widgets'], $file_widget_info, $widget['file_widgets'], 'file_widget_settings');
return $form;
case 'validate':
$valid = FALSE;
foreach ($widget['file_widgets'] as $file_widget_name => $info) {
if ($info['enabled']) {
$valid = TRUE;
break;
}
}
if (!$valid) {
form_set_error('file_widgets', t('At least one type of file widgets must be enabled.'));
}
$file_widget_info = _filefield_file_widget_info($widget);
foreach ($file_widget_info as $file_widget_name => $info) {
$file_widget_settings = isset($widget['file_widgets'][$file_widget_name]) ? $widget['file_widgets'][$file_widget_name] : array();
module_invoke($info['module'], 'file_widget_settings_' . $info['name'], 'validate', $file_widget_settings);
}
break;
case 'save':
return array(
'file_extensions',
'file_path',
'max_filesize_per_file',
'max_filesize_per_node',
'file_widgets',
);
}
}
function _filefield_widget_settings_file_path_validate($element, &$form_state) {
$form_state['values']['file_path'] = trim($form_state['values']['file_path'], '\\/');
}
function _filefield_widget_settings_max_filesize_per_file_validate($element, &$form_state) {
if (empty($form_state['values']['max_filesize_per_file'])) {
return;
}
else {
if (!is_numeric(parse_size($form_state['values']['max_filesize_per_file']))) {
form_error($element, t('The "Maximum file size for each file" option must contain a valid value. You can either leave the text field empty or enter a string like "512" (bytes), "80K" (kilobytes) or "50M" (megabytes).'));
}
}
}
function _filefield_widget_settings_max_filesize_per_node_validate($element, &$form_state) {
if (empty($form_state['values']['max_filesize_per_node'])) {
return;
}
else {
if (!is_numeric(parse_size($form_state['values']['max_filesize_per_node']))) {
form_error($element, t('The "Maximum file size per node" option must contain a valid value. You can either leave the text field empty or enter a string like "512" (bytes), "80K" (kilobytes) or "50M" (megabytes).'));
}
}
}
function _filefield_draggable_settings_table($element, $file_extension_info, $extension_settings, $hook_base) {
$element['#tree'] = TRUE;
$element['#theme'] = 'filefield_draggable_settings_table';
$weight = 1;
foreach ($file_extension_info as $extension_name => $info) {
$element[$extension_name]['enabled'] = array(
'#type' => 'checkbox',
'#title' => $info['title'],
'#description' => $info['description'],
'#default_value' => $info['enabled'],
);
$element[$extension_name]['weight'] = array(
'#type' => 'weight',
'#delta' => count($file_extension_info),
'#default_value' => $weight,
);
$file_extension_settings = isset($extension_settings[$extension_name]) ? $extension_settings[$extension_name] : array();
$additions = module_invoke($info['module'], $hook_base . '_' . $info['name'], 'form', $file_extension_settings);
if (is_array($additions)) {
$element[$extension_name] = array_merge($element[$extension_name], $additions);
}
++$weight;
}
return $element;
}
function _filefield_add_css($widget_or_formatter_info) {
static $done = FALSE;
if ($done) {
return;
}
foreach ($widget_or_formatter_info as $name => $info) {
foreach ($info['css'] as $path) {
drupal_add_css($path);
}
}
}
function filefield_widget_for_file($file, $field, $field_widget) {
$file_widget_info = _filefield_file_widget_info($field_widget);
$file = (object) $file;
$suitability_args = array(
$file,
$field,
$field_widget,
);
return _filefield_extension_for_file($file_widget_info, $suitability_args);
}
function filefield_formatter_for_file($file, $field) {
$file_formatter_info = _filefield_file_formatter_info($field);
$file = (object) $file;
$suitability_args = array(
$file,
$field,
);
return _filefield_extension_for_file($file_formatter_info, $suitability_args);
}
function _filefield_extension_for_file($file_extension_info, $suitability_args) {
$suitable_extension_info = array();
foreach ($file_extension_info as $extension_name => $info) {
if (!$info['enabled']) {
continue;
}
$handles_file = $info['suitability callback'];
if (is_string($handles_file)) {
$handles_file = call_user_func_array($handles_file, $suitability_args);
}
if ($handles_file !== TRUE) {
continue;
}
$suitable_extension_info[] = $info;
}
return empty($suitable_extension_info) ? NULL : reset($suitable_extension_info);
}
function _filefield_file_widget_info($field_widget) {
$file_widget_info = _filefield_file_extension_info_original('widget');
return _filefield_file_extension_info($file_widget_info, $field_widget['file_widgets']);
}
function _filefield_file_formatter_info($field) {
$file_formatter_info = _filefield_file_extension_info_original('formatter');
return _filefield_file_extension_info($file_formatter_info, $field['file_formatters']);
}
function _filefield_file_extension_info($file_extension_info, $settings) {
foreach ($file_extension_info as $extension_name => $info) {
if (isset($settings[$extension_name]['weight'])) {
$info['weight'] = $settings[$extension_name]['weight'];
}
else {
$info['weight'] = $extension_name == 'filefield_generic' ? 1000 : 999;
}
if (isset($settings[$extension_name]['enabled'])) {
$info['enabled'] = $settings[$extension_name]['enabled'];
}
else {
$info['enabled'] = $extension_name == 'filefield_generic';
}
$file_extension_info[$extension_name] = $info;
}
return _filefield_sort_by_weight($file_extension_info);
}
function _filefield_file_extension_info_original($extension_type) {
static $file_extension_info = array();
if (!isset($file_extension_info[$extension_type])) {
$file_extension_info[$extension_type] = array();
$hook = 'file_' . $extension_type . '_info';
foreach (module_implements($hook) as $module) {
$function = $module . '_' . $hook;
$module_extension_info = $function();
foreach ($module_extension_info as $extension_name => $info) {
if ($extension_type == 'formatter') {
$info['theme'] = $module . '_file_formatter_' . $extension_name;
}
$info['module'] = $module;
$info['name'] = $extension_name;
$info['css'] = isset($info['css']) ? $info['css'] : array();
$info['key'] = $module . '_' . $extension_name;
$file_extension_info[$extension_type][$info['key']] = $info;
}
}
drupal_alter($hook, $file_extension_info[$extension_type]);
}
return $file_extension_info[$extension_type];
}
function _filefield_sort_by_weight($items) {
uasort($items, '_filefield_sort_by_weight_helper');
foreach ($items as $delta => $item) {
unset($items[$delta]['weight']);
}
return $items;
}
function _filefield_sort_by_weight_helper($a, $b) {
$a_weight = is_array($a) && isset($a['weight']) ? $a['weight'] : 0;
$b_weight = is_array($b) && isset($b['weight']) ? $b['weight'] : 0;
if ($a_weight == $b_weight) {
return 0;
}
return $a_weight < $b_weight ? -1 : 1;
}
function filefield_file_formatter_info() {
return array(
'generic' => array(
'suitability callback' => TRUE,
'title' => t('Generic files'),
'description' => t('Displays all kinds of files with an icon and a linked file description.'),
),
);
}
function filefield_file_widget_info() {
return array(
'generic' => array(
'form element' => 'filefield_generic_edit',
'suitability callback' => TRUE,
'title' => t('Generic files'),
'description' => t('An edit widget for all kinds of files.'),
),
);
}
function filefield_generic_edit_process($element, $edit, &$form_state, $form) {
$field = $element['#field'];
$delta = $element['#delta'];
$file = $element['#file'];
$url = file_create_url($file->filepath);
$prefix = isset($element['#prefix']) ? $element['#prefix'] : '';
$suffix = isset($element['#suffix']) ? $element['#suffix'] : '';
$element['#prefix'] = $prefix . '<div class="filefield-generic-edit">';
$element['#suffix'] = '</div>' . $suffix;
$element['icon'] = array(
'#type' => 'markup',
'#value' => theme('filefield_icon', $file),
);
$element['description'] = array(
'#type' => 'textfield',
'#default_value' => empty($file->description) ? $file->filename : $file->description,
'#maxlength' => 256,
'#description' => t('Size: !size. Filename: !link', array(
'!size' => format_size($file->filesize),
'!link' => l($file->filename, $url),
)),
'#required' => TRUE,
'#prefix' => '<div class="filefield-generic-edit-description">',
'#suffix' => '</div>',
);
return $element;
}
function theme_filefield_generic_edit($element) {
return theme('form_element', $element, $element['#children']);
}
function filefield_file_download($file) {
$file = file_create_path($file);
$result = db_query("SELECT * FROM {files} WHERE filepath = '%s'", $file);
if (!($file = db_fetch_object($result))) {
return;
}
$cck_files = array();
foreach (content_fields() as $field) {
if ($field['type'] == 'file') {
$db_info = content_database_info($field);
$table = $db_info['table'];
$fid_column = $db_info['columns']['fid']['column'];
$columns = array(
'vid',
'nid',
);
foreach ($db_info['columns'] as $property_name => $column_info) {
$columns[] = $column_info['column'] . ' AS ' . $property_name;
}
$result = db_query("SELECT " . implode(', ', $columns) . "\n FROM {" . $table . "}\n WHERE " . $fid_column . " = %d", $file->fid);
while ($content = db_fetch_array($result)) {
$content['field'] = $field;
$cck_files[$field['field_name']][$content['vid']] = $content;
}
}
}
if (empty($cck_files)) {
return;
}
foreach ($cck_files as $field_name => $field_files) {
if (!filefield_view_access($field_name)) {
return -1;
}
}
$nodes = array();
foreach ($cck_files as $field_name => $field_files) {
foreach ($field_files as $revision_id => $content) {
if (isset($nodes[$content['nid']])) {
continue;
}
$node = node_load($content['nid']);
if (!node_access('view', $node)) {
return -1;
}
$nodes[$content['nid']] = $node;
}
}
$name = mime_header_encode($file->filename);
$type = mime_header_encode($file->filemime);
$disposition = ereg('^(text/|image/)', $file->filemime) ? 'inline' : 'attachment';
return array(
'Content-Type: ' . $type . '; name=' . $name,
'Content-Length: ' . $file->filesize,
'Content-Disposition: ' . $disposition . '; filename=' . $name,
'Cache-Control: private',
);
}
function filefield_token_list($type = 'all') {
if ($type == 'field' || $type == 'all') {
$tokens = array();
$tokens['file']['fid'] = t("File ID");
$tokens['file']['description'] = t("File description");
$tokens['file']['filename'] = t("File name");
$tokens['file']['filepath'] = t("File path");
$tokens['file']['filemime'] = t("File MIME type");
$tokens['file']['filesize'] = t("File size (in bytes)");
$tokens['file']['filesize_formatted'] = t("File size (pretty printed)");
$tokens['file']['view'] = t("Fully formatted HTML file tag");
return $tokens;
}
}
function filefield_token_values($type, $object = NULL) {
if ($type == 'field') {
$item = $object[0];
$tokens['fid'] = $item['fid'];
$tokens['description'] = $item['description'];
$tokens['filename'] = $item['filename'];
$tokens['filepath'] = $item['filepath'];
$tokens['filemime'] = $item['filemime'];
$tokens['filesize'] = $item['filesize'];
$tokens['filesize_formatted'] = format_size($item['filesize']);
$tokens['view'] = $item['view'];
return $tokens;
}
}