-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathPostService+Likes.swift
More file actions
136 lines (112 loc) · 5.68 KB
/
Copy pathPostService+Likes.swift
File metadata and controls
136 lines (112 loc) · 5.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import WordPressData
import WordPressKit
final class PostService {
let managedObjectContext: NSManagedObjectContext
let postServiceRemoteFactory: PostServiceRemoteFactory
init(managedObjectContext: NSManagedObjectContext, postServiceRemoteFactory: PostServiceRemoteFactory = PostServiceRemoteFactory()) {
self.managedObjectContext = managedObjectContext
self.postServiceRemoteFactory = postServiceRemoteFactory
}
}
extension PostService {
/**
Fetches a list of users from remote that liked the post with the given IDs.
@param postID The ID of the post to fetch likes for
@param siteID The ID of the site that contains the post
@param count Number of records to retrieve. Optional. Defaults to the endpoint max of 90.
@param before Filter results to likes before this date/time. Optional.
@param excludingIDs An array of user IDs to exclude from the returned results. Optional.
@param purgeExisting Indicates if existing Likes for the given post and site should be purged before
new ones are created. Defaults to true.
@param success A success block returning:
- Array of LikeUser
- Total number of likes for the given post
- Number of likes per fetch
@param failure A failure block
*/
func getLikesFor(postID: NSNumber,
siteID: NSNumber,
count: Int = 90,
before: String? = nil,
excludingIDs: [NSNumber]? = nil,
purgeExisting: Bool = true,
success: @escaping (([LikeUser], Int, Int) -> Void),
failure: @escaping ((Error?) -> Void)) {
guard let remote = postServiceRemoteFactory.restRemoteFor(siteID: siteID, context: managedObjectContext) else {
DDLogError("Unable to create a REST remote for posts.")
failure(nil)
return
}
remote.getLikesForPostID(postID,
count: NSNumber(value: count),
before: before,
excludeUserIDs: excludingIDs,
success: { remoteLikeUsers, totalLikes in
self.createNewUsers(from: remoteLikeUsers,
postID: postID,
siteID: siteID,
purgeExisting: purgeExisting) {
let users = self.likeUsersFor(postID: postID, siteID: siteID)
success(users, totalLikes.intValue, count)
}
}, failure: { error in
DDLogError("\(String(describing: error))")
failure(error)
})
}
/**
Fetches a list of users from Core Data that liked the post with the given IDs.
@param postID The ID of the post to fetch likes for.
@param siteID The ID of the site that contains the post.
@param after Filter results to likes after this Date.
*/
func likeUsersFor(postID: NSNumber, siteID: NSNumber, after: Date? = nil) -> [LikeUser] {
let request = LikeUser.fetchRequest() as NSFetchRequest<LikeUser>
request.predicate = {
if let after {
// The date comparison is 'less than' because Likes are in descending order.
return NSPredicate(format: "likedSiteID = %@ AND likedPostID = %@ AND dateLiked < %@", siteID, postID, after as CVarArg)
}
return NSPredicate(format: "likedSiteID = %@ AND likedPostID = %@", siteID, postID)
}()
request.sortDescriptors = [NSSortDescriptor(key: "dateLiked", ascending: false)]
if let users = try? managedObjectContext.fetch(request) {
return users
}
return [LikeUser]()
}
}
private extension PostService {
func createNewUsers(from remoteLikeUsers: [RemoteLikeUser]?,
postID: NSNumber,
siteID: NSNumber,
purgeExisting: Bool,
onComplete: @escaping (() -> Void)) {
guard let remoteLikeUsers,
!remoteLikeUsers.isEmpty else {
DispatchQueue.main.async {
onComplete()
}
return
}
ContextManager.shared.performAndSave({ derivedContext in
let likers = remoteLikeUsers.map { remoteUser in
LikeUserHelper.createOrUpdateFrom(remoteUser: remoteUser, context: derivedContext)
}
if purgeExisting {
self.deleteExistingUsersFor(postID: postID, siteID: siteID, from: derivedContext, likesToKeep: likers)
}
LikeUserHelper.purgeStaleLikes(fromContext: derivedContext)
}, completion: onComplete, on: .main)
}
func deleteExistingUsersFor(postID: NSNumber, siteID: NSNumber, from context: NSManagedObjectContext, likesToKeep: [LikeUser]) {
let request = LikeUser.fetchRequest() as NSFetchRequest<LikeUser>
request.predicate = NSPredicate(format: "likedSiteID = %@ AND likedPostID = %@ AND NOT (self IN %@)", siteID, postID, likesToKeep)
do {
let users = try context.fetch(request)
users.forEach { context.delete($0) }
} catch {
DDLogError("Error fetching post Like Users: \(error)")
}
}
}