'admin/settings/node_images', 'title' => t('Node images'), 'description' => t('Control how to upload node images.'), 'callback' => 'drupal_get_form', 'callback arguments' => array('node_images_admin_settings'), 'access' => $admin ); $items[] = array( 'path' => 'node_images/js', 'callback' => '_node_images_js', 'access' => $access, 'type' => MENU_CALLBACK ); } else { if (arg(0) == 'node' && is_numeric(arg(1))) { $node = node_load(arg(1)); if ($node->nid && variable_get('node_images_position_'.$node->type, 'hide') != 'hide') { $items[] = array( 'path' => 'node/' . arg(1) . '/images', 'title' => t('Images'), 'callback' => '_node_images_edit_form', 'callback arguments' => array($node), 'access' => $access && node_access('update', $node), 'type' => MENU_LOCAL_TASK, 'weight' => 2 ); $items[] = array( 'path' => 'node/' . arg(1) . '/image_gallery', 'title' => t('Gallery'), 'callback' => '_node_images_gallery', 'callback arguments' => array($node), 'access' => node_access('view', $node), 'type' => MENU_CALLBACK ); } } } return $items; } /** * implementation of hook_form_alter() */ function node_images_form_alter($form_id, &$form) { $type = $form['#node_type']->type; if ($form_id == 'node_type_form' && isset($form['identity']['type'])) { // radio button in the node's content type configuration page _node_images_check_settings(); $form['node_images'] = array( '#type' => 'fieldset', '#title' => t('Node images'), '#collapsible' => TRUE, ); $form['node_images']['node_images_position'] = array( '#type' => 'radios', '#title' => t('Position'), '#default_value' => variable_get('node_images_position_'.$type, 'hide'), '#options' => array('hide' => t('Do not show'), 'above' => t('Show above node body'), 'below' => t('Show below node body'), 'node_template' => t('Manually set in node template by variable $node->node_images')), '#description' => t('The position of images in the node view.'), ); // WS: added additional option to the Link to image gallery, to only show on the main body not the teaser, $form['node_images']['node_images_gallery_link'] = array( '#type' => 'radios', '#title' => t('Link to image gallery'), '#default_value' => variable_get('node_images_gallery_link_'.$type, TRUE), '#options' => array(t('Do not show'), t('Show'), t('Show only on node body, not node teaser')), '#description' => t('Choose whether to show or not the link to the image gallery.'), ); // Added option to hide gallery link if it won't show any more fullsize images than already seen in the body and teaser $form['node_images']['node_images_gallery_if_needed'] = array( '#type' => 'checkbox', '#title' => t('Only show gallery link if there are more full size images than already shown in full size in the node teaser and node body'), '#default_value' => variable_get('node_images_gallery_if_needed_'.$type, 1), '#required' => FALSE, ); // WS: End of changed code $form['node_images']['node_images_teaser_images'] = array( '#type' => 'textfield', '#title' => t('Number of images in node teaser'), '#default_value' => variable_get('node_images_teaser_images_'.$type, 2), '#size' => 5, '#maxlength' => 2, '#description' => t('The maximum number of images to show in the node teaser. 0 will not show images. Leave blank to show all images.'), ); $form['node_images']['node_images_body_images'] = array( '#type' => 'textfield', '#title' => t('Number of images in node body'), '#size' => 5, '#maxlength' => 2, '#default_value' => variable_get('node_images_body_images_'.$type, NULL), '#description' => t('The maximum number of images to show in the node body. 0 will not show images. Leave blank to show all images.'), ); $form['node_images']['node_images_teaser_format'] = array( '#type' => 'radios', '#title' => t('Image format in node teaser'), '#default_value' => variable_get('node_images_teaser_format_'.$type, 'thumbs'), '#options' => array('thumbs' => t('Thumbnails'), 'fullsize' => t('Full size images')), '#description' => t('Image format in node teaser.'), ); $form['node_images']['node_images_body_format'] = array( '#type' => 'radios', '#title' => t('Image format in node body'), '#default_value' => variable_get('node_images_body_format_'.$type, 'thumbs'), '#options' => array('thumbs' => t('Thumbnails'), 'fullsize' => t('Full size images')), '#description' => t('Image format in node body.'), ); $form['submit']['#weight'] = 30; $form['delete']['#weight'] = 31; $form['reset']['#weight'] = 32; } } /** * Implementation of hook_nodeapi(). */ function node_images_nodeapi(&$node, $op, $teaser, $page) { // test if images are allowed for this node if ($op == 'load' || $op == 'view') { if (variable_get('node_images_position_'.$node->type, 'hide') == 'hide') return; // fire an additional hook for the specific node type // i.e. node images might be a pro feature, so only subscribed users can view them // if the hook is not present in the node type module, images are loaded by default $show = module_invoke($node->type, 'node_images', $op, $node); if ($show === FALSE) return; } switch ($op) { case 'load': // load node images for the current node $sql = db_query('SELECT * FROM {node_images} WHERE nid=%d AND status=1 ORDER BY weight', $node->nid); while ($r = db_fetch_object($sql)) { $node->node_images[$r->id] = $r; } break; case 'insert': if (user_access('create node images') && node_access('update', $node) && variable_get('node_images_position_'.$node->type, 'hide') != 'hide') { drupal_set_message(t('Click the !images tab to add images to this node.', array('!images' => l(t('images'), 'node/'.$node->nid.'/images')))); } break; case 'delete': // Delete image and thumbnail files $sql = db_query('SELECT filepath, thumbpath FROM {node_images} WHERE nid=%d', $node->nid); while ($r = db_fetch_object($sql)) { file_delete($r->filepath); file_delete($r->thumbpath); } // Delete all images associated with the node db_query('DELETE FROM {node_images} WHERE nid=%d', $node->nid); break; case 'count': // WS: added function // Count images associated with this node (avoids having to actually load teh images and then count them) $sql = db_query('SELECT count(*) AS result FROM {node_images} WHERE nid=%d AND status=1 ORDER BY weight', $node->nid); $r = db_fetch_object($sql); if ($r) $node->node_images_count = $r->result; else $node->node_images_count = 0; break; // WS: End of added code case 'view': if (empty($node->node_images)) return; // search for a themed view for the current node type $nodetype_function = 'theme_'.$node->type.'_node_images_view'; if (function_exists($nodetype_function)) { $output = $nodetype_function($node, $teaser, $page); } else { // use the default theme function $output = theme('node_images_view', $node, $teaser, $page); } $node->node_images = $output; $output = '
'.$output.'
'; $position = variable_get('node_images_position_'.$node->type, 'hide'); switch ($position) { case 'node_template': case 'hide': break; case 'above': $node->content['node_images'] = array('#value' => $output, '#weight' => -1); break; default: $node->content['node_images'] = array('#value' => $output, '#weight' => 1); break; } return $node; } } /** * Implementation of hook_link(). */ function node_images_link($type, $node = null, $teaser = false) { $links = array(); if ($type == 'node' && $node->nid && variable_get('node_images_position_'.$node->type, 'hide') != 'hide') { if (node_access('update', $node) && user_access('create node images')) { $links['node_images_edit'] = array( 'title' => t('Edit node images'), 'href' => "node/$node->nid/images", ); } // WS: Added a new option to the gallery link configuration // You now have, as well as 'Do not show' and 'Show', 'Show only on main article, not teaser'. This last option means the Open the Image Gallery // link does not appear unless you are viewing the full item. I found this reduced the links a lot on our main pages. // On top of this I added a cuont items function to the api. This allowed me to query for how many images are publshed // for this particular node. I also computed for this content type how many full size images were already going to be // shown in the teaser and main body. I only show the gallery link if there are more images than are already shown in the node. $viewlink = variable_get('node_images_gallery_link_'.$node->type, 1); if (count($node->node_images) && $viewlink > 0) { if ((!$teaser && $viewlink==2) || $viewlink == 1) { // WS: Added a check to see if we have more images than are already displayed in full // check they are shown full size and how many of them $ifneeded = variable_get('node_images_gallery_if_needed_'.$node->type, TRUE); if ($ifneeded) { // Only show the gallery link if needed $fullsize = 0; $imagetype = variable_get('node_images_body_format_'.$node->type, 'thumb'); if ($imagetype == 'fullsize') { // Count the fullsize images shown in the body $fullsize = variable_get('node_images_body_images_' . $node->type, 1000); if ($fullsize == "") $fullsize = 1000; } $imagetype = variable_get('node_images_teaser_format_'.$node->type, 'thumb'); if ($imagetype == 'fullsize') { // Count the fullsize images shown in the teaser $teasercount = variable_get('node_images_teaser_images_' . $node->type, 1000); if ($teasercount == "") $teasercount = 1000; // If more are shown in the teaser then set fullsize to this value $fullsize = max($fullsize, $teasercount); } // $fullsize now contains a count of how many fullsize images are displayed on this node at the moment based // on this content type. // Get a count of how many images are associated with this node (returned in $node->node_images_count) node_images_nodeapi($node, 'count', $teaser, NULL); } // Only display the gallery link if there are more images than already visible on the node if (!$ifneeded || ($fullsize < $node->node_images_count)) { $links['node_images_gallery'] = array( 'title' => $page. t('Open the image gallery'), 'href' => "node/$node->nid/image_gallery", ); } } } // WS: End fo modified code } return $links; } /** * Implementation of hook_user(). */ function node_images_user($type, &$edit, &$user, $category = NULL) { switch ($type) { case 'delete': // Set uid=0 for images uploaded by the deleted user db_query('UPDATE {node_images} SET uid=0 WHERE uid=%d', $user->uid); } } /** * Implementation of hook_file_download(). * Find out if an image is accessible when download method is set to private */ function node_images_file_download($file) { $path = file_create_path($file); $result = db_query("SELECT * FROM {node_images} WHERE filepath='%s' OR thumbpath='%s'", $path, $path); if ($file = db_fetch_object($result)) { $node = node_load($file->nid); if (node_access('view', $node)) { if ($path == $file->thumbpath) { // update header info if thumb is requested $name = mime_header_encode(basename($file->thumbpath)); $size = $file->thumbsize; } else { $name = mime_header_encode($file->filename); $size = $file->filesize; } $type = mime_header_encode($file->filemime); return array( 'Content-Type: '. $type .'; name='. $name, 'Content-Length: '. $size, 'Cache-Control: private' ); } else { return -1; } } } /************************************************************ * Node edit functions ************************************************************/ /** * Display the page to edit and upload node images. * * @param $node * the current node * @return * the node images page. */ function _node_images_edit_form($node) { global $user; $output = '
'; // Generate image list $sql = db_query('SELECT * FROM {node_images} WHERE nid=%d ORDER BY weight', $node->nid); if (db_num_rows($sql)>0) $output .= drupal_get_form('_node_images_list', $node, $sql); // test if this node can accept new images // i.e. there might be limits to the number of uploaded images for certain node types or user roles // if the hook is not present in the node type module, upload is enabled by default $upload = module_invoke($node->type, 'node_images', 'upload', $node); if ($upload !== FALSE) { $output .= drupal_get_form('_node_images_edit_form_upload', $node); } $output .= '
'; drupal_set_title(check_plain($node->title)); return $output; } function _node_images_edit_form_upload($node) { $path = file_directory_path().'/'.variable_get('node_images_path', 'node_images'); _node_images_check_directory(NULL, $path); $extensions = variable_get('node_images_extensions', 'jpg jpeg gif png'); drupal_add_js('misc/progress.js'); drupal_add_js('misc/upload.js'); // Generate upload form $form['new'] = array( '#type'=>'fieldset', '#title'=>t('Upload a new image'), ); $form['new']['description'] = array( '#type' => 'textfield', '#title' => t('Description'), '#size' => 50, '#maxlength' => 255, '#default_value' => $edit['new']['description'], '#description' => t('Enter a description for the new image, max 255 chars.'), '#prefix' => '
', '#suffix' => '
', ); $form['new']['weight'] = array( '#type' => 'weight', '#title' => t('Weight'), '#prefix' => '
', '#suffix' => '
', ); $form['new']['upload'] = array( '#type' => 'file', '#title' => t('Image file'), '#size' => 50, '#description' => t('Allowed file types: %extensions', array('%extensions' => $extensions)), '#prefix' => '
', '#suffix' => '
', ); $form['new']['submit'] = array( '#type' => 'button', '#value' => t('Upload'), '#name'=> 'submit', '#id' => 'attach-button', ); // The class "upload" triggers the js upload behaviour. $form['attach-url'] = array( '#type' => 'hidden', '#value' => url('node_images/js', NULL, NULL, TRUE), '#attributes' => array('class' => 'upload'), ); // Needed for JS $form['nid'] = array( '#type' => 'hidden', '#value' => $node->nid, ); $form['#attributes']['enctype'] = 'multipart/form-data'; return $form; } /** * Generate a list of images associated to the current node. * * @param $node * the current node * @param $result * SQL result containing the node images * @return * a form representing the image list. */ function _node_images_list($node, $result) { global $user; $images = array(); $form['rows'] = array('#tree' => TRUE); $delete_access = node_access('delete', $node); while ($image = db_fetch_object($result)) { $images[$image->id] = $image; $form['rows'][$image->id]['description'] = array( '#type' => 'textfield', '#default_value' => $image->description, '#size' => 30, '#maxlength' => 255, ); $form['rows'][$image->id]['weight'] = array( '#type' => 'weight', '#default_value' => $image->weight, ); // images can be deleted only by users having delete access or users who uploaded the images $disabled = (!$delete_access && $user->uid != $image->uid); $form['rows'][$image->id]['delete'] = array('#type' => 'checkbox', '#disabled' => $disabled); } $form['nid'] = array('#type' => 'value', '#value' => $node->nid); $form['save'] = array( '#type' => 'submit', '#value' => t('Save changes'), ); $form['images'] = array( '#type' => 'value', '#value' => $images, ); $form['#theme'] = 'node_images_list'; // action must be set, otherwise it will be replaced by "node_images/js" (current $_GET['q'] on JS uploads) $form['#action'] = url('node/'.$node->nid.'/images'); return $form; } /** * Theme node images list. */ function theme_node_images_list($form) { $header = array(t('Thumbnail'), t('Description').' / '.t('Path'), t('Size'), t('Weight'), t('Delete')); $rows = array(); foreach($form['images']['#value'] as $id=>$image) { $row = array(); $row[] = ''; $row[] = drupal_render($form['rows'][$image->id]['description']).$image->filepath; $row[] = array('data' => format_size($image->filesize), 'style' => 'white-space: nowrap'); $row[] = drupal_render($form['rows'][$image->id]['weight']); $row[] = array('data' => drupal_render($form['rows'][$image->id]['delete']), 'align' => 'center'); $rows[] = $row; } $output = '
'.t('Uploaded images').''; $output .= theme('table', $header, $rows); $output .= drupal_render($form); $output .= '
'; return $output; } /** * Process result from node images list. */ function _node_images_list_submit($form_id, $form_values) { global $user; $node = node_load($form_values['nid']); if (!node_access('update', $node)) return; $delete_access = node_access('delete', $node); foreach($form_values['rows'] as $id => $edit) { if ($edit['delete']) { $r = db_fetch_object(db_query('SELECT filepath, thumbpath, uid FROM {node_images} WHERE id=%d AND nid=%d', $id, $node->nid)); // if user has no delete access to the node, he can delete his own images only if (!$delete_access && $user->uid != $r->uid) continue; // delete selected image file_delete($r->filepath); file_delete($r->thumbpath); db_query('DELETE FROM {node_images} WHERE id=%d AND nid=%d', $id, $node->nid); } else { // update image data db_query('UPDATE {node_images} SET description="%s", weight=%d WHERE id=%d AND nid=%d', $edit['description'], $edit['weight'], $id, $node->nid); } } drupal_set_message(t('The changes have been saved.')); } /** * Upload a new image and associate it to the current node. * * @param $edit * array containing the submitted values * @param $node * the image file * @return * the uploaded image file, or FALSE if upload fails */ function _node_images_upload($edit, $node) { global $user; if (($file = file_check_upload()) && user_access('create node images')) { // The uploaded file must be an image $info = image_get_info($file->filepath); if (!$info) { form_set_error('upload', t('The uploaded file !name is not a valid image.', array('!name' => theme('placeholder', $file->filename)))); return FALSE; } //Munge the filename as needed for security purposes. $file->filename = upload_munge_filename($file->filename, NULL, 0); // Validate file extension $extensions = variable_get('node_images_extensions', 'jpg jpeg gif png'); $regex = '/\.('. ereg_replace(' +', '|', preg_quote($extensions)) .')$/i'; if (!preg_match($regex, $file->filename)) { form_set_error('upload', t('The selected file !name can not be uploaded, because it is only possible to attach files with the following extensions: !files-allowed.', array('!name' => theme('placeholder', $file->filename), '!files-allowed' => theme('placeholder', $extensions)))); return FALSE; } // Validate max images for the current node $sql = db_query('SELECT * FROM {node_images} WHERE nid=%d', $node->nid); $max = variable_get('node_images_max_images', 4); $count = db_num_rows($sql); if ($count >= $max) { form_set_error('upload', t('The selected file !name can not be uploaded, because it exceeds the maximum limit of !max files.', array('!name' => theme('placeholder', $file->filename), '!max' => theme('placeholder', $max))), 'error'); return FALSE; } // Scale image to the maximum allowed resolution (default is 400x300) // (if not set in the node_images admin settings, use the default upload max resolution list($width, $height) = explode('x', variable_get('node_images_large_resolution', '400x300')); if (!$width || !$height) { list($width, $height) = explode('x', variable_get('upload_max_resolution', '400x300')); } if (!$width || !$height) { list($width, $height) = explode('x', '400x300'); } 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' => $width.'x'.$height))); } } // Validation from upload.module $fid = 'upload_'.$user->uid; $node->files = array($fid => $file); _upload_validate($node); if (!isset($node->files[$fid])) return FALSE; // Normalize filename and check description $dest = _node_images_get_directory(); if (trim($edit['description']) == '') { $edit['description'] = basename($file->filename); } if (variable_get('node_images_md5name', FALSE)) { // set md5 file name $extension = substr($file->filename, strrpos($file->filename, '.') + 1); $file->filename = substr(md5($dest.'/'.$file->filename), 0, 16); if ($extension) $file->filename .= '.'.$extension; } $file->filename = preg_replace('/ +/', '_', $file->filename); // Save uploaded image if ($file = file_save_upload($file, $dest.'/'.strtolower($file->filename))) { $thumb = _node_images_create_thumbnail($file->filepath); $file->filesize = filesize($file->filepath); db_query("INSERT INTO {node_images} (nid, uid, filename, filepath, filemime, filesize, thumbpath, thumbsize, weight, description) VALUES (%d, %d, '%s', '%s', '%s', %d, '%s', %d, %d, '%s')", $edit['nid'], $user->uid, $file->filename, $file->filepath, $file->filemime, $file->filesize, $thumb->filepath, $thumb->filesize, $edit['weight'], $edit['description']); } return $file; } } /************************************************************ * Node view functions ************************************************************/ /** * Show node images in the node view. */ function theme_node_images_view($node, $teaser, $page, $format = NULL) { if (arg(2) == 'image_gallery' || empty($node->node_images)) return; $output = ''; $i = 0; // set maximum number of images for teaser/body $view = ($teaser ? 'teaser' : 'body'); $count = variable_get('node_images_'.$view.'_images_'.$node->type, 2); if (isset($count) && $count === 0) return; if (!$format) { $format = variable_get('node_images_'.$view.'_format_'.$node->type, 'thumbs'); } foreach((array)$node->node_images as $id=>$image) { $description = check_plain($image->description); $pattern = '%description'; $thumb = strtr($pattern, array('%path'=>file_create_url($image->thumbpath), '%description'=>$description)); $fullsize = strtr($pattern, array('%path'=>file_create_url($image->filepath), '%description'=>$description)); if ($info = getimagesize($image->filepath)) { $width = $info[0] + 36; $height = $info[1] + 36; } else { $width = 420; $height = 315; } if ($format == 'thumbs') { $output .= ''.$thumb.' '; } else { $output .= $fullsize.' '; } if ($count>0 && ++$i >= $count) break; } return $output; } /************************************************************ * Gallery functions ************************************************************/ function _node_images_gallery($node) { if (empty($node->node_images)) { drupal_set_message(t('No images uploaded for this content.')); if (user_access('create node images') && node_access('update', $node)) { $output = t('Click here to upload new images.', array('!url' => url('node/'.$node->nid.'/images'))); } return '

