array('sources' => NULL), ); return $theme; } /** * Implementation of hook_filefield_sources_widgets(). * * This returns a list of widgets that are compatible with FileField Sources. */ function filefield_sources_filefield_sources_widgets() { return array('filefield_widget', 'imagefield_widget'); } /** * Implementation of hook_widget_settings_alter(). */ function filefield_sources_widget_settings_alter(&$settings, $op, $widget) { // Only support modules that implement hook_insert_widgets(). $widget_type = isset($widget['widget_type']) ? $widget['widget_type'] : $widget['type']; if (!in_array($widget_type, module_invoke_all('filefield_sources_widgets'))) { return; } if ($op == 'form') { $settings = array_merge($settings, filefield_sources_form($widget)); } if ($op == 'save') { $settings = array_merge($settings, filefield_sources_widget_settings($widget)); } } /** * A list of settings needed by FileField Sources module on widgets. */ function filefield_sources_widget_settings($widget) { $settings = array( 'filefield_sources', ); $params = array('save', $widget); $settings = array_merge($settings, filefield_sources_invoke_all('settings', $params)); return $settings; } /** * Configuration form for editing FileField Sources settings for a widget. */ function filefield_sources_form($widget) { $form['filefield_sources'] = array( '#type' => 'fieldset', '#title' => t('File sources'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => 15, ); $sources = filefield_sources_list(FALSE); $sources = array_intersect_key(array_merge((array) $widget['filefield_sources'], $sources), $sources); $form['filefield_sources']['filefield_sources'] = array( '#type' => 'checkboxes', '#title' => t('Enabled sources'), '#options' => $sources, '#default_value' => (array) $widget['filefield_sources'], '#description' => t('Select the available locations from which this widget may select files.'), ); $params = array('form', $widget); $form['filefield_sources'] = array_merge($form['filefield_sources'], filefield_sources_invoke_all('settings', $params)); return $form; } /** * A #process callback to extend the filefield_widget element type. * * Add the central JavaScript and CSS files that allow switching between * different sources. Third-party modules can also add to the list of sources * by implementing hook_filefield_sources_info(). */ function filefield_sources_process($element, $edit, &$form_state, $form) { static $js_added; // Do all processing as needed by each source. $sources = filefield_sources_info(); $field = content_fields($element['#field_name'], $element['#type_name']); $enabled_sources = (array) $field['widget']['filefield_sources']; foreach ($sources as $source_name => $source) { if (!$enabled_sources[$source_name]) { unset($sources[$source_name]); } elseif (isset($source['process'])) { $function = $source['process']; $element = $function($element, $edit, $form_state, $form); } } // Exit out if not adding any sources. if (empty($sources)) { return $element; } // Add basic JS and CSS. $path = drupal_get_path('module', 'filefield_sources'); drupal_add_css($path .'/filefield_sources.css'); drupal_add_js($path .'/filefield_sources.js'); // Check the element for hint text that might need to be added. foreach (element_children($element) as $key) { if (isset($element[$key]['#filefield_sources_hint_text']) && !isset($js_added[$key])) { $type = str_replace('filefield_', '', $key); drupal_add_js(array('fileFieldSources' => array($type => array('hintText' => $element[$key]['#filefield_sources_hint_text']))), 'setting'); $js_added[$key] = TRUE; } } // Add the list of sources to the element for toggling between sources. if (empty($element['fid']['#value'])) { $element['filefield_sources_list'] = array( '#type' => 'markup', '#value' => theme('filefield_sources_list', $element, $sources), '#weight' => -1, ); } return $element; } /** * An #element_validate function to run source validations. */ function filefield_sources_validate($element, &$form_state, $form) { // Do all processing as needed by each source. $sources = filefield_sources_info(); foreach ($sources as $source) { if (isset($source['validate'])) { $function = $source['validate']; $function($element, $form_state, $form); } } } /** * A #filefield_value_callback to run source value callbacks. */ function filefield_sources_value($element, &$item) { // Do all processing as needed by each source. $sources = filefield_sources_info(); foreach ($sources as $source) { if (isset($source['value'])) { $function = $source['value']; $function($element, $item); } } } /** * Call all FileField Source hooks stored in the available include files. */ function filefield_sources_invoke_all($method, &$params) { $return = array(); foreach (filefield_sources_includes() as $source) { $function = 'filefield_source_' . $source . '_' . $method; if (function_exists($function)) { $result = call_user_func_array($function, $params); if (isset($result) && is_array($result)) { $return = array_merge_recursive($return, $result); } else if (isset($result)) { $return[] = $result; } } } return $return; } /** * Load hook_filefield_sources_info() data from all modules. */ function filefield_sources_info() { $info = module_invoke_all('filefield_sources_info'); drupal_alter('filefield_sources_info', $info); uasort($info, '_filefield_sources_sort'); return $info; } /** * Create a list of FileField Sources by name, suitable for a select list. */ function filefield_sources_list($include_default = TRUE) { $info = filefield_sources_info(); $list = array(); if ($include_default) { $list['upload'] = t('Upload'); } foreach ($info as $key => $source) { $list[$key] = $source['name']; } return $list; } /** * Implementation of hook_filefield_sources_info(). */ function filefield_sources_filefield_sources_info() { $params = array(); return filefield_sources_invoke_all('info', $params); } /** * Load all the potential sources. */ function filefield_sources_includes($include = TRUE, $enabled_only = TRUE) { if ($enabled_only) { $enabled_includes = variable_get('filefield_sources', filefield_sources_includes(FALSE, FALSE)); } $includes = array(); $directory = drupal_get_path('module', 'filefield_sources') . '/sources'; foreach (file_scan_directory($directory, '.inc$') as $file) { if (!$enabled_only || in_array($file->name, $enabled_includes)) { $includes[] = $file->name; if ($include) { include_once($file->filename); } } } return $includes; } /** * Clean up the file name, munging extensions and transliterating. * * @param $filepath * A string containing a file name or full path. Only the file name will * actually be modified. * @return * A file path with a cleaned-up file name. */ function filefield_sources_clean_filename($filepath) { global $user; $filename = basename($filepath); if (module_exists('transliteration')) { module_load_include('inc', 'transliteration'); $langcode = NULL; if (!empty($_POST['language'])) { $languages = language_list(); $langcode = isset($languages[$_POST['language']]) ? $_POST['language'] : NULL; } $filename = transliteration_clean_filename($filename, $langcode); } // Because this transfer mechanism does not use file_save_upload(), we need // to manually munge the filename to prevent dangerous extensions. // See file_save_upload(). $extensions = ''; foreach ($user->roles as $rid => $name) { $extensions .= ' '. variable_get("upload_extensions_$rid", variable_get('upload_extensions_default', 'jpg jpeg gif png txt html doc xls pdf ppt pps odt ods odp')); } $filename = file_munge_filename($filename, $extensions); $directory = dirname($filepath); return ($directory ? $directory . '/' : $directory) . $filename; } /** * Theme the display of the sources list. */ function theme_filefield_sources_list($element, $sources) { $links = array(); // Add the default "Upload" since it's not in our list. $default['upload'] = array( 'label' => t('Upload'), 'description' => t('Upload a file from your computer.'), ); $sources = array_merge($default, $sources); foreach ($sources as $name => $source) { $links[] = '' . $source['label'] . ''; } return '
' . implode(' | ', $links) . '
'; } /** * Validate a file based on the $element['#upload_validators'] property. */ function filefield_sources_element_validate($element, $file) { $validators = $element['#upload_validators']; $errors = array(); // Since this frequently is used to reference existing files, check that // they exist first in addition to the normal validations. if (!file_exists($file->filepath)) { $errors[] = t('The file does not exist.'); } // Call the validation functions. else { foreach ($validators as $function => $args) { // Add the $file variable to the list of arguments and pass it by // reference (required for PHP 5.3 and higher). array_unshift($args, NULL); $args[0] = &$file; $errors = array_merge($errors, call_user_func_array($function, $args)); } } // Check for validation errors. if (!empty($errors)) { $message = t('The selected file %name could not be referenced.', array('%name' => $file->filename)); if (count($errors) > 1) { $message .= ''; } else { $message .= ' '. array_pop($errors); } form_error($element, $message); return 0; } return 1; } /** * Generate help text based on the $element['#upload_validators'] property. */ function filefield_sources_element_validation_help($validators) { $desc = array(); foreach ($validators as $callback => $arguments) { $help_func = $callback .'_help'; if (function_exists($help_func)) { $desc[] = call_user_func_array($help_func, $arguments); } } return empty($desc) ? '' : implode('
', $desc); } /** * Custom sort function for ordering sources. */ function _filefield_sources_sort($a, $b) { $a = (array)$a + array('weight' => 0, 'label' => ''); $b = (array)$b + array('weight' => 0, 'label' => ''); return $a['weight'] < $b['weight'] ? -1 : ($a['weight'] > $b['weight'] ? 1 : strnatcasecmp($a['label'], $b['label'])); }