diff --git a/field_file.inc b/field_file.inc
index ab68ee0b2215b36c6bdf95060a6eab945f06e474..1d7f851f4ed7bd0baaf8de87d153021dfcc5742b 100644
--- a/field_file.inc
+++ b/field_file.inc
@@ -12,6 +12,10 @@
function field_file_load($fid, $reset = NULL) {
static $files = array();
+ if (empty($fid)) {
+ return FALSE;
+ }
+
// Reset internal cache.
if ($reset) {
$files = array();
@@ -29,6 +33,10 @@ function field_file_load($fid, $reset = NULL) {
$file = db_fetch_object(db_query("SELECT f.* FROM {files} f WHERE f.filepath = '%s'", $fid));
}
+ if (!$file) {
+ return FALSE;
+ }
+
module_invoke_all('file', 'load', $file);
// Cache the fully loaded value by both fid and filepath.
@@ -110,7 +118,6 @@ function field_file_delete($file, $force = FALSE) {
*
* Check that the directory exists and is writable. Directories need to
* have execute permissions to be considered a directory by FTP servers, etc.
- *
*
* @param $directory A string containing the name of a directory path.
* @param $mode A Boolean value to indicate if the directory should be created
@@ -166,4 +173,14 @@ function field_file_check_directory(&$directory, $mode = 0, $form_item = NULL) {
return TRUE;
}
-
+/**
+ * Remove a possible leading file directory path from the given path.
+ */
+function field_file_strip_path($path) {
+ $dirpath = file_directory_path();
+ $dirlen = strlen($dirpath);
+ if (substr($path, 0, $dirlen + 1) == $dirpath .'/') {
+ $path = substr($path, $dirlen + 1);
+ }
+ return $path;
+}
diff --git a/filefield.module b/filefield.module
index 6fcb7109dac962862d9818f349ddeee6c427ecd9..9931a5f31bb9e11fdce57202043e3075f7103b72 100644
--- a/filefield.module
+++ b/filefield.module
@@ -5,25 +5,26 @@
* @file
* Defines a file field type.
*
- * uses content.module to store the fid, and the drupal files
- * table to store the actual file data.
+ * Uses content.module to store the fid, and Drupal's {files} table
+ * to store the actual file data.
*/
-define('FILEFIELD_MINIMUM_PHP', '5.2');
+include_once(drupal_get_path('module', 'filefield') .'/field_file.inc');
-function filefield_menu($may_cache) {
+/**
+ * Implementation of hook_menu().
+ */
+function filefield_menu() {
$items = array();
- if ($may_cache) {
- $items[] = array(
- 'path' => 'filefield/js',
- 'callback' => 'filefield_js',
- //'access' => user_access(),
- 'access' => TRUE,
- 'type' => MENU_CALLBACK
- );
- }
- else if ($_SESSION['filefield']) {
+ $items['filefield/js'] = array(
+ 'page callback' => 'filefield_js',
+ 'access arguments' => array('view content'),
+ 'type' => MENU_CALLBACK,
+ );
+
+ /*
+ if ($_SESSION['filefield']) {
// Add handlers for previewing new uploads.
foreach ($_SESSION['filefield'] as $fieldname => $files) {
if (is_array($files)) {
@@ -40,31 +41,41 @@ function filefield_menu($may_cache) {
}
}
}
+ */
+
return $items;
}
/**
- * Implementation of hook_requirements().
+ * Implementation of hook_perm().
*/
-function filefield_requirements($phase) {
- $requirements = array();
- // Ensure translations don't break at install time
- $t = get_t();
-
- if (version_compare(phpversion(), FILEFIELD_MINIMUM_PHP) < 0) {
- $requirements['filefield_php'] = array(
- 'title' => $t('FileField PHP'),
- 'description' => $t('FileField requires at least PHP %version.', array('%version' => FILEFIELD_MINIMUM_PHP)),
- 'severity' => REQUIREMENT_ERROR
- );
- }
+function filefield_perm() {
+ return array('view filefield uploads');
+}
- return $requirements;
+/**
+ * Implementation of hook_theme().
+ */
+function filefield_theme() {
+ return array(
+ 'filefield_combo' => array(
+ 'arguments' => array('element' => NULL),
+ ),
+ 'filefield_formatter_default' => array(
+ 'arguments' => array('element' => NULL),
+ ),
+ 'filefield' => array(
+ 'arguments' => array('file' => NULL),
+ ),
+ 'filefield_icon' => array(
+ 'arguments' => array('file' => NULL),
+ ),
+ );
}
/**
- * transfer a file that is in a 'preview' state.
- * @todo multiple support
+ * Transfer a file that is in a 'preview' state.
+ * @todo multiple support
*/
function _filefield_preview() {
foreach ($_SESSION['filefield'] as $fieldname => $files) {
@@ -78,16 +89,15 @@ function _filefield_preview() {
}
}
-function filefield_perm() {
- return array('view filefield uploads');
-}
-
/**
* Implementation of hook_field_info().
*/
function filefield_field_info() {
return array(
- 'file' => array('label' => 'File'),
+ 'file' => array(
+ 'label' => 'File',
+ 'description' => t('Store an arbitrary file.'),
+ ),
);
}
@@ -114,153 +124,73 @@ function filefield_field_settings($op, $field) {
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),
- 'list' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'),
+ '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),
);
return $columns;
-
- case 'filters':
- return array(
- 'not null' => array(
- 'operator' => array('=' => t('Has file')),
- 'list' => 'views_handler_operator_yesno',
- 'list-type' => 'select',
- 'handler' => 'filefield_views_handler_filter_is_not_null',
- ),
- );
-
}
}
-function filefield_default_item() {
- return array(
- 'fid' => 0,
- 'description' => '',
- 'list' => 0,
- );
-}
-
/**
- * 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, $field, &$file) {
- $fieldname = $field['field_name'];
-
- // allow tokenized paths.
- if (function_exists('token_replace')) {
- global $user;
- $widget_file_path = token_replace($field['widget']['file_path'], 'user', $user);
- }
- else {
- $widget_file_path = $field['widget']['file_path'];
- }
-
- $filepath = file_create_path($widget_file_path) . '/' . $file['filename'];
-
- if (filefield_check_directory($widget_file_path) && $file = file_save_upload((object)$file, $filepath)) {
- $file = (array)$file;
- $file['fid'] = db_next_id('{files}_fid');
- $file['filemime'] = mimedetect_mime($file);
- 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']);
- module_invoke_all('filefield', 'file_save', $node, $field, $file);
- 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
+ * Implementation of hook_content_is_empty().
+ *
+ * The result of this determines whether content.module will save
+ * the value of the field.
*/
-function filefield_file_update($node, $field, &$file) {
- $file = (array)$file;
- if ($file['delete'] == TRUE) {
- // don't delete files if we're creating new revisions,
- // but still return an empty array...
- if ($node->old_vid) {
- return array();
- }
- if (_filefield_file_delete($node, $field, $file)) {
- return array();
- }
- }
- if ($file['fid'] == 'upload') {
- return filefield_file_insert($node, $field, $file);
+function filefield_content_is_empty($item, $field) {
+ if (empty($item['fid'])) {
+ return TRUE;
}
- else {
- // if fid is not numeric here we should complain.
- // else we update the file table.
- }
- return $file;
+ return FALSE;
}
/**
* Implementation of hook_field().
*/
-function filefield_field($op, &$node, $field, &$items = array()) {
+function filefield_field($op, $node, $field, &$items, $teaser, $page) {
$fieldname = $field['field_name'];
+
switch ($op) {
- // called after content.module loads default data.
+ // Called after content.module loads default data.
case 'load':
- if (is_array($items)) {
- $items = array_filter($items); // drop empty deltas, cuz cck sends 'em some times.
- }
if (empty($items)) {
return array();
}
foreach ($items as $delta => $item) {
- if (!empty($item['fid'])) { // otherwise, merge our info with CCK's, and all is fine.
- $items[$delta] = array_merge($item, _filefield_file_load($item['fid']));
+ // Despite hook_content_is_empty(), CCK still doesn't filter out
+ // empty items from $op = 'load', so we need to do that ourselves.
+ if (empty($item['fid']) || !($file = field_file_load($item['fid']))) {
+ unset($items[$delta]);
+ }
+ else {
+ $items[$delta] = array_merge($item, $file);
}
}
$items = array_values($items); // compact deltas
return array($fieldname => $items);
- // called before content.module defaults.
case 'insert':
+ case 'update':
foreach ($items as $delta => $item) {
- $items[$delta] = filefield_file_insert($node, $field, $item);
+ $items[$delta] = field_file_save($node, $item);
}
$items = array_values($items); // compact deltas
- filefield_clear_field_session($fieldname);
break;
- // called before content.module defaults.
- case 'update':
+ case 'presave':
+ // When saving a file for the first time, if there is no description set,
+ // default it to the file name. Same for being listed by default.
foreach ($items as $delta => $item) {
- $items[$delta] = filefield_file_update($node, $field, $item);
+ if ($item['status'] == FILE_STATUS_TEMPORARY && !$item['description']) {
+ $items[$delta]['description'] = $items[$delta]['filename'];
+ $items[$delta]['list'] = 1;
+ }
}
- $items = array_filter($items); // unset empty items.
- $items = array_values($items); // compact deltas
- filefield_clear_field_session($fieldname);
break;
-
case 'delete revision':
- $db_info = content_database_info($field);
foreach ($items as $delta => $item) {
- $references = db_result(db_query(
- "SELECT COUNT(vid) FROM {" . $db_info['table'] . "}
- WHERE nid = %d AND vid != %d
- AND " . $db_info['columns']['fid']['column'] . " = %d",
- $node->nid, $node->vid, $item['fid']
- ));
- if ($references || _filefield_file_delete($node, $field, $item)) {
+ if (field_file_delete($item)) {
$items[$delta] = array();
}
}
@@ -269,7 +199,24 @@ function filefield_field($op, &$node, $field, &$items = array()) {
case 'delete':
foreach ($items as $delta => $item) {
- _filefield_file_delete($node, $field, $item);
+ field_file_delete($item);
+ }
+ break;
+
+ case 'sanitize':
+ foreach ($items as $delta => $item) {
+ // Cleanup $items during node preview.
+ if (empty($item['fid']) || !empty($item['delete'])) {
+ unset($items[$delta]);
+ }
+ else {
+ // Load the complete file if a filepath is not available.
+ if (!empty($item['fid']) && empty($item['filepath'])) {
+ $items[$delta] = array_merge($item, field_file_load($item['fid']));
+ }
+ // Add nid so formatters can create a link to the node.
+ $items[$delta]['nid'] = $node->nid;
+ }
}
break;
}
@@ -280,38 +227,56 @@ function filefield_field($op, &$node, $field, &$items = array()) {
*/
function filefield_widget_info() {
return array(
- 'file' => array(
+ 'filefield_combo' => array(
'label' => 'File',
'field types' => array('file'),
+ 'multiple values' => CONTENT_HANDLE_CORE,
+ 'callbacks' => array('default value' => CONTENT_CALLBACK_CUSTOM),
),
);
}
+/**
+ * Implementation of hook_widget().
+ */
+function filefield_widget(&$form, &$form_state, $field, $items, $delta = 0) {
+ $form['#attributes']['enctype'] = 'multipart/form-data';
+
+ $widget = array(
+ '#type' => $field['widget']['type'],
+ '#title' => $field['widget']['label'],
+ '#description' => $field['widget']['description'],
+ '#default_value' => isset($items[$delta]) ? $items[$delta] : NULL,
+ '#field' => $field,
+ '#delta' => $delta,
+ '#force_list' => is_bool($field['force_list']) ? FALSE : $field['force_list'],
+ );
+ return $widget;
+}
+
/**
* Implementation of hook_widget_settings().
*/
function filefield_widget_settings($op, $widget) {
switch ($op) {
- case 'callbacks':
- return array('default value' => CONTENT_CALLBACK_CUSTOM);
-
case 'form':
$form = array();
$form['file_extensions'] = array (
'#type' => 'textfield',
'#title' => t('Permitted upload file extensions'),
- '#default_value' => isset($widget['file_extensions']) ? $widget['file_extensions'] : 'txt',
+ '#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' => $widget['file_path'] ? $widget['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 (function_exists('token_replace')) {
- $form['file_path']['#description'] .= theme('token_help', 'user');
+ if (module_exists('token')) {
+ $form['file_path']['#suffix'] = theme('token_help', 'user');
}
// Let extension modules add their settings to the form.
foreach (module_implements('filefield_widget_settings') as $module) {
@@ -319,9 +284,11 @@ function filefield_widget_settings($op, $widget) {
$function('form_alter', $widget, $form);
}
return $form;
+
case 'validate':
module_invoke_all('filefield_widget_settings', $op, $widget, NULL);
break;
+
case 'save':
$core_settings = array('file_extensions', 'file_path');
$additional_settings = module_invoke_all(
@@ -331,6 +298,179 @@ function filefield_widget_settings($op, $widget) {
}
}
+function _filefield_widget_settings_file_path_validate($element, &$form_state) {
+ // Strip slashes from the beginning and end of $widget['file_path']
+ $form_state['values']['file_path'] = trim($form_state['values']['file_path'], '\\/');
+}
+
+
+/**
+ * Implementation of hook_elements().
+ */
+function filefield_elements() {
+ $elements = array();
+ $elements['filefield_combo'] = array(
+ '#input' => TRUE,
+ '#columns' => array('fid', 'description', 'list'),
+ '#process' => array('filefield_combo_process'),
+ '#value_callback' => 'filefield_combo_value',
+ '#description' => t('Changes made to the attachments are not permanent until you save this post.'),
+ );
+ return $elements;
+}
+
+/**
+ * The 'process' callback for 'filefield_combo' form elements.
+ * Called after defining the form and while building it, transforms the
+ * barebone element array into a full-fledged file upload widget.
+ */
+function filefield_combo_process($element, $edit, &$form_state, $form) {
+ $field = $element['#field'];
+ $fieldname = $field['field_name'];
+ $fid = $element['#value']['fid'];
+
+ drupal_add_css(drupal_get_path('module', 'filefield') .'/filefield.css');
+
+ // Make an array out of these child elements.
+ $element['#tree'] = TRUE;
+
+ // Present an upload widget if the element doesn't contain an fid.
+ if (empty($fid)) {
+ //drupal_add_js('misc/progress.js');
+ //drupal_add_js('misc/upload.js');
+ //drupal_add_js(drupal_get_path('module', 'filefield') .'/filefield.js');
+
+ $element[$fieldname .'_'. $element['#delta']] = array(
+ '#type' => 'file',
+ '#title' => t('Upload file'),
+ '#description' => $element['#description'],
+ '#weight' => 9,
+ '#attributes' => array(
+ 'class' => 'filefield filefield-'. $fieldname,
+ 'accept' => str_replace(' ', '|', trim($field['widget']['file_extensions']))
+ ),
+ // Emulate how FAPI normalizes the _FILES array since this won't go through form_builder.
+ '#name' => 'files['. $fieldname .'_'. $element['#delta'] .']',
+ '#tree' => FALSE,
+ );
+ $element['submit'] = array(
+ '#type' => 'button',
+ '#value' => t('Upload'),
+ '#weight' => 10,
+ );
+ }
+ // Present the existing file if the element contains the corresponding fid.
+ else {
+ // Load file from fid.
+ $file = array_merge($element['#value'], field_file_load($fid));
+ $url = file_create_url($file['filepath']);
+
+ $element['icon'] = array(
+ '#type' => 'markup',
+ '#value' => theme('filefield_icon', $file),
+ );
+ $element['description'] = array(
+ '#type' => 'textfield',
+ '#default_value' => (strlen($file['description'])) ? $file['description'] : $file['filename'],
+ '#maxlength' => 256,
+ );
+ $element['url'] = array(
+ '#type' => 'markup',
+ '#value' => ''. t('URL: @url', array('@url' => $url)) .'',
+ '#prefix' => '
',
+ '#suffix' => '
',
+ );
+ $element['size'] = array(
+ '#type' => 'markup',
+ '#value' => format_size($file['filesize']),
+ '#prefix' => '',
+ '#suffix' => '
',
+ );
+ $element['delete'] = array(
+ '#type' => 'checkbox',
+ '#default_value' => 0,
+ '#title' => t('Delete'),
+ );
+
+ // Only show the list checkbox if files are not forced to be listed.
+ if (!$element['#force_list']) {
+ $element['list'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('List'),
+ '#default_value' => $file['list'],
+ );
+ }
+ else {
+ $element['list'] = array(
+ '#type' => 'value',
+ '#value' => isset($file['list']) ? $file['list'] : 1,
+ );
+ }
+
+ $element['filename'] = array('#type' => 'value', '#value' => $file['filename']);
+ $element['filepath'] = array('#type' => 'value', '#value' => $file['filepath']);
+ $element['filemime'] = array('#type' => 'value', '#value' => $file['filemime']);
+ $element['filesize'] = array('#type' => 'value', '#value' => $file['filesize']);
+ $element['fid'] = array('#type' => 'value', '#value' => $file['fid']);
+ }
+
+ return $element;
+}
+
+/**
+ * Every form element needs a themeing function.
+ */
+function theme_filefield_combo($element) {
+ return theme('form_element', $element, $element['#children']);
+}
+
+/**
+ * The 'value' callback for 'filefield_combo' form elements.
+ * Transforms the original widget value into a file array.
+ */
+function filefield_combo_value($element, $edit = FALSE) {
+ $default_value = $element['#default_value'];
+
+ if (!isset($default_value)) {
+ $default_value = array('fid' => 0, 'description' => '', 'list' => 0);
+ }
+ if (is_object($default_value)) {
+ $default_value = (array) $default_value;
+ }
+
+ if ($edit === FALSE) {
+ return $default_value;
+ }
+
+ $field = $element['#field'];
+ $fieldname = $field['field_name'];
+ $upload_name = $fieldname .'_'. $element['#delta'];
+
+ if (module_exists('token')) {
+ global $user;
+ $widget_file_path = token_replace($field['widget']['file_path'], 'user', $user);
+ }
+ else {
+ $widget_file_path = $field['widget']['file_path'];
+ }
+
+ $validators = array(
+ 'file_validate_extensions' => array($field['widget']['file_extensions']),
+ );
+
+ $complete_file_path = file_directory_path() .'/'. $widget_file_path;
+
+ if (!filefield_check_directory($widget_file_path, $upload_name)) {
+ // @todo: watchdog.
+ return $default_value;
+ }
+
+ if (!$file = file_save_upload($upload_name, $validators, $complete_file_path)) {
+ // @todo: watchdog.
+ return $default_value;
+ }
+ return (array) $file;
+}
function filefield_clear_session() {
if (is_array($_SESSION['filefield']) && count($_SESSION['filefield'])) {
@@ -352,67 +492,36 @@ function filefield_clear_field_session($fieldname) {
}
}
-function _filefield_file_delete($node, $field, $file) {
- if (is_numeric($file['fid'])) {
- db_query('DELETE FROM {files} WHERE fid = %d', $file['fid']);
- }
- else {
- unset($_SESSION['filefield'][$field['field_name']][$file['sessionid']]);
- }
- module_invoke_all('filefield', 'file_delete', $node, $field, $file);
- return file_delete($file['filepath']);
-}
-
-/**
- * Implementation of hook_widget().
- */
-function filefield_widget($op, $node, $field, &$items) {
- $fieldname = $field['field_name'];
- switch ($op) {
- case 'default value':
- return array();
-
- case 'prepare form values':
- _filefield_widget_prepare_form_values($node, $field, $items);
- break;
-
- case 'form':
- return _filefield_widget_form($node, $field, $items);
-
- case 'validate':
- _filefield_widget_validate($node, $field, $items);
- break;
- }
-}
function _filefield_widget_prepare_form_values($node, $field, &$items) {
$fieldname = $field['field_name'];
+
// @todo split this into its own function. determine if we can make it a form element.
- if (!count($_POST)) {
+ if (empty($_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.
- $last_ext = array_pop(explode('.', $file['filename']));
- $valid = TRUE;
- // only check extensions if there extensions to check.
- // @todo: trim & strtolower file_extenstions with a formapi validate callback.
+
+ // Attach new files.
+ if ($file = file_check_upload($fieldname .'_upload')) {
+ // test allowed extensions. We do this when the file is uploaded,
+ // rather than waiting for the field itseld to reach op==validate.
+ // Only check extensions if specific extensions are actually required.
if (strlen(trim($field['widget']['file_extensions']))) {
- $allowed_extensions = array_unique(explode(' ', strtolower(trim($field['widget']['file_extensions']))));
- $ext = strtolower(array_pop(explode('.', $file['filename'])));
- if (!in_array($ext, $allowed_extensions)) {
- $valid = FALSE;
- 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' => $last_ext, '%allowed_extensions' => $field['widget']['file_extensions'])));
- }
+ $errors = file_validate_extensions($file, $field['widget']['file_extensions']);
}
+ $file = (array)$file;
+
// let extended validation from other module happen so we get all error messages.
// if you implement hook_filefield_file() return FALSE to stop the upload.
- if (!$valid || in_array(FALSE, module_invoke_all('filefield', 'file_validate', $node, $field, $file))) {
- return FALSE;
+ if (empty($errors)) {
+ $errors = module_invoke_all('filefield', 'file_validate', $node, $field, $file);
+ }
+ if (!empty($errors)) {
+ foreach ($errors as $error) {
+ form_set_error($fieldname .'_upload', $error);
+ }
}
+
// let modules massage act on the file.
foreach(module_implements('filefield') as $module) {
$function = $module .'_filefield';
@@ -441,10 +550,11 @@ function _filefield_widget_prepare_form_values($node, $field, &$items) {
// Remove old temporary file from session.
filefield_clear_field_session($fieldname);
}
+
$file_id = count($items) + count($_SESSION['filefield'][$fieldname]);
$_SESSION['filefield'][$fieldname][$file_id] = $file;
}
-
+
// Load files from preview state. before committing actions.
if (!empty($_SESSION['filefield'][$fieldname])) {
foreach($_SESSION['filefield'][$fieldname] as $delta => $file) {
@@ -453,16 +563,16 @@ function _filefield_widget_prepare_form_values($node, $field, &$items) {
}
}
+/*
function _filefield_widget_form($node, $field, &$items) {
drupal_add_js('misc/progress.js');
drupal_add_js('misc/upload.js');
drupal_add_js(drupal_get_path('module', 'filefield') .'/filefield.js');
-
+ drupal_add_css(drupal_get_path('module', 'filefield') .'/filefield.css');
$fieldname = $field['field_name'];
- drupal_add_css(drupal_get_path('module', 'filefield') .'/filefield.css');
-
- $form = array();
+
+ $form = array();
$form[$fieldname] = array(
'#type' => 'fieldset',
'#title' => t($field['widget']['label']),
@@ -573,116 +683,17 @@ function _filefield_widget_form($node, $field, &$items) {
return $form;
}
-
-function _filefield_file_form($node, $field, $file) {
- // Lets be a good boy and initialize our variables.
- $form = array();
- $form['#after_build'] = array('_filefield_file_form_description_reset');
-
- $form['icon'] = array(
- '#type' => 'markup',
- '#value' => theme('filefield_icon', $file),
- );
-
- $form['file_preview'] = array();
-
- $filepath = ($file['fid'] == 'upload')
- ? file_create_filename($file['filename'], file_create_path($field['widget']['file_path']))
- : $file['filepath'];
-
- $url = file_create_url($filepath);
-
- $form['description'] = array(
- '#type' => 'textfield',
- '#default_value' => (strlen($file['description'])) ? $file['description'] : $file['filename'], '#maxlength' => 256,
- '#size' => 40,
- '#attributes' => array('class' => 'filefield-description', 'size' => '40'),
- );
- $form['url'] = array(
- '#type' => 'markup',
- '#value' => l($url, $url),
- '#prefix' => '',
- '#suffix' => '
',
- );
- $form['size'] = array(
- '#type' => 'markup',
- '#value' => format_size($file['filesize']),
- '#prefix' => '',
- '#suffix' => '
',
- );
- $form['delete'] = array(
- '#type' => 'checkbox',
- '#default_value' => $file['delete'],
- );
-
- // Only show the list checkbox if files are not forced to be listed.
- if (!$field['force_list']) {
- $form['list'] = array(
- '#type' => 'checkbox',
- '#default_value' => $file['list'],
- );
- }
- else {
- $form['list'] = array(
- '#type' => 'value',
- '#value' => isset($file['list']) ? $file['list'] : 1,
- );
- }
-
- $form['filename'] = array('#type' => 'value', '#value' => $file['filename']);
- $form['filepath'] = array('#type' => 'value', '#value' => $file['filepath']);
- $form['filemime'] = array('#type' => 'value', '#value' => $file['filemime']);
- $form['filesize'] = array('#type' => 'value', '#value' => $file['filesize']);
- $form['fid'] = array('#type' => 'value', '#value' => $file['fid']);
-
- // Remember the current filename for the check in
- // _filefield_file_form_description_reset() that happens after submission.
- $form['previous_filepath'] = array('#type' => 'hidden', '#value' => $file['filepath']);
-
- foreach (module_implements('filefield') as $module) {
- $function = $module .'_filefield';
- $function('file_form', $node, $field, $file, $form);
- }
- return $form;
-}
-
-/**
- * This after_build function is needed as fix for tricky Form API behaviour:
- * When using filefield without AJAX uploading, the description field was not
- * updated to a new '#default_value' because the textfield has been submitted,
- * which causes Form API to override the '#default_value'.
- *
- * That bug is fixed with this function by comparing the previous filename
- * to the new one, and resetting the description to the '#default_value'
- * if the filename has changed.
- */
-function _filefield_file_form_description_reset($form, $form_values) {
- // Don't bother resetting the description of files that stay the same
- if ($form['fid']['#value'] != 'upload') {
- return $form;
- }
- // Get the previous filename for comparison with the current one.
- $previous = $form['previous_filepath']['#post'];
- foreach ($form['previous_filepath']['#parents'] as $parent) {
- $previous = isset($previous[$parent]) ? $previous[$parent] : NULL;
- }
- // If a new file was uploaded (the file path changed), reset the description.
- if ($previous != $form['filepath']['#value']) {
- $form['description']['#value'] = $form['description']['#default_value'];
- }
- return $form;
-}
+*/
/**
* Validate the form widget.
*/
function _filefield_widget_validate($node, $field, $items) {
-
if (!$field['required']) {
return;
}
-
+
// if there aren't any items.. throw an error.
if (!count($items)) {
form_set_error($field['field_name'], t('@field is required. Please upload a file.', array('@field' => $field['widget']['label'])));
@@ -692,7 +703,9 @@ function _filefield_widget_validate($node, $field, $items) {
// isn't deleting all of the files.
$count_deleted = 0;
foreach($items as $item) {
- $count_deleted += isset($item['delete']) && $item['delete'];
+ if (isset($item['delete']) && $item['delete']) {
+ ++$count_deleted;
+ }
}
if (count($items) == $count_deleted) {
form_set_error($field['field_name'], t('@field is required. Please keep at least one file or upload a new one.', array('@field' => $field['widget']['label'])));
@@ -702,47 +715,37 @@ function _filefield_widget_validate($node, $field, $items) {
/**
- * Implementation of hook_field formatter.
- * @todo: finish transformer.module and integrate like imagecache with imagefield.
+ * Implementation of hook_field_formatter_info().
*/
function filefield_field_formatter_info() {
- $formatters = array(
- 'default' => array(
- 'label' => t('Default'),
- 'field types' => array('file'),
- ),
+ return array(
+ 'default' => array(
+ 'label' => t('Default'),
+ 'field types' => array('file'),
+ 'multiple values' => CONTENT_HANDLE_CORE,
+ ),
);
- return $formatters;
}
-function filefield_field_formatter($field, $item, $formatter) {
- if($field['force_list']) {
- $item['list'] = 1; // always show the files if that option is enabled
- }
- if(!empty($item['fid'])) {
- $item = array_merge($item, _filefield_file_load($item['fid']));
- }
- if (!empty($item['filepath'])) {
- drupal_add_css(drupal_get_path('module', 'filefield') .'/filefield.css');
- return theme('filefield', $item);
+/**
+ * Theme function for the 'default' filefield field formatter.
+ */
+function theme_filefield_formatter_default($element) {
+ $file = $element['#item'];
+ if (!$file['fid']) {
+ return '';
}
-}
-function _filefield_file_load($fid = NULL) {
- // Don't bother if we weren't passed and fid.
- if (!empty($fid) && is_numeric($fid)) {
- $result = db_query('SELECT * FROM {files} WHERE fid = %d', $fid);
- $file = db_fetch_array($result);
- if ($file) {
- // let modules load extended attributes.
- $file += module_invoke_all('filefield', 'file_load', $node, $field, $file);
- return $file;
- }
+ // @todo: retrieve the $field.
+ if($field['force_list']) {
+ $file['list'] = 1; // always show the files if that option is enabled
}
- // return an empty array if nothing was found.
- return array();
+ drupal_add_css(drupal_get_path('module', 'filefield') .'/filefield.css');
+ return theme('filefield', $file);
}
+/* @todo: remove, and transform into a single-element widget
+ (or steer away from CONTENT_HANDLE_CORE for 'multiple values')
function theme_filefield_form_current($form) {
$header = $form['#force_list']
? array('', t('Delete'), '', t('Description'), t('Size'))
@@ -770,7 +773,7 @@ function theme_filefield_form_current($form) {
$output = theme('table', $header, $rows, array('class' => 'filefield-filebrowser'));
$output .= drupal_render($form);
return $output;
-}
+}*/
function theme_filefield_icon($file) {
$dashed_mime = check_plain(strtr($file['filemime'], array('/' => '-')));
@@ -781,10 +784,6 @@ function theme_filefield_icon($file) {
return ''. $icon .'
';
}
-function theme_filefield_view_file($file) {
- return theme('filefield', $file);
-}
-
function theme_filefield($file) {
if (user_access('view filefield uploads') && is_file($file['filepath']) && $file['list']) {
$path = ($file['fid'] == 'upload')
@@ -799,6 +798,7 @@ function theme_filefield($file) {
return '';
}
+
function filefield_file_download($file) {
$file = file_create_path($file);
@@ -808,20 +808,21 @@ function filefield_file_download($file) {
return;
}
+ // @todo: check the node for this file to be referenced in a field
+ // to determine if it is managed by filefield. and do the access denied part here.
+ if (!user_access('view filefield uploads')) {
+ // sorry you do not have the proper permissions to view filefield uploads.
+ return -1;
+ }
+
+ /* @todo: D6 port - files don't have any direct connection with nodes anymore
$node = node_load($file->nid);
if (!node_access('view', $node)) {
// You don't have permission to view the node
// this file is attached to.
return -1;
}
-
- // @todo: check the node for this file to be referenced in a field
- // to determine if it is managed by filefield. and do the access denied part here.
- if (!user_access('view filefield uploads')) {
- // sorry you do not have the proper permissions to view
- // filefield uploads.
- return -1;
- }
+ */
// Well I guess you can see this file.
$name = mime_header_encode($file->filename);
@@ -839,17 +840,23 @@ function filefield_file_download($file) {
/**
* Create the file directory relative to the 'files' dir recursively for every
* directory in the path.
- *
+ *
* @param $directory
* The directory path under files to check, such as 'photo/path/here'
- * @param $form_element
- * A form element to throw an error on if the directory is not writable
- */
-function filefield_check_directory($directory, $form_element = array()) {
- foreach(explode('/', $directory) as $dir) {
+ * @param $form_item
+ * An optional string containing the name of a form item that any errors
+ * will be attached to. (See field_file_check_directory() for more details.)
+ */
+function filefield_check_directory($directory, $form_item = NULL) {
+ $directory = field_file_strip_path($directory);
+
+ foreach (explode('/', $directory) as $dir) {
$dirs[] = $dir;
- $path = file_create_path(implode($dirs,'/'));
- file_check_directory($path, FILE_CREATE_DIRECTORY, $form_element['#parents'][0]);
+ $path = file_create_path(implode($dirs, '/'));
+ if (!field_file_check_directory($path, FILE_CREATE_DIRECTORY, $form_item)) {
+ watchdog('filefield', t('FileField failed to create directory (%d) at (%p).', array('%d' => $directory, '%p' => $path)), WATCHDOG_ERROR);
+ return FALSE;
+ }
}
return TRUE;
}
@@ -932,6 +939,7 @@ function filefield_token_values($type, $object = NULL) {
/**
* Custom filter for filefield NOT NULL
*/
+/* @todo: port to views 2
function filefield_views_handler_filter_is_not_null($op, $filter, $filterinfo, &$query) {
if ($op == 'handler') {
$query->ensure_table($filterinfo['table']);
@@ -943,7 +951,7 @@ function filefield_views_handler_filter_is_not_null($op, $filter, $filterinfo, &
}
$query->add_where($qs, $filterinfo['table'], $filterinfo['field'], $filterinfo['table'], $filterinfo['field']);
}
-}
+}*/
/**