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

Commit 2613f21

Browse files
committed
Generalized Archive endpoint parser
1 parent c31ddf1 commit 2613f21

File tree

4 files changed

+84
-89
lines changed

4 files changed

+84
-89
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/21388771/WordPressKit.zip",
15-
checksum: "543f8dd4ee1bef8912c640aca0bfbb74db95e4577cc19fa82461edeeac45a02b"
14+
url: "https://github.com/user-attachments/files/21420518/WordPressKit.zip",
15+
checksum: "c57f60d8476cb1ba7000a2aa1fe0607794e1660c964d31ddab6e5add5db70499"
1616
),
1717
]
1818
)

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

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,19 @@ public struct StatsArchiveTimeIntervalData {
44
public let period: StatsPeriodUnit
55
public let unit: StatsPeriodUnit?
66
public let periodEndDate: Date
7-
public let summary: StatsArchiveSummary
7+
public let summary: [String: [StatsArchiveItem]]
88

99
public init(period: StatsPeriodUnit,
1010
unit: StatsPeriodUnit? = nil,
1111
periodEndDate: Date,
12-
summary: StatsArchiveSummary) {
12+
summary: [String: [StatsArchiveItem]]) {
1313
self.period = period
1414
self.unit = unit
1515
self.periodEndDate = periodEndDate
1616
self.summary = summary
1717
}
1818
}
1919

20-
public struct StatsArchiveSummary {
21-
public let other: [StatsArchiveItem]
22-
public let author: [StatsArchiveItem]
23-
24-
public init(other: [StatsArchiveItem], author: [StatsArchiveItem]) {
25-
self.other = other
26-
self.author = author
27-
}
28-
}
29-
3020
public struct StatsArchiveItem {
3121
public let href: String
3222
public let value: String
@@ -57,15 +47,21 @@ extension StatsArchiveTimeIntervalData: StatsTimeIntervalData {
5747
return nil
5848
}
5949

60-
let otherItems = (summary["other"] as? [[String: AnyObject]] ?? []).compactMap { StatsArchiveItem(jsonDictionary: $0) }
61-
let authorItems = (summary["author"] as? [[String: AnyObject]] ?? []).compactMap { StatsArchiveItem(jsonDictionary: $0) }
62-
63-
let archiveSummary = StatsArchiveSummary(other: otherItems, author: authorItems)
64-
6550
self.period = period
6651
self.unit = unit
6752
self.periodEndDate = date
68-
self.summary = archiveSummary
53+
self.summary = {
54+
var map: [String: [StatsArchiveItem]] = [:]
55+
for (key, value) in summary {
56+
let items = (value as? [[String: AnyObject]])?.compactMap {
57+
StatsArchiveItem(jsonDictionary: $0)
58+
} ?? []
59+
if !items.isEmpty {
60+
map[key] = items
61+
}
62+
}
63+
return map
64+
}()
6965
}
7066
}
7167

