The attached patch adds a module with a simple interface for associating images with taxonomy terms. The patch applies against current cvs. In addition to adding a new module and updating the database, it also updates the xtemplate theme to display category images (if enabled). If merged into core, all themes should then be updated to support category images.

Some changes may need to be made for this patch to be merged into core. Suggestions are welcome. (For example, perhaps the functionality should actually be merged into the taxonomy module itself?)

Features of this module include:
- integrated into existing taxonomy (category) menu structure
- allows one-to-one and many-to-one term-to-image relationships
- administrator can configure to auto-scale images
- images can be disabled by individual users (with proper permissions)
- utilizes core file api
- small, focused feature-set.

Requires:
- cvs version of Drupal
- taxonomy module

For a live demo, go to http://kerneltrap.org/

Screenshots to follow.

Comments

jeremy’s picture

StatusFileSize
new22.49 KB

Here's an overview look at the administrative interface. In this screenshot, one image has already been uploaded.

jeremy’s picture

StatusFileSize
new14.71 KB

Here's the upload page, after having clicked 'upload image'.

jeremy’s picture

StatusFileSize
new31.65 KB

And now we're back at the overview administration page, after having uploaded a new image.

jeremy’s picture

StatusFileSize
new24.08 KB

Here's the form you see when clicking 'edit image'. If you upload a new image when an old image was already uploaded, the old image will first be automatically deleted, then the new image will be saved.

jeremy’s picture

StatusFileSize
new26.28 KB

Here's a look at the module's settings page. It allows the administrator to auto-resize category images when displayed, and to support many-to-one term-to-image relationships (recursive image display) to support taxonomy hierarchies.

jeremy’s picture

StatusFileSize
new34.15 KB

And finally, here's a look at the front page of a site running with the patched xtemplate, displaying category images...

jeremy’s picture

StatusFileSize
new34.23 KB

I was asked how it handles multiple categories assigned to one node. This depends on the theme. The attached screenshot shows how xtemplate handles it with my patch applied, displaying both images together.

Anonymous’s picture

Excellent! I've been wishing Drupal had this feature for a long time; this would be so much easier than hardcoding images into my theme.

How does this interact with the avatar functionality? (Meaning: What would it look like if someone enabled both avatar display and taxonomy image display for a node?)

dries’s picture

I'm in favor of integrating this into taxonomy.module. Maybe we could start by reviewing the GUI?

jeremy’s picture

Assigned: Unassigned » jeremy

The main argument for not merging this functionality into the taxonomy module is that it's very possible that the majority of Drupal users do not need this functionality.

Do you think it should retain its own menu item called 'images' under categories? Or should it actually be merged into the existing add/edit term page?

If kept as is, then what recommendations for improving the user interface?

If merged into the existing taxonomy add/edit page, where would you get an image overview? (It can't easily be added to the existing taxonomy overview page, which is already quite "busy")

jeremy’s picture

"How does this interact with the avatar functionality? (Meaning: What would it 
look like if someone enabled both avatar display and taxonomy image display for a 
node?)"

This is up to the theme implementation. I've never used avatars - I don't even know how - so I didn't give this any though with my sample patch. A quick look at the code, however, suggests that they would all be displayed together on the right side of the screen.

I'm not a gui guy. I would hope that theme designers would be the ones to actually add taxonomy_image support to their themes once this functionality is merged.

jeremy’s picture

StatusFileSize
new20.76 KB

I've updated the patch mainly per feedback on the drupal-devel mailing list:
- added support for private images
- stores images in configurable files/ subdirectory
- refers to images as pictures, to standardize with avatar support

This brings the patch current with all outstanding recommendations.
(BTW: If interested in trying the latest code with Drupal 4.4.x, download the cvs version of the module in contrib)

jeremy’s picture

FWIW: This module has been updated to work with the latest CVS code (Drupal 4.5). I'm not going to update this patch though, as I assume effort is being made to address this issue in another way. Should an updated patch be desired, let me know.

nedjo’s picture

The proposed patch is an improvement on functionality previously roughed in in the node_image module. I'd like to look at the possibility of rolling node_image functionality into this patch. Potential modifications might be:

  • Images could be associated with individual nodes as well as terms (and, perhaps, other objects, e.g., comments, vocabularies, and potentially user avatars).
  • Option for two image versions for each object: (a) for listings (generally, thumbnail versions) and (b) for full version (e.g., for node objects, display of one or other determined by value of $main variable). So, for instance, thumbnails would be displayed with listings of nodes in a taxonomy, while the full display of an individual node would display the full (potentially, larger) image.

Would extending this to include nodes make sense?

jeremy’s picture

As is, the module does exactly what I need it to do, so I'm very hesitant to add functionality.

However, the first idea on your list does interest me. I like the idea of being able to associate an image to a specific node, as opposed to only a taxonomy term. I would be interested in seeing a patch that accomplishes this without making the user interface exceedingly difficult. (ie, where would the administrative interface go for listing/editing/deleting these images go?)

nedjo’s picture

I strongly support inclusion of this functionality in core. Yet I think it would be worth the time to genericize image association so that it can be used with multiple object types (at a minimum, terms, vocabularies, and nodes) and multiple image categories (at a minimum, thumbnail and full). Hard-coding this to taxonomies would have the disadvantage of requiring different, partially duplicated systems for associating images with other object types. Given the sound design of taxonomy_image, this additional functionality could be added with a minimum of additional code.

