'imagefield/js', 'callback' => 'imagefield_js', //'access' => user_access(), 'access' => TRUE, 'type' => MENU_CALLBACK ); } elseif ($_SESSION['imagefield']) { // Add handlers for previewing new uploads. foreach ($_SESSION['imagefield'] as $fieldname => $files) { if (is_array($files)) { $download_method = variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC); foreach($files as $delta => $file) { if ($file['preview']) { $filepath = $file['preview']; if ($download_method == FILE_DOWNLOADS_PRIVATE) { if (strpos($file['preview'], file_directory_path()) !== FALSE) { $file['preview'] = trim(substr($file['preview'], strlen(file_directory_path())), '\\/'); } $file['preview'] = 'system/files/' . $file['preview']; } $items[] = array( 'path' => $file['preview'], 'callback' => '_imagefield_preview', 'callback arguments' => array($filepath), 'access' => TRUE, 'type' => MENU_CALLBACK, ); } } } } } return $items; } /** * transfer a file that is in a 'preview' state. * @todo multiple support */ function _imagefield_preview($filepath) { foreach ($_SESSION['imagefield'] as $fieldname => $files) { foreach ($files as $delta => $file) { if ($file['preview'] == $filepath) { file_transfer($file['filepath'], array('Content-Type: '. mime_header_encode($file['filemime']), 'Content-Length: '. $file['filesize'])); exit(); } } } } function imagefield_perm() { return array('view imagefield uploads'); } /** * Implementation of hook_field_info(). */ function imagefield_field_info() { return array( 'image' => array('label' => 'Image'), ); } /** * Implementation of hook_field_settings(). */ function imagefield_field_settings($op, $field) { switch ($op) { case 'callbacks': return array('view' => CONTENT_CALLBACK_CUSTOM); case 'form': $form = array(); return $form; case 'validate': break; case 'save': return array(); case 'database columns': $columns = array( 'fid' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'), 'title' => array('type' => 'varchar', length => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE), 'alt' => array('type' => 'varchar', length => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE), ); return $columns; } } function imagefield_default_item() { return array( 'fid' => 0, 'title' => '', 'alt' => '', ); } /** * 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 imagefield_file_insert($node, &$file, $field) { $fieldname = $field['field_name']; // allow tokenized paths. if (function_exists('token_replace')) { global $user; $widget_image_path = token_replace($field['widget']['image_path'],'user', $user); } else { $widget_image_path = $field['widget']['image_path']; } $filepath = file_create_path($widget_image_path) . '/' . $file['filename']; if (imagefield_check_directory($widget_image_path) && $file = file_save_upload((object)$file, $filepath)) { $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('Image upload was unsuccessful.')); return FALSE; } } /** * update the file record if necessary * @param $node * @param $file * @param $field */ function imagefield_file_update($node, &$file, $field) { $file = (array)$file; if ($file['flags']['delete'] == TRUE) { if(_imagefield_file_delete($file, $field['field_name'])) { return array(); } } if ($file['fid'] == 'upload') { return imagefield_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 imagefield_field($op, $node, $field, &$items, $teaser, $page) { $fieldname = $field['field_name']; switch ($op) { case 'view': $context = $teaser ? 'teaser' : 'full'; $formatter = isset($field['display_settings'][$context]['format']) ? $field['display_settings'][$context]['format'] : 'default'; if (!count($items) && $field['widget']['use_default_image']) { // build a fake items array $items = array(array( 'fid' => 0, 'title' => $field['widget']['default_image']['filename'], 'alt' => $field['widget']['default_image']['filename'], 'nid' => $node->nid, 'filename' => $field['widget']['default_image']['filename'], 'filepath' => $field['widget']['default_image']['filepath'], 'filemime' => $field['widget']['default_image']['filemime'], 'filesize' => $field['widget']['default_image']['filesize'], )); } foreach ($items as $delta => $item) { $items[$delta]['view'] = content_format($field, $item, $formatter, $node); } return theme('field', $node, $field, $items, $teaser, $page); // called after content.module loads default data. case 'load': if (count($items)) { foreach ($items as $delta => $file) { if (!empty($file)) { $file = _imagefield_file_load($file['fid']); // In certain cases, content.module calls this function with // $items[$delta] set, even if the field has not yet been stored at // all or has already been deleted. In that case, $file['fid'] == 0 // and file_load() returns an empty array. When that happens, // unset() the delta so that subsequent hooks are not bothered. if (empty($file)) { unset($items[$delta]); } else { // otherwise, merge our info with CCK's, and all is fine. $items[$delta] = array_merge((array)$items[$delta], $file); } } } $items = array_values($items); // compact deltas return array($fieldname => $items); } return array(); // called before content.module defaults. case 'insert': foreach ($items as $delta => $item) { $items[$delta] = imagefield_file_insert($node, $item, $field); // Remove non-existant images from items if (empty($items[$delta])) { unset($items[$delta]); } } $items = array_values($items); // compact deltas imagefield_clear_field_session($fieldname); break; // called before content.module defaults. case 'update': foreach ($items as $delta => $item) { // If we're dealing with a single value field, and we just received // a new file item, we need to mark the existing (old) one for // deletion. Otherwise, it will become orphaned. if (!$field['multiple'] && (count($items) > 1) && ($delta === 0)) { $item['flags']['delete'] = TRUE; } // Update each file item. $items[$delta] = imagefield_file_update($node, $item, $field); // If the file has been deleted, unset the file entry so that it's // actually deleted from the database, or at least set it to a // default item if CCK won't delete it. if (empty($items[$delta])) { if ($field['multiple']) { unset($items[$delta]); } else { $items[$delta] = imagefield_default_item(); } } } $items = array_values($items); // compact deltas imagefield_clear_field_session($fieldname); break; case 'delete': foreach ($items as $delta => $item) { _imagefield_file_delete($item, $field['field_name']); } break; } } /** * Implementation of hook_widget_info(). */ function imagefield_widget_info() { return array( 'image' => array( 'label' => 'Image', 'field types' => array('image'), ), ); } /** * Implementation of hook_widget_settings(). */ function imagefield_widget_settings($op, $widget) { switch ($op) { case 'callbacks': return array('default value' => CONTENT_CALLBACK_CUSTOM); case 'form': $form = array(); $form['max_resolution'] = array ( '#type' => 'textfield', '#title' => t('Maximum resolution for Images'), '#default_value' => $widget['max_resolution'] ? $widget['max_resolution'] : 0, '#size' => 15, '#maxlength' => 10, '#description' => t('The maximum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Set to 0 for no restriction.') ); $form['image_path'] = array( '#type' => 'textfield', '#title' => t('Image path'), '#default_value' => $widget['image_path'] ? $widget['image_path'] : '', '#description' => t('Optional subdirectory within the "%dir" directory where images will be stored. Do not include trailing slash.', array('%dir' => variable_get('file_directory_path', 'files'))), '#after_build' => array('imagefield_form_check_directory'), ); if (function_exists('token_replace')) { $form['image_path']['#description'] .= theme('token_help', 'user'); } $form['file_extensions'] = array ( '#type' => 'textfield', '#title' => t('Permitted upload file extensions.'), '#default_value' => $widget['file_extensions'] ? $widget['file_extensions'] : 'jpg jpeg png gif', '#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.') ); $form['custom_alt'] = array( '#type' => 'checkbox', '#title' => t('Enable custom alternate text'), '#default_value' => $widget['custom_alt'] ? $widget['custom_alt'] : 0, '#description' => t('Enable custom alternate text for images. Filename will be used if not checked.'), ); $form['custom_title'] = array( '#type' => 'checkbox', '#title' => t('Enable custom title text'), '#default_value' => $widget['custom_title'] ? $widget['custom_title'] : 0, '#description' => t('Enable custom title text for images. Filename will be used if not checked.'), ); $form['default'] = array( '#type' => 'fieldset', '#title' => t('Default image'), '#collapsible' => TRUE, '#collapsed' => !$widget['use_default_image'], ); // Present a thumbnail of the current default image. $form['default']['use_default_image'] = array( '#type' => 'checkbox', '#title' => t('Use default image'), '#default_value' => $widget['use_default_image'], '#description' => t('Check here if you want to use a image as default.'), ); if (!empty($widget['default_image'])) { $form['default']['default_image_thumbnail'] = array( '#type' => 'markup', '#value' => theme('imagefield_image', $widget['default_image'], '', '', array('width' => '150'), FALSE), ); } $form['default']['default_image_upload'] = array( '#type' => 'file', '#title' => t('Upload image'), '#description' => t('Choose a image that will be used as default.'), ); // We set this value on 'validate' so we can get cck to add it // as a standard field setting. $form['default_image'] = array( '#type' => 'value', '#value' => $widget['default_image'], ); return $form; case 'validate': // strip slashes from the beginning and end of $widget['image_path'] $widget['image_path'] = trim($widget['image_path'], '\\/'); form_set_value(array('#parents' => array('image_path')), $widget['image_path']); // We save the upload here because we can't know the correct // file path until we save the file. if ($file = file_check_upload('default_image_upload')) { $filepath = file_create_path($widget['image_path']); if ($file = file_save_upload('default_image_upload', $filepath)) { form_set_value(array('#parents' => array('default_image')), (array) $file); } } break; case 'save': return array('max_resolution', 'image_path', 'file_extensions', 'custom_alt', 'custom_title', 'use_default_image', 'default_image'); } } /** * Implementation of hook_form_alter(). Set the appropriate * attibutes to allow file uploads on the field settings form. */ function imagefield_form_alter($form_id, &$form) { if ($form_id == '_content_admin_field') { $form['#attributes'] = array('enctype' => 'multipart/form-data'); } } /** * Wrapper function for imagefield_check_directory that accepts a form element * to validate - if user specified one. Won't allow form submit unless the * directory exists & is writable * * @param $form_element * The form element containing the name of the directory to check. */ function imagefield_form_check_directory($form_element) { if(!empty($form_element['#value'])) { imagefield_check_directory($form_element['#value'], $form_element); } return $form_element; } /** * Create the image 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 imagefield_check_directory($directory, $form_element = array()) { foreach(explode('/', $directory) as $dir) { $dirs[] = $dir; $path = file_create_path(implode($dirs,'/')); file_check_directory($path, FILE_CREATE_DIRECTORY, $form_element['#parents'][0]); } return true; } function _imagefield_scale_image($file, $resolution = 0) { $info = image_get_info($file['filepath']); if ($info) { list($width, $height) = explode('x', $resolution); if ($width && $height) { $result = image_scale($file['filepath'], $file['filepath'], $width, $height); if ($result) { $file['filesize'] = filesize($file['filepath']); drupal_set_message(t('The image was resized to fit within the maximum allowed resolution of %resolution pixels', array('%resolution' => $resolution))); } } } return $file; } function imagefield_clear_session() { if (is_array($_SESSION['imagefield']) && count($_SESSION['imagefield'])) { foreach (array_keys($_SESSION['imagefield']) as $fieldname) { imagefield_clear_field_session($fieldname); } unset($_SESSION['imagefield']); } } function imagefield_clear_field_session($fieldname) { if (is_array($_SESSION['imagefield'][$fieldname]) && count($_SESSION['imagefield'][$fieldname])) { foreach ($_SESSION['imagefield'][$fieldname] as $delta => $file) { if (is_file($file['filepath'])) { file_delete($file['filepath']); } } unset($_SESSION['imagefield'][$fieldname]); } } function _imagefield_file_delete($file, $fieldname) { if (is_numeric($file['fid'])) { db_query('DELETE FROM {files} WHERE fid = %d', $file['fid']); } else { unset($_SESSION['imagefield'][$fieldname][$file['sessionid']]); } return file_delete($file['filepath']); } /** * Implementation of hook_widget(). */ function imagefield_widget($op, &$node, $field, &$items) { switch ($op) { case 'default value': return array(); case 'prepare form values': _imagefield_widget_prepare_form_values($node, $field, $items); return; case 'form': return _imagefield_widget_form($node, $field, $items); case 'validate': _imagefield_widget_validate($node, $field, $items); return; } } function _imagefield_widget_prepare_form_values(&$node, $field, &$items) { $fieldname = $field['field_name']; // clean up the session if we weren't posted. if (!count($_POST)) { imagefield_clear_session(); } // Attach new files if ($file = file_check_upload($fieldname . '_upload')) { $file = (array)$file; // Validation must happen immediately after the image is uploaded so we // can discard the file if it turns out not to be a valid mime type $valid_image = _imagefield_widget_upload_validate($node, $field, $items, $file); //$valid_image = TRUE; if ($valid_image) { $file = _imagefield_scale_image($file, $field['widget']['max_resolution']); // Allow tokenized paths if available if (function_exists('token_replace')) { global $user; $widget_image_path = token_replace($field['widget']['image_path'],'user', $user); } else { $widget_image_path = $field['widget']['image_path']; } imagefield_check_directory($widget_image_path); $filepath = file_create_filename($file['filename'], file_create_path($widget_image_path)); $file['fid'] = 'upload'; $file['preview'] = $filepath; // If a single field, mark any other images for deletion and delete files in session if (!$field['multiple']) { if (is_array($items)) { foreach ($items as $delta => $session_file) { $items[$delta]['flags']['delete'] = TRUE; } } imagefield_clear_field_session($fieldname); } // Add the file to the session $file_id = count($items) + count($_SESSION['imagefield'][$fieldname]); $file['sessionid'] = $file_id; $_SESSION['imagefield'][$fieldname][$file_id] = $file; } else { // Delete the invalid file file_delete($file['filepath']); // If a single field and a valid file is in the session, mark existing image for deletion if (!$field['multiple']) { if (count($_SESSION['imagefield'][$fieldname]) && count($items)) { foreach ($items as $delta => $session_file) { $items[$delta]['flags']['delete'] = TRUE; } } } } } // Load files from preview state. before committing actions. if (is_array($_SESSION['imagefield'][$fieldname]) && count($_SESSION['imagefield'][$fieldname])) { foreach($_SESSION['imagefield'][$fieldname] as $delta => $file) { $items[] = $file; } } } function _imagefield_widget_form($node, $field, &$items) { drupal_add_js('misc/progress.js'); drupal_add_js('misc/upload.js'); $fieldname = $field['field_name']; drupal_add_css(drupal_get_path('module', 'imagefield') .'/imagefield.css'); $form = array(); $form[$fieldname] = array( '#type' => 'fieldset', '#title' => t($field['widget']['label']), '#weight' => $field['widget']['weight'], '#collapsible' => TRUE, '#collapsed' => FALSE, '#tree' => TRUE, '#prefix' => '