Skip to content

Commit 5faa93f

Browse files
committed
Merge branch 'trunk' into try/prologue-cta-order-ab-test
# Conflicts: # WooCommerce/Classes/AppDelegate.swift
2 parents 9a518d5 + bdc0b42 commit 5faa93f

File tree

70 files changed

+2812
-348
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+2812
-348
lines changed

Experiments/Experiments/DefaultFeatureFlagService.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ public struct DefaultFeatureFlagService: FeatureFlagService {
3737
return buildConfig == .localDeveloper || buildConfig == .alpha
3838
case .inPersonPaymentGatewaySelection:
3939
return true
40-
case .unifiedOrderEditing:
41-
return true
4240
case .backgroundProductImageUpload:
4341
return true
4442
case .appleIDAccountDeletion:

Experiments/Experiments/FeatureFlag.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,6 @@ public enum FeatureFlag: Int {
7474
///
7575
case inPersonPaymentGatewaySelection
7676

77-
/// Enable order editing from the order detailed screen.
78-
///
79-
case unifiedOrderEditing
80-
8177
/// Enable image upload after leaving the product form
8278
///
8379
case backgroundProductImageUpload

Fakes/Fakes/Networking.generated.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,18 @@ extension PaymentGateway {
579579
title: .fake(),
580580
description: .fake(),
581581
enabled: .fake(),
582-
features: .fake()
582+
features: .fake(),
583+
instructions: .fake()
584+
)
585+
}
586+
}
587+
extension PaymentGateway.Setting {
588+
/// Returns a "ready to use" type filled with fake values.
589+
///
590+
public static func fake() -> PaymentGateway.Setting {
591+
.init(
592+
settingID: .fake(),
593+
value: .fake()
583594
)
584595
}
585596
}

