A while back I was asking about how to easily incoporporate image.module functionality into a module.

I got it working and thought I would share it here in case anyone else is trying to do this. This solution requires under 50 lines of code and will ignore the image functionality if image.module is not enabled on the site.

Step 1. hook_form

Add this code into your hook_form function.

  // image form code
  if(function_exists('_image_check_settings')){
    _image_check_settings();
    $param['options'] = array("enctype" => "multipart/form-data");
    if (is_array($node->images)) {
      foreach ($node->images as $label => $image) {
        $output .= form_hidden('images]['.$label, $image);
      }
    }
    if ($node->images['thumbnail']) {
      $output.= form_item(t('Thumbnail'), image_display($node, 'thumbnail'));
    }
    $output .= form_file(t('Image'), 'image', 50, t('Click "Browse..." to select an image to upload.'), TRUE);
  }

Step 2. hook_insert

First, you will need to change hook_insert($node) to hook_insert(&$node). This is because image_validate acts on the $node object and if you do not import the reference to the actual $node object via the '&' prefix, these changes will be lost. After this change has been made, add this code:

  // image insert code (remember that image.module acts on $node to create $node->images)
  if(function_exists('image_validate') && function_exists('_image_insert')){
    image_validate($node, 'image');
    foreach ($node->images as $label => $image) {
      _image_insert($node->nid, $label, file_create_path($image));
    }
  }

Step 3. hook_update

