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

Commit 32f9410

Browse files
committed
Extend StatsPostDetails
1 parent a8b31bc commit 32f9410

File tree

4 files changed

+226
-33
lines changed

4 files changed

+226
-33
lines changed

Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ let package = Package(
1111
targets: [
1212
.binaryTarget(
1313
name: "WordPressKit",
14-
url: "https://github.com/user-attachments/files/21352383/WordPressKit.zip",
15-
checksum: "8054b66ecf39b8c23acea6d8c5c6c9f65fda01fcce4da7acf7db4273cb8e9145"
14+
url: "https://github.com/user-attachments/files/21373882/WordPressKit.zip",
15+
checksum: "57a23a1340f2a9d24f1848b337da89c3556f1440767d91cc2a5ee8a6fe16b79b"
1616
),
1717
]
1818
)

Sources/WordPressKit/Models/Stats/StatsPostDetails.swift

Lines changed: 134 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,87 @@
1+
import Foundation
2+
13
public struct StatsPostDetails: Equatable {
24
public let fetchedDate: Date
35
public let totalViewsCount: Int
4-
6+
57
public let recentWeeks: [StatsWeeklyBreakdown]
68
public let dailyAveragesPerMonth: [StatsPostViews]
79
public let monthlyBreakdown: [StatsPostViews]
810
public let lastTwoWeeks: [StatsPostViews]
11+
12+
public let highestMonth: Int?
13+
public let highestDayAverage: Int?
14+
public let highestWeekAverage: Int?
15+
16+
public let yearlyTotals: [Int: Int]
17+
public let overallAverages: [Int: Int]
18+
19+
public let fields: [String]?
20+
21+
public let post: Post?
22+
23+
public struct Post: Equatable {
24+
public let postID: Int
25+
public let title: String
26+
public let authorID: String?
27+
public let dateGMT: Date?
28+
public let content: String?
29+
public let excerpt: String?
30+
public let status: String?
31+
public let commentStatus: String?
32+
public let password: String?
33+
public let name: String?
34+
public let modifiedGMT: Date?
35+
public let contentFiltered: String?
36+
public let parent: Int?
37+
public let guid: String?
38+
public let type: String?
39+
public let mimeType: String?
40+
public let commentCount: String?
41+
public let permalink: String?
42+
43+
init?(jsonDictionary: [String: AnyObject]) {
44+
guard
45+
let postID = jsonDictionary["ID"] as? Int,
46+
let title = jsonDictionary["post_title"] as? String
47+
else {
48+
return nil
49+
}
50+
51+
let dateFormatter = DateFormatter()
52+
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
53+
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
54+
55+
var dateGMT: Date?
56+
var modifiedGMT: Date?
57+
58+
if let postDateGMTString = jsonDictionary["post_date_gmt"] as? String {
59+
dateGMT = dateFormatter.date(from: postDateGMTString)
60+
}
61+
if let postModifiedGMTString = jsonDictionary["post_modified_gmt"] as? String {
62+
modifiedGMT = dateFormatter.date(from: postModifiedGMTString)
63+
}
64+
65+
self.postID = postID
66+
self.title = title
67+
self.authorID = jsonDictionary["post_author"] as? String
68+
self.dateGMT = dateGMT
69+
self.content = jsonDictionary["post_content"] as? String
70+
self.excerpt = jsonDictionary["post_excerpt"] as? String
71+
self.status = jsonDictionary["post_status"] as? String
72+
self.commentStatus = jsonDictionary["comment_status"] as? String
73+
self.password = jsonDictionary["post_password"] as? String
74+
self.name = jsonDictionary["post_name"] as? String
75+
self.modifiedGMT = modifiedGMT
76+
self.contentFiltered = jsonDictionary["post_content_filtered"] as? String
77+
self.parent = jsonDictionary["post_parent"] as? Int
78+
self.guid = jsonDictionary["guid"] as? String
79+
self.type = jsonDictionary["post_type"] as? String
80+
self.mimeType = jsonDictionary["post_mime_type"] as? String
81+
self.commentCount = jsonDictionary["comment_count"] as? String
82+
self.permalink = jsonDictionary["permalink"] as? String
83+
}
84+
}
985
}
1086

