Skip to content

Commit 57b1813

Browse files
authored
Merge branch 'release/19.8' into merge/19.7.1-hotfix-into-release-19.8
2 parents 1ab07be + 6c88236 commit 57b1813

File tree

180 files changed

+2457
-1923
lines changed

Some content is hidden

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

180 files changed

+2457
-1923
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ Closes: #
1818

1919
---
2020
- [ ] I have considered if this change warrants user-facing release notes and have added them to `RELEASE-NOTES.txt` if necessary.
21+
- [ ] This PR includes refactoring; smoke testing of the entire section is needed.

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<!--
22
Contains editorialized release notes. Raw release notes should go into `RELEASE-NOTES.txt`.
33
-->
4+
## 19.8
5+
Experience seamless updates with our latest release! Now enjoy background updates for your order list and dashboard analytics cards. We've enhanced the dynamic dashboard to display unavailable analytics views when not logged into WPCom. Plus, we've fixed large text support in the Barcode Scanner for better accessibility. Update now for a smoother experience!
6+
47
## 19.7
58
Exciting updates in our WooCommerce mobile app! Manage Google Ads campaigns with plugin version 2.7.7 or later. Enjoy consistent order status across various lists. Easily create paid campaigns with our new call to action in Google Campaign analytics. Plus, we've improved Blaze and Product Creation AI features for a smoother experience. Update now!
69

Fakes/Fakes/Networking.generated.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,13 +1235,13 @@ extension Networking.Product {
12351235
bundleMinSize: .fake(),
12361236
bundleMaxSize: .fake(),
12371237
bundledItems: .fake(),
1238+
password: .fake(),
12381239
compositeComponents: .fake(),
12391240
subscription: .fake(),
12401241
minAllowedQuantity: .fake(),
12411242
maxAllowedQuantity: .fake(),
12421243
groupOfQuantity: .fake(),
1243-
combineVariationQuantities: .fake(),
1244-
password: .fake()
1244+
combineVariationQuantities: .fake()
12451245
)
12461246
}
12471247
}

Networking/Networking/ApplicationPassword/ApplicationPasswordStorage.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ import KeychainAccess
55
import WordPressShared
66
#endif
77

