Skip to content

Commit 8ded2dd

Browse files
authored
Update WC plugin matching to use the file name in plugin path: use cases that match plugin by name - part 2 (#15941)
2 parents 494ef48 + 29921a8 commit 8ded2dd

31 files changed

+333
-634
lines changed

Modules/Sources/Storage/Tools/StorageType+Extensions.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -831,14 +831,6 @@ public extension StorageType {
831831
return allObjects(ofType: SystemPlugin.self, matching: predicate, sortedBy: [descriptor])
832832
}
833833

834-
/// Returns stored system plugins for a provided `siteID` matching the given `names`
835-
///
836-
func loadSystemPlugins(siteID: Int64, matching names: [String]) -> [SystemPlugin] {
837-
let predicate = NSPredicate(format: "siteID == %lld && name in %@", siteID, names)
838-
let descriptor = NSSortDescriptor(keyPath: \SystemPlugin.name, ascending: true)
839-
return allObjects(ofType: SystemPlugin.self, matching: predicate, sortedBy: [descriptor])
840-
}
841-
842834
/// Returns a system plugin with a specified `siteID` and `path`.
843835
///
844836
/// - Parameters:

Modules/Sources/Yosemite/Actions/SystemStatusAction.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ public enum SystemStatusAction: Action {
88
///
99
case synchronizeSystemInformation(siteID: Int64, onCompletion: (Result<SystemInformation, Error>) -> Void)
1010

11-
/// Fetch an specific systemPlugin by siteID and name
12-
///
13-
case fetchSystemPlugin(siteID: Int64, systemPluginName: String, onCompletion: (SystemPlugin?) -> Void)
14-
1511
/// Fetch a specific systemPlugin by path.
1612
///
1713
case fetchSystemPluginWithPath(siteID: Int64, pluginPath: String, onCompletion: (SystemPlugin?) -> Void)

Modules/Sources/Yosemite/Model/Mocks/ActionHandlers/MockSystemStatusActionHandler.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,6 @@ struct MockSystemStatusActionHandler: MockActionHandler {
1414
synchronizeSystemPlugins(siteID: siteID) { result in
1515
onCompletion(result.map { SystemInformation(systemPlugins: $0) })
1616
}
17-
case .fetchSystemPlugin(let siteID, let systemPluginName, let onCompletion):
18-
let systemPlugins = objectGraph.systemPlugins(for: siteID)
19-
let filteredSystemPlugin = systemPlugins.first { $0.name == systemPluginName }
20-
let matchingPlugin = systemPlugins.first { $0.name == systemPluginName && $0.active } ?? filteredSystemPlugin
21-
onCompletion(matchingPlugin)
2217
case .fetchSystemPluginWithPath(let siteID, let pluginPath, let onCompletion):
2318
let systemPlugins = objectGraph.systemPlugins(for: siteID)
2419
let matchingPlugin = systemPlugins.first { $0.plugin == pluginPath }

Modules/Sources/Yosemite/Stores/SystemStatusStore.swift

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ public final class SystemStatusStore: Store {
2929
switch action {
3030
case .synchronizeSystemInformation(let siteID, let onCompletion):
3131
synchronizeSystemInformation(siteID: siteID, completionHandler: onCompletion)
32-
case .fetchSystemPlugin(let siteID, let systemPluginName, let onCompletion):
33-
fetchSystemPlugin(siteID: siteID, systemPluginNameList: [systemPluginName], completionHandler: onCompletion)
3432
case .fetchSystemPluginWithPath(let siteID, let pluginPath, let onCompletion):
3533
fetchSystemPluginWithPath(siteID: siteID,
3634
pluginPath: pluginPath,
@@ -89,17 +87,6 @@ private extension SystemStatusStore {
8987
dispatcher.dispatch(action)
9088
}
9189

92-
93-
/// Retrieve a `SystemPlugin` entity from storage whose name matches any name from the provided name list.
94-
/// Useful when a plugin has had multiple names.
95-
///
96-
func fetchSystemPlugin(siteID: Int64, systemPluginNameList: [String], completionHandler: @escaping (SystemPlugin?) -> Void) {
97-
let matchingPlugins = storageManager.viewStorage.loadSystemPlugins(siteID: siteID, matching: systemPluginNameList)
98-
.map { $0.toReadOnly() }
99-
let matchingPlugin = matchingPlugins.first { $0.active } ?? matchingPlugins.first
100-
completionHandler(matchingPlugin)
101-
}
102-
10390
func fetchSystemPluginWithPath(siteID: Int64, pluginPath: String, onCompletion: @escaping (SystemPlugin?) -> Void) {
10491
let viewStorage = storageManager.viewStorage
10592
onCompletion(viewStorage.loadSystemPlugin(siteID: siteID, path: pluginPath)?.toReadOnly())

Modules/Sources/Yosemite/Tools/Plugin.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import Foundation
22

33
public enum Plugin: Equatable, CaseIterable {
4+
case stripe
45
case wooCommerce
6+
case wooPayments
57
case wooSubscriptions
68
case wooShipmentTracking
79
case wooSquare
@@ -10,8 +12,12 @@ public enum Plugin: Equatable, CaseIterable {
1012
/// Full plugin path is like `woocommerce/woocommerce.php`.
1113
var fileNameWithoutExtension: String {
1214
switch self {
15+
case .stripe:
16+
return "woocommerce-gateway-stripe"
1317
case .wooCommerce:
1418
return "woocommerce"
19+
case .wooPayments:
20+
return "woocommerce-payments"
1521
case .wooSubscriptions:
1622
return "woocommerce-subscriptions"
1723
case .wooShipmentTracking:

Modules/Sources/Yosemite/Tools/Plugins/PluginsService.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ public protocol PluginsServiceProtocol {
1818
/// - plugin: The plugin to load.
1919
/// - isActive: Whether the plugin is active, inactive, or nil for any state.
2020
/// - Returns: The SystemPlugin if found in storage, nil otherwise.
21+
@MainActor
2122
func loadPluginInStorage(siteID: Int64, plugin: Plugin, isActive: Bool?) -> SystemPlugin?
2223
}
2324

2425
public extension PluginsServiceProtocol {
26+
@MainActor
2527
func isPluginActiveInStorage(siteID: Int64, plugin: Plugin) -> Bool {
2628
let plugin = loadPluginInStorage(siteID: siteID, plugin: plugin, isActive: true)
2729
return plugin != nil && plugin?.active == true
@@ -65,6 +67,7 @@ public class PluginsService: PluginsServiceProtocol {
6567
}
6668
}
6769

70+
@MainActor
6871
public func loadPluginInStorage(siteID: Int64, plugin: Plugin, isActive: Bool?) -> SystemPlugin? {
6972
storageManager.viewStorage.loadSystemPlugin(siteID: siteID,
7073
fileNameWithoutExtension: plugin.fileNameWithoutExtension,

Modules/Tests/StorageTests/Tools/StorageTypeExtensionsTests.swift

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,31 +1407,6 @@ final class StorageTypeExtensionsTests: XCTestCase {
14071407
XCTAssertEqual(storedSystemPlugins, [systemPlugin1, systemPlugin3])
14081408
}
14091409

1410-
func test_loadSystemPlugins_by_siteID_matching_names() {
1411-
// Given
1412-
let systemPlugin1 = storage.insertNewObject(ofType: SystemPlugin.self)
1413-
systemPlugin1.name = "Plugin 1"
1414-
systemPlugin1.siteID = sampleSiteID
1415-
1416-
let systemPlugin2 = storage.insertNewObject(ofType: SystemPlugin.self)
1417-
systemPlugin2.name = "Plugin 1"
1418-
systemPlugin2.siteID = sampleSiteID + 1
1419-
1420-
let systemPlugin3 = storage.insertNewObject(ofType: SystemPlugin.self)
1421-
systemPlugin3.name = "Plugin 3"
1422-
systemPlugin3.siteID = sampleSiteID
1423-
1424-
let systemPlugin4 = storage.insertNewObject(ofType: SystemPlugin.self)
1425-
systemPlugin4.name = "Plugin 4"
1426-
systemPlugin4.siteID = sampleSiteID
1427-
1428-
// When
1429-
let storedSystemPlugins = storage.loadSystemPlugins(siteID: sampleSiteID, matching: ["Plugin 1", "Plugin 4"])
1430-
1431-
// Then
1432-
XCTAssertEqual(storedSystemPlugins, [systemPlugin1, systemPlugin4])
1433-
}
1434-
14351410
func test_loadSystemPlugin_by_siteID_and_path() throws {
14361411
// Given
14371412
let systemPlugin1 = storage.insertNewObject(ofType: SystemPlugin.self)

Modules/Tests/YosemiteTests/Stores/SystemStatusStoreTests.swift

Lines changed: 0 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -101,99 +101,6 @@ final class SystemStatusStoreTests: XCTestCase {
101101
XCTAssertNil(viewStorage.loadSystemPlugin(siteID: sampleSiteID, fileNameWithoutExtension: "stale-plugin"))
102102
}
103103

104-
func test_fetchSystemPlugins_return_systemPlugins_correctly() {
105-
// Given
106-
let systemPlugin1 = viewStorage.insertNewObject(ofType: SystemPlugin.self)
107-
systemPlugin1.name = "Plugin 1"
108-
systemPlugin1.siteID = sampleSiteID
109-
110-
let systemPlugin3 = viewStorage.insertNewObject(ofType: SystemPlugin.self)
111-
systemPlugin3.name = "Plugin 3"
112-
systemPlugin3.siteID = sampleSiteID
113-
114-
let store = SystemStatusStore(dispatcher: dispatcher, storageManager: storageManager, network: network)
115-
116-
// When
117-
let systemPluginResult: Yosemite.SystemPlugin? = waitFor { promise in
118-
let action = SystemStatusAction.fetchSystemPlugin(siteID: self.sampleSiteID,
119-
systemPluginName: "Plugin 3") { result in
120-
promise(result)
121-
}
122-
store.onAction(action)
123-
}
124-
125-
// Then
126-
XCTAssertEqual(systemPluginResult?.name, "Plugin 3") // number of systemPlugins in storage
127-
}
128-
129-
func test_fetchSystemPlugin_prefers_active_plugin_when_multiple_plugins_exist() throws {
130-
// Given
131-
let pluginName = "Plugin 1"
132-
let inactivePlugin = viewStorage.insertNewObject(ofType: SystemPlugin.self)
133-
inactivePlugin.name = pluginName
134-
inactivePlugin.active = false
135-
inactivePlugin.siteID = sampleSiteID
136-
137-
let activePlugin = viewStorage.insertNewObject(ofType: SystemPlugin.self)
138-
activePlugin.name = pluginName
139-
activePlugin.active = true
140-
activePlugin.siteID = sampleSiteID
141-
142-
let store = SystemStatusStore(dispatcher: dispatcher, storageManager: storageManager, network: network)
143-
144-
// When
145-
let fetchedPlugin = waitFor { promise in
146-
store.onAction(SystemStatusAction.fetchSystemPlugin(siteID: self.sampleSiteID,
147-
systemPluginName: pluginName) { result in
148-
promise(result)
149-
})
150-
}
151-
152-
// Then
153-
let plugin = try XCTUnwrap(fetchedPlugin)
154-
XCTAssertTrue(plugin.active)
155-
XCTAssertEqual(plugin.name, pluginName)
156-
}
157-
158-
func test_fetchSystemPlugin_returns_inactive_plugin_when_no_active_plugin_exists() throws {
159-
// Given
160-
let inactivePlugin = viewStorage.insertNewObject(ofType: SystemPlugin.self)
161-
inactivePlugin.name = "Plugin 1"
162-
inactivePlugin.active = false
163-
inactivePlugin.siteID = sampleSiteID
164-
165-
let store = SystemStatusStore(dispatcher: dispatcher, storageManager: storageManager, network: network)
166-
167-
// When
168-
let fetchedPlugin = waitFor { promise in
169-
store.onAction(SystemStatusAction.fetchSystemPlugin(siteID: self.sampleSiteID,
170-
systemPluginName: "Plugin 1") { result in
171-
promise(result)
172-
})
173-
}
174-
175-
// Then
176-
let plugin = try XCTUnwrap(fetchedPlugin)
177-
XCTAssertFalse(plugin.active)
178-
XCTAssertEqual(plugin.name, "Plugin 1")
179-
}
180-
181-
func test_fetchSystemPlugin_returns_nil_when_no_plugin_exists() {
182-
// Given
183-
let store = SystemStatusStore(dispatcher: dispatcher, storageManager: storageManager, network: network)
184-
185-
// When
186-
let fetchedPlugin = waitFor { promise in
187-
store.onAction(SystemStatusAction.fetchSystemPlugin(siteID: self.sampleSiteID,
188-
systemPluginName: "NonExistentPlugin") { result in
189-
promise(result)
190-
})
191-
}
192-
193-
// Then
194-
XCTAssertNil(fetchedPlugin)
195-
}
196-
197104
func test_fetchSystemPluginWithPath_returns_plugin_when_matching_plugin_is_in_storage() {
198105
// Given
199106
let systemPlugin1 = viewStorage.insertNewObject(ofType: SystemPlugin.self)

Modules/Tests/YosemiteTests/Tools/Plugins/PluginsServiceTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Testing
22
import WooFoundation
33
@testable import Yosemite
44

5+
@MainActor
56
struct PluginsServiceTests {
67
private var storageManager: MockStorageManager!
78
private var sut: PluginsService!

WooCommerce/Classes/POS/Controllers/PointOfSaleOrderController.swift

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ import protocol Experiments.FeatureFlagService
44
import protocol Yosemite.StoresManager
55
import protocol Yosemite.POSOrderServiceProtocol
66
import protocol Yosemite.POSReceiptServiceProtocol
7+
import protocol Yosemite.PluginsServiceProtocol
78
import struct Yosemite.Order
89
import struct Yosemite.POSCart
910
import struct Yosemite.POSCartItem
1011
import struct Yosemite.POSCoupon
1112
import struct Yosemite.CouponsError
1213
import enum Yosemite.OrderAction
1314
import enum Yosemite.OrderUpdateField
14-
import enum Yosemite.SystemStatusAction
15+
import enum Yosemite.Plugin
1516
import class WooFoundation.CurrencyFormatter
1617
import class WooFoundation.CurrencySettings
18+
import class Yosemite.PluginsService
1719
import enum WooFoundation.CurrencyCode
1820
import protocol WooFoundation.Analytics
1921
import enum Alamofire.AFError
@@ -45,6 +47,7 @@ protocol PointOfSaleOrderControllerProtocol {
4547
currencySettings: CurrencySettings = ServiceLocator.currencySettings,
4648
analytics: Analytics = ServiceLocator.analytics,
4749
featureFlagService: FeatureFlagService = ServiceLocator.featureFlagService,
50+
pluginsService: PluginsServiceProtocol = PluginsService(storageManager: ServiceLocator.storageManager),
4851
celebration: PaymentCaptureCelebrationProtocol = PaymentCaptureCelebration()) {
4952
self.orderService = orderService
5053
self.receiptService = receiptService
@@ -53,6 +56,7 @@ protocol PointOfSaleOrderControllerProtocol {
5356
self.currencyFormatter = CurrencyFormatter(currencySettings: currencySettings)
5457
self.analytics = analytics
5558
self.featureFlagService = featureFlagService
59+
self.pluginsService = pluginsService
5660
self.celebration = celebration
5761
}
5862

@@ -65,6 +69,7 @@ protocol PointOfSaleOrderControllerProtocol {
6569
private let analytics: Analytics
6670
private let stores: StoresManager
6771
private let featureFlagService: FeatureFlagService
72+
private let pluginsService: PluginsServiceProtocol
6873

6974
private(set) var orderState: PointOfSaleInternalOrderState = .idle
7075
private var order: Order? = nil
@@ -104,6 +109,7 @@ protocol PointOfSaleOrderControllerProtocol {
104109
})
105110
}
106111

112+
@MainActor
107113
func sendReceipt(recipientEmail: String) async throws {
108114
var isEligibleForPOSReceipt: Bool?
109115
do {
@@ -115,8 +121,8 @@ protocol PointOfSaleOrderControllerProtocol {
115121

116122
let posReceiptEligibility: Bool
117123
if featureFlagService.isFeatureFlagEnabled(.pointOfSaleReceipts) {
118-
posReceiptEligibility = await isPluginSupported(
119-
POSReceiptEligibilityConstants.wcPluginName,
124+
posReceiptEligibility = isPluginSupported(
125+
.wooCommerce,
120126
minimumVersion: POSReceiptEligibilityConstants.wcPluginMinimumVersion,
121127
siteID: order.siteID
122128
)
@@ -207,22 +213,18 @@ private extension PointOfSaleOrderController {
207213
@available(iOS 17.0, *)
208214
private extension PointOfSaleOrderController {
209215
@MainActor
210-
func isPluginSupported(_ pluginName: String, minimumVersion: String, siteID: Int64) async -> Bool {
211-
await withCheckedContinuation { continuation in
212-
let action = SystemStatusAction.fetchSystemPlugin(siteID: siteID, systemPluginName: pluginName) { plugin in
213-
// Plugin must be installed and active
214-
guard let plugin, plugin.active, plugin.name == pluginName else {
215-
return continuation.resume(returning: false)
216-
}
217-
218-
// If plugin version is higher than minimum required version, mark as eligible
219-
let isSupported = VersionHelpers.isVersionSupported(version: plugin.version,
220-
minimumRequired: minimumVersion,
221-
includesDevAndBetaVersions: true)
222-
continuation.resume(returning: isSupported)
223-
}
224-
stores.dispatch(action)
216+
func isPluginSupported(_ plugin: Plugin, minimumVersion: String, siteID: Int64) -> Bool {
217+
// Plugin must be installed and active
218+
guard let systemPlugin = pluginsService.loadPluginInStorage(siteID: siteID, plugin: plugin, isActive: true),
219+
systemPlugin.active else {
220+
return false
225221
}
222+
223+
// If plugin version is higher than minimum required version, mark as eligible
224+
let isSupported = VersionHelpers.isVersionSupported(version: systemPlugin.version,
225+
minimumRequired: minimumVersion,
226+
includesDevAndBetaVersions: true)
227+
return isSupported
226228
}
227229
}
228230

@@ -245,7 +247,6 @@ private extension PointOfSaleOrderController {
245247
@available(iOS 17.0, *)
246248
private extension PointOfSaleOrderController {
247249
enum POSReceiptEligibilityConstants {
248-
static let wcPluginName = "WooCommerce"
249250
static let wcPluginMinimumVersion = "10.0.0"
250251
}
251252
}

0 commit comments

Comments
 (0)