Skip to content

Commit 42bef0c

Browse files
authored
[BUGFIX] Fix gravatar (#182)
Releases: main, 13.4
1 parent ef496a6 commit 42bef0c

File tree

7 files changed

+127
-46
lines changed

7 files changed

+127
-46
lines changed

Classes/ViewHelpers/GravatarViewHelper.php

Lines changed: 75 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,52 +29,106 @@
2929
* <code>
3030
* <blog:gravatar emailAddress="[email protected]"
3131
* size="40"
32-
* defaultImageUri="someDefaultImage"
32+
* defaultImage="retro"
3333
* alt="Gravator icon of {comment.author}"
3434
* data-name="{comment.author}" />
3535
* </code>
3636
* <output>
37-
* <img src="http://www.gravatar.com/avatar/4a28b782cade3dbcd6e306fa4757849d?d=someDefaultImage&s=40" />
37+
* <img src="http://www.gravatar.com/avatar/4a28b782cade3dbcd6e306fa4757849d?d=retro&s=40" />
3838
* </output>
3939
*/
40-
class GravatarViewHelper extends AbstractTagBasedViewHelper
40+
final class GravatarViewHelper extends AbstractTagBasedViewHelper
4141
{
42-
/**
43-
* @var string
44-
*/
4542
protected $tagName = 'img';
46-
public function __construct(private readonly UriFactory $uriFactory)
47-
{
43+
44+
public function __construct(
45+
private readonly UriFactory $uriFactory,
46+
) {
4847
parent::__construct();
4948
}
5049

5150
public function initializeArguments(): void
5251
{
53-
$this->registerArgument('emailAddress', 'string', '', true);
54-
$this->registerArgument('defaultImageUri', 'string', '');
55-
$this->registerArgument('size', 'int', '');
52+
$this->registerArgument(
53+
'emailAddress',
54+
'string',
55+
'Email address used to generate the Gravatar hash',
56+
true,
57+
);
58+
59+
$this->registerArgument(
60+
'defaultImage',
61+
'string',
62+
'Gravatar default image (mp, identicon, retro, monsterid, wavatar, robohash, blank)',
63+
false,
64+
'mp',
65+
);
66+
67+
$this->registerArgument(
68+
'size',
69+
'int',
70+
'Size of the avatar in pixels',
71+
false,
72+
40,
73+
);
5674
}
5775

5876
public function render(): string
5977
{
60-
$gravatarUri = $this->uriFactory->createUri(
61-
'https://gravatar.com/avatar/' . md5((string)$this->arguments['emailAddress']),
78+
$emailHash = $this->normalizeEmailToHash(
79+
(string)$this->arguments['emailAddress'],
6280
);
6381

64-
$queryArguments = [];
65-
if ($this->arguments['defaultImageUri'] !== null) {
66-
$queryArguments['d'] = urlencode($this->arguments['defaultImageUri']);
67-
}
82+
$defaultImage = $this->normalizeDefaultImage(
83+
(string)$this->arguments['defaultImage'],
84+
);
6885

69-
if ($this->arguments['size'] !== null) {
70-
$queryArguments['s'] = MathUtility::forceIntegerInRange((int)$this->arguments['size'], 1, 2048);
71-
}
86+
$size = $this->normalizeSize(
87+
(int)$this->arguments['size'],
88+
);
7289

7390
$this->tag->addAttribute(
7491
'src',
75-
(string)$gravatarUri->withQuery(HttpUtility::buildQueryString($queryArguments, '', true)),
92+
$this->buildGravatarUri($emailHash, $defaultImage, $size),
7693
);
7794

7895
return $this->tag->render();
7996
}
97+
98+
private function normalizeEmailToHash(string $email): string
99+
{
100+
return md5(strtolower(trim($email)));
101+
}
102+
103+
private function normalizeDefaultImage(string $default): string
104+
{
105+
$allowed = [
106+
'mp',
107+
'identicon',
108+
'retro',
109+
'monsterid',
110+
'wavatar',
111+
'robohash',
112+
'blank',
113+
];
114+
115+
return in_array($default, $allowed, true) ? $default : 'mp';
116+
}
117+
118+
private function normalizeSize(int $size): int
119+
{
120+
return MathUtility::forceIntegerInRange($size, 1, 2048);
121+
}
122+
123+
private function buildGravatarUri(string $hash, string $default, int $size): string
124+
{
125+
return (string)$this->uriFactory
126+
->createUri('https://www.gravatar.com/avatar/' . $hash)
127+
->withQuery(
128+
HttpUtility::buildQueryString([
129+
'd' => $default,
130+
's' => $size,
131+
]),
132+
);
133+
}
80134
}

Configuration/Sets/BlogExample/settings.definitions.yaml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,17 @@ settings:
5757
description: 'How many posts should be displayed per page of pagination?'
5858
type: int
5959
default: 3
60-
blogExample.defaultGravator:
61-
label: 'Default gravator icon'
60+
blogExample.gravatarDefault:
61+
label: 'Gravatar default image'
6262
category: BlogExample.layout
63-
description: 'This icon is displayed for a comment if the email address of the commentary is not registered. '
63+
description: 'Fallback image used by Gravatar when an email has no avatar.'
6464
type: string
65-
default: 'EXT:blog_example/Resources/Public/Icons/default_gravatar.gif'
65+
default: 'mp'
66+
enum:
67+
mp: 'Mystery Person (mp)'
68+
identicon: 'Identicon'
69+
retro: 'Retro'
70+
monsterid: 'MonsterID'
71+
wavatar: 'Wavatar'
72+
robohash: 'Robohash'
73+
blank: 'Blank'

Configuration/Sets/BlogExample/setup.typoscript

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ plugin.tx_blogexample {
33
settings {
44
postsPerPage = {$blogExample.postsPerPage}
55
editorUsergroupUid = {$blogExample.editorUsergroupUid}
6-
defaultGravator = {$blogExample.defaultGravator}
6+
gravatarDefault = {$blogExample.gravatarDefault}
77
}
88

99
persistence {

Resources/Private/Backend/Templates/ShowAllComments.html

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,14 @@ <h2>List of all comments</h2>
1414
<div class="tx-blogexample-comment">
1515
<div class="tx-blogexample-comment-info">
1616
<span class="tx-blogexample-comment-author">
17-
<blog:gravatar emailAddress="{comment.email}" size="40" class="tx-blogexample-gravatar" />
17+
<blog:gravatar
18+
emailAddress="{comment.email}"
19+
defaultImage="{settings.gravatarDefault}"
20+
size="40"
21+
class="tx-blogexample-gravatar"
22+
alt="Gravatar icon of {comment.author}"
23+
data-name="{comment.author}"
24+
/>
1825
<a href="mailto:{comment.email}">{comment.author}</a> posted on
1926
<span class="tx-blogexample-date"><f:format.date>{comment.date}</f:format.date></span>
2027
</span>

Resources/Private/Backend/Templates/ShowPost.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,15 @@ <h3>Comments</h3>
3737
<div class="tx-blogexample-comment">
3838
<div class="tx-blogexample-comment-info">
3939
<span class="tx-blogexample-comment-author">
40-
<blog:gravatar emailAddress="{comment.email}" size="40" class="tx-blogexample-gravatar" />
40+
41+
<blog:gravatar
42+
emailAddress="{comment.email}"
43+
defaultImage="{settings.gravatarDefault}"
44+
size="40"
45+
class="tx-blogexample-gravatar"
46+
alt="Gravatar icon of {comment.author}"
47+
data-name="{comment.author}"
48+
/>
4149
<a href="mailto:{comment.email}">{comment.author}</a> posted on
4250
<span class="tx-blogexample-date"><f:format.date>{comment.date}</f:format.date></span>
4351
</span>

Resources/Private/Templates/Post/Show.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ <h2>
5050
<li>
5151
<blog:gravatar
5252
emailAddress="{comment.email}"
53-
defaultImageUri="{f:uri.resource(path: '{settings.defaultGravator}', absolute: 1)}"
53+
defaultImage="{settings.gravatarDefault}"
5454
size="40"
5555
class="tx-blogexample-gravatar"
56-
alt="Gravator icon of {comment.author}"
56+
alt="Gravatar icon of {comment.author}"
5757
data-name="{comment.author}"
5858
/>
59-
<f:link.email email="{comment.author}">{comment.author}</f:link.email>
59+
<f:link.email email="{comment.email}">{comment.author}</f:link.email>
6060
<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>
6161
<p>
6262
<f:format.nl2br>{comment.content}</f:format.nl2br>

Tests/Functional/ViewHelpers/GravatarViewHelperTest.php

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,37 +44,41 @@ protected function setUp(): void
4444
public static function renderDataProvider(): array
4545
{
4646
return [
47-
'renderWillHashEmailAndAddItToImgTag' => [
47+
'renderWillHashEmailAndAddDefaultArgumentsToImgTag' => [
4848
'<blog:gravatar emailAddress="[email protected]" />',
49-
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d" />',
49+
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=mp&amp;s=40" />',
5050
],
51-
'renderWillEncodeDefaultImageUriToImgTag' => [
52-
'<blog:gravatar emailAddress="[email protected]" defaultImageUri="https://typo3.org?test=123&foo=bar" />',
53-
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=https%253A%252F%252Ftypo3.org%253Ftest%253D123%2526foo%253Dbar" />',
51+
'renderWillUseDefaultImageKeyword' => [
52+
'<blog:gravatar emailAddress="[email protected]" defaultImage="identicon" />',
53+
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=identicon&amp;s=40" />',
5454
],
55-
'renderWithCombinedSizeAndDefaultImageUri' => [
56-
'<blog:gravatar emailAddress="[email protected]" size="256" defaultImageUri="https://typo3.org" />',
57-
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=https%253A%252F%252Ftypo3.org&amp;s=256" />',
55+
'renderWillFallbackToMpForInvalidDefaultImageKeyword' => [
56+
'<blog:gravatar emailAddress="[email protected]" defaultImage="https://typo3.org?test=123&amp;foo=bar" />',
57+
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=mp&amp;s=40" />',
5858
],
59-
'renderWithCombinedSizeAndEmptyDefaultImageUriWillOnlyAddSizeArgument' => [
60-
'<blog:gravatar emailAddress="[email protected]" size="512" defaultImageUri="" />',
61-
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?s=512" />',
59+
'renderWithCombinedSizeAndDefaultImage' => [
60+
'<blog:gravatar emailAddress="[email protected]" size="256" defaultImage="monsterid" />',
61+
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=monsterid&amp;s=256" />',
62+
],
63+
'renderWithEmptyDefaultImageWillFallbackToMp' => [
64+
'<blog:gravatar emailAddress="[email protected]" size="512" defaultImage="" />',
65+
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=mp&amp;s=512" />',
6266
],
6367
'renderWithStringForSizeWillCastValueToIntAndForceValueTo1' => [
6468
'<blog:gravatar emailAddress="[email protected]" size="XXL" />',
65-
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?s=1" />',
69+
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=mp&amp;s=1" />',
6670
],
6771
'renderWithTooSmallIntForSizeWillBeForcedTo1' => [
6872
'<blog:gravatar emailAddress="[email protected]" size="-12" />',
69-
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?s=1" />',
73+
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=mp&amp;s=1" />',
7074
],
7175
'renderWithIntForSizeWillStayTheSame' => [
7276
'<blog:gravatar emailAddress="[email protected]" size="120" />',
73-
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?s=120" />',
77+
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=mp&amp;s=120" />',
7478
],
7579
'renderWithTooHighSizeWillForceValueTo2048' => [
7680
'<blog:gravatar emailAddress="[email protected]" size="217348" />',
77-
'<img src="https://gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?s=2048" />',
81+
'<img src="https://www.gravatar.com/avatar/64f677e30cd713a9467794a26711e42d?d=mp&amp;s=2048" />',
7882
],
7983
];
8084
}

0 commit comments

Comments
 (0)