Networking/Networking.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@
7777
02E7FFCB256218F600C53030 /* ShippingLabelRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02E7FFCA256218F600C53030 /* ShippingLabelRemoteTests.swift */; };
7878
02E7FFCF25621C7900C53030 /* shipping-label-print.json in Resources */ = {isa = PBXBuildFile; fileRef = 02E7FFCE25621C7900C53030 /* shipping-label-print.json */; };
7979
02F096C22406691100C0C1D5 /* media-library.json in Resources */ = {isa = PBXBuildFile; fileRef = 02F096C12406691100C0C1D5 /* media-library.json */; };
80+
0313651928AE559D00EEE571 /* PaymentGatewayMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0313651828AE559D00EEE571 /* PaymentGatewayMapper.swift */; };
81+
0313651B28AE60E000EEE571 /* payment-gateway-cod.json in Resources */ = {isa = PBXBuildFile; fileRef = 0313651A28AE60E000EEE571 /* payment-gateway-cod.json */; };
82+
0313651D28AE625300EEE571 /* PaymentGatewayMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0313651C28AE625300EEE571 /* PaymentGatewayMapperTests.swift */; };
8083
0329CF9B27A82E19008AFF91 /* WCPayCharge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0329CF9A27A82E19008AFF91 /* WCPayCharge.swift */; };
8184
034480C327A42F9100DFACD2 /* order-with-charge.json in Resources */ = {isa = PBXBuildFile; fileRef = 034480C227A42F9100DFACD2 /* order-with-charge.json */; };
8285
0359EA0D27AAC5F80048DE2D /* WCPayChargeStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0359EA0C27AAC5F80048DE2D /* WCPayChargeStatus.swift */; };
@@ -751,6 +754,9 @@
751754
02E7FFCA256218F600C53030 /* ShippingLabelRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingLabelRemoteTests.swift; sourceTree = "<group>"; };
752755
02E7FFCE25621C7900C53030 /* shipping-label-print.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "shipping-label-print.json"; sourceTree = "<group>"; };
753756
02F096C12406691100C0C1D5 /* media-library.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "media-library.json"; sourceTree = "<group>"; };
757+
0313651828AE559D00EEE571 /* PaymentGatewayMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentGatewayMapper.swift; sourceTree = "<group>"; };
758+
0313651A28AE60E000EEE571 /* payment-gateway-cod.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "payment-gateway-cod.json"; sourceTree = "<group>"; };
759+
0313651C28AE625300EEE571 /* PaymentGatewayMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentGatewayMapperTests.swift; sourceTree = "<group>"; };
754760
0329CF9A27A82E19008AFF91 /* WCPayCharge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WCPayCharge.swift; sourceTree = "<group>"; };
755761
034480C227A42F9100DFACD2 /* order-with-charge.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "order-with-charge.json"; sourceTree = "<group>"; };
756762
0359EA0C27AAC5F80048DE2D /* WCPayChargeStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WCPayChargeStatus.swift; sourceTree = "<group>"; };
@@ -1913,6 +1919,7 @@
19131919
0272E3FA254AABB800436277 /* order-with-line-item-attributes-before-API-support.json */,
19141920
A69FE19C2588D70E0059A96B /* order-with-deleted-refunds.json */,
19151921
261CF1B3255AD6B30090D8D3 /* payment-gateway-list.json */,
1922+
0313651A28AE60E000EEE571 /* payment-gateway-cod.json */,
19161923
261CF2CA255C50010090D8D3 /* payment-gateway-list-half.json */,
19171924
DEC51A96274DD962009F3DF4 /* plugin.json */,
19181925
DEC51A9A274E3206009F3DF4 /* plugin-inactive.json */,
@@ -2077,6 +2084,7 @@
20772084
02C254B825637BA000A04423 /* OrderShippingLabelListMapper.swift */,
20782085
D8FBFF1022D3B3FC006E3336 /* OrderStatsV4Mapper.swift */,
20792086
26731336255ACA850026F7EF /* PaymentGatewayListMapper.swift */,
2087+
0313651828AE559D00EEE571 /* PaymentGatewayMapper.swift */,
20802088
74749B96224134FF005C4CF2 /* ProductMapper.swift */,
20812089
45152810257A81730076B03C /* ProductAttributeMapper.swift */,
20822090
4515280C257A7EEC0076B03C /* ProductAttributeListMapper.swift */,
@@ -2217,6 +2225,7 @@
22172225
74C8F06D20EEC1E700B6EDC9 /* OrderNotesMapperTests.swift */,
22182226
D8FBFF1D22D51F39006E3336 /* OrderStatsMapperV4Tests.swift */,
22192227
262E5AD4255ACD6F000B2416 /* PaymentGatewayListMapperTests.swift */,
2228+
0313651C28AE625300EEE571 /* PaymentGatewayMapperTests.swift */,
22202229
D8A2849925FBB2E70019A84B /* ProductAttributeTermListMapperTests.swift */,
22212230
CE0A0F1C22398D520075ED8D /* ProductListMapperTests.swift */,
22222231
74CF0A8B22414D7800DB993F /* ProductMapperTests.swift */,
@@ -2534,6 +2543,7 @@
25342543
D865CE6B278CA266002C8520 /* stripe-payment-intent-error.json in Resources */,
25352544
CCB2CAA82620ABCC00285CA0 /* shipping-label-create-package-error.json in Resources */,
25362545
B57B1E6C21C94C9F0046E764 /* timeout_error.json in Resources */,
2546+
0313651B28AE60E000EEE571 /* payment-gateway-cod.json in Resources */,
25372547
B5C6FCD620A3768900A4F8E4 /* order.json in Resources */,
25382548
3158FE7426129D9F00E566B9 /* wcpay-account-rejected-other.json in Resources */,
25392549
CC0786C7267BB10700BA9AC1 /* shipping-label-status-success.json in Resources */,
@@ -2877,6 +2887,7 @@
28772887
CC6A1FF5270E042200F6AF4A /* OrderMetaData.swift in Sources */,
28782888
DEC51B02276AFB35009F3DF4 /* SystemStatus+DropinMustUsePlugin.swift in Sources */,
28792889
02C254A4256371B200A04423 /* ShippingLabelSettings.swift in Sources */,
2890+
0313651928AE559D00EEE571 /* PaymentGatewayMapper.swift in Sources */,
28802891
B554FA912180BCFC00C54DFF /* NoteHash.swift in Sources */,
28812892
CE0A0F19223987DF0075ED8D /* ProductListMapper.swift in Sources */,
28822893
021C7BF723863D1800A3BCBD /* Encodable+Serialization.swift in Sources */,
@@ -3067,6 +3078,7 @@
30673078
B505F6D320BEE3A500BB1B69 /* AccountMapperTests.swift in Sources */,
30683079
CC9A254A26442D26005DE56E /* ShippingLabelCreationEligibilityMapperTests.swift in Sources */,
30693080
5726F7342460A8F00031CAAC /* CopiableTests.swift in Sources */,
3081+
0313651D28AE625300EEE571 /* PaymentGatewayMapperTests.swift in Sources */,
30703082
26615479242DA54D00A31661 /* ProductCategoyListMapperTests.swift in Sources */,
30713083
B5C6FCC820A32E4800A4F8E4 /* DateFormatterWooTests.swift in Sources */,
30723084
74C8F06A20EEBC8C00B6EDC9 /* OrderMapperTests.swift in Sources */,

