http://drupal.org/project/imagecache_external Would benefit cases like #334630: Cache gravatar images locally to store external images as profile pictures.

Comments

andypost’s picture

Any ideas?

lightsurge’s picture

I'm not sure how imagecache profiles hooks into core just now.

But on a really simplistic level... In the case of image cache external being enabled, we could give users an option of an absolute url path instead of upload/relative path (for both user pictures and default pictures), and when imagecache profiles comes across an external url instead of a relative path, it could just wrap the imagecache external function around it imagecache_external_generate_path($url, $preset) instead of calling in an imagecache preset in the normal way.

andypost’s picture

So anyway we need to store some data locally. I think it's better to fetch remote data and ICP will work as usual

lightsurge’s picture

You mean so ICP grabs the image instead of doing anything with IC external? Fair enough, although it does have some added benefits of whitelist/blacklist of external addresses, ability to flush grabbed images (to periodically update the source image in case of change, as opposed to just flushing the imagecache).

andypost’s picture

The core ICP functionality in imagecache_profiles_preprocess_user_picture() function

So is enough to set $account->picture to some file ID and 'user_picture_style' variable

$account->picture = $file_id; // Or assign a image-file object itself.
// $account->picture->uri is ONLY used for theme_image_style().

// Optionally assign a style to file. 
// $account->picture->style_name = 'medium';
// Or account itself.
// $account->user_picture_style = 'large';
$output = theme('user_picture', array('account' => $account, 'user_picture_style' => 'thumbnail')); 
lightsurge’s picture

I don't totally see how this is easier or offers any extra value?

Can't just do something like this (this is 6.x code)?

$variables['picture'] = $default; //theme('image', $picture, $alt, $alt, '', FALSE);
      }
      else {
        if (!empty($account->uid) && user_access('access user profiles')) {
          $title = t('View user profile.');
          $attributes = array('attributes' => array('title' => $title), 'html' => TRUE);
	  if (!file_exists($picture) && valid_url($picture, TRUE) && module_exists(imagecache_external)) { // if no file but is a valid url, use ICE to get the image in the appropriate format
            $image = theme_image(imagecache_external_generate_path($picture, $preset['presetname']), $alt, $title, $attributes);
	  }
	  else {
            $image = theme('imagecache', $preset['presetname'], $picture, $alt, $title);
	  }
        $variables['picture'] = l($image, "user/$account->uid", $attributes);
        }
        else if (!file_exists($picture) && valid_url($picture, TRUE) && module_exists(imagecache_external)) { //same if uid is empty
          $variables['picture'] = theme_image(imagecache_external_generate_path($picture, $preset['presetname']), $alt, $title, $attributes);
	}
	else {
          $variables['picture'] = theme('imagecache', $preset['presetname'], $picture, $alt, $alt);
        }
      }
    }
  }
}
lightsurge’s picture

Tested this and it works fine in principle (although there are errors in above code). I couldn't figure out how to pass $account->picture from one lower-weight preprocess to ICP, so ended up adding a new variable $variables['picture_override'] which allows it to be carried from one to the other:

    if (isset($variables['picture_override'])) {
    $picture = $variables['picture_override'];
    }    
    else if (!empty($account->picture) && file_exists($account->picture)) {
      $picture = $account->picture;
    }
    else if (variable_get('user_picture_default', '')) {
      $picture = variable_get('user_picture_default', '');
    }

    if (isset($picture)) {

But there must be a better way.

Also, this doesn't work with Views for some reason which continues with the unaltered image, guessing something to do with imagecache_profiles_handler_field_user_picture.inc, but I can't see why.

andypost’s picture

Suppose you need to change module's weight to order _preprocess functions
Also views uses $account->picture.

lightsurge’s picture

If you think that's the only way then it probably is.

I think I just didn't understand what you were doing with imagecache_profiles_handler_field_user_picture.inc

I didn't really understand if the $this->that thing was actually pulling in real information (realise that might sound pretty stupid but I just don't know if these are real variables, thought it might be a sense of humour - still learning!) or just an empty object. If not, I suppose $account->uid might be within the information that Views generates when getting the $account->picture field, so we could probably fill in more real data to $account instead of giving just empty information.

andypost’s picture

As I pointed above views handler just sets $account->imagecache_preset and calls theme('user_picture')

lightsurge’s picture

Turned out it was just a template overriding the handler, grr. Why Commons has a template that does exactly the same job as this module, I don't know.

So these 3 small changes are pretty much all we'd need to get gravatar/libravatar/imagecache_external integration. This way modules with a lower weight can override the image that imagecache_profiles then manipulates.

The substr in file_create_url(substr(imagecache_external_generate_path($picture, $preset['presetname']), 1)); was only necessary for me I think, because ICE seems to add an initial / which messes up file_create_url.

    if (isset($variables['picture_override'])) { 
      $picture = $variables['picture_override']; // add an override variable for modules to alter user pictures before imagecache profiles processes them
    }    
    else if (!empty($account->picture) && file_exists($account->picture)) {
      $picture = $account->picture;
    }
    else if (variable_get('user_picture_default', '')) {
      $picture = variable_get('user_picture_default', '');
    }

if (isset($picture)) {
      $alt = t("@user's picture", array('@user' => $account->name ? $account->name : variable_get('anonymous', t('Anonymous'))));
      $preset = is_numeric($size) ? imagecache_preset($size) : imagecache_preset_by_name($size);
      if (empty($preset)) {
        $variables['picture'] = $default; //theme('image', $picture, $alt, $alt, '', FALSE);
      }
      else {
        if (!empty($account->uid) && user_access('access user profiles')) {
          $title = t('View user profile.');
          $attributes = array('attributes' => array('title' => $title), 'html' => TRUE);
          if (!file_exists($picture) && valid_url($picture, TRUE) && module_exists(imagecache_external)) { 
	    $imagecacheexternalpath = file_create_url(substr(imagecache_external_generate_path($picture, $preset['presetname']), 1)); // if external image being used
            $image = theme_image($imagecacheexternalpath, $alt, $title, $attributes, FALSE);
          }
          else {
            $image = theme('imagecache', $preset['presetname'], $picture, $alt, $title);
            }
            $variables['picture'] = l($image, "user/$account->uid", $attributes);
        }
        else if (!file_exists($picture) && valid_url($picture, TRUE) && module_exists(imagecache_external)) { 
	  $imagecacheexternalpath = file_create_url(substr(imagecache_external_generate_path($picture, $preset['presetname']), 1)); // same again
          $variables['picture'] = theme_image($imagecacheexternalpath, $alt, $alt, $attributes, FALSE);
        }
        else {
          $variables['picture'] = theme('imagecache', $preset['presetname'], $picture, $alt, $alt);
        }
      }
    }
lightsurge’s picture