Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 75 additions & 21 deletions Classes/ViewHelpers/GravatarViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,52 +29,106 @@
* <code>
* <blog:gravatar emailAddress="[email protected]"
* size="40"
* defaultImageUri="someDefaultImage"
* defaultImage="retro"
* alt="Gravator icon of {comment.author}"
* data-name="{comment.author}" />
* </code>
* <output>
* <img src="http://www.gravatar.com/avatar/4a28b782cade3dbcd6e306fa4757849d?d=someDefaultImage&s=40" />
* <img src="http://www.gravatar.com/avatar/4a28b782cade3dbcd6e306fa4757849d?d=retro&s=40" />
* </output>
*/
class GravatarViewHelper extends AbstractTagBasedViewHelper
final class GravatarViewHelper extends AbstractTagBasedViewHelper
{
/**
* @var string
*/
protected $tagName = 'img';
public function __construct(private readonly UriFactory $uriFactory)
{

public function __construct(
private readonly UriFactory $uriFactory,
) {
parent::__construct();
}

public function initializeArguments(): void
{
$this->registerArgument('emailAddress', 'string', '', true);
$this->registerArgument('defaultImageUri', 'string', '');
$this->registerArgument('size', 'int', '');
$this->registerArgument(
'emailAddress',
'string',
'Email address used to generate the Gravatar hash',
true,
);

$this->registerArgument(
'defaultImage',
'string',
'Gravatar default image (mp, identicon, retro, monsterid, wavatar, robohash, blank)',
false,
'mp',
);

$this->registerArgument(
'size',
'int',
'Size of the avatar in pixels',
false,
40,
);
}

public function render(): string
{
$gravatarUri = $this->uriFactory->createUri(
'https://gravatar.com/avatar/' . md5((string)$this->arguments['emailAddress']),
$emailHash = $this->normalizeEmailToHash(
(string)$this->arguments['emailAddress'],
);

$queryArguments = [];
if ($this->arguments['defaultImageUri'] !== null) {
$queryArguments['d'] = urlencode($this->arguments['defaultImageUri']);
}
$defaultImage = $this->normalizeDefaultImage(
(string)$this->arguments['defaultImage'],
);

if ($this->arguments['size'] !== null) {
$queryArguments['s'] = MathUtility::forceIntegerInRange((int)$this->arguments['size'], 1, 2048);
}
$size = $this->normalizeSize(
(int)$this->arguments['size'],
);

$this->tag->addAttribute(
'src',
(string)$gravatarUri->withQuery(HttpUtility::buildQueryString($queryArguments, '', true)),
$this->buildGravatarUri($emailHash, $defaultImage, $size),
);

return $this->tag->render();
}

private function normalizeEmailToHash(string $email): string
{
return md5(strtolower(trim($email)));
}

private function normalizeDefaultImage(string $default): string
{
$allowed = [
'mp',
'identicon',
'retro',
'monsterid',
'wavatar',
'robohash',
'blank',
];

return in_array($default, $allowed, true) ? $default : 'mp';
}

private function normalizeSize(int $size): int
{
return MathUtility::forceIntegerInRange($size, 1, 2048);
}

private function buildGravatarUri(string $hash, string $default, int $size): string
{
return (string)$this->uriFactory
->createUri('https://www.gravatar.com/avatar/' . $hash)
->withQuery(
HttpUtility::buildQueryString([
'd' => $default,
's' => $size,
]),
);
}
}
16 changes: 12 additions & 4 deletions Configuration/Sets/BlogExample/settings.definitions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,17 @@ settings:
description: 'How many posts should be displayed per page of pagination?'
type: int
default: 3
blogExample.defaultGravator:
label: 'Default gravator icon'
blogExample.gravatarDefault:
label: 'Gravatar default image'
category: BlogExample.layout
description: 'This icon is displayed for a comment if the email address of the commentary is not registered. '
description: 'Fallback image used by Gravatar when an email has no avatar.'
type: string
default: 'EXT:blog_example/Resources/Public/Icons/default_gravatar.gif'
default: 'mp'
enum:
mp: 'Mystery Person (mp)'
identicon: 'Identicon'
retro: 'Retro'
monsterid: 'MonsterID'
wavatar: 'Wavatar'
robohash: 'Robohash'
blank: 'Blank'
2 changes: 1 addition & 1 deletion Configuration/Sets/BlogExample/setup.typoscript
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ plugin.tx_blogexample {
settings {
postsPerPage = {$blogExample.postsPerPage}
editorUsergroupUid = {$blogExample.editorUsergroupUid}
defaultGravator = {$blogExample.defaultGravator}
gravatarDefault = {$blogExample.gravatarDefault}
}

persistence {
Expand Down
9 changes: 8 additions & 1 deletion Resources/Private/Backend/Templates/ShowAllComments.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ <h2>List of all comments</h2>
<div class="tx-blogexample-comment">
<div class="tx-blogexample-comment-info">
<span class="tx-blogexample-comment-author">
<blog:gravatar emailAddress="{comment.email}" size="40" class="tx-blogexample-gravatar" />
<blog:gravatar
emailAddress="{comment.email}"
defaultImage="{settings.gravatarDefault}"
size="40"
class="tx-blogexample-gravatar"
alt="Gravatar icon of {comment.author}"
data-name="{comment.author}"
/>
<a href="mailto:{comment.email}">{comment.author}</a> posted on
<span class="tx-blogexample-date"><f:format.date>{comment.date}</f:format.date></span>
</span>
Expand Down
10 changes: 9 additions & 1 deletion Resources/Private/Backend/Templates/ShowPost.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,15 @@ <h3>Comments</h3>
<div class="tx-blogexample-comment">
<div class="tx-blogexample-comment-info">
<span class="tx-blogexample-comment-author">
<blog:gravatar emailAddress="{comment.email}" size="40" class="tx-blogexample-gravatar" />

<blog:gravatar
emailAddress="{comment.email}"
defaultImage="{settings.gravatarDefault}"
size="40"
class="tx-blogexample-gravatar"
alt="Gravatar icon of {comment.author}"
data-name="{comment.author}"
/>
<a href="mailto:{comment.email}">{comment.author}</a> posted on
<span class="tx-blogexample-date"><f:format.date>{comment.date}</f:format.date></span>
</span>
Expand Down
6 changes: 3 additions & 3 deletions Resources/Private/Templates/Post/Show.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ <h2>
<li>
<blog:gravatar
emailAddress="{comment.email}"
defaultImageUri="{f:uri.resource(path: '{settings.defaultGravator}', absolute: 1)}"
defaultImage="{settings.gravatarDefault}"
size="40"
class="tx-blogexample-gravatar"
alt="Gravator icon of {comment.author}"
alt="Gravatar icon of {comment.author}"
data-name="{comment.author}"
/>
<f:link.email email="{comment.author}">{comment.author}</f:link.email>
<f:link.email email="{comment.email}">{comment.author}</f:link.email>
<span class="tx-blogexample-metadata"><f:translate key="postedOn" default="[posted on]" /> {post.date -> f:format.date(format: '{f:translate(key: \'culture.date.formatLong\')}')}</span>
<p>
<f:format.nl2br>{comment.content}</f:format.nl2br>
Expand Down
34 changes: 19 additions & 15 deletions Tests/Functional/ViewHelpers/GravatarViewHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,37 +44,41 @@ protected function setUp(): void
public static function renderDataProvider(): array
{
return [
'renderWillHashEmailAndAddItToImgTag' => [
'renderWillHashEmailAndAddDefaultArgumentsToImgTag' => [
'<blog:gravatar emailAddress="[email protected]" />',
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d" />',
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=mp&amp;s=40" />',
],
'renderWillEncodeDefaultImageUriToImgTag' => [
'<blog:gravatar emailAddress="[email protected]" defaultImageUri="https://typo3.org?test=123&foo=bar" />',
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=https%253A%252F%252Ftypo3.org%253Ftest%253D123%2526foo%253Dbar" />',
'renderWillUseDefaultImageKeyword' => [
'<blog:gravatar emailAddress="[email protected]" defaultImage="identicon" />',
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=identicon&amp;s=40" />',
],
'renderWithCombinedSizeAndDefaultImageUri' => [
'<blog:gravatar emailAddress="[email protected]" size="256" defaultImageUri="https://typo3.org" />',
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=https%253A%252F%252Ftypo3.org&amp;s=256" />',
'renderWillFallbackToMpForInvalidDefaultImageKeyword' => [
'<blog:gravatar emailAddress="[email protected]" defaultImage="https://typo3.org?test=123&amp;foo=bar" />',
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=mp&amp;s=40" />',
],
'renderWithCombinedSizeAndEmptyDefaultImageUriWillOnlyAddSizeArgument' => [
'<blog:gravatar emailAddress="[email protected]" size="512" defaultImageUri="" />',
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?s=512" />',
'renderWithCombinedSizeAndDefaultImage' => [
'<blog:gravatar emailAddress="[email protected]" size="256" defaultImage="monsterid" />',
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=monsterid&amp;s=256" />',
],
'renderWithEmptyDefaultImageWillFallbackToMp' => [
'<blog:gravatar emailAddress="[email protected]" size="512" defaultImage="" />',
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=mp&amp;s=512" />',
],
'renderWithStringForSizeWillCastValueToIntAndForceValueTo1' => [
'<blog:gravatar emailAddress="[email protected]" size="XXL" />',
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?s=1" />',
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=mp&amp;s=1" />',
],
'renderWithTooSmallIntForSizeWillBeForcedTo1' => [
'<blog:gravatar emailAddress="[email protected]" size="-12" />',
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?s=1" />',
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=mp&amp;s=1" />',
],
'renderWithIntForSizeWillStayTheSame' => [
'<blog:gravatar emailAddress="[email protected]" size="120" />',
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?s=120" />',
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=mp&amp;s=120" />',
],
'renderWithTooHighSizeWillForceValueTo2048' => [
'<blog:gravatar emailAddress="[email protected]" size="217348" />',
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?s=2048" />',
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=mp&amp;s=2048" />',
],
];
}
Expand Down
Loading