1187
public struct StatsWeeklyBreakdown: Equatable {
@@ -15,6 +91,7 @@ public struct StatsWeeklyBreakdown: Equatable {
1591
public let totalViewsCount: Int
1692
public let averageViewsCount: Int
1793
public let changePercentage: Double
94+
public let isChangeInfinity: Bool
1895

1996
public let days: [StatsPostViews]
2097
}
@@ -26,7 +103,7 @@ public struct StatsPostViews: Equatable {
26103
}
27104

28105
extension StatsPostDetails {
29-
init?(jsonDictionary: [String: AnyObject]) {
106+
public init?(jsonDictionary: [String: AnyObject]) {
30107
guard
31108
let fetchedDateString = jsonDictionary["date"] as? String,
32109
let date = type(of: self).dateFormatter.date(from: fetchedDateString),
@@ -35,8 +112,8 @@ extension StatsPostDetails {
35112
let monthlyAverages = jsonDictionary["averages"] as? [String: AnyObject],
36113
let recentWeeks = jsonDictionary["weeks"] as? [[String: AnyObject]],
37114
let data = jsonDictionary["data"] as? [[Any]]
38-
else {
39-
return nil
115+
else {
116+
return nil
40117
}
41118

42119
self.fetchedDate = date
@@ -50,6 +127,42 @@ extension StatsPostDetails {
50127
self.monthlyBreakdown = StatsPostViews.mapMonthlyBreakdown(jsonDictionary: monthlyBreakdown)
51128
self.dailyAveragesPerMonth = StatsPostViews.mapMonthlyBreakdown(jsonDictionary: monthlyAverages)
52129
self.lastTwoWeeks = StatsPostViews.mapDailyData(data: Array(data.suffix(14)))
130+
131+
// Parse new fields
132+
self.highestMonth = jsonDictionary["highest_month"] as? Int
133+
self.highestDayAverage = jsonDictionary["highest_day_average"] as? Int
134+
self.highestWeekAverage = jsonDictionary["highest_week_average"] as? Int
135+
136+
self.fields = jsonDictionary["fields"] as? [String]
137+
138+
// Parse yearly totals
139+
var yearlyTotals: [Int: Int] = [:]
140+
if let years = monthlyBreakdown as? [String: [String: AnyObject]] {
141+
for (yearKey, yearData) in years {
142+
if let yearInt = Int(yearKey), let total = yearData["total"] as? Int {
143+
yearlyTotals[yearInt] = total
144+
}
145+
}
146+
}
147+
self.yearlyTotals = yearlyTotals
148+
149+
// Parse overall averages
150+
var overallAverages: [Int: Int] = [:]
151+
if let averages = monthlyAverages as? [String: [String: AnyObject]] {
152+
for (yearKey, yearData) in averages {
153+
if let yearInt = Int(yearKey), let overall = yearData["overall"] as? Int {
154+
overallAverages[yearInt] = overall
155+
}
156+
}
157+
}
158+
self.overallAverages = overallAverages
159+
160+
// Parse post object using the new Post model
161+
if let postDict = jsonDictionary["post"] as? [String: AnyObject] {
162+
self.post = Post(jsonDictionary: postDict)
163+
} else {
164+
self.post = nil
165+
}
53166
}
54167

55168
static var dateFormatter: DateFormatter {
@@ -93,19 +206,30 @@ extension StatsPostViews {
93206
let totalViews = $0["total"] as? Int,
94207
let averageViews = $0["average"] as? Int,
95208
let days = $0["days"] as? [[String: AnyObject]]
96-
else {
97-
return nil
209+
else {
210+
return nil
98211
}
99212

100-
let change = ($0["change"] as? Double) ?? 0.0
213+
var change: Double = 0.0
214+
var isChangeInfinity = false
215+
216+
if let changeValue = $0["change"] {
217+
if let changeDict = changeValue as? [String: AnyObject],
218+
let isInfinity = changeDict["isInfinity"] as? Bool {
219+
isChangeInfinity = isInfinity
220+
change = isInfinity ? Double.infinity : 0.0
221+
} else if let changeDouble = changeValue as? Double {
222+
change = changeDouble
223+
}
224+
}
101225

102226
let mappedDays: [StatsPostViews] = days.compactMap {
103227
guard
104228
let dayString = $0["day"] as? String,
105229
let date = StatsPostDetails.dateFormatter.date(from: dayString),
106230
let viewsCount = $0["count"] as? Int
107-
else {
108-
return nil
231+
else {
232+
return nil
109233
}
110234

111235
return StatsPostViews(period: .day,
@@ -122,9 +246,9 @@ extension StatsPostViews {
122246
totalViewsCount: totalViews,
123247
averageViewsCount: averageViews,
124248
changePercentage: change,
249+
isChangeInfinity: isChangeInfinity,
125250
days: mappedDays)
126251
}
127-
128252
}
129253
}
130254

Tests/WordPressKitTests/Mock Data/stats-post-details.json

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5424,5 +5424,31 @@
54245424
"highest_month": 8800,
54255425
"highest_day_average": 283,
54265426
"highest_week_average": 334,
5427-
"post": null
5427+
"post": {
5428+
"ID": 12345,
5429+
"post_author": "1234567",
5430+
"post_date": "2019-01-15 12:30:00",
5431+
"post_date_gmt": "2019-01-15 12:30:00",
5432+
"post_content": "<!-- wp:paragraph -->\n<p>This is a sample blog post content.</p>\n<!-- /wp:paragraph -->\n\n<!-- wp:heading -->\n<h2>Sample Heading</h2>\n<!-- /wp:heading -->\n\n<!-- wp:paragraph -->\n<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>\n<!-- /wp:paragraph -->",
5433+
"post_title": "Sample Blog Post Title",
5434+
"post_excerpt": "This is a sample excerpt.",
5435+
"post_status": "publish",
5436+
"comment_status": "open",
5437+
"ping_status": "open",
5438+
"post_password": "",
5439+
"post_name": "sample-blog-post-title",
5440+
"to_ping": "",
5441+
"pinged": "",
5442+
"post_modified": "2019-01-15 14:45:00",
5443+
"post_modified_gmt": "2019-01-15 14:45:00",
5444+
"post_content_filtered": "",
5445+
"post_parent": 0,
5446+
"guid": "https://example.wordpress.com/?p=12345",
5447+
"menu_order": 0,
5448+
"post_type": "post",
5449+
"post_mime_type": "",
5450+
"comment_count": "3",
5451+
"filter": "raw",
5452+
"permalink": "http://example.wordpress.com/2019/01/15/sample-blog-post-title/"
5453+
}
54285454
}

0 commit comments

Comments
 (0)