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

Commit 92c1536

Browse files
authored
Updates to fetching Stats time interval data (#712)
2 parents 14523ee + 8ef69a0 commit 92c1536

File tree

8 files changed

+221
-5
lines changed

8 files changed

+221
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ _None._
3838

3939
### New Features
4040

41-
_None._
41+
- `StatsTimeIntervalData` now accepts an optional `unit: StatsPeriodUnit` parameter that allows to describe the granularity of data fetched for a given period. [#712]
4242

4343
### Bug Fixes
4444

WordPressKit.xcodeproj/project.pbxproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
01438D352B6A2B2C0097D60A /* stats-visits-month-unit-week.json in Sources */ = {isa = PBXBuildFile; fileRef = 01438D342B6A2B2C0097D60A /* stats-visits-month-unit-week.json */; };
11+
01438D362B6A31540097D60A /* stats-visits-month-unit-week.json in Resources */ = {isa = PBXBuildFile; fileRef = 01438D342B6A2B2C0097D60A /* stats-visits-month-unit-week.json */; };
12+
01438D382B6A35FB0097D60A /* stats-summary.json in Sources */ = {isa = PBXBuildFile; fileRef = 01438D372B6A35FB0097D60A /* stats-summary.json */; };
13+
01438D392B6A361B0097D60A /* stats-summary.json in Resources */ = {isa = PBXBuildFile; fileRef = 01438D372B6A35FB0097D60A /* stats-summary.json */; };
14+
01438D3B2B6A36BF0097D60A /* StatsTotalsSummaryData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01438D3A2B6A36BF0097D60A /* StatsTotalsSummaryData.swift */; };
1015
0152100C28EDA9E400DD6783 /* StatsAnnualAndMostPopularTimeInsightDecodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0152100B28EDA9E400DD6783 /* StatsAnnualAndMostPopularTimeInsightDecodingTests.swift */; };
1116
0847B92C2A4442730044D32F /* IPLocationRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0847B92B2A4442730044D32F /* IPLocationRemote.swift */; };
1217
08C7493E2A45EA11000DA0E2 /* IPLocationRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08C7493D2A45EA11000DA0E2 /* IPLocationRemoteTests.swift */; };
@@ -723,6 +728,9 @@
723728
/* End PBXContainerItemProxy section */
724729

