Skip to content
This repository was archived by the owner on Jun 4, 2025. It is now read-only.

Commit ecc2e79

Browse files
authored
Merge pull request #133 from wordpress-mobile/task/refactor-gravatar
UI Modernization: Extract gravatarUrl to Gravatar
2 parents 733e331 + 4b8c5b7 commit ecc2e79

File tree

5 files changed

+90
-72
lines changed

5 files changed

+90
-72
lines changed

Sources/WordPressUI/Extensions/Gravatar/Gravatar.swift

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,55 @@
11
import Foundation
22

3+
/// Helper Enum that specifies all of the available Gravatar Image Ratings
4+
/// TODO: Convert into a pure Swift String Enum. It's done this way to maintain ObjC Compatibility
5+
///
6+
@objc
7+
public enum GravatarRatings: Int {
8+
case g
9+
case pg
10+
case r
11+
case x
12+
case `default`
13+
14+
func stringValue() -> String {
15+
switch self {
16+
case .default:
17+
fallthrough
18+
case .g:
19+
return "g"
20+
case .pg:
21+
return "pg"
22+
case .r:
23+
return "r"
24+
case .x:
25+
return "x"
26+
}
27+
}
28+
}
29+
30+
/// Helper Enum that specifies some of the options for default images
31+
/// To see all available options, visit : https://en.gravatar.com/site/implement/images/
32+
///
33+
public enum GravatarDefaultImage: String {
34+
case fileNotFound = "404"
35+
case mp
36+
case identicon
37+
}
38+
339
public struct Gravatar {
440
fileprivate struct Defaults {
541
static let scheme = "https"
642
static let host = "secure.gravatar.com"
743
static let unknownHash = "ad516503a11cd5ca435acc9bb6523536"
44+
static let baseURL = "https://gravatar.com/avatar"
45+
static let imageSize = 80
846
}
947

1048
public let canonicalURL: URL
1149

12-
public func urlWithSize(_ size: Int) -> URL {
50+
public func urlWithSize(_ size: Int, defaultImage: GravatarDefaultImage? = nil) -> URL {
1351
var components = URLComponents(url: canonicalURL, resolvingAgainstBaseURL: false)!
14-
components.query = "s=\(size)&d=404"
52+
components.query = "s=\(size)&d=\(defaultImage?.rawValue ?? GravatarDefaultImage.fileNotFound.rawValue)"
1553
return components.url!
1654
}
1755

@@ -30,6 +68,43 @@ public struct Gravatar {
3068

3169
return true
3270
}
71+
72+
/// Returns the Gravatar URL, for a given email, with the specified size + rating.
73+
///
74+
/// - Parameters:
75+
/// - email: the user's email
76+
/// - size: required download size
77+
/// - rating: image rating filtering
78+
///
79+
/// - Returns: Gravatar's URL
80+
///
81+
public static func gravatarUrl(for email: String,
82+
defaultImage: GravatarDefaultImage? = nil,
83+
size: Int? = nil,
84+
rating: GravatarRatings = .default) -> URL? {
85+
let hash = gravatarHash(of: email)
86+
let targetURL = String(format: "%@/%@?d=%@&s=%d&r=%@",
87+
Defaults.baseURL,
88+
hash,
89+
defaultImage?.rawValue ?? GravatarDefaultImage.fileNotFound.rawValue,
90+
size ?? Defaults.imageSize,
91+
rating.stringValue())
92+
return URL(string: targetURL)
93+
}
94+
95+
/// Returns the gravatar hash of an email
96+
///
97+
/// - Parameter email: the email associated with the gravatar
98+
/// - Returns: hashed email
99+
///
100+
/// This really ought to be in a different place, like Gravatar.swift, but there's
101+
/// lots of duplication around gravatars -nh
102+
private static func gravatarHash(of email: String) -> String {
103+
return email
104+
.lowercased()
105+
.trimmingCharacters(in: .whitespaces)
106+
.sha256Hash()
107+
}
33108
}
34109

35110
extension Gravatar: Equatable {}

Sources/WordPressUI/Extensions/UIImageView+Gravatar.swift

Lines changed: 3 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -22,33 +22,6 @@ private class GravatarNotificationWrapper {
2222
///
2323
extension UIImageView {
2424

25-
/// Helper Enum that specifies all of the available Gravatar Image Ratings
26-
/// TODO: Convert into a pure Swift String Enum. It's done this way to maintain ObjC Compatibility
27-
///
28-
@objc
29-
public enum GravatarRatings: Int {
30-
case g
31-
case pg
32-
case r
33-
case x
34-
case `default`
35-
36-
func stringValue() -> String {
37-
switch self {
38-
case .default:
39-
fallthrough
40-
case .g:
41-
return "g"
42-
case .pg:
43-
return "pg"
44-
case .r:
45-
return "r"
46-
case .x:
47-
return "x"
48-
}
49-
}
50-
}
51-
5225
/// Downloads and sets the User's Gravatar, given his email.
5326
/// TODO: This is a convenience method. Please, remove once all of the code has been migrated over to Swift.
5427
///
@@ -70,7 +43,7 @@ extension UIImageView {
7043
///
7144
@objc
7245
public func downloadGravatarWithEmail(_ email: String, rating: GravatarRatings = .default, placeholderImage: UIImage = .gravatarPlaceholderImage) {
73-
let gravatarURL = gravatarUrl(for: email, size: gravatarDefaultSize(), rating: rating)
46+
let gravatarURL = Gravatar.gravatarUrl(for: email, size: gravatarDefaultSize(), rating: rating)
7447

7548
listenForGravatarChanges(forEmail: email)
7649
downloadImage(from: gravatarURL, placeholderImage: placeholderImage)
@@ -167,7 +140,7 @@ extension UIImageView {
167140
/// Hope buddah, and the code reviewer, can forgive me for this hack.
168141
///
169142
@objc public func overrideGravatarImageCache(_ image: UIImage, rating: GravatarRatings, email: String) {
170-
guard let gravatarURL = gravatarUrl(for: email, size: gravatarDefaultSize(), rating: rating) else {
143+
guard let gravatarURL = Gravatar.gravatarUrl(for: email, size: gravatarDefaultSize(), rating: rating) else {
171144
return
172145
}
173146

@@ -191,35 +164,6 @@ extension UIImageView {
191164

192165
// MARK: - Private Helpers
193166

194-
/// Returns the Gravatar URL, for a given email, with the specified size + rating.
195-
///
196-
/// - Parameters:
197-
/// - email: the user's email
198-
/// - size: required download size
199-
/// - rating: image rating filtering
200-
///
201-
/// - Returns: Gravatar's URL
202-
///
203-
private func gravatarUrl(for email: String, size: Int, rating: GravatarRatings) -> URL? {
204-
let hash = gravatarHash(of: email)
205-
let targetURL = String(format: "%@/%@?d=404&s=%d&r=%@", Defaults.baseURL, hash, size, rating.stringValue())
206-
return URL(string: targetURL)
207-
}
208-
209-
/// Returns the gravatar hash of an email
210-
///
211-
/// - Parameter email: the email associated with the gravatar
212-
/// - Returns: hashed email
213-
///
214-
/// This really ought to be in a different place, like Gravatar.swift, but there's
215-
/// lots of duplication around gravatars -nh
216-
private func gravatarHash(of email: String) -> String {
217-
return email
218-
.lowercased()
219-
.trimmingCharacters(in: .whitespaces)
220-
.md5Hash()
221-
}
222-
223167
/// Returns the required gravatar size. If the current view's size is zero, falls back to the default size.
224168
///
225169
private func gravatarDefaultSize() -> Int {
@@ -235,13 +179,12 @@ extension UIImageView {
235179
///
236180
private struct Defaults {
237181
static let imageSize = 80
238-
static let baseURL = "https://gravatar.com/avatar"
239182
static var gravatarWrapperKey = "gravatarWrapperKey"
240183
static let emailKey = "email"
241184
static let imageKey = "image"
242185
}
243186
}
244187

245-
extension NSNotification.Name {
188+
public extension NSNotification.Name {
246189
static let GravatarImageUpdateNotification = NSNotification.Name(rawValue: "GravatarImageUpdateNotification")
247190
}

Sources/WordPressUIObjC/Extensions/NSString+Gravatar.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
@interface NSString (Gravatar)
44

5-
- (NSString *)md5Hash;
5+
- (NSString *)sha256Hash;
66

77
@end

Sources/WordPressUIObjC/Extensions/NSString+Gravatar.m

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44

55
@implementation NSString (Gravatar)
66

7-
- (NSString *)md5Hash
7+
- (NSString *)sha256Hash
88
{
99
const char *cStr = [self UTF8String];
10-
unsigned char result[CC_MD5_DIGEST_LENGTH];
10+
unsigned char result[CC_SHA256_DIGEST_LENGTH];
1111

12-
CC_MD5(cStr, (CC_LONG)strlen(cStr), result);
12+
CC_SHA256(cStr, (CC_LONG)strlen(cStr), result);
1313

14-
return [NSString stringWithFormat:
15-
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
16-
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
17-
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]
18-
];
14+
NSMutableString *hashString = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH*2];
15+
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
16+
[hashString appendFormat:@"%02x",result[i]];
17+
}
18+
return hashString;
1919
}
2020

2121
@end

WordPressUI.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Pod::Spec.new do |s|
44
s.name = 'WordPressUI'
5-
s.version = '1.14.1'
5+
s.version = '1.14.2-beta.1'
66

77
s.summary = 'Home of reusable WordPress UI components.'
88
s.description = <<-DESC

0 commit comments

Comments
 (0)