8-
struct ApplicationPasswordStorage {
8+
public struct ApplicationPasswordStorage {
99
/// Stores the application password
1010
///
1111
private let keychain: Keychain
1212

13-
init(keychain: Keychain = Keychain(service: WooConstants.keychainServiceName)) {
13+
public init(keychain: Keychain = Keychain(service: WooConstants.keychainServiceName)) {
1414
self.keychain = keychain
1515
}
1616

1717
/// Returns the saved application password if available
1818
///
19-
var applicationPassword: ApplicationPassword? {
19+
public var applicationPassword: ApplicationPassword? {
2020
guard let password = keychain.password,
2121
let username = keychain.username,
2222
let uuid = keychain.uuid else {
@@ -29,15 +29,15 @@ struct ApplicationPasswordStorage {
2929
///
3030
/// - Parameter password: `ApplicationPasword` to be saved
3131
///
32-
func saveApplicationPassword(_ password: ApplicationPassword) {
32+
public func saveApplicationPassword(_ password: ApplicationPassword) {
3333
keychain.username = password.wpOrgUsername
3434
keychain.password = password.password.secretValue
3535
keychain.uuid = password.uuid
3636
}
3737

3838
/// Removes the currently saved password from storage
3939
///
40-
func removeApplicationPassword() {
40+
public func removeApplicationPassword() {
4141
// Delete password from keychain
4242
keychain.username = nil
4343
keychain.password = nil

Networking/Networking/Model/ApplicationPassword/ApplicationPassword.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import WordPressShared
33
#endif
44

5-
public struct ApplicationPassword: Decodable {
5+
public struct ApplicationPassword: Codable, Equatable {
66
/// WordPress org username that the application password belongs to
77
///
88
public let wpOrgUsername: String
@@ -24,7 +24,12 @@ public struct ApplicationPassword: Decodable {
2424
public init(from decoder: Decoder) throws {
2525
let container = try decoder.container(keyedBy: CodingKeys.self)
2626

27-
guard let wpOrgUsername = decoder.userInfo[.wpOrgUsername] as? String else {
27+
// Search for `wpOrgUsername` either in the decoder or in the user info
28+
let wpOrgUsername: String? = {
29+
return try? container.decodeIfPresent(String.self, forKey: .wpOrgUsername) ?? decoder.userInfo[.wpOrgUsername] as? String
30+
}()
31+
32+
guard let wpOrgUsername else {
2833
throw ApplicationPasswordDecodingError.missingWpOrgUsername
2934
}
3035

@@ -33,7 +38,15 @@ public struct ApplicationPassword: Decodable {
3338
self.init(wpOrgUsername: wpOrgUsername, password: Secret(password), uuid: uuid)
3439
}
3540

41+
public func encode(to encoder: Encoder) throws {
42+
var container = encoder.container(keyedBy: CodingKeys.self)
43+
try container.encode(wpOrgUsername, forKey: .wpOrgUsername)
44+
try container.encodeIfPresent(password.secretValue, forKey: .password)
45+
try container.encodeIfPresent(uuid, forKey: .uuid)
46+
}
47+
3648
enum CodingKeys: String, CodingKey {
49+
case wpOrgUsername
3750
case password
3851
case uuid
3952
}
@@ -44,3 +57,6 @@ public struct ApplicationPassword: Decodable {
4457
enum ApplicationPasswordDecodingError: Error {
4558
case missingWpOrgUsername
4659
}
60+
61+
// Add equatable conformance to Secret when possible
62+
extension Secret: Equatable where Self.RawValue: Equatable {}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,6 +1928,7 @@ extension Networking.Product {
19281928
bundleMinSize: NullableCopiableProp<Decimal> = .copy,
19291929
bundleMaxSize: NullableCopiableProp<Decimal> = .copy,
19301930
bundledItems: CopiableProp<[ProductBundleItem]> = .copy,
1931+
password: NullableCopiableProp<String> = .copy,
19311932
compositeComponents: CopiableProp<[ProductCompositeComponent]> = .copy,
19321933
subscription: NullableCopiableProp<ProductSubscription> = .copy,
19331934
minAllowedQuantity: NullableCopiableProp<String> = .copy,
@@ -2004,6 +2005,7 @@ extension Networking.Product {
20042005
let bundleMinSize = bundleMinSize ?? self.bundleMinSize
20052006
let bundleMaxSize = bundleMaxSize ?? self.bundleMaxSize
20062007
let bundledItems = bundledItems ?? self.bundledItems
2008+
let password = password ?? self.password
20072009
let compositeComponents = compositeComponents ?? self.compositeComponents
20082010
let subscription = subscription ?? self.subscription
20092011
let minAllowedQuantity = minAllowedQuantity ?? self.minAllowedQuantity
@@ -2081,13 +2083,13 @@ extension Networking.Product {
20812083
bundleMinSize: bundleMinSize,
20822084
bundleMaxSize: bundleMaxSize,
20832085
bundledItems: bundledItems,
2086+
password: password,
20842087
compositeComponents: compositeComponents,
20852088
subscription: subscription,
20862089
minAllowedQuantity: minAllowedQuantity,
20872090
maxAllowedQuantity: maxAllowedQuantity,
20882091
groupOfQuantity: groupOfQuantity,
2089-
combineVariationQuantities: combineVariationQuantities,
2090-
password: password
2092+
combineVariationQuantities: combineVariationQuantities
20912093
)
20922094
}
20932095
}

Networking/Networking/Model/Product/AIProduct.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,12 @@ public extension Product {
195195
bundleMinSize: nil,
196196
bundleMaxSize: nil,
197197
bundledItems: [],
198+
password: nil,
198199
compositeComponents: [],
199200
subscription: nil,
200201
minAllowedQuantity: nil,
201202
maxAllowedQuantity: nil,
202203
groupOfQuantity: nil,
203-
combineVariationQuantities: nil,
204-
password: nil)
204+
combineVariationQuantities: nil)
205205
}
206206
}

Networking/Networking/Model/Product/Product.swift

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -255,13 +255,13 @@ public struct Product: Codable, GeneratedCopiable, Equatable, GeneratedFakeable
255255
bundleMinSize: Decimal?,
256256
bundleMaxSize: Decimal?,
257257
bundledItems: [ProductBundleItem],
258+
password: String?,
258259
compositeComponents: [ProductCompositeComponent],
259260
subscription: ProductSubscription?,
260261
minAllowedQuantity: String?,
261262
maxAllowedQuantity: String?,
262263
groupOfQuantity: String?,
263-
combineVariationQuantities: Bool?,
264-
password: String?) {
264+
combineVariationQuantities: Bool?) {
265265
self.siteID = siteID
266266
self.productID = productID
267267
self.name = name
@@ -331,13 +331,13 @@ public struct Product: Codable, GeneratedCopiable, Equatable, GeneratedFakeable
331331
self.bundleMinSize = bundleMinSize
332332
self.bundleMaxSize = bundleMaxSize
333333
self.bundledItems = bundledItems
334+
self.password = password
334335
self.compositeComponents = compositeComponents
335336
self.subscription = subscription
336337
self.minAllowedQuantity = minAllowedQuantity.refinedMinMaxQuantityEmptyValue
337338
self.groupOfQuantity = groupOfQuantity.refinedMinMaxQuantityEmptyValue
338339
self.maxAllowedQuantity = maxAllowedQuantity
339340
self.combineVariationQuantities = combineVariationQuantities
340-
self.password = password
341341
}
342342

343343
/// The public initializer for Product.
@@ -538,6 +538,9 @@ public struct Product: Codable, GeneratedCopiable, Equatable, GeneratedFakeable
538538
let bundleMaxSize = container.failsafeDecodeIfPresent(decimalForKey: .bundleMaxSize)
539539
let bundledItems = try container.decodeIfPresent([ProductBundleItem].self, forKey: .bundledItems) ?? []
540540

541+
// Password
542+
let password = container.failsafeDecodeIfPresent(stringForKey: .password)
543+
541544
// Composite Product properties
542545
let compositeComponents = try container.decodeIfPresent([ProductCompositeComponent].self, forKey: .compositeComponents) ?? []
543546

@@ -554,9 +557,6 @@ public struct Product: Codable, GeneratedCopiable, Equatable, GeneratedFakeable
554557
combineVariationQuantities = combineVariationQuantitiesString == Values.combineVariationQuantitiesTrueValue
555558
}
556559

557-
// Password
558-
let password = container.failsafeDecodeIfPresent(stringForKey: .password)
559-
560560
self.init(siteID: siteID,
561561
productID: productID,
562562
name: name,
@@ -626,13 +626,13 @@ public struct Product: Codable, GeneratedCopiable, Equatable, GeneratedFakeable
626626
bundleMinSize: bundleMinSize,
627627
bundleMaxSize: bundleMaxSize,
628628
bundledItems: bundledItems,
629+
password: password,
629630
compositeComponents: compositeComponents,
630631
subscription: subscription,
631632
minAllowedQuantity: minAllowedQuantity,
632633
maxAllowedQuantity: maxAllowedQuantity,
633634
groupOfQuantity: groupOfQuantity,
634-
combineVariationQuantities: combineVariationQuantities,
635-
password: password)
635+
combineVariationQuantities: combineVariationQuantities)
636636
}
637637

638638
public func encode(to encoder: Encoder) throws {
@@ -759,6 +759,13 @@ public struct Product: Codable, GeneratedCopiable, Equatable, GeneratedFakeable
759759
}
760760
}
761761

762+
public extension Product {
763+
/// Default product URL {site_url}?post_type=product&p={product_id} works for all sites.
764+
func alternativePermalink(with siteURL: String) -> String {
765+
String(format: "%@?post_type=product&p=%d", siteURL, productID)
766+
}
767+
}
768+
762769
/// Defines all of the Product CodingKeys
763770
///
764771
private extension Product {
@@ -846,14 +853,14 @@ private extension Product {
846853
case bundleMaxSize = "bundle_max_size"
847854
case bundledItems = "bundled_items"
848855

856+
case password = "post_password"
857+
849858
case compositeComponents = "composite_components"
850859

851860
case minAllowedQuantity = "min_quantity"
852861
case maxAllowedQuantity = "max_quantity"
853862
case groupOfQuantity = "group_of_quantity"
854863
case combineVariations = "combine_variations"
855-
856-
case password = "post_password"
857864
}
858865

859866
enum MetadataKeys {

Networking/Networking/Network/AlamofireNetwork.swift

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,7 @@ public class AlamofireNetwork: Network {
3232
///
3333
public required init(credentials: Credentials?, sessionManager: Alamofire.Session? = nil) {
3434
self.requestConverter = RequestConverter(credentials: credentials)
35-
36-
// When `DefaultRequestAuthenticator` receives a `credential.applicationPassword` case it doesn't use the information provided in the credential object.
37-
// Instead, it fetches it from the Keychain, as it is assumes that the application password credentials are already saved.
38-
// This does not work in the watch app, because the keychains are not shared/connected.
39-
// To solve this issue without doing a major refactor on how credentials are stored and used,
40-
// We are providing an specific application password use case only when running this code in the watch.
41-
let applicationPasswordUseCase: ApplicationPasswordUseCase? = {
42-
#if os(watchOS)
43-
if let credentials, case let .applicationPassword(username, password, siteAddress) = credentials {
44-
let appPassword = ApplicationPassword(wpOrgUsername: username, password: .init(password), uuid: UUID().uuidString.lowercased())
45-
return OneTimeApplicationPasswordUseCase(applicationPassword: appPassword, siteAddress: siteAddress)
46-
}
47-
#endif
48-
return nil
49-
}()
50-
51-
self.requestAuthenticator = RequestProcessor(requestAuthenticator: DefaultRequestAuthenticator(credentials: credentials,
52-
applicationPasswordUseCase: applicationPasswordUseCase))
35+
self.requestAuthenticator = RequestProcessor(requestAuthenticator: DefaultRequestAuthenticator(credentials: credentials))
5336
if let sessionManager {
5437
self.alamofireSession = sessionManager
5538
}

Networking/NetworkingTests/Mapper/ProductMapperTests.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ final class ProductMapperTests: XCTestCase {
2828
XCTAssertEqual(product.name, "Book the Green Room")
2929
XCTAssertEqual(product.slug, "book-the-green-room")
3030
XCTAssertEqual(product.permalink, "https://example.com/product/book-the-green-room/")
31+
XCTAssertEqual(product.alternativePermalink(with: "https://example.com"),
32+
"https://example.com?post_type=product&p=\(dummyProductID)")
3133

3234
let dateCreated = DateFormatter.Defaults.dateTimeFormatter.date(from: "2019-02-19T17:33:31")
3335
let dateModified = DateFormatter.Defaults.dateTimeFormatter.date(from: "2019-02-19T17:48:01")
@@ -102,6 +104,7 @@ final class ProductMapperTests: XCTestCase {
102104
XCTAssertEqual(product.menuOrder, 0)
103105
XCTAssertEqual(product.productType, ProductType(rawValue: "booking"))
104106
XCTAssertTrue(product.isSampleItem)
107+
XCTAssertEqual(product.password, "Fortuna Major")
105108
}
106109
}
107110

0 commit comments

Comments
 (0)