Skip to content

Commit 8f6240c

Browse files
authored
Merge pull request #473 from woocommerce/issue/398-fancy-wc35
Adds fancy alert warning if site's WC is lower than v3.5
2 parents b5983a1 + b23fe79 commit 8f6240c

File tree

20 files changed

+57863
-7
lines changed

20 files changed

+57863
-7
lines changed

Networking/Networking.xcodeproj/project.pbxproj

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
740CF89921937A030023ED3A /* CommentRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 740CF89821937A030023ED3A /* CommentRemote.swift */; };
2222
7412A51121702E9700994370 /* order-stats-alt.json in Resources */ = {isa = PBXBuildFile; fileRef = 7412A51021702E9700994370 /* order-stats-alt.json */; };
2323
741B950120EBC8A700DD6E2D /* OrderCouponLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 741B950020EBC8A700DD6E2D /* OrderCouponLine.swift */; };
24+
7426CA0D21AF27B9004E9FFC /* SiteAPIRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7426CA0C21AF27B9004E9FFC /* SiteAPIRemote.swift */; };
25+
7426CA0F21AF2C90004E9FFC /* SiteAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7426CA0E21AF2C90004E9FFC /* SiteAPI.swift */; };
26+
7426CA1121AF30BD004E9FFC /* SiteAPIMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7426CA1021AF30BD004E9FFC /* SiteAPIMapper.swift */; };
27+
7426CA1321AF34A3004E9FFC /* site-api.json in Resources */ = {isa = PBXBuildFile; fileRef = 7426CA1221AF34A3004E9FFC /* site-api.json */; };
2428
743057B5218B6ACD00441A76 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 743057B4218B6ACD00441A76 /* Queue.swift */; };
2529
743BF8BE21191B63008A9D87 /* site-visits.json in Resources */ = {isa = PBXBuildFile; fileRef = 743BF8BD21191B63008A9D87 /* site-visits.json */; };
2630
743FDB9C210FB36900AC737F /* order-stats-month.json in Resources */ = {isa = PBXBuildFile; fileRef = 743FDB99210FB36900AC737F /* order-stats-month.json */; };
@@ -48,6 +52,9 @@
4852
74A7B4BC217A807400E85A8B /* SiteSettingsMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74A7B4BB217A807400E85A8B /* SiteSettingsMapperTests.swift */; };
4953
74A7B4BE217A841400E85A8B /* broken-settings-general.json in Resources */ = {isa = PBXBuildFile; fileRef = 74A7B4BD217A841400E85A8B /* broken-settings-general.json */; };
5054
74AB0ACA21948CE4008220CD /* CommentResultMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74AB0AC921948CE4008220CD /* CommentResultMapperTests.swift */; };
55+
74AB5B4D21AF354E00859C12 /* SiteAPIMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74AB5B4C21AF354E00859C12 /* SiteAPIMapperTests.swift */; };
56+
74AB5B4F21AF3F0E00859C12 /* site-api-no-woo.json in Resources */ = {isa = PBXBuildFile; fileRef = 74AB5B4E21AF3F0D00859C12 /* site-api-no-woo.json */; };
57+
74AB5B5121AF426D00859C12 /* SiteAPIRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74AB5B5021AF426D00859C12 /* SiteAPIRemoteTests.swift */; };
5158
74ABA1C5213F17AA00FFAD30 /* top-performers-day.json in Resources */ = {isa = PBXBuildFile; fileRef = 74ABA1C4213F17AA00FFAD30 /* top-performers-day.json */; };
5259
74ABA1C9213F19FE00FFAD30 /* top-performers-month.json in Resources */ = {isa = PBXBuildFile; fileRef = 74ABA1C6213F19FD00FFAD30 /* top-performers-month.json */; };
5360
74ABA1CA213F19FE00FFAD30 /* top-performers-year.json in Resources */ = {isa = PBXBuildFile; fileRef = 74ABA1C7213F19FE00FFAD30 /* top-performers-year.json */; };
@@ -178,6 +185,10 @@
178185
740CF89821937A030023ED3A /* CommentRemote.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommentRemote.swift; sourceTree = "<group>"; };
179186
7412A51021702E9700994370 /* order-stats-alt.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "order-stats-alt.json"; sourceTree = "<group>"; };
180187
741B950020EBC8A700DD6E2D /* OrderCouponLine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderCouponLine.swift; sourceTree = "<group>"; };
188+
7426CA0C21AF27B9004E9FFC /* SiteAPIRemote.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SiteAPIRemote.swift; sourceTree = "<group>"; };
189+
7426CA0E21AF2C90004E9FFC /* SiteAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SiteAPI.swift; sourceTree = "<group>"; };
190+
7426CA1021AF30BD004E9FFC /* SiteAPIMapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SiteAPIMapper.swift; sourceTree = "<group>"; };
191+
7426CA1221AF34A3004E9FFC /* site-api.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "site-api.json"; sourceTree = "<group>"; };
181192
743057B4218B6ACD00441A76 /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Queue.swift; path = ../../Yosemite/Yosemite/Internal/Queue.swift; sourceTree = "<group>"; };
182193
743BF8BD21191B63008A9D87 /* site-visits.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "site-visits.json"; sourceTree = "<group>"; };
183194
743FDB99210FB36900AC737F /* order-stats-month.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "order-stats-month.json"; sourceTree = "<group>"; };
@@ -205,6 +216,9 @@
205216
74A7B4BB217A807400E85A8B /* SiteSettingsMapperTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SiteSettingsMapperTests.swift; sourceTree = "<group>"; };
206217
74A7B4BD217A841400E85A8B /* broken-settings-general.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "broken-settings-general.json"; sourceTree = "<group>"; };
207218
74AB0AC921948CE4008220CD /* CommentResultMapperTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommentResultMapperTests.swift; sourceTree = "<group>"; };
219+
74AB5B4C21AF354E00859C12 /* SiteAPIMapperTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SiteAPIMapperTests.swift; sourceTree = "<group>"; };
220+
74AB5B4E21AF3F0D00859C12 /* site-api-no-woo.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "site-api-no-woo.json"; sourceTree = "<group>"; };
221+
74AB5B5021AF426D00859C12 /* SiteAPIRemoteTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SiteAPIRemoteTests.swift; sourceTree = "<group>"; };
208222
74ABA1C4213F17AA00FFAD30 /* top-performers-day.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "top-performers-day.json"; sourceTree = "<group>"; };
209223
74ABA1C6213F19FD00FFAD30 /* top-performers-month.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "top-performers-month.json"; sourceTree = "<group>"; };
210224
74ABA1C7213F19FE00FFAD30 /* top-performers-year.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "top-performers-year.json"; sourceTree = "<group>"; };
@@ -406,6 +420,7 @@
406420
B554FA8A2180B1D500C54DFF /* NotificationsRemoteTests.swift */,
407421
B518662920A09C6F00037A38 /* OrdersRemoteTests.swift */,
408422
74AE244C2113704C00CA8C54 /* OrderStatsRemoteTests.swift */,
423+
74AB5B5021AF426D00859C12 /* SiteAPIRemoteTests.swift */,
409424
74D5BECD217E0F98007B0348 /* SiteSettingsRemoteTests.swift */,
410425
74002D6B2118B88200A63C19 /* SiteVisitStatsRemoteTests.swift */,
411426
74CF5E8321402C04000CED0A /* TopEarnerStatsRemoteTests.swift */,
@@ -502,6 +517,7 @@
502517
B5DAEFEF2180DD5A0002356A /* NotificationsRemote.swift */,
503518
B557DA0120975500005962F4 /* OrdersRemote.swift */,
504519
748D4247210F89ED00CF7D1B /* OrderStatsRemote.swift */,
520+
7426CA0C21AF27B9004E9FFC /* SiteAPIRemote.swift */,
505521
74046E1A217A684D007DD7BF /* SiteSettingsRemote.swift */,
506522
74A1D26E21189EA000931DFA /* SiteVisitStatsRemote.swift */,
507523
74ABA1D0213F22CA00FFAD30 /* TopEarnersStatsRemote.swift */,
@@ -550,6 +566,7 @@
550566
74C8F06320EEB44800B6EDC9 /* OrderNote.swift */,
551567
B5BB1D1120A255EC00112D92 /* OrderStatus.swift */,
552568
B56C1EB720EA76F500D749F9 /* Site.swift */,
569+
7426CA0E21AF2C90004E9FFC /* SiteAPI.swift */,
553570
74046E1C217A6989007DD7BF /* SiteSetting.swift */,
554571
);
555572
path = Model;
@@ -587,6 +604,8 @@
587604
74046E20217A73D0007DD7BF /* settings-general.json */,
588605
7492FAE2217FBDBC00ED2C69 /* settings-general-alt.json */,
589606
B56C1EB920EA7D2C00D749F9 /* sites.json */,
607+
7426CA1221AF34A3004E9FFC /* site-api.json */,
608+
74AB5B4E21AF3F0D00859C12 /* site-api-no-woo.json */,
590609
74A1D25F211898F000931DFA /* site-visits-day.json */,
591610
74A1D260211898F000931DFA /* site-visits-week.json */,
592611
74A1D261211898F000931DFA /* site-visits-month.json */,
@@ -616,6 +635,7 @@
616635
74C8F06720EEB7BC00B6EDC9 /* OrderNotesMapper.swift */,
617636
CE583A0D2109154500D73C1C /* OrderNoteMapper.swift */,
618637
748D424B210FA34400CF7D1B /* OrderStatsMapper.swift */,
638+
7426CA1021AF30BD004E9FFC /* SiteAPIMapper.swift */,
619639
B56C1EB520EA757B00D749F9 /* SiteListMapper.swift */,
620640
74046E1E217A6B70007DD7BF /* SiteSettingsMapper.swift */,
621641
74A1D26C21189DFE00931DFA /* SiteVisitStatsMapper.swift */,
@@ -665,6 +685,7 @@
665685
74C8F06920EEBC8C00B6EDC9 /* OrderMapperTests.swift */,
666686
74C8F06D20EEC1E700B6EDC9 /* OrderNotesMapperTests.swift */,
667687
743FDB9F210FB3E500AC737F /* OrderStatsMapperTests.swift */,
688+
74AB5B4C21AF354E00859C12 /* SiteAPIMapperTests.swift */,
668689
74A7B4BB217A807400E85A8B /* SiteSettingsMapperTests.swift */,
669690
74002D692118B26000A63C19 /* SiteVisitStatsMapperTests.swift */,
670691
74ABA1D4213F26B300FFAD30 /* TopEarnerStatsMapperTests.swift */,
@@ -796,12 +817,14 @@
796817
B5147876211B9227007562E5 /* broken-orders-mark-2.json in Resources */,
797818
B58D10C82114D21D00107ED4 /* generic_error.json in Resources */,
798819
B505F6D520BEE4E700BB1B69 /* me.json in Resources */,
820+
74AB5B4F21AF3F0E00859C12 /* site-api-no-woo.json in Resources */,
799821
74C947832193A6C70024CB60 /* comment-moderate-trash.json in Resources */,
800822
B58D10CA2114D22E00107ED4 /* new-order-note.json in Resources */,
801823
B5C6FCD620A3768900A4F8E4 /* order.json in Resources */,
802824
74C947862193A6C70024CB60 /* comment-moderate-unapproved.json in Resources */,
803825
B559EBAA20A0B5CD00836CD4 /* orders-load-all.json in Resources */,
804826
74C8F06620EEB76400B6EDC9 /* order-notes.json in Resources */,
827+
7426CA1321AF34A3004E9FFC /* site-api.json in Resources */,
805828
748D424E210FB1F500CF7D1B /* order-stats-day.json in Resources */,
806829
743FDB9E210FB36900AC737F /* order-stats-week.json in Resources */,
807830
B554FA8D2180B59700C54DFF /* notifications-load-hashes.json in Resources */,
@@ -899,6 +922,7 @@
899922
7452387421124B7700A973CD /* AnyDecodable.swift in Sources */,
900923
B56C1EB620EA757B00D749F9 /* SiteListMapper.swift in Sources */,
901924
B50A583921AD861700617455 /* APNSDevice.swift in Sources */,
925+
7426CA0D21AF27B9004E9FFC /* SiteAPIRemote.swift in Sources */,
902926
B59325D4217E4206000B0E8E /* NoteBlock.swift in Sources */,
903927
B557DA1A20979D66005962F4 /* Settings.swift in Sources */,
904928
74ABA1D1213F22CA00FFAD30 /* TopEarnersStatsRemote.swift in Sources */,
@@ -917,6 +941,7 @@
917941
74ABA1CD213F1B6B00FFAD30 /* TopEarnerStats.swift in Sources */,
918942
B557DA0220975500005962F4 /* JetpackRequest.swift in Sources */,
919943
74046E1F217A6B70007DD7BF /* SiteSettingsMapper.swift in Sources */,
944+
7426CA1121AF30BD004E9FFC /* SiteAPIMapper.swift in Sources */,
920945
B56C1EB820EA76F500D749F9 /* Site.swift in Sources */,
921946
B5A2417D217F9ECC00595DEF /* MetaContainer.swift in Sources */,
922947
B53EF53821813806003E146F /* DotcomError.swift in Sources */,
@@ -937,6 +962,7 @@
937962
7452387321124B7700A973CD /* AnyCodable.swift in Sources */,
938963
B5A036A1214C0F5400774E2C /* CocoaLumberjack.swift in Sources */,
939964
B567AF2920A0FA1E00AB6C62 /* Mapper.swift in Sources */,
965+
7426CA0F21AF2C90004E9FFC /* SiteAPI.swift in Sources */,
940966
B53EF5322180F21C003E146F /* Dictionary+Woo.swift in Sources */,
941967
74A1D26D21189DFF00931DFA /* SiteVisitStatsMapper.swift in Sources */,
942968
74D522B62113607F00042831 /* StatGranularity.swift in Sources */,
@@ -986,6 +1012,7 @@
9861012
B505F6D320BEE3A500BB1B69 /* AccountMapperTests.swift in Sources */,
9871013
B5C6FCC820A32E4800A4F8E4 /* DateFormatterWooTests.swift in Sources */,
9881014
74C8F06A20EEBC8C00B6EDC9 /* OrderMapperTests.swift in Sources */,
1015+
74AB5B4D21AF354E00859C12 /* SiteAPIMapperTests.swift in Sources */,
9891016
B5C151C0217EE3FB00C7BDC1 /* NoteListMapperTests.swift in Sources */,
9901017
B567AF3120A0FB8F00AB6C62 /* JetpackRequestTests.swift in Sources */,
9911018
B505F6D720BEE58800BB1B69 /* AccountRemoteTests.swift in Sources */,
@@ -994,6 +1021,7 @@
9941021
B5969E1520A47F99005E9DF1 /* RemoteTests.swift in Sources */,
9951022
74C8F06E20EEC1E800B6EDC9 /* OrderNotesMapperTests.swift in Sources */,
9961023
74ABA1D5213F26B300FFAD30 /* TopEarnerStatsMapperTests.swift in Sources */,
1024+
74AB5B5121AF426D00859C12 /* SiteAPIRemoteTests.swift in Sources */,
9971025
B567AF2F20A0FB8F00AB6C62 /* AuthenticatedRequestTests.swift in Sources */,
9981026
B5C6FCCD20A34B8300A4F8E4 /* OrderListMapperTests.swift in Sources */,
9991027
B518663520A0A2E800037A38 /* Constants.swift in Sources */,
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import Foundation
2+
3+
4+
/// Mapper: SiteAPI
5+
///
6+
struct SiteAPIMapper: Mapper {
7+
8+
/// Site Identifier associated to the API information that will be parsed.
9+
/// We're injecting this field via `JSONDecoder.userInfo` because the remote endpoints don't return the SiteID.
10+
///
11+
let siteID: Int
12+
13+
/// (Attempts) to convert a dictionary into [SiteSetting].
14+
///
15+
func map(response: Data) throws -> SiteAPI {
16+
let decoder = JSONDecoder()
17+
decoder.dateDecodingStrategy = .formatted(DateFormatter.Defaults.dateTimeFormatter)
18+
decoder.userInfo = [
19+
.siteID: siteID
20+
]
21+
22+
return try decoder.decode(SiteAPIEnvelope.self, from: response).siteAPI
23+
}
24+
}
25+
26+
27+
/// SiteAPIEnvelope Disposable Entity:
28+
/// The settings endpoint returns the settings document within a `data` key. This entity
29+
/// allows us to do parse all the things with JSONDecoder.
30+
///
31+
private struct SiteAPIEnvelope: Decodable {
32+
let siteAPI: SiteAPI
33+
34+
private enum CodingKeys: String, CodingKey {
35+
case siteAPI = "data"
36+
}
37+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import Foundation
2+
3+
4+
/// Encapsulates API Information for a given site
5+
///
6+
public struct SiteAPI: Decodable {
7+
8+
/// Site Identifier.
9+
///
10+
public let siteID: Int
11+
12+
/// Available API namespaces
13+
///
14+
public let namespaces: [String]
15+
16+
/// Highest Woo API version installed on the site
17+
///
18+
public var highestWooVersion: WooAPIVersion {
19+
if namespaces.contains(WooAPIVersion.mark3.rawValue) {
20+
return .mark3
21+
} else if namespaces.contains(WooAPIVersion.mark2.rawValue) {
22+
return .mark2
23+
} else if namespaces.contains(WooAPIVersion.mark1.rawValue) {
24+
return .mark1
25+
}
26+
27+
return .none
28+
}
29+
30+
/// Decodable Conformance.
31+
///
32+
public init(from decoder: Decoder) throws {
33+
guard let siteID = decoder.userInfo[.siteID] as? Int else {
34+
throw SiteAPIError.missingSiteID
35+
}
36+
37+
let siteAPIContainer = try decoder.container(keyedBy: SiteAPIKeys.self)
38+
let namespaces = siteAPIContainer.failsafeDecodeIfPresent([String].self, forKey: .namespaces) ?? []
39+
40+
self.init(siteID: siteID, namespaces: namespaces)
41+
}
42+
43+
/// Designated Initializer.
44+
///
45+
public init(siteID: Int, namespaces: [String]) {
46+
self.siteID = siteID
47+
self.namespaces = namespaces
48+
}
49+
}
50+
51+
52+
// MARK: - Comparable Conformance
53+
//
54+
extension SiteAPI: Comparable {
55+
public static func == (lhs: SiteAPI, rhs: SiteAPI) -> Bool {
56+
return lhs.siteID == rhs.siteID &&
57+
lhs.namespaces == rhs.namespaces &&
58+
lhs.highestWooVersion == rhs.highestWooVersion
59+
60+
}
61+
62+
public static func < (lhs: SiteAPI, rhs: SiteAPI) -> Bool {
63+
return lhs.siteID < rhs.siteID
64+
}
65+
66+
public static func > (lhs: SiteAPI, rhs: SiteAPI) -> Bool {
67+
return lhs.siteID > rhs.siteID
68+
}
69+
}
70+
71+
72+
/// Defines all of the SiteAPI CodingKeys.
73+
///
74+
private extension SiteAPI {
75+
76+
enum SiteAPIKeys: String, CodingKey {
77+
case namespaces = "namespaces"
78+
}
79+
}
80+
81+
82+
// MARK: - Decoding Errors
83+
//
84+
enum SiteAPIError: Error {
85+
case missingSiteID
86+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import Foundation
2+
import Alamofire
3+
4+
5+
/// Site API: Remote Endpoints
6+
///
7+
public class SiteAPIRemote: Remote {
8+
9+
/// Calls the root wp-json endpoint (`/`) via the Jetpack tunnel for the provided siteID
10+
/// and parses the response for API information.
11+
///
12+
/// - Parameters:
13+
/// - siteID: Site for which we'll fetch the API settings.
14+
/// - completion: Closure to be executed upon completion.
15+
///
16+
public func loadAPIInformation(for siteID: Int, completion: @escaping (SiteAPI?, Error?) -> Void) {
17+
let path = String()
18+
let request = JetpackRequest(wooApiVersion: .none, method: .get, siteID: siteID, path: path)
19+
let mapper = SiteAPIMapper(siteID: siteID)
20+
21+
enqueue(request, mapper: mapper, completion: completion)
22+
}
23+
}

Networking/Networking/Settings/WooAPIVersion.swift

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,31 @@ import Foundation
33

44
/// Defines the supported Woo API Versions.
55
///
6-
enum WooAPIVersion: String {
6+
public enum WooAPIVersion: String {
7+
8+
/// No version
9+
///
10+
case none = ""
11+
12+
/// Woo Endpoint Mark 1
13+
///
14+
case mark1 = "wc/v1"
715

816
/// Woo Endpoint Mark 2
917
///
10-
case mark2 = "/wc/v2/"
18+
case mark2 = "wc/v2"
19+
20+
/// Woo Endpoint Mark 3
21+
///
22+
case mark3 = "wc/v3"
1123

1224
/// Returns the path for the current API Version
1325
///
1426
var path: String {
15-
return rawValue
27+
guard self != .none else {
28+
return "/"
29+
}
30+
31+
return "/" + rawValue + "/"
1632
}
1733
}

0 commit comments

Comments
 (0)