Skip to content

Commit 6f41d6e

Browse files
committed
Adds ProductVariationGenerator type
1 parent a1acb44 commit 6f41d6e

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import Foundation
2+
import Yosemite
3+
4+
/// Generates all possible variations from a product attributes
5+
///
6+
struct ProductVariationGenerator {
7+
8+
/// Group a colection of attribute options.
9+
/// EG: [Size: Large, Color: Black, Fabric: Cotton]
10+
///
11+
private struct Combination: Hashable {
12+
let options: [Option]
13+
}
14+
15+
/// Represents an attribute option.
16+
/// EG: Size: Large
17+
///
18+
private struct Option: Hashable {
19+
let attributeID: Int64
20+
let attributeName: String
21+
let value: String
22+
}
23+
24+
/// Generates all possible variations from a product attributes.
25+
/// Additionally it excludes variations that already exists in the `variations` parameter.
26+
///
27+
static func generateVariations(for product: Product, excluding variations: [ProductVariation]) -> [CreateProductVariation] {
28+
let allCombinations = getCombinations(from: product)
29+
let uniqueCombinations = filterExistingCombinations(allCombinations, existing: variations)
30+
return buildVariations(from: uniqueCombinations, for: product)
31+
}
32+
33+
/// Generates all posible combination for a product attributes.
34+
///
35+
private static func getCombinations(from product: Product) -> [Combination] {
36+
// Iterates through attributes while eceiving the previous combinations list.
37+
product.attributes.reduce([Combination(options: [])]) { combinations, attribute in
38+
combinations.flatMap { combination in
39+
// When receiving a previous combination list, we add each attribute to each previous combination util we finish with them.
40+
attribute.options.map { option in
41+
Combination(options: combination.options + [Option(attributeID: attribute.attributeID, attributeName: attribute.name, value: option)])
42+
}
43+
}
44+
}
45+
}
46+
47+
/// Removes the provided variations from the given combinations array.
48+
///
49+
private static func filterExistingCombinations(_ combinations: [Combination], existing variations: [ProductVariation]) -> [Combination] {
50+
// Convert variations into combinations
51+
let existingCombinations = variations.map { existingVariation in
52+
let options = existingVariation.attributes.map { attibute in
53+
Option(attributeID: attibute.id, attributeName: attibute.name, value: attibute.option)
54+
}
55+
return Combination(options: options)
56+
}
57+
58+
// Filter existing combinations.
59+
let existingSet = Set(existingCombinations)
60+
return combinations.filter { combination in
61+
!existingSet.contains(combination)
62+
}
63+
}
64+
65+
/// Convert the provided combinations into `[CreateProductVariation]` types that are consumed by our Yosemite stores.
66+
///
67+
private static func buildVariations(from combinations: [Combination], for product: Product) -> [CreateProductVariation] {
68+
combinations.map { combination in
69+
let attributes = combination.options.map { option in
70+
ProductVariationAttribute(id: option.attributeID, name: option.attributeName, option: option.value)
71+
}
72+
return CreateProductVariation(regularPrice: "", attributes: attributes)
73+
}
74+
}
75+
}

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@
596596
262C921F26EEF8B100011F92 /* Binding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 262C921E26EEF8B100011F92 /* Binding.swift */; };
597597
262C922126F1370000011F92 /* StorePickerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 262C922026F1370000011F92 /* StorePickerError.swift */; };
598598
26309F17277D0AEA0012797F /* SafeAreaInsetsKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26309F16277D0AEA0012797F /* SafeAreaInsetsKey.swift */; };
599+
263C4CC02963784900CA7E05 /* ProductVariationGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 263C4CBF2963784900CA7E05 /* ProductVariationGenerator.swift */; };
599600
263E37E12641AD8300260D3B /* Codegen in Frameworks */ = {isa = PBXBuildFile; productRef = 263E37E02641AD8300260D3B /* Codegen */; };
600601
263E37E22641AD8300260D3B /* Codegen in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 263E37E02641AD8300260D3B /* Codegen */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
601602
263E38462641FF3400260D3B /* Codegen in Frameworks */ = {isa = PBXBuildFile; productRef = 263E38452641FF3400260D3B /* Codegen */; };
@@ -2649,6 +2650,7 @@
26492650
262C921E26EEF8B100011F92 /* Binding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Binding.swift; sourceTree = "<group>"; };
26502651
262C922026F1370000011F92 /* StorePickerError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorePickerError.swift; sourceTree = "<group>"; };
26512652
26309F16277D0AEA0012797F /* SafeAreaInsetsKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafeAreaInsetsKey.swift; sourceTree = "<group>"; };
2653+
263C4CBF2963784900CA7E05 /* ProductVariationGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductVariationGenerator.swift; sourceTree = "<group>"; };
26522654
263EB408242C58EA00F3A15F /* ProductFormActionsFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductFormActionsFactoryTests.swift; sourceTree = "<group>"; };
26532655
2647F7B429280A7F00D59FDF /* AnalyticsHubView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsHubView.swift; sourceTree = "<group>"; };
26542656
2647F7B9292BE2F900D59FDF /* AnalyticsReportCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsReportCard.swift; sourceTree = "<group>"; };
@@ -4768,6 +4770,7 @@
47684770
0202B68C23876BC100F3EBE0 /* ProductsTabProductViewModel+ProductVariation.swift */,
47694771
26F65C9725DEDAF0008FAE29 /* GenerateVariationUseCase.swift */,
47704772
269A2F46295CC683000828A8 /* GenerateVariationsSelectorCommand.swift */,
4773+
263C4CBF2963784900CA7E05 /* ProductVariationGenerator.swift */,
47714774
4515262B2577D48D0076B03C /* Add Attributes */,
47724775
AEDDDA0825CA9C0A0077F9B2 /* Edit Attributes */,
47734776
);
@@ -10134,6 +10137,7 @@
1013410137
028FA466257E021100F88A48 /* RefundShippingLabelViewModel.swift in Sources */,
1013510138
CCC284112768C18500F6CC8B /* ProductInOrder.swift in Sources */,
1013610139
DE2FE5882925DD950018040A /* JetpackInstallHeaderView.swift in Sources */,
10140+
263C4CC02963784900CA7E05 /* ProductVariationGenerator.swift in Sources */,
1013710141
B59D49CD219B587E006BF0AD /* UILabel+OrderStatus.swift in Sources */,
1013810142
265BCA0C2430E741004E53EE /* ProductCategoryTableViewCell.swift in Sources */,
1013910143
02ACD25A2852E11700EC928E /* CloseAccountCoordinator.swift in Sources */,

0 commit comments

Comments
 (0)