Tests/WordPressKitTests/Mock Data/stats-visits-hourly.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"data": [
1212
[
1313
"2025-07-17 00:00:00",
14-
0,
14+
5140,
1515
null,
1616
null,
1717
null
@@ -74,7 +74,8 @@
7474
],
7575
[
7676
"2025-07-17 09:00:00",
77-
0,
77+
3244
78+
,
7879
null,
7980
null,
8081
null

Tests/WordPressKitTests/Tests/StatsRemoteV2Tests.swift

Lines changed: 65 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -447,25 +447,20 @@ class StatsRemoteV2Tests: RemoteTestCase, RESTTestable {
447447
let feb21 = DateComponents(year: 2019, month: 2, day: 21)
448448
let date = Calendar.autoupdatingCurrent.date(from: feb21)!
449449

450-
remote.getData(for: .day, endingOn: date) { (summary: StatsSummaryTimeIntervalData?, error: Error?) in
450+
remote.getData(for: .hour, endingOn: date) { (summary: StatsSiteMetricsResponse?, error: Error?) in
451451
XCTAssertNil(error)
452452
XCTAssertNotNil(summary)
453453

454-
XCTAssertEqual(summary?.summaryData.count, 10)
454+
XCTAssertEqual(summary?.data.count, 24)
455455

456-
XCTAssertEqual(summary?.summaryData[0].viewsCount, 5140)
457-
XCTAssertEqual(summary?.summaryData[0].visitorsCount, 3560)
458-
XCTAssertEqual(summary?.summaryData[0].likesCount, 70)
459-
XCTAssertEqual(summary?.summaryData[0].commentsCount, 1)
456+
XCTAssertEqual(summary?.data[0].views, 5140)
457+
XCTAssertNil(summary?.data[0].visitors)
458+
XCTAssertNil(summary?.data[0].likes)
459+
XCTAssertNil(summary?.data[0].comments)
460460

461-
let nineDaysAgo = Calendar.autoupdatingCurrent.date(byAdding: .day, value: -9, to: date)!
462-
XCTAssertEqual(summary?.summaryData[0].periodStartDate, nineDaysAgo)
463-
464-
XCTAssertEqual(summary?.summaryData[9].viewsCount, 3244)
465-
XCTAssertEqual(summary?.summaryData[9].visitorsCount, 2127)
466-
XCTAssertEqual(summary?.summaryData[9].likesCount, 25)
467-
XCTAssertEqual(summary?.summaryData[9].commentsCount, 0)
468-
XCTAssertEqual(summary?.summaryData[9].periodStartDate, date)
461+
XCTAssertEqual(summary?.data[9].views, 3244)
462+
XCTAssertNil(summary?.data[9].likes)
463+
XCTAssertNil(summary?.data[9].comments)
469464

470465
expect.fulfill()
471466
}
@@ -475,51 +470,51 @@ class StatsRemoteV2Tests: RemoteTestCase, RESTTestable {
475470

476471
func testFetchPostDetail() {
477472
let expect = expectation(description: "It should return post detail")
478-
473+
479474
stubRemoteResponse(sitePostDetailsEndpoint, filename: getPostsDetailsFilename, contentType: .ApplicationJSON)
480-
475+
481476
let feb21 = DateComponents(year: 2019, month: 2, day: 21)
482477
let date = Calendar.autoupdatingCurrent.date(from: feb21)!
483-
478+
484479
remote.getDetails(forPostID: 9001) { (postDetails, error) in
485480
XCTAssertNil(error)
486481
XCTAssertNotNil(postDetails)
487-
482+
488483
XCTAssertEqual(postDetails?.fetchedDate, date)
489484
XCTAssertEqual(postDetails?.totalViewsCount, 163343)
490-
485+
491486
let dailyAverages = 10 + 12 + 12 + 12 + 2
492487
XCTAssertEqual(postDetails?.dailyAveragesPerMonth.count, postDetails?.monthlyBreakdown.count)
493488
XCTAssertEqual(postDetails?.dailyAveragesPerMonth.count, dailyAverages)
494-
489+
495490
let feb19Averages = postDetails?.dailyAveragesPerMonth.first { $0.date == DateComponents(year: 2019, month: 2) }
496491
XCTAssertNotNil(feb19Averages)
497492
XCTAssertEqual(feb19Averages?.period, .month)
498493
XCTAssertEqual(feb19Averages?.viewsCount, 112)
499-
494+
500495
let feb19Views = postDetails?.monthlyBreakdown.first { $0.date == DateComponents(year: 2019, month: 2) }
501496
XCTAssertNotNil(feb19Views)
502497
XCTAssertEqual(feb19Views?.period, .month)
503498
XCTAssertEqual(feb19Views?.viewsCount, 2578)
504-
499+
505500
XCTAssertEqual(postDetails?.lastTwoWeeks.count, 14)
506-
501+
507502
XCTAssertEqual(postDetails?.lastTwoWeeks.first?.viewsCount, 112)
508503
XCTAssertEqual(postDetails?.lastTwoWeeks.first?.period, .day)
509504
XCTAssertEqual(postDetails?.lastTwoWeeks.first?.date, DateComponents(year: 2019, month: 2, day: 08))
510-
505+
511506
XCTAssertEqual(postDetails?.lastTwoWeeks.last?.viewsCount, 324)
512507
XCTAssertEqual(postDetails?.lastTwoWeeks.last?.period, .day)
513508
XCTAssertEqual(postDetails?.lastTwoWeeks.last?.date, DateComponents(year: 2019, month: 2, day: 21))
514-
509+
515510
XCTAssertEqual(postDetails?.recentWeeks.count, 6)
516-
511+
517512
let leastRecentWeek = postDetails?.recentWeeks.first
518513
let mostRecentWeek = postDetails?.recentWeeks.last
519-
514+
520515
XCTAssertNotNil(leastRecentWeek)
521516
XCTAssertNotNil(mostRecentWeek)
522-
517+
523518
XCTAssertEqual(leastRecentWeek?.totalViewsCount, 688)
524519
XCTAssertEqual(leastRecentWeek?.averageViewsCount, 98)
525520
XCTAssertEqual(leastRecentWeek!.changePercentage, 0.0, accuracy: 0.0000000001)
@@ -531,7 +526,7 @@ class StatsRemoteV2Tests: RemoteTestCase, RESTTestable {
531526
XCTAssertEqual(leastRecentWeek?.days.last?.date, leastRecentWeek?.endDay)
532527
XCTAssertEqual(leastRecentWeek?.days.first?.viewsCount, 174)
533528
XCTAssertEqual(leastRecentWeek?.days.last?.viewsCount, 60)
534-
529+
535530
XCTAssertEqual(mostRecentWeek?.totalViewsCount, 867)
536531
XCTAssertEqual(mostRecentWeek?.averageViewsCount, 181)
537532
XCTAssertEqual(mostRecentWeek!.changePercentage, 38.7732, accuracy: 0.001)
@@ -543,29 +538,29 @@ class StatsRemoteV2Tests: RemoteTestCase, RESTTestable {
543538
XCTAssertEqual(mostRecentWeek?.days.last?.date, mostRecentWeek?.endDay)
544539
XCTAssertEqual(mostRecentWeek?.days.first?.viewsCount, 157)
545540
XCTAssertEqual(mostRecentWeek?.days.last?.viewsCount, 324)
546-
541+
547542
// Test newly added fields
548543
XCTAssertEqual(postDetails?.highestMonth, 8800)
549544
XCTAssertEqual(postDetails?.highestDayAverage, 283)
550545
XCTAssertEqual(postDetails?.highestWeekAverage, 334)
551-
546+
552547
// Test yearly totals
553548
XCTAssertEqual(postDetails?.yearlyTotals[2015], 37861)
554549
XCTAssertEqual(postDetails?.yearlyTotals[2016], 36447)
555550
XCTAssertEqual(postDetails?.yearlyTotals[2017], 37529)
556551
XCTAssertEqual(postDetails?.yearlyTotals[2018], 45429)
557552
XCTAssertEqual(postDetails?.yearlyTotals[2019], 6077)
558-
553+
559554
// Test overall averages
560555
XCTAssertEqual(postDetails?.overallAverages[2015], 130)
561556
XCTAssertEqual(postDetails?.overallAverages[2016], 99)
562557
XCTAssertEqual(postDetails?.overallAverages[2017], 102)
563558
XCTAssertEqual(postDetails?.overallAverages[2018], 124)
564559
XCTAssertEqual(postDetails?.overallAverages[2019], 112)
565-
560+
566561
// Test fields array
567562
XCTAssertEqual(postDetails?.fields, ["period", "views"])
568-
563+
569564
// Test post object
570565
XCTAssertNotNil(postDetails?.post)
571566
XCTAssertEqual(postDetails?.post?.postID, 12345)
@@ -582,10 +577,10 @@ class StatsRemoteV2Tests: RemoteTestCase, RESTTestable {
582577
XCTAssertEqual(postDetails?.post?.mimeType, "")
583578
XCTAssertEqual(postDetails?.post?.commentCount, "3")
584579
XCTAssertEqual(postDetails?.post?.permalink, "http://example.wordpress.com/2019/01/15/sample-blog-post-title/")
585-
580+
586581
expect.fulfill()
587582
}
588-
583+
589584
waitForExpectations(timeout: timeout, handler: nil)
590585
}
591586

@@ -784,54 +779,57 @@ class StatsRemoteV2Tests: RemoteTestCase, RESTTestable {
784779

785780
}
786781

787-
func testArchives() {
782+
func testArchives() throws {
788783
let expect = expectation(description: "It should return archives data for a day")
789784

790785
stubRemoteResponse(siteArchivesDataEndpoint, filename: getArchivesDataFilename, contentType: .ApplicationJSON)
791786

792787
let july21 = DateComponents(year: 2025, month: 7, day: 21)
793788
let date = Calendar.autoupdatingCurrent.date(from: july21)!
794789

795-
remote.getData(for: .day, endingOn: date) { (archives: StatsArchiveTimeIntervalData?, error: Error?) in
790+
var returnValue: StatsArchiveTimeIntervalData?
791+
remote.getData(for: .day, endingOn: date) { (value: StatsArchiveTimeIntervalData?, error: Error?) in
796792
XCTAssertNil(error)
797-
XCTAssertNotNil(archives)
798-
799-
XCTAssertEqual(archives?.period, .day)
800-
XCTAssertEqual(archives?.periodEndDate, date)
793+
returnValue = value
794+
expect.fulfill()
795+
}
796+
waitForExpectations(timeout: timeout, handler: nil)
801797

802-
// Test other items
803-
XCTAssertEqual(archives?.summary.other.count, 8)
798+
let archives = try XCTUnwrap(returnValue)
804799

805-
XCTAssertEqual(archives?.summary.other.first?.href, "http://example.com/wp-admin/admin.php?page=stats")
806-
XCTAssertEqual(archives?.summary.other.first?.value, "/wp-admin/admin.php?page=stats")
807-
XCTAssertEqual(archives?.summary.other.first?.views, 10)
800+
XCTAssertEqual(archives.period, .day)
801+
XCTAssertEqual(archives.periodEndDate, date)
808802

809-
XCTAssertEqual(archives?.summary.other[1].href, "http://example.com/wp-admin/")
810-
XCTAssertEqual(archives?.summary.other[1].value, "/wp-admin/")
811-
XCTAssertEqual(archives?.summary.other[1].views, 4)
803+
// Test other items
804+
let other = try XCTUnwrap(archives.summary["other"])
805+
XCTAssertEqual(other.count, 8)
812806

813-
XCTAssertEqual(archives?.summary.other.last?.href, "http://example.com/wp-admin/profile.php")
814-
XCTAssertEqual(archives?.summary.other.last?.value, "/wp-admin/profile.php")
815-
XCTAssertEqual(archives?.summary.other.last?.views, 1)
807+
XCTAssertEqual(other.first?.href, "http://example.com/wp-admin/admin.php?page=stats")
808+
XCTAssertEqual(other.first?.value, "/wp-admin/admin.php?page=stats")
809+
XCTAssertEqual(other.first?.views, 10)
816810

817-
// Test author items
818-
XCTAssertEqual(archives?.summary.author.count, 4)
811+
XCTAssertEqual(other[1].href, "http://example.com/wp-admin/")
812+
XCTAssertEqual(other[1].value, "/wp-admin/")
813+
XCTAssertEqual(other[1].views, 4)
819814

820-
XCTAssertEqual(archives?.summary.author.first?.href, "http://example.com/author/johndoe/")
821-
XCTAssertEqual(archives?.summary.author.first?.value, "johndoe")
822-
XCTAssertEqual(archives?.summary.author.first?.views, 31)
815+
XCTAssertEqual(other.last?.href, "http://example.com/wp-admin/profile.php")
816+
XCTAssertEqual(other.last?.value, "/wp-admin/profile.php")
817+
XCTAssertEqual(other.last?.views, 1)
823818

824-
XCTAssertEqual(archives?.summary.author[1].href, "http://example.com/author/janedoe/")
825-
XCTAssertEqual(archives?.summary.author[1].value, "janedoe")
826-
XCTAssertEqual(archives?.summary.author[1].views, 5)
819+
// Test author items
820+
let author = try XCTUnwrap(archives.summary["author"])
821+
XCTAssertEqual(author.count, 4)
827822

828-
XCTAssertEqual(archives?.summary.author.last?.href, "http://example.com/author//")
829-
XCTAssertEqual(archives?.summary.author.last?.value, "")
830-
XCTAssertEqual(archives?.summary.author.last?.views, 2)
823+
XCTAssertEqual(author.first?.href, "http://example.com/author/johndoe/")
824+
XCTAssertEqual(author.first?.value, "johndoe")
825+
XCTAssertEqual(author.first?.views, 31)
831826

832-
expect.fulfill()
833-
}
827+
XCTAssertEqual(author[1].href, "http://example.com/author/janedoe/")
828+
XCTAssertEqual(author[1].value, "janedoe")
829+
XCTAssertEqual(author[1].views, 5)
834830

835-
waitForExpectations(timeout: timeout, handler: nil)
831+
XCTAssertEqual(author.last?.href, "http://example.com/author//")
832+
XCTAssertEqual(author.last?.value, "")
833+
XCTAssertEqual(author.last?.views, 2)
836834
}
837835
}

0 commit comments

Comments
 (0)