725730
/* Begin PBXFileReference section */
731+
01438D342B6A2B2C0097D60A /* stats-visits-month-unit-week.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "stats-visits-month-unit-week.json"; sourceTree = "<group>"; };
732+
01438D372B6A35FB0097D60A /* stats-summary.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "stats-summary.json"; sourceTree = "<group>"; };
733+
01438D3A2B6A36BF0097D60A /* StatsTotalsSummaryData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatsTotalsSummaryData.swift; sourceTree = "<group>"; };
726734
0152100B28EDA9E400DD6783 /* StatsAnnualAndMostPopularTimeInsightDecodingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsAnnualAndMostPopularTimeInsightDecodingTests.swift; sourceTree = "<group>"; };
727735
0847B92B2A4442730044D32F /* IPLocationRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPLocationRemote.swift; sourceTree = "<group>"; };
728736
08C7493D2A45EA11000DA0E2 /* IPLocationRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPLocationRemoteTests.swift; sourceTree = "<group>"; };
@@ -1531,6 +1539,7 @@
15311539
404057C3221B30140060250C /* Time Interval */ = {
15321540
isa = PBXGroup;
15331541
children = (
1542+
01438D3A2B6A36BF0097D60A /* StatsTotalsSummaryData.swift */,
15341543
984E34EA22EF7209005C3F92 /* StatsFileDownloadsTimeIntervalData.swift */,
15351544
40819772221E10C900A298E4 /* StatsPublishedPostsTimeIntervalData.swift */,
15361545
404057C4221B30400060250C /* StatsSearchTermTimeIntervalData.swift */,
@@ -2409,7 +2418,9 @@
24092418
404057CA221B80BC0060250C /* stats-top-authors.json */,
24102419
404057CF221C46780060250C /* stats-videos-data.json */,
24112420
4081977A221F153A00A298E4 /* stats-visits-day.json */,
2421+
01438D372B6A35FB0097D60A /* stats-summary.json */,
24122422
4081977D221F269A00A298E4 /* stats-visits-month.json */,
2423+
01438D342B6A2B2C0097D60A /* stats-visits-month-unit-week.json */,
24132424
40819779221F153A00A298E4 /* stats-visits-week.json */,
24142425
436D56392118DE3B00CEAA33 /* supported-countries-success.json */,
24152426
436D56522121F60400CEAA33 /* supported-states-empty.json */,
@@ -2905,6 +2916,8 @@
29052916
isa = PBXResourcesBuildPhase;
29062917
buildActionMask = 2147483647;
29072918
files = (
2919+
01438D392B6A361B0097D60A /* stats-summary.json in Resources */,
2920+
01438D362B6A31540097D60A /* stats-visits-month-unit-week.json in Resources */,
29082921
32A29A1F236BE4CC009488C2 /* post-autosave-mapping-success.json in Resources */,
29092922
CEAD827B25E421DE00758DF2 /* reader-post-comments-subscribe-failure.json in Resources */,
29102923
7403A2FC1EF06FEB00DED7DC /* me-settings-change-lastname-success.json in Resources */,
@@ -3345,6 +3358,7 @@
33453358
74650F721F0EA1A700188EDB /* GravatarServiceRemote.swift in Sources */,
33463359
B5969E1D20A49AC4005E9DF1 /* NSString+MD5.m in Sources */,
33473360
FF807251241FB90E00809AF5 /* WordPressOrgRestApi.swift in Sources */,
3361+
01438D3B2B6A36BF0097D60A /* StatsTotalsSummaryData.swift in Sources */,
33483362
4A68E3E1294076C1004AC3DC /* RemoteReaderSiteInfo.swift in Sources */,
33493363
3F391E1A2B50F3EB007975C4 /* Result+Callback.swift in Sources */,
33503364
8236EB4D2024B9F8007C7CF9 /* RemoteBlogJetpackModulesSettings.swift in Sources */,
@@ -3544,6 +3558,7 @@
35443558
BAFA775624ADAB3C000F0D3A /* MockPluginDirectoryEntryProvider.swift in Sources */,
35453559
3F8308A729EE683500354497 /* ActivityTests.swift in Sources */,
35463560
9AB6D64A218727D60008F274 /* PostServiceRemoteRESTRevisionsTest.swift in Sources */,
3561+
01438D382B6A35FB0097D60A /* stats-summary.json in Sources */,
35473562
7430C9BD1F192C0F0051B8E6 /* ReaderPostServiceRemoteTests.m in Sources */,
35483563
1DC837C229B9F04F009DCD4B /* RemoteVideoPressVideoTests.swift in Sources */,
35493564
FAD1345125909DEA00A8FEB1 /* JetpackBackupServiceRemoteTests.swift in Sources */,
@@ -3572,6 +3587,7 @@
35723587
73B3DAD621FBB20D00B2CF18 /* WordPressComRestApiTests+Locale.swift in Sources */,
35733588
C738CAEF28622325001BE107 /* QRLoginServiceRemoteTests.swift in Sources */,
35743589
3297E1DE2564653A00287D21 /* JetpackScanServiceRemoteTests.swift in Sources */,
3590+
01438D352B6A2B2C0097D60A /* stats-visits-month-unit-week.json in Sources */,
35753591
9F3E0BAC20873785009CB5BA /* ServiceRequestTest.swift in Sources */,
35763592
4624223E2548C26D002B8A12 /* SiteDesignServiceRemoteTests.swift in Sources */,
35773593
4A1DEF44293051BC00322608 /* LoggingTests.swift in Sources */,

WordPressKit/StatsServiceRemoteV2.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,21 +94,24 @@ open class StatsServiceRemoteV2: ServiceRemoteWordPressComREST {
9494
/// Used to fetch data about site over a specific timeframe.
9595
/// - parameters:
9696
/// - period: An enum representing whether either a day, a week, a month or a year worth's of data.
97+
/// - unit: An enum representing whether the data is retuned in a day, a week, a month or a year granularity. Default is `period`.
9798
/// - endingOn: Date on which the `period` for which data you're interested in **is ending**.
9899
/// e.g. if you want data spanning 11-17 Feb 2019, you should pass in a period of `.week` and an
99100
/// ending date of `Feb 17 2019`.
100101
/// - limit: Limit of how many objects you want returned for your query. Default is `10`. `0` means no limit.
101102
public func getData<TimeStatsType: StatsTimeIntervalData>(for period: StatsPeriodUnit,
103+
unit: StatsPeriodUnit? = nil,
102104
endingOn: Date,
103105
limit: Int = 10,
104106
completion: @escaping ((TimeStatsType?, Error?) -> Void)) {
105107
let pathComponent = TimeStatsType.pathComponent
106108
let path = self.path(forEndpoint: "sites/\(siteID)/\(pathComponent)/", withVersion: ._1_1)
107109

108110
let staticProperties = ["period": period.stringValue,
111+
"unit": unit?.stringValue ?? period.stringValue,
109112
"date": periodDataQueryDateFormatter.string(from: endingOn)] as [String: AnyObject]
110113

111-
let classProperties = TimeStatsType.queryProperties(with: endingOn, period: period, maxCount: limit) as [String: AnyObject]
114+
let classProperties = TimeStatsType.queryProperties(with: endingOn, period: unit ?? period, maxCount: limit) as [String: AnyObject]
112115

113116
let properties = staticProperties.merging(classProperties) { val1, _ in
114117
return val1
@@ -125,12 +128,15 @@ open class StatsServiceRemoteV2: ServiceRemoteWordPressComREST {
125128
}
126129

127130
let periodString = jsonResponse["period"] as? String
131+
let unitString = jsonResponse["unit"] as? String
128132
let parsedPeriod = periodString.flatMap { StatsPeriodUnit(string: $0) } ?? period
133+
let parsedUnit = unitString.flatMap { StatsPeriodUnit(string: $0) } ?? unit ?? period
129134
// some responses omit this field! not a reason to fail a whole request parsing though.
130135

131136
guard
132137
let timestats = TimeStatsType(date: date,
133138
period: parsedPeriod,
139+
unit: parsedUnit,
134140
jsonDictionary: jsonResponse)
135141
else {
136142
completion(nil, ResponseError.decodingFailure)
@@ -257,7 +263,7 @@ extension StatsServiceRemoteV2 {
257263
success: { (response, _) in
258264
guard
259265
let jsonResponse = response as? [String: AnyObject],
260-
let response = StatsPublishedPostsTimeIntervalData(date: endingOn, period: period, jsonDictionary: jsonResponse) else {
266+
let response = StatsPublishedPostsTimeIntervalData(date: endingOn, period: period, unit: nil, jsonDictionary: jsonResponse) else {
261267
completion(nil, ResponseError.decodingFailure)
262268
return
263269
}
@@ -322,19 +328,29 @@ public protocol StatsTimeIntervalData {
322328
static var pathComponent: String { get }
323329

324330
var period: StatsPeriodUnit { get }
331+
var unit: StatsPeriodUnit? { get }
325332
var periodEndDate: Date { get }
326333

327334
init?(date: Date, period: StatsPeriodUnit, jsonDictionary: [String: AnyObject])
335+
init?(date: Date, period: StatsPeriodUnit, unit: StatsPeriodUnit?, jsonDictionary: [String: AnyObject])
328336

329337
static func queryProperties(with date: Date, period: StatsPeriodUnit, maxCount: Int) -> [String: String]
330338
}
331339

332340
extension StatsTimeIntervalData {
333341

342+
public var unit: StatsPeriodUnit? {
343+
return nil
344+
}
345+
334346
public static func queryProperties(with date: Date, period: StatsPeriodUnit, maxCount: Int) -> [String: String] {
335347
return ["max": String(maxCount)]
336348
}
337349

350+
public init?(date: Date, period: StatsPeriodUnit, unit: StatsPeriodUnit?, jsonDictionary: [String: AnyObject]) {
351+
self.init(date: date, period: period, jsonDictionary: jsonDictionary)
352+
}
353+
338354
// Most of the responses for time data come in a unwieldy format, that requires awkwkard unwrapping
339355
// at the call-site — unfortunately not _all of them_, which means we can't just do it at the request level.
340356
static func unwrapDaysDictionary(jsonDictionary: [String: AnyObject]) -> [String: AnyObject]? {

WordPressKit/Time Interval/StatsSummaryTimeIntervalData.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,17 @@ public enum StatsSummaryType: Int {
1414

1515
public struct StatsSummaryTimeIntervalData {
1616
public let period: StatsPeriodUnit
17+
public let unit: StatsPeriodUnit?
1718
public let periodEndDate: Date
1819

1920
public let summaryData: [StatsSummaryData]
2021

2122
public init(period: StatsPeriodUnit,
23+
unit: StatsPeriodUnit?,
2224
periodEndDate: Date,
2325
summaryData: [StatsSummaryData]) {
2426
self.period = period
27+
self.unit = unit
2528
self.periodEndDate = periodEndDate
2629
self.summaryData = summaryData
2730
}
@@ -63,6 +66,10 @@ extension StatsSummaryTimeIntervalData: StatsTimeIntervalData {
6366
}
6467

6568
public init?(date: Date, period: StatsPeriodUnit, jsonDictionary: [String: AnyObject]) {
69+
self.init(date: date, period: period, unit: nil, jsonDictionary: jsonDictionary)
70+
}
71+
72+
public init?(date: Date, period: StatsPeriodUnit, unit: StatsPeriodUnit?, jsonDictionary: [String: AnyObject]) {
6673
guard
6774
let fieldsArray = jsonDictionary["fields"] as? [String],
6875
let data = jsonDictionary["data"] as? [[Any]]
@@ -91,9 +98,10 @@ extension StatsSummaryTimeIntervalData: StatsTimeIntervalData {
9198
}
9299

93100
self.period = period
101+
self.unit = unit
94102
self.periodEndDate = date
95103
self.summaryData = data.compactMap { StatsSummaryData(dataArray: $0,
96-
period: period,
104+
period: unit ?? period,
97105
periodIndex: periodIndex,
98106
viewsIndex: viewsIndex,
99107
visitorsIndex: visitorsIndex,
@@ -233,6 +241,10 @@ extension StatsLikesSummaryTimeIntervalData: StatsTimeIntervalData {
233241
}
234242

235243
public init?(date: Date, period: StatsPeriodUnit, jsonDictionary: [String: AnyObject]) {
244+
self.init(date: date, period: period, unit: nil, jsonDictionary: jsonDictionary)
245+
}
246+
247+
public init?(date: Date, period: StatsPeriodUnit, unit: StatsPeriodUnit?, jsonDictionary: [String: AnyObject]) {
236248
guard
237249
let fieldsArray = jsonDictionary["fields"] as? [String],
238250
let data = jsonDictionary["data"] as? [[Any]]
@@ -249,7 +261,7 @@ extension StatsLikesSummaryTimeIntervalData: StatsTimeIntervalData {
249261
self.period = period
250262
self.periodEndDate = date
251263
self.summaryData = data.compactMap { StatsSummaryData(dataArray: $0,
252-
period: period,
264+
period: unit ?? period,
253265
periodIndex: periodIndex,
254266
viewsIndex: nil,
255267
visitorsIndex: nil,
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
public struct StatsTotalsSummaryData {
2+
public let period: StatsPeriodUnit
3+
public let periodEndDate: Date
4+
public let viewsCount: Int
5+
public let visitorsCount: Int
6+
public let likesCount: Int
7+
public let commentsCount: Int
8+
9+
public init(
10+
period: StatsPeriodUnit,
11+
periodEndDate: Date,
12+
viewsCount: Int,
13+
visitorsCount: Int,
14+
likesCount: Int,
15+
commentsCount: Int
16+
) {
17+
self.period = period
18+
self.periodEndDate = periodEndDate
19+
self.viewsCount = viewsCount
20+
self.visitorsCount = visitorsCount
21+
self.likesCount = likesCount
22+
self.commentsCount = commentsCount
23+
}
24+
}
25+
26+
extension StatsTotalsSummaryData: StatsTimeIntervalData {
27+
public static var pathComponent: String {
28+
return "stats/summary"
29+
}
30+
31+
public init?(date: Date, period: StatsPeriodUnit, jsonDictionary: [String: AnyObject]) {
32+
self.period = period
33+
self.periodEndDate = date
34+
self.visitorsCount = jsonDictionary["visitors"] as? Int ?? 0
35+
self.viewsCount = jsonDictionary["views"] as? Int ?? 0
36+
self.likesCount = jsonDictionary["likes"] as? Int ?? 0
37+
self.commentsCount = jsonDictionary["comments"] as? Int ?? 0
38+
}
39+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"date": "2024-01-31",
3+
"period": "week",
4+
"views": 43607,
5+
"visitors": 3497,
6+
"likes": 2378,
7+
"reblogs": 0,
8+
"comments": 154,
9+
"followers": 103296780
10+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"date": "2024-01-31",
3+
"unit": "week",
4+
"fields": [
5+
"period",
6+
"views",
7+
"visitors",
8+
"likes",
9+
"reblogs",
10+
"comments",
11+
"posts"
12+
],
13+
"data": [
14+
[
15+
"2024W01W01",
16+
25724,
17+
16227,
18+
908,
19+
0,
20+
50,
21+
1
22+
],
23+
[
24+
"2024W01W08",
25+
24147,
26+
14715,
27+
1398,
28+
0,
29+
89,
30+
8
31+
],
32+
[
33+
"2024W01W15",
34+
18581,
35+
12151,
36+
1057,
37+
0,
38+
58,
39+
1
40+
],
41+
[
42+
"2024W01W22",
43+
19386,
44+
12458,
45+
1182,
46+
0,
47+
84,
48+
2
49+
],
50+
[
51+
"2024W01W29",
52+
5589,
53+
3472,
54+
137,
55+
0,
56+
12,
57+
0
58+
]
59+
]
60+
}

0 commit comments

Comments
 (0)