I'm working on proposed revisions. Meantime, a few comments:

  • where would the administrative interface go for listing/editing/deleting these images go. This would be done, as in node_image, directly in the node editing form via a _nodeapi() hook.
  • Would require two additional fields in module table:
    CREATE TABLE associated_image (
      iid int(10) unsigned NOT NULL,
      type varchar(255) NULL,
      class varchar(255) NULL,
      path varchar(255) NULL,
      PRIMARY KEY (iid)
    );
    
  • To include node functionality, the main function would become:
    /**
     * Call this function from your theme or other php code to display the
     * image associated with the given object id.  An html <img> tag will be returned
     * if an image is found.  The format of the link can be modified with the
     * tags parameter.
     *
     * @param  int     $id	 id of term, node, or other object.
     * @param  string  $type type of object image associated with, e.g., 'term', 'node'
     * @param  string  $class class of image, e.g., 'thumb' (for thumbnail version), 'full'
     * @param  string  $tags optional tags to add into the <img src=''> link
     * 
     * @return string  An html <img src> link.
     */
    function associated_image_display($id, $type = 'term', $class = 'full', $tags = NULL) {
      global $user;
    
      if (user_access('access associated images') &&
          !$user->associated_image_disable_images) {
        // do lookup, return full display path
        if ($image = db_fetch_object(db_query('SELECT path FROM {associated_image} WHERE type = %s AND class = %s AND iid = %d', $type, $class, $id))) {
          $image->url = file_create_url($image->path);
        }
        else if (variable_get('associated_image_recursive', 0)) {
          // walk up the taxonomy hierarchy and look for an image
          if($type == 'node') {
            $tids = taxonomy_node_get_terms($node->nid);
            $tid = $tids[0]->tid;
          }
          if ($image = db_fetch_object(db_query('SELECT path FROM {associated_image} WHERE type = %s AND class = %s AND iid = %d', 'term', $class, $tid))) {
            $image->url = file_create_url($image->path);
          }
          else {
            while ($parent = db_fetch_object(db_query('SELECT t.tid FROM {term_hierarchy} h, {term_data} t WHERE h.parent = t.tid AND h.tid = %d ORDER BY weight, name', $tid))) {
              $tid = $parent->tid;
              if ($image = db_fetch_object(db_query('SELECT path FROM {associated_image} WHERE type = %s AND class = %s AND iid = %d', 'term', $class, $tid))) {
                // we found a parent with a configured image, use it
                $image->url = file_create_url($image->path);
                break;
              }
            }
          }
        }
        if ($image->url) {
          list($image->width, $image->height) = getimagesize($image->path);
          // handle image resizing
          switch (variable_get('associated_image_resize_' . $class, 0)) {
            case 3: // exact
              if ($width = variable_get('associated_image_width_' . $class, 0))
                $image->width = $width;
              if ($height = variable_get('associated_image_height_' . $class, 0))
                $image->height = $height;
              break;
            case 2: // not less than
              if (($width = variable_get('associated_image_width_' . $class, 0)) &&
                  ($width > $image->width)) {
                $width_scale = $image->width / $width;
              }
              if (($height = variable_get('associated_image_height_' . $class, 0)) &&
                  ($height > $image->height)) {
                $height_scale = $image->height / $height;
              }
              if ($height_scale || $width_scale) {
                if ($width_scale && $height_scale)
                  $scale = min($width_scale, $height_scale);
                else
                  $scale = $width_scale ? $width_scale : $height_scale;
                $image->height = $image->height / $scale;
                $image->width = $image->width / $scale;
              }
              break;
            case 1: // not greater than
              if (($width = variable_get('associated_image_width_' . $class, 0)) &&
                  ($width < $image->width)) {
                $width_scale = $image->width / $width;
              }
              if (($height = variable_get('associated_image_height_' . $class, 0)) &&
                  ($height < $image->height)) {
                $height_scale = $image->height / $height;
              }
              if ($height_scale || $width_scale) {
                $scale = max($width_scale, $height_scale);
                $image->height = $image->height / $scale;
                $image->width = $image->width / $scale;
              }
              break;
          }
          return "<img src='$image->url' width='$image->width' height='$image->height' $tags />";
        }
      }
      return '';
    }
    
  • Steven’s picture

    With the new image API, this function can probably be implemented very cleanly and with less code. Perhaps it should be revisited? I think many people will like it, but I also agree that it should not be in the way.

    dries’s picture

    moshe weitzman’s picture

    would be nice to get this one done. anyone?

    LAsan’s picture

    Version: x.y.z » 7.x-dev

    Feature request moving to cvs.

    dman’s picture

    Status: Active » Closed (won't fix)

    Woah!
    This is so old. Check that date.

    Surely taxonomy_image.module does all this nowadays?
    Closing this, unless someone can say why this optional feature needs to be core, or what that's described here is lacking and can't be put into taxonomy_image.
    Anyone interested can help out with taxonomy_image to make it more popular...

    dman’s picture

    double-post

    dman’s picture

    Woah!
    That double-post took 3 hours lost in the system!
    (triple-post actually, although I went back and checked each time before reposting :)