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

Commit 0a0dac0

Browse files
committed
Add new StatsSiteStats to avoid changing previous APIs
1 parent 8bf6082 commit 0a0dac0

File tree

9 files changed

+451
-116
lines changed

9 files changed

+451
-116
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/21328509/WordPressKit.zip",
15-
checksum: "e01a5e91e822b84058346b163663c88ee2ee50a9b1614804dbc0429567f00835"
14+
url: "https://github.com/user-attachments/files/21328988/WordPressKit.zip",
15+
checksum: "963e7189b0b2e207267c94138f2b08dd2d26d3fc5cbedae8b38d49a2c1e7d72b"
1616
),
1717
]
1818
)

Sources/WordPressKit/Models/Stats/StatsSubscribersSummaryData.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ extension StatsSubscribersSummaryData: StatsTimeIntervalData {
8888
}
8989
}
9090

91-
public static func queryProperties(period: StatsPeriodUnit, maxCount: Int) -> [String: String] {
91+
public static func queryProperties(with date: Date, period: StatsPeriodUnit, maxCount: Int) -> [String: String] {
9292
return ["quantity": String(maxCount), "unit": period.stringValue]
9393
}
9494
}

Sources/WordPressKit/Models/Stats/Time Interval/StatsFileDownloadsTimeIntervalData.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ extension StatsFileDownloadsTimeIntervalData: StatsTimeIntervalData {
3535
return "stats/file-downloads"
3636
}
3737

