<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[
<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[
This view helper receives avatars from Gravatar service.Zend Framework: Zend_View_Helper_Gravatar Component Proposal
Proposed Component Name
Zend_View_Helper_Gravatar
Developer Notes
http://framework.zend.com/wiki/display/ZFDEV/Zend_View_Helper_Gravatar
Proposers
Marcin Morawski
Zend Liaison
TBD
Revision
1.0 - 1 January 2008: Initial Draft. (wiki revision: 25)
Table of Contents
1. Overview
2. References
3. Component Requirements, Constraints, and Acceptance Criteria
4. Dependencies on Other Framework Components
- Zend_View_Helper_HtmlElement
- Zend_View_Exception
5. Theory of Operation
6. Milestones / Tasks
Milestone 1: [DONE] Proposal finished
Milestone 2: [DONE] Proposal accepted
Milestone 3: [DONE] Working implementation
Milestone 4: [DONE] Unit tests
Milestone 5: [DONE] Documentation
Milestone 6: [DONE] Moved to core
7. Class Index
- Zend_View_Helper_Gravatar
8. Use Cases
24 Comments
comments.show.hideDec 18, 2009
Shaun Farrell
<p>Marcin, If you need help on this I will be more than glad to help develop this view helper. One suggestion I would have is to default the avatar to 80px. And check to see if the size of the image is between 1 and 512px</p>
<p>Gravatar Doc - "You can specify a "size" or "s" parameter to the URL between 1 and 512 (pixels.) If you omit this step we use a default size of 80 pixels."</p>
Dec 20, 2009
Marcin Morawski
<p>Thanks for the suggestion.<br />
I changed this. Now default size of image is 80. I also add a validator, so you must set a value between 1 and 512. <br />
This class is finished. You can download it. <br />
I added this class as attachment to this wiki page. </p>
<p>If you want help me you can help me with write documentation and unit test. Of course you can also check this class, but i think, that this class is completed and work nicely<ac:emoticon ac:name="cheeky" />.</p>
Jan 30, 2010
Benjamin Steininger
<p>Would be nice if it supports ssl via api-url: <a class="external-link" href="https://secure.gravatar.com/">https://secure.gravatar.com/</a></p>
<p>Mentioned here: <a class="external-link" href="http://blog.gravatar.com/#post-150">http://blog.gravatar.com/#post-150</a></p>
<p>And what about the rating-parameter ? </p>
Jan 31, 2010
Marcin Morawski
<p>Done</p>
May 12, 2010
Colin Guthrie
<p>Awesome <ac:emoticon ac:name="smile" /> I was just about to write a similar class and figured I'd check first. Glad I did <ac:emoticon ac:name="smile" /></p>
<p>Would be nice to get this added to the main distribution.</p>
Jul 21, 2010
Dolf Schimmel (Freeaqingme)
<p>Why do you want to not use SSL by default?</p>
Jul 22, 2010
Marc Bennewitz (private)
<p>Using the secure url should be part of the options and if not specified it should be auto selected.</p>
<ul>
<li>add option secure<br />
Default to:
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
if (isset($options['secure'])) {
$options['secure'] = (bool)$options['secure'];
} else {
$options['secure'] = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']);
}
]]></ac:plain-text-body></ac:macro></li>
</ul>
Jul 31, 2010
Marcin Morawski
<p>implemented</p>
Aug 18, 2010
Marc Bennewitz (private)
<p>Today I looked your code on incubator and I have 2 small explanatory notes:</p>
<p>1. options must be underscored<br />
2. the secure option need 3 different values true, false and null for autodetect<br />
else getSecure returns the wrong value</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
// ...
protected $_options = array(
'img_size' => 80,
'default_img' => self::DEFAULT_MM,
'rating' => self::RATING_G,
'secure' => null // auto detect
);
// ...
public function gravatar( $email = null, $options = array(), $attribs = array() )
{
if ($email === null)
$this->setEmail($email);
$this->setAttribs($attribs);
foreach ($options as $k => $v) {
$m = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $k)));
if (!method_exists($this, $m))
$this->{$m}($value);
}
return $this->getImgTag();
}
// ...
public function setSecure($flag)
public function getSecure()
{
if ($this->_options['secure'] === null)
else
}
// ....
]]></ac:plain-text-body></ac:macro>
Aug 18, 2010
Marc Bennewitz (private)
<p>Oh - additionally the main gravator method should return $this ever<br />
and the class should implement the magic method __toString().</p>
<p>Than the following also works:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
echo $this->gravatar('my@mail.com')->setSecure(true);
]]></ac:plain-text-body></ac:macro>
Aug 19, 2010
Marcin Morawski
<p>I'll do it and:<br />
I remove third parameter(attribs for image). And move it to second parameter(atttribs key).<br />
Then I can use setOptions method to set all options for this class.</p>
Aug 19, 2010
Marc Bennewitz (private)
<p>html attributes should be still separated from gravatar options.<br />
-> Some JS-Libs define special html attributes and this could overlap with gravatar options.</p>
Aug 22, 2010
Marcin Morawski
<p>I was thinking about something like this:<br />
$this->gravatar()->setOptions(<br />
array(<br />
'img_size' => 80,<br />
'default_img' => Zend_View_Helper_Gravatar::DEFAULT_WAVATAR,<br />
........<br />
'attribs' => array('class' => 'gravatar', 'title' => 'title value')<br />
));<br />
Then html attributes are seperated.</p>
<p>I now that html attributes have other function than options for gravatar. Pass it to one parameter may be confusing(even with key attribs). </p>
Aug 22, 2010
Marc Bennewitz (private)
<p>Than your gravatar view helper would be the only view helper (extending HtmlElement) where the attrib parameter must be an option.<br />
-> It should be similar to other view helper based on html element.</p>
Jul 22, 2010
Colin Guthrie
<p>For most uses, this is not needed and add unnecessary overhead at the client side. It also means that round-robin DNS names (e.g. using 0.gravatar.com, 1.gravatar.com etc.) is not possible. Using different host names is something Google recommends as part of it's "Page Speed" metrics. There is obviously a practical limit, but 2 or 3 different domains for loading e.g. 10-20 Gravatars each would seem sensible. Sadly there is only one SSL URL so this technique cannot be used on SSL. </p>
<p>So that is one reason why it may not be nice to be on by default., but that is not to say that it cannot be auto-detected: e.g. if the request is a secure one, then use secure with Gravatar as Marc suggests above.</p>
Aug 18, 2010
Marc Bennewitz (private)
<p>Browsers displays a warning if a ssl page loads insecure content (like the gravatar image)</p>
Aug 18, 2010
Colin Guthrie
<p>Yes I know, that's why I said it should be autodetected rather than on by default. I was trying to point out all the reasons why using SSL by default (even if the request is non-ssl) would be a bad idea. I fully appreciate the need to use SSL on an SSL request.</p>
Aug 01, 2010
Georgy Turevich
<p>Why do you use validation in "view" helper? Typically, validation is used in the model-layer.</p>
<p>I think, it must be removed or must be optional and disabled by default</p>
Aug 02, 2010
Marcin Morawski
<p>Yes, you are right.<br />
I fix it.</p>
Aug 03, 2010
Dolf Schimmel (Freeaqingme)
<ac:macro ac:name="note"><ac:rich-text-body><p><strong>Community Review Team Recommendation</strong></p>
<p>The CR Team advises accepting this proposal as-is.</p></ac:rich-text-body></ac:macro>
Aug 10, 2010
Shahar Evron
<p>Hi,</p>
<p>This looks very good. I needed something just like this and didn't know about your proposal, so I suggested this: <a class="external-link" href="http://framework.zend.com/svn/framework/laboratory/Zend_View_Helper_Gravatar/library/Zend/View/Helper/Gravatar.php">http://framework.zend.com/svn/framework/laboratory/Zend_View_Helper_Gravatar/library/Zend/View/Helper/Gravatar.php</a> - I will drop my implementation since it looks like you already did the thinking and got reviewed, but maybe you can take a look at my implementation and borrow something <ac:emoticon ac:name="smile" /></p>
<p>BTW I don't think it's the view helper's job to validate the email address. My assumption is that an email address being used from a gravater was already validated in the past by the app - e.g. if used for user comments, you probably validate the user's email when accepting the comment in the form or before saving to the DB. </p>
<p>In any case an invalid email address will result in falling back to the default image, and not in some security problem. So I think validating here would be waste of CPU cycles. </p>
<p>Shahar.</p>
Aug 11, 2010
Marcin Morawski
<p>Thanks for sharing.<br />
I borrowed some ideas.</p>
<p>I also don't check email address and image size.<br />
You check image size, but i think that this value also should be set from model/configuration file.</p>
<p>Moreover, if you pass invalid value, this not destroy your application. You get only very small or very big avatar(1px or 512px)</p>
Aug 24, 2010
Marcin Morawski
<p>Last Changes:</p>
<ul>
<li>added __toString method</li>
<li>added setOptions method</li>
<li>restored third parameter(html attributes)</li>
<li>now gravatar method returns object</li>
<li>fixed set/getSecure</li>
<li>changed name of keys options</li>
<li>modified Wiki page</li>
</ul>
Sep 19, 2010
Adam Dyson
<p>I am in the process of building a blog extension for the Magento platform and I just happened to stumble across this page. Thanks for all your efforts, it came in very handy! I've made some minor adjustments to suit my needs, maybe they'll be of some help.</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
class Ontic_Blog_Helper_Gravatar extends Ontic_Core_Helper_Abstract
{
/**
*/
const GRAVATAR_URL = 'http://www.gravatar.com/avatar';
/**
*/
const GRAVATAR_URL_SECURE = 'https://secure.gravatar.com/avatar';
/**
*/
const RATING_G = 'g';
/**
*/
const RATING_PG = 'pg';
/**
*/
const RATING_R = 'r';
/**
*/
const RATING_X = 'x';
/**
*/
const DEFAULT_404 = '404';
/**
*/
const DEFAULT_MM = 'mm';
/**
*/
const DEFAULT_IDENTICON = 'identicon';
/**
*/
const DEFAULT_MONSTERID = 'monsterid';
/**
*/
const DEFAULT_WAVATAR = 'wavatar';
/**
*/
protected $_email;
/**
*/
protected $_secure;
/**
*/
protected $_options = array(
'size' => 80,
'default' => self::DEFAULT_MM,
'rating' => self::RATING_G
);
/**
*/
protected $_attributes;
/**
*/
public function gravatar($email = '', $options = array(), $attributes = array())
/**
*/
public function getEmail()
/**
*/
public function setEmail($email)
/**
*/
public function getSize()
/**
*/
public function setSize($size)
{
if (is_numeric($size) && $size >= 1 && $size <= 512)
return $this;
}
/**
*/
public function getDefault()
/**
*/
public function setDefault($image)
{
if (preg_match('/^(https?:\/\/[\w\-]\.[\w\-]+)/i', $image))
else if (in_array($image, array(self::DEFAULT_404, self::DEFAULT_MM, self::DEFAULT_IDENTICON, self::DEFAULT_MONSTERID, self::DEFAULT_WAVATAR)))
return $this;
}
/**
*/
public function getRating()
/**
*/
public function setRating($rating)
{
if (in_array($rating, array(self::RATING_G, self::RATING_PG, self::RATING_R, self::RATING_X)))
return $this;
}
/**
*/
public function getSecure()
{
if ($this->_secure === null)
return $this->_secure;
}
/**
*/
public function setSecure($flag)
{
if ($flag === null)
else
return $this;
}
/**
*/
public function setOptions(array $options)
{
foreach ($options as $key => $value)
{
$method = 'set'.uc_words($key, '');
if (method_exists($this, $method))
{
$this->{$method}($value);
}
}
return $this;
}
/**
*/
public function getAttributes()
/**
*/
public function setAttributes(array $attributes)
/**
*/
public function toHtml()
/**
*/
protected function _getGravatarUrl()
{
if ($this->_secure === false)
return self::GRAVATAR_URL_SECURE;
}
/**
*/
protected function _getAvatarUrl()
}
]]></ac:plain-text-body></ac:macro>