Gravatar Helper

By Graham Weldon (predominant)
From the Gravatar Website:
A gravatar, or globally recognized avatar, is quite simply an avatar image that follows you from weblog to weblog appearing beside your name when you comment on gravatar enabled sites. Avatars help identify your posts on web forums, so why not on weblogs?

Gravatars are a great addition to any blog, or indeed any user submitted content. This helper is designed to provide gravatar output without the fuss

Introduction

This is my first community posted code. Criticism welcome, but please be kind.

There isn't much to this Helper, so I will jump right in.

The code is available at the end of this article, and is also hosted on Github: http://github.com/predominant/CakePHP-Goodies


Usage

More than likely you just want to use the thing... Well, its as simple as this:


Including the helper in your application

As with any helper, ensure that it is included in the helpers array in your controller. This will allow you access to it when you need it, in your views.


Controller
Download code class MyController extends AppController {
  public $helpers = array('Gravatar');
  // ...
}

View

Basic Gravatar with default settings:

Download code <?php echo $gravatar->image('someone@cakeisawesome.com'); ?>

Altering the default gravatar:

Download code <?php echo $gravatar->image(
  
'someone@cakeisawesome.com',
  array(
    
'default' => 'identicon'
  
); ?>

Altering the default gravatar with a custom image:

Download code <?php echo $gravatar->image(
  
'someone@cakeisawesome.com',
  array(
    
'default' => 'http://mysite.com/defaultavatar.png'
  
)); ?>

Changing the gravatar size:

Download code <?php echo $gravatar->image(
  
'someone@cakeisawesome.com',
  array(
    
'default' => 'identicon',
    
'size' => 120
  
); ?>

Adjusting the gravatar ratings to display:

Download code <?php echo $gravatar->image(
  
'someone@cakeisawesome.com',
  array(
    
'rating' => 'x'
  
); ?>

Including image filename extension on the generated URL:

Download code <?php echo $gravatar->image(
  
'someone@cakeisawesome.com',
  array(
    
'default' => 'identicon',
    
'ext' => true
  
); ?>

Options

The options and their valid values are as follows:


default


size

  • Minimum value 1
  • Maximum value 512
In the event that your Gravatar size is outside these bounds, the helper will adjust it to be size 1 or 512, depending which side of the allowed range your specified value was.


rating

  • 'g'
  • 'pg'
  • 'r'
  • 'x'
If rating is either invalid or not specified, Gravatars will automatically be delivered for the 'g' rating. These ratings should be reasonably self explainatory.


ext

  • true
  • false
If not supplied, an image filename extension will not be included as part of the gravatar generation.


Helper Code

Helper Class:

Download code <?php 
<?php
App
::import(array('Security''Validation'));

/**
 * CakePHP Gravatar Helper
 *
 * A CakePHP View Helper for the display of Gravatar images (http://www.gravatar.com)
 *
 * @copyright Copyright 2010, Graham Weldon
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
 * @package goodies
 * @subpackage goodies.tests.cases.helpers
 *
 */
class GravatarHelper extends AppHelper {

/**
 * Gravatar avatar image base URL
 *
 * @var string
 * @access private
 */
    
private $__url = array(
        
'http' => 'http://www.gravatar.com/avatar/',
        
'https' => 'https://secure.gravatar.com/avatar/'
    
);

/**
 * Hash type to use for email addresses
 *
 * @var string
 * @access private
 */
    
private $__hashType 'md5';

/**
 * Collection of allowed ratings
 *
 * @var array
 * @access private
 */
    
private $__allowedRatings = array('g''pg''r''x');

/**
 * Default Icon sets
 *
 * @var array
 * @access private
 */
    
private $__defaultIcons = array('none''identicon''monsterid''wavatar''404');

/**
 * Default settings
 *
 * @var array
 * @access private
 */
    
private $__default = array(
        
'default' => null,
        
'size' => null,
        
'rating' => null,
        
'ext' => false);

/**
 * Helpers used by this helper
 *
 * @var array
 * @access public
 */
    
public $helpers = array('Html');

/**
 * Constructor
 *
 * @access public
 */
    
public function __construct() {
        
// Default the secure option to match the current URL.
        
$this->__default['secure'] = env('HTTPS');
    }

/**
 * Show gravatar for the supplied email address
 *
 * @param string $email Email address
 * @param array $options Array of options, keyed from default settings
 * @return string Gravatar image string
 * @access public
 */
    
public function image($email$options = array()) {
        
$imageUrl $this->url($email$options);
        unset(
$options['default'], $options['size'], $options['rating'], $options['ext']);
        return 
$this->Html->image($imageUrl$options);
    }

/**
 * Generate image URL
 *
 * @param string $email Email address
 * @param string $options Array of options, keyed from default settings
 * @return string Gravatar Image URL
 * @access public
 */
    
public function url($email$options = array()) {
        
$options $this->__cleanOptions(array_merge($this->__default$options));
        
$ext $options['ext'];
        
$secure $options['secure'];
        unset(
$options['ext'], $options['secure']);
        
$protocol $secure === true 'https' 'http';

        
$imageUrl $this->__url[$protocol] . $this->__emailHash($email$this->__hashType);
        if (
$ext === true) {
            
// If 'ext' option is supplied and true, append an extension to the generated image URL.
            // This helps systems that don't display images unless they have a specific image extension on the URL.
            
$imageUrl .= '.jpg';
        }
        
$imageUrl .= $this->__buildOptions($options);
        return 
$imageUrl;
    }

/**
 * Sanitize the options array
 *
 * @param array $options Array of options, keyed from default settings
 * @return array Clean options array
 * @access private
 */
    
private function __cleanOptions($options) {
        if (!isset(
$options['size']) || empty($options['size']) || !is_numeric($options['size'])) {
            unset(
$options['size']);
        } else {
            
$options['size'] = min(max($options['size'], 1), 512);
        }

        if (!
$options['rating'] || !in_array(mb_strtolower($options['rating']), $this->__allowedRatings)) {
            unset(
$options['rating']);
        }

        if (!
$options['default']) {
            unset(
$options['default']);
        } else {
            if (!
in_array($options['default'], $this->__defaultIcons) && !Validation::url($options['default'])) {
                unset(
$options['default']);
            }
        }
        return 
$options;
    }

/**
 * Generate email address hash
 *
 * @param string $email Email address
 * @param string $type Hash type to employ
 * @return string Email address hash
 * @access private
 */
    
private function __emailHash($email$type) {
        return 
Security::hash(mb_strtolower($email), $type);
    }

/**
 * Build Options URL string
 *
 * @param array $options Array of options, keyed from default settings
 * @return string URL string of options
 * @access private
 */
    
private function __buildOptions($options = array()) {
        
$gravatarOptions array_intersect(array_keys($options), array_keys($this->__default));
        if (!empty(
$gravatarOptions)) {
            
$optionArray = array();
            foreach (
$gravatarOptions as $key) {
                
$value $options[$key];
                
$optionArray[] = $key '=' mb_strtolower($value);
            }
            return 
'?' implode('&amp;'$optionArray);
        }
        return 
'';
    }
}
?>
?>

Final Note

My final note is with regard to the options provided to the helper. Given that the HTML helper already deals extensively with images, it is used to process the actual image tage and return it. Thus, providing any Html Helper image options will ensure they are passed through the gravatar component and onto the Html component, rendering as you would naturally expect from the core Html helper.

Comments and suggestions are encouraged.

If you are using this on your site, let me know!


Code also available on Github: http://github.com/predominant/CakePHP-Goodies

 

Comments 832

CakePHP Team Comments Author Comments
 

Comment

1 Nicely done

Thank you for posting this. I'll offer a small suggestion, as the URL isn't properly encoded. On line 94, change:

$optionString = implode('&', $optionArray);
To:

$optionString = implode('&amp;', $optionArray);
Posted Nov 30, 2008 by Tyler Seymour
 

Question

2 How to implement the code?

Hi there.
I'm a newbe and would like to know how to place this code in a html page?
Do I need a seperate php page with script for each persons Gravatar?
Do I place the script like this below directly into the html page??

image(
'someone@cakeisawesome.com',
array(
'rating' => 'x'
); ?>
Posted Jan 7, 2009 by Will
 

Comment

3 Code Implementation example

Do I need a seperate php page with script for each persons Gravatar?
Do I place the script like this below directly into the html page??

image(
'someone@cakeisawesome.com',
array(
'rating' => 'x'
); ?>

You actually spotted an error in the code samples there, as there is a missing close bracket, but you can place this into any view .ctp file in your CakePHP Application / Plugin.

The simplest and easiest way to display a gravatar is to do:

View Template:


echo $gravatar->image('someone@cakeisawesome.com');

And just ensure you include the Gravatar helper in your controller (or AppController), like this:

Controller Class:

<?php 
public $helpers = array('Html''Gravatar');
?>
Posted Jan 11, 2009 by Graham Weldon
 

Bug

4 Hash method should be case-insensitive

This is a pretty nice helper you wrote!

You should update your code to reflect Tyler's suggestion about encoding the URL properly.

Also, your hashing method is not taking into account the fact that Gravatar is expecting the email to be hashed in its lower-case form. Hence, the following change should be applied...

Change this:

Helper Class:

<?php 
return Security::hash($email$type);
?>

To this:

Helper Class:

<?php 
return Security::hash(strtolower($email), $type);
?>

That's all there is to it. :)
Posted Jun 10, 2009 by Ben Pesso
 

Comment

5 Helper code updates

Updates applied:
  1. HTML Encoding corrected (Thhanks Tyler)
  2. EMail addresses forced lowercase (Thanks Ben)
  3. Moved to PHP 5 only.
  4. Various code cleanup

Thanks for the suggestions and help with this helpers code. And enjoy the updates.
Posted Jun 10, 2009 by Graham Weldon
 

Comment

6 Well done

Clean and simple, just the way we like it.

Great work Graham!
Posted Jun 21, 2009 by Hannibal Lecter
 

Comment

7 Yummy yummy

Nice one, Graham!
Posted Jul 17, 2009 by Jon Adams
 

Comment

8 Updated Code

Updated the helper code, and also mirrored on github: http://github.com/predominant/CakePHP-Goodies/tree/master
Thanks to Mark Scherer for various updates and contributions.
Posted Jul 30, 2009 by Graham Weldon
 

Comment

9 Another code update

Updated to add url() method to generate and return the url for the image without the img tag. Handy if you want to generate your own image tag, or if you need to use the image url in some other manner.

This doesnt affect the previous functionality at all.
Posted Aug 17, 2009 by Graham Weldon
 

Comment

10 Sweet

Really nice job.
Just ask google about 'gravatar cakephp' and what pops up if not the perfect solution.
Posted Aug 29, 2009 by Kristoffer Darj
 

Comment

11 gravatar api

did anyone build a component yet with the gravatar api?
you would be able to check on whether an email has an account or get all pics of that account etc

just wondering
would be cool to validate that first before a user can add his gravatar
Posted Oct 6, 2009 by Mark
 

Comment

12 Awesome

This works perfectly. Thanks for packing it nicely in git hub. Just pulled it into my plugins directory and worked like a charm!

Thanks!
Posted Oct 29, 2009 by Nick Baker
 

Comment

13 Thank you

^
Posted Dec 14, 2009 by Jonas Hartmann
 

Comment

14 You're very welcome :-)

Thanks for all the great feedback folks.

If you have any suggestions or improvements, please let me know.
Posted Dec 28, 2009 by Graham Weldon