Networking/Networking/Mapper/PaymentGatewayListMapper.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Foundation
44
///
55
struct PaymentGatewayListMapper: Mapper {
66

7-
/// Site Identifier associated to the shipment trackings that will be parsed.
7+
/// Site Identifier associated to the payment gateways that will be parsed.
88
/// We're injecting this field via `JSONDecoder.userInfo` because the remote endpoints don't
99
/// return the siteID for the payment gateway endpoint
1010
///
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import Foundation
2+
3+
/// Mapper for a `PaymentGateway` JSON object
4+
///
5+
struct PaymentGatewayMapper: Mapper {
6+
7+
/// Site Identifier associated to the payment gateway that will be parsed.
8+
/// We're injecting this field via `JSONDecoder.userInfo` because the remote endpoints don't
9+
/// return the siteID for the payment gateway endpoint
10+
///
11+
let siteID: Int64
12+
13+
/// (Attempts) to convert a dictionary into `PaymentGateway`
14+
///
15+
func map(response: Data) throws -> PaymentGateway {
16+
let decoder = JSONDecoder()
17+
decoder.userInfo = [
18+
.siteID: siteID,
19+
]
20+
return try decoder.decode(PaymentGatewayEnvelope.self, from: response).paymentGateway
21+
}
22+
}
23+
24+
/// PaymentGateway list disposable entity:
25+
/// `Load Payment Gateway` endpoint returns all of the gateway information within a `body` obejcts in the `data` key. This entity
26+
/// allows us to parse all the things with JSONDecoder.
27+
///
28+
private struct PaymentGatewayEnvelope: Decodable {
29+
private enum CodingKeys: String, CodingKey {
30+
case paymentGateway = "data"
31+
}
32+
33+
let paymentGateway: PaymentGateway
34+
}

Networking/Networking/Model/Copiable/Models+Copiable.generated.swift

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -665,22 +665,40 @@ extension PaymentGateway {
665665
title: CopiableProp<String> = .copy,
666666
description: CopiableProp<String> = .copy,
667667
enabled: CopiableProp<Bool> = .copy,
668-
features: CopiableProp<[PaymentGateway.Feature]> = .copy
668+
features: CopiableProp<[PaymentGateway.Feature]> = .copy,
669+
instructions: NullableCopiableProp<String> = .copy
669670
) -> PaymentGateway {
670671
let siteID = siteID ?? self.siteID
671672
let gatewayID = gatewayID ?? self.gatewayID
672673
let title = title ?? self.title
673674
let description = description ?? self.description
674675
let enabled = enabled ?? self.enabled
675676
let features = features ?? self.features
677+
let instructions = instructions ?? self.instructions
676678

677679
return PaymentGateway(
678680
siteID: siteID,
679681
gatewayID: gatewayID,
680682
title: title,
681683
description: description,
682684
enabled: enabled,
683-
features: features
685+
features: features,
686+
instructions: instructions
687+
)
688+
}
689+
}
690+
691+
extension PaymentGateway.Setting {
692+
public func copy(
693+
settingID: CopiableProp<String> = .copy,
694+
value: CopiableProp<String> = .copy
695+
) -> PaymentGateway.Setting {
696+
let settingID = settingID ?? self.settingID
697+
let value = value ?? self.value
698+
699+
return PaymentGateway.Setting(
700+
settingID: settingID,
701+
value: value
684702
)
685703
}
686704
}

Networking/Networking/Model/PaymentGateway.swift

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ public struct PaymentGateway: Equatable, GeneratedFakeable, GeneratedCopiable {
1313
case custom(raw: String)
1414
}
1515