38-
public static func queryProperties(period: StatsPeriodUnit, maxCount: Int) -> [String: String] {
38+
public static func queryProperties(with date: Date, period: StatsPeriodUnit, maxCount: Int) -> [String: String] {
3939
// num = number of periods to include in the query. default: 1.
4040
return ["num": String(maxCount)]
4141
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import Foundation
2+
3+
public struct StatsSiteStats {
4+
public var period: StatsPeriodUnit
5+
public var periodEndDate: Date
6+
public let data: [PeriodData]
7+
8+
enum Metric: String, CaseIterable {
9+
case views
10+
case visitors
11+
case likes
12+
case comments
13+
case posts
14+
}
15+
16+
public struct PeriodData {
17+
/// Periods date in the site timezone.
18+
var date: Date
19+
var views: Int?
20+
var visitors: Int?
21+
var likes: Int?
22+
var comments: Int?
23+
var posts: Int?
24+
25+
subscript(metric: Metric) -> Int? {
26+
switch metric {
27+
case .views: views
28+
case .visitors: visitors
29+
case .likes: likes
30+
case .comments: comments
31+
case .posts: posts
32+
}
33+
}
34+
}
35+
}
36+
37+
extension StatsSiteStats: StatsTimeIntervalData {
38+
public static var pathComponent: String {
39+
"stats/visits"
40+
}
41+
42+
public static func queryProperties(with date: Date, period: StatsPeriodUnit, maxCount: Int) -> [String: String] {
43+
return [
44+
"unit": period.stringValue,
45+
"quantity": String(maxCount),
46+
"stat_fields": Metric.allCases.map(\.rawValue).joined(separator: ",")
47+
]
48+
}
49+
50+
public init?(date: Date, period: StatsPeriodUnit, jsonDictionary: [String: AnyObject]) {
51+
self.init(date: date, period: period, unit: nil, jsonDictionary: jsonDictionary)
52+
}
53+
54+
public init?(date: Date, period: StatsPeriodUnit, unit: StatsPeriodUnit?, jsonDictionary: [String: AnyObject]) {
55+
guard let fields = jsonDictionary["fields"] as? [String],
56+
let data = jsonDictionary["data"] as? [[Any]] else {
57+
return nil
58+
}
59+
60+
guard let periodIndex = fields.firstIndex(of: "period") else {
61+
return nil
62+
}
63+
64+
self.period = period
65+
self.periodEndDate = date
66+
67+
let indices = (
68+
views: fields.firstIndex(of: Metric.views.rawValue),
69+
visitors: fields.firstIndex(of: Metric.visitors.rawValue),
70+
likes: fields.firstIndex(of: Metric.likes.rawValue),
71+
comments: fields.firstIndex(of: Metric.comments.rawValue),
72+
posts: fields.firstIndex(of: Metric.posts.rawValue)
73+
)
74+
75+
let dateFormatter = makeDateFormatter(for: period)
76+
77+
self.data = data.compactMap { data in
78+
guard let periodDate = dateFormatter.date(from: data[periodIndex] as? String ?? "") else {
79+
return nil
80+
}
81+
func getValue(at index: Int?) -> Int? {
82+
guard let index else { return nil }
83+
return data[index] as? Int
84+
}
85+
return PeriodData(
86+
date: periodDate,
87+
views: getValue(at: indices.views),
88+
visitors: getValue(at: indices.visitors),
89+
likes: getValue(at: indices.likes),
90+
comments: getValue(at: indices.comments),
91+
posts: getValue(at: indices.posts)
92+
)
93+
}
94+
}
95+
}
96+
97+
private func makeDateFormatter(for unit: StatsPeriodUnit) -> DateFormatter {
98+
let formatter = DateFormatter()
99+
formatter.locale = Locale(identifier: "en_US_POSIX")
100+
formatter.dateFormat = {
101+
switch unit {
102+
case .hour: "yyyy-MM-dd HH:mm:ss"
103+
case .week: "yyyy'W'MM'W'dd"
104+
case .day, .month, .year: "yyyy-MM-dd"
105+
}
106+
}()
107+
return formatter
108+
}

Sources/WordPressKit/Models/Stats/Time Interval/StatsSummaryTimeIntervalData.swift

Lines changed: 85 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -35,26 +35,23 @@ public struct StatsSummaryData {
3535
public let period: StatsPeriodUnit
3636
public let periodStartDate: Date
3737

38-
public let viewsCount: Int?
39-
public let visitorsCount: Int?
40-
public let likesCount: Int?
41-
public let commentsCount: Int?
42-
public let postsCount: Int?
38+
public let viewsCount: Int
39+
public let visitorsCount: Int
40+
public let likesCount: Int
41+
public let commentsCount: Int
4342

4443
public init(period: StatsPeriodUnit,
4544
periodStartDate: Date,
46-
viewsCount: Int?,
47-
visitorsCount: Int?,
48-
likesCount: Int?,
49-
commentsCount: Int?,
50-
postsCount: Int?) {
45+
viewsCount: Int,
46+
visitorsCount: Int,
47+
likesCount: Int,
48+
commentsCount: Int) {
5149
self.period = period
5250
self.periodStartDate = periodStartDate
5351
self.viewsCount = viewsCount
5452
self.visitorsCount = visitorsCount
5553
self.likesCount = likesCount
5654
self.commentsCount = commentsCount
57-
self.postsCount = postsCount
5855
}
5956
}
6057

@@ -63,7 +60,7 @@ extension StatsSummaryTimeIntervalData: StatsTimeIntervalData {
6360
return "stats/visits"
6461
}
6562

66-
public static func queryProperties(period: StatsPeriodUnit, maxCount: Int) -> [String: String] {
63+
public static func queryProperties(with date: Date, period: StatsPeriodUnit, maxCount: Int) -> [String: String] {
6764
return ["unit": period.stringValue,
6865
"quantity": String(maxCount),
6966
"stat_fields": "views,visitors,comments,likes"]
@@ -91,79 +88,106 @@ extension StatsSummaryTimeIntervalData: StatsTimeIntervalData {
9188
// [["2019-01-01", 9001, 1234], ["2019-02-01", 1234, 1234]], where the first object in the "inner" array
9289
// is the `period`, second is `views`, etc.
9390

94-
guard let periodIndex = fieldsArray.firstIndex(of: "period") else {
95-
return nil
91+
guard
92+
let periodIndex = fieldsArray.firstIndex(of: "period"),
93+
let viewsIndex = fieldsArray.firstIndex(of: "views"),
94+
let visitorsIndex = fieldsArray.firstIndex(of: "visitors"),
95+
let commentsIndex = fieldsArray.firstIndex(of: "comments"),
96+
let likesIndex = fieldsArray.firstIndex(of: "likes")
97+
else {
98+
return nil
9699
}
97100

98101
self.period = period
99102
self.unit = unit
100103
self.periodEndDate = date
101-
self.summaryData = data.compactMap {
102-
StatsSummaryData(
103-
dataArray: $0,
104-
period: unit ?? period,
105-
periodIndex: periodIndex,
106-
viewsIndex: fieldsArray.firstIndex(of: "views"),
107-
visitorsIndex: fieldsArray.firstIndex(of: "visitors"),
108-
likesIndex: fieldsArray.firstIndex(of: "likes"),
109-
commentsIndex: fieldsArray.firstIndex(of: "comments"),
110-
postsIndex: fieldsArray.firstIndex(of: "posts")
111-
)
112-
}
104+
self.summaryData = data.compactMap { StatsSummaryData(dataArray: $0,
105+
period: unit ?? period,
106+
periodIndex: periodIndex,
107+
viewsIndex: viewsIndex,
108+
visitorsIndex: visitorsIndex,
109+
likesIndex: likesIndex,
110+
commentsIndex: commentsIndex) }
113111
}
114112
}
115113

116114
private extension StatsSummaryData {
117-
init?(
118-
dataArray: [Any],
119-
period: StatsPeriodUnit,
120-
periodIndex: Int,
121-
viewsIndex: Int?,
122-
visitorsIndex: Int?,
123-
likesIndex: Int?,
124-
commentsIndex: Int?,
125-
postsIndex: Int?
126-
) {
115+
init?(dataArray: [Any],
116+
period: StatsPeriodUnit,
117+
periodIndex: Int,
118+
viewsIndex: Int?,
119+
visitorsIndex: Int?,
120+
likesIndex: Int?,
121+
commentsIndex: Int?) {
122+
127123
guard
128124
let periodString = dataArray[periodIndex] as? String,
129125
let periodStart = type(of: self).parsedDate(from: periodString, for: period) else {
130126
return nil
131127
}
132128

133-
func getValue(at index: Int?) -> Int? {
134-
guard let index else { return nil }
135-
return dataArray[index] as? Int
129+
let viewsCount: Int
130+
let visitorsCount: Int
131+
let likesCount: Int
132+
let commentsCount: Int
133+
134+
if let viewsIndex = viewsIndex {
135+
guard let count = dataArray[viewsIndex] as? Int else {
136+
return nil
137+
}
138+
viewsCount = count
139+
} else {
140+
viewsCount = 0
141+
}
142+
143+
if let visitorsIndex = visitorsIndex {
144+
guard let count = dataArray[visitorsIndex] as? Int else {
145+
return nil
146+
}
147+
visitorsCount = count
148+
} else {
149+
visitorsCount = 0
150+
}
151+
152+
if let likesIndex = likesIndex {
153+
guard let count = dataArray[likesIndex] as? Int else {
154+
return nil
155+
}
156+
likesCount = count
157+
} else {
158+
likesCount = 0
159+
}
160+
161+
if let commentsIndex = commentsIndex {
162+
guard let count = dataArray[commentsIndex] as? Int else {
163+
return nil
164+
}
165+
commentsCount = count
166+
} else {
167+
commentsCount = 0
136168
}
137169

138170
self.period = period
139171
self.periodStartDate = periodStart
140172

141-
self.viewsCount = getValue(at: viewsIndex)
142-
self.visitorsCount = getValue(at: visitorsIndex)
143-
self.likesCount = getValue(at: likesIndex)
144-
self.commentsCount = getValue(at: commentsIndex)
145-
self.postsCount = getValue(at: postsIndex)
173+
self.viewsCount = viewsCount
174+
self.visitorsCount = visitorsCount
175+
self.likesCount = likesCount
176+
self.commentsCount = commentsCount
146177
}
147178

148179
static func parsedDate(from dateString: String, for period: StatsPeriodUnit) -> Date? {
149180
switch period {
150181
case .hour:
151-
// Example: "2025-07-17 09:00:00" (in a site timezone)
152-
return self.hourlyDateFormatter.date(from: dateString)
182+
assertionFailure("Unsupported time period")
183+
return nil
153184
case .week:
154185
return self.weeksDateFormatter.date(from: dateString)
155186
case .day, .month, .year:
156187
return self.regularDateFormatter.date(from: dateString)
157188
}
158189
}
159190

160-
static var hourlyDateFormatter: DateFormatter {
161-
let df = DateFormatter()
162-
df.locale = Locale(identifier: "en_US_POSIX")
163-
df.dateFormat = "yyyy-MM-dd HH:mm:ss"
164-
return df
165-
}
166-
167191
static var regularDateFormatter: DateFormatter {
168192
let df = DateFormatter()
169193
df.locale = Locale(identifier: "en_US_POS")
@@ -214,7 +238,7 @@ extension StatsLikesSummaryTimeIntervalData: StatsTimeIntervalData {
214238
return "stats/visits"
215239
}
216240

217-
public static func queryProperties(period: StatsPeriodUnit, maxCount: Int) -> [String: String] {
241+
public static func queryProperties(with date: Date, period: StatsPeriodUnit, maxCount: Int) -> [String: String] {
218242
return ["unit": period.stringValue,
219243
"quantity": String(maxCount),
220244
"stat_fields": "likes"]
@@ -240,16 +264,12 @@ extension StatsLikesSummaryTimeIntervalData: StatsTimeIntervalData {
240264

241265
self.period = period
242266
self.periodEndDate = date
243-
self.summaryData = data.compactMap {
244-
StatsSummaryData(
245-
dataArray: $0,
246-
period: unit ?? period,
247-
periodIndex: periodIndex,
248-
viewsIndex: nil,
249-
visitorsIndex: nil,
250-
likesIndex: likesIndex,
251-
commentsIndex: nil, postsIndex: nil
252-
)
253-
}
267+
self.summaryData = data.compactMap { StatsSummaryData(dataArray: $0,
268+
period: unit ?? period,
269+
periodIndex: periodIndex,
270+
viewsIndex: nil,
271+
visitorsIndex: nil,
272+
likesIndex: likesIndex,
273+
commentsIndex: nil) }
254274
}
255275
}

0 commit comments

Comments
 (0)