'.$output.'

'; } $settings = array('images' => array()); $i = 1; $thumbs = array(); foreach ($node->node_images as $id=>$image) { $thumb_path = file_create_url($image->thumbpath); $thumbs[$i] = array( 'src' => $thumb_path, 'title' => $image->description, ); $path = $image->filepath; $info = image_get_info($path); $settings['images'][$i++] = array( 'src' => file_create_url($path), 'title' => $image->description, 'description' => $image->description, 'width' => $info['width'], 'height' => $info['height'], 'thumb' => $thumb_path, ); } $total = count($settings['images']); if ($total > 0) { $current = (int)$_GET['page']; $current = ($current < 1 || $current > $total) ? 1 : $current; $settings['current'] = $current; $settings['total'] = $total; $path = drupal_get_path('module', 'node_images'); drupal_add_js($path.'/node_images.js'); drupal_add_js(array('slideshow' => array($node->nid => $settings)), 'setting'); drupal_add_css($path.'/node_images.css'); $slideshow = array( '#type' => 'node_images_gallery', '#title' => $settings['images'][$current]['title'], '#attributes' => array('class' => 'slideshow-'. $node->nid), '#status' => array( 'current' => $current, 'total' => $total, 'previous' => $current < 1 ? $total : $current - 1, 'next' => $current >= $total ? 1 : $current + 1, ), '#image' => $settings['images'][$current], '#weight' => -5, ); } list($width, $height) = explode('x', variable_get('upload_max_resolution', 0)); $output = ''; $output .= ''; $output .= ''; $output .= '
'.drupal_render($slideshow).''.theme('node_images_gallery_thumbs', $thumbs).'
'; $output .= '
'.node_view($node); $title = t('Photo gallery for %title', array('%title' => $node->title)); drupal_set_title($title); return $output; } function theme_node_images_gallery($element) { $output = '
'. l(t('Previous'), $_GET['q'], array('class' => 'previous', 'rel' => 'nofollow'), 'page='. $element['#status']['previous']) .' | '. t('Image !current of !total', array( '!current' => ''. $element['#status']['current'] .'', '!total' => ''. $element['#status']['total'] .'')) .' | '. l(t('Next'), $_GET['q'], array('class' => 'next', 'rel' => 'nofollow'), 'page='. $element['#status']['next']) .'