First change hook_update($node) to hook_update(&$node) for the same reasons listed above. Then add this code to the function:

  // image update code
  if(function_exists('image_validate') && function_exists('_image_insert')){
  image_validate($node, 'image');
  foreach ($node->images as $label => $image) {
    $old_path = db_result(db_query("SELECT filepath FROM {files} WHERE filename='%s' AND nid=%d", $label, $node->nid));
    // This is a new image.
    if ($old_path != $image) {
      file_delete(file_create_path($old_path));
      db_query("DELETE FROM {files} WHERE filename='%s' AND nid=%d", $label, $node->nid);
      _image_insert($node->nid, $label, file_create_path($image));
    }
  }

Step 4. hook_view / your custom view theme function

Now we want to put the following code into either hook_view or the custom theme function you are using to view a node created by your module. This method can also be used to add the image into the teaser.

  // image view code
  if(function_exists(image_display)){
    if($node->images){
      $request = ($_GET['size']) ? $_GET['size'] : 'preview';
      $output .= l(image_display($node, 'thumbnail'), 'node/'.$node->nid, array(), NULL, NULL, FALSE, TRUE);
    }
  }

Step 5. settings / admin

The above code uses the function_exists check and is written in such a way that if the Image module is not enabled on your site, all the image code will be ignored. As a result, you may want to allow system admins to know why the image functionality is not available for their site. Add something like this in your settings / admin screen:

  // Let the admin know that images are not enabled if the module is not found
  if(!function_exists(_image_check_settings)){
    drupal_set_message(t('The Image module is not enabled. This module needs it enabled in order to allow users to upload images. If you would like to take advantaeg of the image upload functions, please enable image module.'), 'message');
  }

Hope that saves people some time. Any suggestions are welcome.

Also, as Boris Mann and sepeck suggested to me, check out the code from walkah's image.module and mathias' img_assists for more.

Enjoy.

Comments

seanbfuller’s picture

The image viewing code in step four is somewhat incomplete. It creates the image as a link to the node you are already viewing, which is a bit silly.

I rewrote the code to allow thumbnails to link to the larger versions of the image. Here it is:

  // image code
  if(function_exists('image_display')){
    if($node->images){
      $request = ($_GET['size']) ? $_GET['size'] : 'thumbnail';
	  if($request == 'preview'){
	    $image_output = '';	  
        $image_output .= '<div class="image_backtonode">Back to '. l($node->title, 'node/'.$node->nid) .'</div><br />'."\n";
        if (variable_get('image_view_original', 0)) {
          $image_output .= l(image_display($node, $request), 'node/'.$node->nid .'&size=_original', array(), NULL, NULL, FALSE, TRUE);
        } else {
          $image_output .= image_display($node, $request);
        }
		return $image_output;
      } 
	  else if($request == '_original'){
	    $image_output = '';	  
        $image_output .= '<div class="image_backtonode">Back to '. l($node->title, 'node/'.$node->nid) .'</div><br />'."\n";
	    $image_output .= image_display($node, $request);
		return $image_output;
	  }
	  else {
	    $output .= l(image_display($node, $request), 'node/'.$node->nid .'&size=preview', array(), NULL, NULL, FALSE, TRUE);	    
	  }
    }
  }

Notice that it also creates a link back to the node.

--------------------
Sean B. Fuller
www.seanbfuller.com

seanbfuller’s picture

You will also need to add a reference to the $param object in your hook_form by changing this:

function example_form(&$node) {

to this:

function example_form(&$node, &$param) {

Sorry about leaving that out.

--------------------
Sean B. Fuller
www.seanbfuller.com

seanbfuller’s picture

You will also need to add some code to hook_load. Here is what mine looks like:

 function example_load(&$node) {

  // first I load my other stuff into $additions
  //$additions = db_fetch_object(/* node type data load here */);
  
  // image loading code lifted from image.module
  // changed from $node to $additions allowing the object to be passed back to node_load()
  $result = db_query("SELECT filename, filepath FROM {files} WHERE nid=%d", $node->nid);
  $additions->images = array();
  while ($file = db_fetch_object($result)) {
    $additions->images[$file->filename] = $file->filepath;
  }
  // special images
  if(!empty($additions->images['_original'])){
    if (empty($additions->images['thumbnail'])) {
      $additions->images['thumbnail'] = $additions->images['_original'];
    }
    if (empty($additions->images['preview'])) {
      $additions->images['preview'] = $additions->images['_original'];
    }
  }

  return $additions;
}

--------------------
Sean B. Fuller
www.seanbfuller.com

kerrizor’s picture

I think you're missing a closing parens in Step 3.

Testing right now.. this is cool :)

kerrizor’s picture

Upload seems to work fine, but I'm having trouble with retreiving the image from node->image. Probably just me tho.

seanbfuller’s picture

Make sure you are passing the reference to the node object into the functions.

Also, I suggest putting a print_r($node); in your view functions. You should see an array element in there that looks like this:

[images] => Array ( [_original] => images/thailand5_0.jpg [thumbnail] => images/thailand5_0.thumbnail.jpg [preview] => images/thailand5_0.preview.jpg ) 

If not, then the images array is not getting set into the $node correctly. Your best bet is to move your print_r statement up higher (ie- node_load).

Also, check the files database to make sure everything is getting saved.

There's a good chance something is missing in the code above, but I can't edit the original post. For now, we will have to post comments for fixes. When this code is a bit more solid maybe it can be added to the handbook or whatever.

Sean
www.seanbfuller.com

--------------------
Sean B. Fuller
www.seanbfuller.com

kerrizor’s picture

..I just missed step 6, so I wasn't actually loading.. I left in the middle of installing, and lost my place, that's all :)

Thanks for showing the way on this.

maartenstorm’s picture

What can be wrong when I get these error messages?

warning: Invalid argument supplied for foreach() in /var/www/localhost/htdocs/drupal-4.6.3/modules/node_composer.module on line 116.

warning: Cannot modify header information - headers already sent by (output started at /var/www/localhost/htdocs/drupal-4.6.3/includes/common.inc:384) in /var/www/localhost/htdocs/drupal-4.6.3/includes/common.inc on line 192.

I have installed the images module and before I added this code my own module (node_composer.module) was working fine.

Thanks for helping me out

Maarten

seanbfuller’s picture

Good chance you are getting a null argument instead of the array that the foreach loop is using. Try doing a print_r() of whatever you are looking at in the foreach loop at line 116.

If that doesn't show you the problem, post your code around line 116.

www.seanbfuller.com

--------------------
Sean B. Fuller
www.seanbfuller.com

coupet’s picture

Excellent thread!

Updates for 4.7?

Thanks, Darly
---------------------
Apache is bandwidth limited, PHP is CPU limited, and MySQL is memory limited.

vikramdhani’s picture

gr8 thread

nellus’s picture