16+
/// Setting for a payment gateway
17+
///
18+
public struct Setting: Equatable, GeneratedCopiable, GeneratedFakeable {
19+
public let settingID: String
20+
public let value: String
21+
22+
public init(settingID: String,
23+
value: String) {
24+
self.settingID = settingID
25+
self.value = value
26+
}
27+
}
28+
1629
/// Site identifier.
1730
///
1831
public let siteID: Int64
@@ -37,18 +50,29 @@ public struct PaymentGateway: Equatable, GeneratedFakeable, GeneratedCopiable {
3750
///
3851
public let features: [Feature]
3952

40-
public init(siteID: Int64, gatewayID: String, title: String, description: String, enabled: Bool, features: [Feature]) {
53+
/// Instructions shown to the customer after purchase.
54+
///
55+
public let instructions: String?
56+
57+
public init(siteID: Int64,
58+
gatewayID: String,
59+
title: String,
60+
description: String,
61+
enabled: Bool,
62+
features: [Feature],
63+
instructions: String?) {
4164
self.siteID = siteID
4265
self.gatewayID = gatewayID
4366
self.title = title
4467
self.description = description
4568
self.enabled = enabled
4669
self.features = features
70+
self.instructions = instructions
4771
}
4872
}
4973

50-
// MARK: Gateway Decodable
51-
extension PaymentGateway: Decodable {
74+
// MARK: Gateway Codable
75+
extension PaymentGateway: Codable {
5276

5377
public enum DecodingError: Error {
5478
case missingSiteID
@@ -60,7 +84,8 @@ extension PaymentGateway: Decodable {
6084
case description
6185
case enabled
6286
case features = "method_supports"
63-
87+
case instructions
88+
case settings
6489
}
6590

6691
public init(from decoder: Decoder) throws {
@@ -75,17 +100,38 @@ extension PaymentGateway: Decodable {
75100
let enabled = try container.decode(Bool.self, forKey: .enabled)
76101
let features = try container.decode([Feature].self, forKey: .features)
77102

103+
// Settings can have different types for `value`, this implementation only handles `String`
104+
let settings = try? container.decodeIfPresent([String: Setting].self, forKey: .settings)
105+
let instructions = settings?[Setting.Keys.instructions]?.value
106+
78107
self.init(siteID: siteID,
79108
gatewayID: gatewayID,
80109
title: title,
81110
description: description,
82111
enabled: enabled,
83-
features: features)
112+
features: features,
113+
instructions: instructions)
114+
}
115+
116+
public func encode(to encoder: Encoder) throws {
117+
var container = encoder.container(keyedBy: CodingKeys.self)
118+
119+
try container.encode(gatewayID, forKey: .gatewayID)
120+
try container.encode(title, forKey: .title)
121+
try container.encode(description, forKey: .description)
122+
try container.encode(enabled, forKey: .enabled)
123+
try container.encode(features, forKey: .features)
124+
125+
guard let instructions = instructions else {
126+
return
127+
}
128+
let settings = [Setting.Keys.instructions: instructions]
129+
try container.encode(settings, forKey: .settings)
84130
}
85131
}
86132

87-
// MARK: Features Decodable
88-
extension PaymentGateway.Feature: RawRepresentable, Decodable {
133+
// MARK: - Features Decodable
134+
extension PaymentGateway.Feature: RawRepresentable, Codable {
89135

90136
/// Enum containing the 'Known' Feature Keys
91137
///
@@ -116,3 +162,20 @@ extension PaymentGateway.Feature: RawRepresentable, Decodable {
116162
}
117163
}
118164
}
165+
166+
// MARK: - Settings Codable
167+
extension PaymentGateway.Setting: Codable {
168+
/// The known keys, which match `settingID`
169+
///
170+
fileprivate enum Keys {
171+
static let title = "title"
172+
static let instructions = "instructions"
173+
static let enableForMethods = "enable_for_methods"
174+
static let enableForVirtual = "enable_for_virtual"
175+
}
176+
177+
private enum CodingKeys: String, CodingKey {
178+
case settingID = "id"
179+
case value
180+
}
181+
}

Networking/Networking/Remote/PaymentGatewayRemote.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,35 @@ public class PaymentGatewayRemote: Remote {
1515
let mapper = PaymentGatewayListMapper(siteID: siteID)
1616
enqueue(request, mapper: mapper, completion: completion)
1717
}
18+
19+
// MARK: - Update Payment Gateway
20+
21+
/// Updates a `PaymentGateway`.
22+
///
23+
/// - Parameters:
24+
/// - paymentGateway: The Payment Gateway to be updated remotely.
25+
/// - completion: Closure to be executed upon completion.
26+
///
27+
public func updatePaymentGateway(_ paymentGateway: PaymentGateway,
28+
completion: @escaping (Result<PaymentGateway, Error>) -> Void) {
29+
do {
30+
let parameters = try paymentGateway.toDictionary(keyEncodingStrategy: .convertToSnakeCase)
31+
let siteID = paymentGateway.siteID
32+
let path = Constants.path + "/\(paymentGateway.gatewayID)"
33+
34+
let request = JetpackRequest(wooApiVersion: .mark3,
35+
method: .put,
36+
siteID: siteID,
37+
path: path,
38+
parameters: parameters)
39+
40+
let mapper = PaymentGatewayMapper(siteID: siteID)
41+
42+
enqueue(request, mapper: mapper, completion: completion)
43+
} catch {
44+
completion(.failure(error))
45+
}
46+
}
1847
}
1948

2049
// MARK: Constant

0 commit comments

Comments
 (0)