'. $element['#title'] .'

'; return $output; } function theme_node_images_gallery_thumbs($thumbs, $cols = 2) { $count = count($thumbs); $output = ''; $i = 0; foreach($thumbs as $id => $thumb) { if ($i % $cols == 0) $output .= ''; $description = '
'.truncate_utf8($thumb['title'], 40, FALSE, TRUE).'
'; $output .= ''; if ($i % $cols == $cols - 1 || $n >= $count) $output .= ""; $i++; } $output .= '
'.l('', $_GET['q'], array('title' => $thumb['title'], 'rel' => 'nofollow'), 'page='.$id, NULL, FALSE, TRUE).$description.'
'; return $output; } /************************************************************ * Helper functions - admin settings ************************************************************/ /** * Menu callback; admin settings page. */ function node_images_admin_settings() { _node_images_check_settings(); $form['node_images_path'] = array( '#type' => 'textfield', '#title' => t('Node images path'), '#default_value' => variable_get('node_images_path', 'node_images'), '#maxlength' => 255, '#description' => t('Subdirectory in the directory %dir where the node images will be stored. This directory has to exist and be writable by Drupal. You can use the following variables: %uid, %username', array('%dir' => file_directory_path() .'/')), '#after_build' => array('_node_images_check_directory'), ); $form['node_images_large_resolution'] = array( '#type' => 'textfield', '#title' => t('Resolution for large images'), '#default_value' => variable_get('node_images_large_resolution', '400x300'), '#size' => 19, '#maxlength' => 9, '#description' => t('The size for large images in the node gallery, expressed as WIDTHxHEIGHT (e.g. 400x300). If not set, the image will be resized to the maximum allowed resolution in the upload module settings.'), ); $form['node_images_thumb_resolution'] = array( '#type' => 'textfield', '#title' => t('Resolution for thumbnails'), '#default_value' => variable_get('node_images_thumb_resolution', '100x100'), '#size' => 15, '#maxlength' => 7, '#description' => t('The thumbnail size expressed as WIDTHxHEIGHT (e.g. 100x75).'), ); $form['node_images_extensions'] = array( '#type' => 'textfield', '#title' => t('Default permitted image extensions'), '#default_value' => variable_get('node_images_extensions', 'jpg jpeg gif png'), '#maxlength' => 255, '#description' => t('Default image extensions that users can upload. Separate extensions with a space and do not include the leading dot.'), ); $form['node_images_max_images'] = array( '#type' => 'textfield', '#title' => t('Maximum number of images'), '#default_value' => variable_get('node_images_max_images', 4), '#size' => 6, '#maxlength' => 2, '#description' => t('The maximum number of images a user can upload for each node.'), ); $form['node_images_md5name'] = array( '#type' => 'checkbox', '#title'=> t('MD5 filenames'), '#description' => t('Override uploaded filenames with the MD5 hash of the file.'), '#default_value' => variable_get('node_images_md5name', FALSE), ); return system_settings_form($form); } /** * Checks if the upload.module is enabled, and the existence of an image toolkit. * * @param $form_element * The form element containing the name of the directory to check. */ function _node_images_check_settings() { // Make sure upload module is enabled if (!module_exists('upload')) { drupal_set_message(t('node_images.module require upload.module to be enabled.'), 'error'); } // Make sure we've got a working toolkit if (!image_get_toolkit()) { drupal_set_message(t('Make sure you have a working image toolkit installed and enabled, for more information see: %settings', array('%settings' => l(t('the settings page'), 'admin/settings/image-toolkit'))), 'error'); } } /************************************************************ * Helper functions - other ************************************************************/ /** * Checks the existence of the destination directory. * The directory can be specified either in $form_element (when called from the admin settings) * or in $path (when called from the node images edit page). * * @param $form_element * The form element containing the name of the directory to check. */ function _node_images_check_directory($form_element = NULL, $path = '') { global $user; $variables = array('%uid' => $user->uid, '%username' => $user->name); if ($form_element) { $path = file_directory_path().'/'.strtr($form_element['#value'], $variables); _node_images_mkdir_recursive($path, FILE_CREATE_DIRECTORY, $form_element['#parents'][0]); return $form_element; } $path = strtr($path, $variables); _node_images_mkdir_recursive($path, FILE_CREATE_DIRECTORY, $form_element['#parents'][0]); } function _node_images_mkdir_recursive($path, $mode, $form_item) { $folders = explode("/", $path); $dirs = array(); foreach($folders as $folder) { $dirs[] = $folder; $dir = implode('/', $dirs); if (!file_check_directory($dir, $mode, $form_item)) { mkdir($dir); } } } /** * Return the destination directory. */ function _node_images_get_directory() { global $user; $path = file_directory_path().'/'.variable_get('node_images_path', 'node_images'); return strtr($path, array('%uid' => $user->uid, '%username' => $user->name)); } /** * Create the thumbnail for the uploaded image. */ function _node_images_create_thumbnail($source, $suffix = '_tn') { $size = variable_get('node_images_thumb_resolution', '100x100'); list($width, $height) = explode('x', $size); $dest = preg_replace('!(\.[^/.]+?)?$!', "$suffix\\1", $source, 1); if ($size = @getimagesize($source)) { if (!image_scale($source, $dest, $width, $height)) { file_copy($source, $dest, FILE_EXISTS_REPLACE); } $info = image_get_info($dest); $thumb = new stdClass(); $thumb->filename = basename($dest); $thumb->filepath = $dest; $thumb->filesize = $info['file_size']; $thumb->filemime = $info['mime_type']; return $thumb; } return NULL; } /** * Determine how much disk space is occupied by a user's uploaded files. * * @param $uid * The integer user id of a user. * @return * The amount of disk space used by the user in bytes. */ function _node_images_space_used($uid) { return db_result(db_query('SELECT SUM(filesize+thumbsize) FROM {node_images} WHERE uid=%d', $uid)); } /** * Menu-callback for JavaScript-based uploads. */ function _node_images_js() { $edit = $_POST; if ($nid = $edit['nid']) { $node = node_load($nid); // upload image _node_images_upload($edit, $node); // generate node images edit page $form = _node_images_edit_form($node); } else { drupal_set_message(t('Unable to attach images to the current node.')); } $output = theme('status_messages'); if ($form) $output .= $form; // We send the updated file attachments form. print drupal_to_js(array('status' => TRUE, 'data' => $output)); exit(); } /************************************************************ * Views API hooks ************************************************************/ /** * Implementation of hook_views_default_tables(). */ function node_images_views_tables() { require_once './'. drupal_get_path('module', 'node_images') .'/node_images.views.inc'; return _node_images_views_tables(); } /** * Implementation of hook_views_pre_query(). */ function node_images_views_pre_query() { require_once './'. drupal_get_path('module', 'node_images') .'/node_images.views.inc'; }