Newer
Older
<?php
// $Id$
/**
* @file
* Defines a file field type.
*
* uses content.module to store the fid, and the drupal files
* table to store the actual file data.
*
* @todo
* - access control
*/
function filefield_menu($maycache) {
$items = array();
// Add handlers for previewing new uploads.
if ($_SESSION['filefield']) {
foreach ($_SESSION['filefield'] as $fieldname => $files) {
foreach($files as $delta => $file) {
$filename = file_create_filename($file['filename'], file_create_path());
// strip file_directory_path() from private downloads path. @see file_create_url
if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PRIVATE) {
if (strpos($filename, file_directory_path()) !== false) {
$filename = trim(substr($filename, strlen(file_directory_path())), '\\/');
}
$filename = 'system/files/' . $filename;
}
$items[] = array(
'path' => $filename, 'title' => t('file download'),
'callback' => '_filefield_preview',
'access' => TRUE,
'type' => MENU_CALLBACK
);
$file['preview'] = $filename;
$_SESSION['filefield'][$fieldname][$delta] = $file;
}
}
}
//drupal_set_message('SESSION @ hook_menu: <pre>'. print_r($_SESSION['filefield'], true) .'</pre>');
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
return $items;
}
/**
* transfer a file that is in a 'preview' state.
* @todo multiple support
*/
function _filefield_preview() {
foreach ($_SESSION['filefield'] as $fieldname => $files) {
foreach ($files as $delta => $file) {
if ($file['preview'] == $_GET['q']) {
file_transfer($file['filepath'], array('Content-Type: '. mime_header_encode($file['filemime']),
'Content-Length: '. $file['filesize']));
exit();
}
}
}
}
/**
* Implementation of hook_field_info().
*/
function filefield_field_info() {
return array(
'file' => array('label' => 'file'),
);
}
/**
* Implementation of hook_field_settings().
*/
function filefield_field_settings($op, $field) {
switch ($op) {
case 'form':
$form = array();
return $form;
case 'save':
return array();
case 'database columns':
$columns = array(
'fid' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'),
'description' => array('type' => 'varchar', length => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
Darrel O'Pry
committed
'list' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'),
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
);
return $columns;
}
}
/**
* insert a file into the database.
* @param $node
* node object file will be associated with.
* @param $file
* file to be inserted, passed by reference since fid should be attached.
*
*/
function filefield_file_insert($node, &$file, $field) {
$fieldname = $field['field_name'];
if ($file = file_save_upload((object)$file, file_directory_path() . '/'.$file['filename'])) {
$file = (array)$file;
$file['fid'] = db_next_id('{files}_fid');
db_query('INSERT into {files} (fid, nid, filename, filepath, filemime, filesize)
VALUES (%d, %d, "%s","%s","%s",%d)',
$file['fid'], $node->nid, $file['filename'], $file['filepath'], $file['filemime'], $file['filesize']);
return (array)$file;
}
else {
// Include file name in upload error.
form_set_error(NULL, t('file upload was unsuccessful.'));
return FALSE;
}
}
/**
* update the file record if necessary
* @param $node
* @param $file
* @param $field
*/
function filefield_file_update($node, &$file, $field) {
$file = (array)$file;
//drupal_set_message(' filefield_file_update: <pre>'. print_r($file, true) .'</pre>');
Darrel O'Pry
committed
if ($file['remove'] == TRUE) {
_filefield_file_delete($file, $field['field_name']);
return NULL;
}
if ($file['fid'] == 'upload') {
return filefield_file_insert($node, $file, $field);
}
else {
// if fid is not numeric here we should complain.
// else we update the file table.
}
return $file;
}
/**
* Implementation of hook_field().
*/
function filefield_field($op, $node, $field, &$node_field, $a1, $a2) {
$fieldname = $field['field_name'];
switch ($op) {
case 'load':
$output = array();
if (count($node_field)) {
$values = array();
foreach ($node_field as $delta => $file) {
if (!empty($file)) {
$values[$delta] = array_merge($node_field[$delta], _filefield_file_load($file['fid']));
$node_field[$delta] = $values[$delta];
}
$output = array($fieldname => $values);
Darrel O'Pry
committed
}
}
break;
case 'view':
Darrel O'Pry
committed
$files = array();
foreach ($node_field as $delta => $item) {
Darrel O'Pry
committed
if (!$item['remove'] && $item['list']) {
$node_field[$delta]['view'] = content_format($field, $item, ($page ? 'default' : 'preview'));
$output = theme('field', $node, $field, $node_field, $a1, $a2);
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
break;
// called before content.module defaults.
case 'insert':
foreach ($node_field as $delta => $item) {
$node_field[$delta] = filefield_file_insert($node, $item, $field);
}
break;
// called before content.module defaults.
case 'update':
foreach ($node_field as $delta => $item) {
$node_field[$delta] = filefield_file_update($node, $item, $field);
}
break;
case 'delete':
foreach ($node_field as $delta => $item) {
_filefield_file_delete($item, $field['field_name']);
}
break;
}
return $output;
}
/**
* Implementation of hook_widget_info().
*/
function filefield_widget_info() {
return array(
'file' => array(
'label' => 'File',
'field types' => array('file'),
),
);
}
/**
* Implementation of hook_widget_settings().
*/
function filefield_widget_settings($op, $widget) {
switch ($op) {
case 'form':
$form = array();
Darrel O'Pry
committed
$form['file_extensions'] = array (
'#type' => 'textfield',
Darrel O'Pry
committed
'#title' => t('Permitted upload file extensions.'),
'#default_value' => $widget['file_extensions'] ? $widget['file_extensions'] : 'txt',
'#size' => 64,
'#maxlength' => 64,
'#description' => t('Extensions a user can upload to this field. Seperate extensions with a space and do not include the leading dot.')
);
return $form;
case 'validate':
break;
case 'save':
Darrel O'Pry
committed
return array('file_extensions');
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
}
}
function filefield_clear_session() {
if (is_array($_SESSION['filefield']) && count($_SESSION['filefield'])) {
foreach (array_keys($_SESSION['filefield']) as $fieldname) {
filefield_clear_field_session($fieldname);
}
unset($_SESSION['filefield']);
}
}
function filefield_clear_field_session($fieldname) {
if (count($_SESSION['filefield'][$fieldname])) {
foreach ($_SESSION['filefield'][$fieldname] as $files) {
foreach ($files as $delta => $file) {
if (is_file($file['filepath'])) {
file_delete($file['filepath']);
}
}
}
unset($_SESSION['filefield'][$fieldname]);
}
}
function _filefield_file_delete($file, $fieldname) {
//drupal_set_message(' _filefield_file_delete: <pre>'. print_r($file, true) .'</pre>');
if (is_numeric($file['fid'])) {
db_query('DELETE FROM {files} WHERE fid = %d', $file['fid']);
}
else {
unset($_SESSION['filefield'][$fieldname][$file['sessionid']]);
}
return file_delete($file['filepath']);
}
/**
* Implementation of hook_widget().
*/
function filefield_widget($op, $node, $field, &$node_field) {
//drupal_set_message('pre filefield_widget: '. $op .'<pre>'. print_r($node_field, true) .'</pre>');
$fieldname = $field['field_name'];
switch ($op) {
case 'prepare form values':
if (!count($_POST)) {
filefield_clear_session();
}
// Attach new files
if ($file = file_check_upload($fieldname . '_upload')) {
$file = (array)$file;
// test allowed extensions. We do this when the file is uploaded, rather than waiting for the
// field itseld to reach op==validate.
$ext = array_pop(explode('.',$file['filename']));
Darrel O'Pry
committed
$allowed_extensions = array_unique(explode(' ', trim($field['widget']['file_extensions'])));
if (in_array($ext, $allowed_extensions)) {
}
else {
form_set_error($field['field_name'] .'_upload',t('Files with the extension %ext are not allowed. Please upload a file with an extension from the following list: %allowed_extensions', array('%ext' => $ext, '%allowed_extensions' => $field['widget']['file_extensions'])));
Darrel O'Pry
committed
return FALSE;
$file['fid'] = 'upload';
if (!$field['multiple']) {
// Remove old temporary file from session.
filefield_clear_field_session($fieldname);
}
$file['sessionid'] = count($_SESSION['filefield'][$fieldname]);
$_SESSION['filefield'][$fieldname][$file['sessionid']] = $file;
}
// Load files from preview state. before committing actions.
/* commented out until cck prepare form values / node_field situation is worked out
if (is_array($_SESSION['filefield'][$fieldname]) && count($_SESSION['filefield'][$fieldname])) {
foreach($_SESSION['filefield'][$fieldname] as $delta => $file) {
$node_field[] = $file;
}
}
break;
case 'form':
if (is_array($_SESSION['filefield'][$fieldname]) && count($_SESSION['filefield'][$fieldname])) {
foreach($_SESSION['filefield'][$fieldname] as $delta => $file) {
$node_field[] = $file;
}
}
$form = _filefield_widget_form($node, $field, $node_field);
return $form;
case 'validate':
if ($field['required']) {
if (!count($node_field)) {
form_set_error($fieldname, $field['widget']['label'] .' is required.');
}
}
return;
}
//drupal_set_message('post filefield_widget: '. $op .'<pre>'. print_r($node_field, true) .'<pre>');
}
function _filefield_widget_form($node, $field, &$node_field) {
$fieldname = $field['field_name'];
drupal_add_css(drupal_get_path('module', 'filefield') .'/filefield.css');
$form = array();
$form[$fieldname] = array(
'#type' => 'fieldset',
'#title' => t($field['widget']['label']),
'#weight' => $field['widget']['weight'],
'#collapsible' => TRUE,
'#collapsed' => FALSE,
'#tree' => TRUE,
'#theme' => 'filefield_current',
$form[$fieldname][$fieldname .'_upload'] = array(
'#type' => 'file',
'#description' => $field['widget']['description'] . t('<br />allowed extensions(%ext)', array('%ext' => $field['widget']['file_extensions'])),
'#weight' => 9,
'#tree' => FALSE,
);
$form[$fieldname]['Update'] = array(
'#type' => 'button',
'#value' => t('Update'),
'#name' => 'cck_filefield_'.$fieldname.'_op',
'#attributes' => array('id' => $fieldname.'-attach-button'),
'#tree' => FALSE,
'#weight' => 10,
);
Darrel O'Pry
committed
if (is_array($node_field) && count($node_field)) {
foreach($node_field as $delta => $file) {
$form[$fieldname][$delta]['icon'] = array(
'#type' => 'markup',
if (strpos($file['fid'], 'upload') === false) {
$filepath = $file['filepath'];
}
else {
$filepath = file_create_filename($file['filename'], file_create_path());
}
$description = file_create_url($filepath);
$description = "<small>". check_plain($description) ."</small>";
$form[$fieldname][$delta]['description'] = array('#type' => 'textfield', '#default_value' => (strlen($file['description'])) ? $file['description'] : $file['filename'], '#maxlength' => 256, '#description' => $description );
$form[$fieldname][$delta]['size'] = array('#type' => 'markup', '#value' => format_size($file['filesize']));
$form[$fieldname][$delta]['remove'] = array('#type' => 'checkbox', '#default_value' => $file['remove']);
$form[$fieldname][$delta]['list'] = array('#type' => 'checkbox', '#default_value' => $file['list']);
$form[$fieldname][$delta]['filename'] = array('#type' => 'value', '#value' => $file['filename']);
$form[$fieldname][$delta]['filepath'] = array('#type' => 'value', '#value' => $file['filepath']);
$form[$fieldname][$delta]['filemime'] = array('#type' => 'value', '#value' => $file['filemime']);
$form[$fieldname][$delta]['filesize'] = array('#type' => 'value', '#value' => $file['filesize']);
$form[$fieldname][$delta]['fid'] = array('#type' => 'value', '#value' => $file['fid']);
// Special handling for single value fields
// mark original item for deletion.
if (!$field['multiple'] && $delta == 0) {
$form[$fieldname][$delta]['remove']['#value'] = 1;
$form[$fieldname][$delta]['replace'] = array(
'#type' => 'markup',
'#value' => t('If a new file is uploaded, this file will be replaced upon submitting this form.'),
);
Darrel O'Pry
committed
}
}
//drupal_set_message('filefield_form('. $fieldname .'): <pre>'. print_r($form, TRUE) .'</pre>');
return $form;
}
Darrel O'Pry
committed
function theme_filefield_current(&$form) {
$header = array(t('Type'), t('Description'), t('Size'), t('List'), t('Delete'));
//drupal_set_message('form: <pre>'. print_r($form, TRUE) .'</pre>');
Darrel O'Pry
committed
foreach (element_children($form) as $key) {
//drupal_set_message($key);
//only display numerically keyed fields in form.
//numeric key == $delta
if (is_numeric($key)) {
$row = array();
$row[] = drupal_render($form[$key]['icon']);
$row[] = drupal_render($form[$key]['description']);
$row[] = drupal_render($form[$key]['size']);
$row[] = drupal_render($form[$key]['list']);
$row[] = drupal_render($form[$key]['remove']);
$rows[] = $row;
}
}
if (count($rows)) {
$output = theme('table', $header, $rows);
Darrel O'Pry
committed
}
$output .= drupal_render($form);
Darrel O'Pry
committed
return $output;
}
/**
* Implementation of hook_field formatter.
* @todo: finish transformer.module and integrate like imagecache with imagefield.
*/
function filefield_field_formatter_info() {
$formatters = array(
'default' => array(
'label' => t('Default'),
'field types' => array('file'),
),
);
return $formatters;
}
function filefield_field_formatter($field, $item, $formatter) {
if(!isset($item['fid'])) {
return '';
}
$file = _filefield_file_load($item['fid']);
return theme('filefield', $file, $item);
}
/*
deprecated dodo delete when we're sure its safe to go.
function filefield_field_view_item($field, $node_field_item) {
$file = _filefield_file_load($node_field_item['fid']);
return theme('filefield_view_file', $file, $node_field_item['description']);
function _filefield_file_load($fid = NULL) {
if (isset($fid)) {
if (is_numeric($fid)) {
$result = db_query('SELECT * FROM {files} WHERE fid = %d', $fid);
$file = db_fetch_array($result);
return ($file) ? $file : array();
}
function theme_filefield_icon($file) {
$ext = array_pop(explode('.',$file['filename']));
Darrel O'Pry
committed
$known_extensions = array('0','ace','aif','ai','ani','asf','asp','avi','bak','bat','bin','bmp','bz2','bz','cab','cdr','cfg','com','conf','cpt','css','cur','dat','db','dcr','dic','diff','dir','dll','dmg','doc','dwg','edir','eml','eps','exe','fla','flv','fon','gif','gz','hqx','html','htm','ico','inc','ini','iso','jpeg','jpg','js','lnk','log','m3u','mdb','midi','mid','mov','mp3','mpeg','mpg','nfo','odb','odc','odf','odg','odm','odp','ods','odt','ogg','otg','oth','otp','ots','ott','patch','pdf','php3','php','phtml','pl','png','pps','ppt','psd','pwl','qt','ram','ra','rar','reg','rpm','rtf','sh','shtml','sit','sql','svg','swf','sxc','sxi','sxw','sys','tar','tgz','tiff','tif','tmp','tpl','ttf','txt','wav','wma','wmv','wp','xls','xml','zip');
if (!in_array($ext, $known_extensions)) {
$ext = 0;
}
$imagepath = drupal_get_path('module','filefield') .'/ico/'. $ext .'.png';
return '<div class="filefield-icon-container"><div class="filefield-icon field-icon-'. $ext .'"><img src="'. $imagepath .'" /></div></div>';
//return '<div class="filefield-icon-container"><div class="filefield-icon field-icon-'. $ext .'"> </div></div>'."\n";
function theme_filefield_view_file($file) {
Darrel O'Pry
committed
return theme('filefield', $file);
Darrel O'Pry
committed
function theme_filefield($file) {
$file = (array)$file;
if (is_file($file['filepath'])) {
if ($file['fid'] == 'upload') {
$path = file_create_filename($file['filename'], file_create_path());
}
else {
$path = $file['filepath'];
}
$url = file_create_url($path);
$name = $file['filename'];
$desc = $file['description'];
return '<a href="'. check_url($url) .'">'.check_plain($name).'</a>';
}
}