Skip to content

Commit 1afdbdb

Browse files
committed
Revert "Remove new code to reduce the PR to reviewable size."
This reverts commit 0a7ca20.
1 parent 702700a commit 1afdbdb

File tree

3 files changed

+189
-0
lines changed

3 files changed

+189
-0
lines changed

Networking/Networking.xcodeproj/project.pbxproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,14 @@
5050
02A26F1B2744F5FC008E4EDB /* wc-site-settings-partial.json in Resources */ = {isa = PBXBuildFile; fileRef = 02A26F192744F5FC008E4EDB /* wc-site-settings-partial.json */; };
5151
02A26F1C2744F5FC008E4EDB /* wp-site-settings.json in Resources */ = {isa = PBXBuildFile; fileRef = 02A26F1A2744F5FC008E4EDB /* wp-site-settings.json */; };
5252
02AAD53F250092A400BA1E26 /* product-add-or-delete.json in Resources */ = {isa = PBXBuildFile; fileRef = 02AAD53E250092A300BA1E26 /* product-add-or-delete.json */; };
53+
02AF07EA27492DBC00B2D81E /* WordPressMedia.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02AF07E927492DBC00B2D81E /* WordPressMedia.swift */; };
54+
02AF07EC27492FDD00B2D81E /* media-library-from-wordpress-site.json in Resources */ = {isa = PBXBuildFile; fileRef = 02AF07EB27492FDD00B2D81E /* media-library-from-wordpress-site.json */; };
55+
02AF07EE27493AE700B2D81E /* media-upload-to-wordpress-site.json in Resources */ = {isa = PBXBuildFile; fileRef = 02AF07ED27493AE700B2D81E /* media-upload-to-wordpress-site.json */; };
5356
02BA23C922EEF62C009539E7 /* order-stats-v4-wcadmin-deactivated.json in Resources */ = {isa = PBXBuildFile; fileRef = 02BA23C722EEF62C009539E7 /* order-stats-v4-wcadmin-deactivated.json */; };
5457
02BA23CA22EEF62C009539E7 /* order-stats-v4-wcadmin-activated.json in Resources */ = {isa = PBXBuildFile; fileRef = 02BA23C822EEF62C009539E7 /* order-stats-v4-wcadmin-activated.json */; };
5558
02BDB83523EA98C800BCC63E /* String+HTML.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02BDB83423EA98C800BCC63E /* String+HTML.swift */; };
5659
02BDB83723EA9C4D00BCC63E /* String+HTMLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02BDB83623EA9C4D00BCC63E /* String+HTMLTests.swift */; };
60+
02BE0A7B274B695F001176D2 /* WordPressMediaMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02BE0A7A274B695F001176D2 /* WordPressMediaMapper.swift */; };
5761
02C11276274285FF00F4F0B4 /* WooCommerceAvailabilityMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C11275274285FF00F4F0B4 /* WooCommerceAvailabilityMapper.swift */; };
5862
02C112782742862600F4F0B4 /* WordPressSiteSettingsMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C112772742862600F4F0B4 /* WordPressSiteSettingsMapper.swift */; };
5963
02C1CEF424C6A02B00703EBA /* ProductVariationMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C1CEF324C6A02B00703EBA /* ProductVariationMapper.swift */; };
@@ -632,10 +636,14 @@
632636
02A26F192744F5FC008E4EDB /* wc-site-settings-partial.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "wc-site-settings-partial.json"; sourceTree = "<group>"; };
633637
02A26F1A2744F5FC008E4EDB /* wp-site-settings.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "wp-site-settings.json"; sourceTree = "<group>"; };
634638
02AAD53E250092A300BA1E26 /* product-add-or-delete.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "product-add-or-delete.json"; sourceTree = "<group>"; };
639+
02AF07E927492DBC00B2D81E /* WordPressMedia.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressMedia.swift; sourceTree = "<group>"; };
640+
02AF07EB27492FDD00B2D81E /* media-library-from-wordpress-site.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "media-library-from-wordpress-site.json"; sourceTree = "<group>"; };
641+
02AF07ED27493AE700B2D81E /* media-upload-to-wordpress-site.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "media-upload-to-wordpress-site.json"; sourceTree = "<group>"; };
635642
02BA23C722EEF62C009539E7 /* order-stats-v4-wcadmin-deactivated.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "order-stats-v4-wcadmin-deactivated.json"; sourceTree = "<group>"; };
636643
02BA23C822EEF62C009539E7 /* order-stats-v4-wcadmin-activated.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "order-stats-v4-wcadmin-activated.json"; sourceTree = "<group>"; };
637644
02BDB83423EA98C800BCC63E /* String+HTML.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+HTML.swift"; sourceTree = "<group>"; };
638645
02BDB83623EA9C4D00BCC63E /* String+HTMLTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+HTMLTests.swift"; sourceTree = "<group>"; };
646+
02BE0A7A274B695F001176D2 /* WordPressMediaMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressMediaMapper.swift; sourceTree = "<group>"; };
639647
02C11275274285FF00F4F0B4 /* WooCommerceAvailabilityMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooCommerceAvailabilityMapper.swift; sourceTree = "<group>"; };
640648
02C112772742862600F4F0B4 /* WordPressSiteSettingsMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressSiteSettingsMapper.swift; sourceTree = "<group>"; };
641649
02C1CEF324C6A02B00703EBA /* ProductVariationMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductVariationMapper.swift; sourceTree = "<group>"; };
@@ -1173,6 +1181,7 @@
11731181
children = (
11741182
020D07B723D852BB00FD9580 /* Media.swift */,
11751183
020D07B923D8542000FD9580 /* UploadableMedia.swift */,
1184+
02AF07E927492DBC00B2D81E /* WordPressMedia.swift */,
11761185
);
11771186
path = Media;
11781187
sourceTree = "<group>";
@@ -1634,7 +1643,9 @@
16341643
B505F6D420BEE4E600BB1B69 /* me.json */,
16351644
93D8BBFE226BC1DA00AD2EB3 /* me-settings.json */,
16361645
02F096C12406691100C0C1D5 /* media-library.json */,
1646+
02AF07EB27492FDD00B2D81E /* media-library-from-wordpress-site.json */,
16371647
020D07C123D858BB00FD9580 /* media-upload.json */,
1648+
02AF07ED27493AE700B2D81E /* media-upload-to-wordpress-site.json */,
16381649
B58D10C92114D22E00107ED4 /* new-order-note.json */,
16391650
022902D322E2436400059692 /* no_stats_permission_error.json */,
16401651
B5A24178217F98F600595DEF /* notifications-load-all.json */,
@@ -1854,6 +1865,7 @@
18541865
FE28F6E326842848004465C7 /* UserMapper.swift */,
18551866
077F39D326A58DE700ABEADC /* SystemStatusMapper.swift */,
18561867
02C11275274285FF00F4F0B4 /* WooCommerceAvailabilityMapper.swift */,
1868+
02BE0A7A274B695F001176D2 /* WordPressMediaMapper.swift */,
18571869
02C112772742862600F4F0B4 /* WordPressSiteSettingsMapper.swift */,
18581870
);
18591871
path = Mapper;
@@ -2136,6 +2148,7 @@
21362148
45D685FA23D0C3CF005F87D0 /* product-search-sku.json in Resources */,
21372149
CCF48B2C2628AE160034EA83 /* shipping-label-account-settings.json in Resources */,
21382150
31054734262E36AB00C5C02B /* wcpay-payment-intent-error.json in Resources */,
2151+
02AF07EE27493AE700B2D81E /* media-upload-to-wordpress-site.json in Resources */,
21392152
45ED4F12239E8C57004F1BE3 /* taxes-classes.json in Resources */,
21402153
B5A2417B217F98FC00595DEF /* broken-notifications.json in Resources */,
21412154
3158A4A32729F42500C3CFA8 /* wcpay-account-dev-test.json in Resources */,
@@ -2145,6 +2158,7 @@
21452158
4599FC5C24A6276F0056157A /* product-tags-all.json in Resources */,
21462159
74A7B4BE217A841400E85A8B /* broken-settings-general.json in Resources */,
21472160
026CF624237D839B009563D4 /* product-variations-load-all.json in Resources */,
2161+
02AF07EC27492FDD00B2D81E /* media-library-from-wordpress-site.json in Resources */,
21482162
CC9A253C26442C71005DE56E /* shipping-label-eligibility-success.json in Resources */,
21492163
B5A24179217F98F600595DEF /* notifications-load-all.json in Resources */,
21502164
0282DD91233A120A006A5FDB /* products-search-photo.json in Resources */,
@@ -2439,6 +2453,7 @@
24392453
26B2F74524C5573F0065CCC8 /* LeaderboardListMapper.swift in Sources */,
24402454
24F98C542502E8DD00F49B68 /* Bundle+Woo.swift in Sources */,
24412455
31D27C812602889C002EDB1D /* SitePluginsRemote.swift in Sources */,
2456+
02BE0A7B274B695F001176D2 /* WordPressMediaMapper.swift in Sources */,
24422457
45150A9A268340D2006922EA /* Country.swift in Sources */,
24432458
450106852399A7CB00E24722 /* TaxClass.swift in Sources */,
24442459
CC0786612677B2DA00BA9AC1 /* ShippingLabelPurchaseMapper.swift in Sources */,
@@ -2482,6 +2497,7 @@
24822497
74A1D26F21189EA100931DFA /* SiteVisitStatsRemote.swift in Sources */,
24832498
029BA4F4255D72EC006171FD /* ShippingLabelPrintData.swift in Sources */,
24842499
24F98C562502EA4800F49B68 /* FeatureFlag.swift in Sources */,
2500+
02AF07EA27492DBC00B2D81E /* WordPressMedia.swift in Sources */,
24852501
B557DA1D20979E7D005962F4 /* Order.swift in Sources */,
24862502
74159625224D4045003C21CF /* SiteSettingGroup.swift in Sources */,
24872503
26B2F74D24C696E70065CCC8 /* LeaderboardRowContent.swift in Sources */,

Networking/Networking/Remote/MediaRemote.swift

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,36 @@ public class MediaRemote: Remote {
3535
enqueue(request, mapper: mapper, completion: completion)
3636
}
3737

38+
/// Loads an array of media from the site's WP Media Library via WordPress site API.
39+
/// API reference: https://developer.wordpress.org/rest-api/reference/media/#list-media
40+
///
41+
/// - Parameters:
42+
/// - siteID: Site for which we'll load the media from.
43+
/// - pageNumber: The index of the page of media data to load from, starting from 1.
44+
/// - pageSize: The number of media items to return.
45+
/// - completion: Closure to be executed upon completion.
46+
public func loadMediaLibraryFromWordPressSite(siteID: Int64,
47+
pageNumber: Int = Default.pageNumber,
48+
pageSize: Int = 25,
49+
context: String = Default.context,
50+
completion: @escaping (Result<[WordPressMedia], Error>) -> Void) {
51+
let parameters: [String: Any] = [
52+
ParameterKey.pageSize: pageSize,
53+
ParameterKey.pageNumber: pageNumber,
54+
ParameterKey.fieldsWordPressSite: Default.wordPressMediaFields,
55+
ParameterKey.mimeType: "image"
56+
]
57+
58+
let path = "sites/\(siteID)/media"
59+
let request = DotcomRequest(wordpressApiVersion: .wpMark2,
60+
method: .get,
61+
path: path,
62+
parameters: parameters)
63+
let mapper = WordPressMediaListMapper()
64+
65+
enqueue(request, mapper: mapper, completion: completion)
66+
}
67+
3868
/// Uploads an array of media in the local file system.
3969
/// API reference: https://developer.wordpress.com/docs/api/1.1/post/sites/%24site/media/new/
4070
///
@@ -79,6 +109,40 @@ public class MediaRemote: Remote {
79109
}
80110
}, completion: completion)
81111
}
112+
113+
/// Uploads an array of media in the local file system to the WordPress site.via WordPress site API
114+
/// API reference: https://developer.wordpress.org/rest-api/reference/media/#create-a-media-item
115+
///
116+
/// - Parameters:
117+
/// - siteID: Site for which we'll upload the media to.
118+
/// - productID: Product for which the media items are first added to.
119+
/// - mediaItems: An array of uploadable media items.
120+
/// - completion: Closure to be executed upon completion.
121+
public func uploadMediaToWordPressSite(siteID: Int64,
122+
productID: Int64,
123+
mediaItems: [UploadableMedia],
124+
completion: @escaping (Result<WordPressMedia, Error>) -> Void) {
125+
let formParameters: [String: String] = [
126+
"post": "\(productID)",
127+
ParameterKey.fieldsWordPressSite: Default.wordPressMediaFields,
128+
]
129+
let path = "sites/\(siteID)/media"
130+
let request = DotcomRequest(wordpressApiVersion: .wpMark2, method: .post, path: path, parameters: nil)
131+
let mapper = WordPressMediaMapper()
132+
133+
enqueueMultipartFormDataUpload(request, mapper: mapper, multipartFormData: { multipartFormData in
134+
formParameters.forEach { (key, value) in
135+
multipartFormData.append(Data(value.utf8), withName: key)
136+
}
137+
138+
mediaItems.forEach { mediaItem in
139+
multipartFormData.append(mediaItem.localURL,
140+
withName: ParameterValue.mediaUploadName,
141+
fileName: mediaItem.filename,
142+
mimeType: mediaItem.mimeType)
143+
}
144+
}, completion: completion)
145+
}
82146
}
83147

84148

Networking/NetworkingTests/Remote/MediaRemoteTests.swift

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,60 @@ final class MediaRemoteTests: XCTestCase {
5959
XCTAssertTrue(result.isFailure)
6060
}
6161

62+
// MARK: - Load Media From Media Library `loadMediaLibrary` via WordPress Site API
63+
64+
/// Verifies that `loadMediaLibraryFromWordPressSite` properly parses the `media-library-from-wordpress-site` sample response.
65+
///
66+
func test_loadMediaLibraryFromWordPressSite_properly_returns_parsed_media_list() throws {
67+
// Given
68+
let remote = MediaRemote(network: network)
69+
network.simulateResponse(requestUrlSuffix: "media", filename: "media-library-from-wordpress-site")
70+
71+
// When
72+
let result = waitFor { promise in
73+
remote.loadMediaLibraryFromWordPressSite(siteID: self.sampleSiteID) { result in
74+
promise(result)
75+
}
76+
}
77+
78+
// Then
79+
let mediaItems = try XCTUnwrap(result.get())
80+
XCTAssertEqual(mediaItems.count, 2)
81+
let uploadedMedia = try XCTUnwrap(mediaItems.first)
82+
XCTAssertEqual(uploadedMedia.mediaID, 22)
83+
XCTAssertEqual(uploadedMedia.date, Date(timeIntervalSince1970: 1637546157))
84+
XCTAssertEqual(uploadedMedia.slug, "img_0111-2")
85+
XCTAssertEqual(uploadedMedia.mimeType, "image/jpeg")
86+
XCTAssertEqual(uploadedMedia.src, "https://ninja.media/wp-content/uploads/2021/11/img_0111-2-scaled.jpeg")
87+
XCTAssertEqual(uploadedMedia.alt, "Floral")
88+
XCTAssertEqual(uploadedMedia.details?.width, 2560)
89+
XCTAssertEqual(uploadedMedia.details?.height, 1920)
90+
XCTAssertEqual(uploadedMedia.details?.fileName, "2021/11/img_0111-2-scaled.jpeg")
91+
XCTAssertEqual(uploadedMedia.title, .init(rendered: "img_0111-2"))
92+
XCTAssertEqual(uploadedMedia.details?.sizes["thumbnail"],
93+
.init(fileName: "img_0111-2-150x150.jpeg",
94+
src: "https://ninja.media/wp-content/uploads/2021/11/img_0111-2-150x150.jpeg",
95+
width: 150,
96+
height: 150))
97+
}
98+
99+
/// Verifies that `loadMediaLibraryFromWordPressSite` properly relays Networking Layer errors.
100+
///
101+
func test_loadMediaLibraryFromWordPressSite_properly_relays_networking_errors() throws {
102+
// Given
103+
let remote = MediaRemote(network: network)
104+
105+
// When
106+
let result = waitFor { promise in
107+
remote.loadMediaLibraryFromWordPressSite(siteID: self.sampleSiteID) { result in
108+
promise(result)
109+
}
110+
}
111+
112+
// Then
113+
XCTAssertTrue(result.isFailure)
114+
}
115+
62116
// MARK: - uploadMedia
63117

64118
/// Verifies that `uploadMedia` properly parses the `media-upload` sample response.
@@ -101,4 +155,59 @@ final class MediaRemoteTests: XCTestCase {
101155
// Then
102156
XCTAssertTrue(result.isFailure)
103157
}
158+
159+
/// Verifies that `uploadMediaToWordPressSite` properly parses the `media-upload-to-wordpress-site` sample response.
160+
///
161+
func test_uploadMediaToWordPressSite_properly_returns_parsed_media() throws {
162+
// Given
163+
let remote = MediaRemote(network: network)
164+
let path = "sites/\(sampleSiteID)/media"
165+
network.simulateResponse(requestUrlSuffix: path, filename: "media-upload-to-wordpress-site")
166+
167+
// When
168+
let result = waitFor { promise in
169+
remote.uploadMediaToWordPressSite(siteID: self.sampleSiteID,
170+
productID: self.sampleProductID,
171+
mediaItems: []) { result in
172+
promise(result)
173+
}
174+
}
175+
176+
// Then
177+
let uploadedMedia = try XCTUnwrap(result.get())
178+
XCTAssertEqual(uploadedMedia.mediaID, 23)
179+
XCTAssertEqual(uploadedMedia.date, Date(timeIntervalSince1970: 1637477423))
180+
XCTAssertEqual(uploadedMedia.slug, "img_0005-1")
181+
XCTAssertEqual(uploadedMedia.mimeType, "image/jpeg")
182+
XCTAssertEqual(uploadedMedia.src, "https://ninja.media/wp-content/uploads/2021/11/img_0005-1-scaled.jpeg")
183+
XCTAssertEqual(uploadedMedia.alt, "Floral")
184+
XCTAssertEqual(uploadedMedia.details?.width, 2560)
185+
XCTAssertEqual(uploadedMedia.details?.height, 1708)
186+
XCTAssertEqual(uploadedMedia.details?.fileName, "2021/11/img_0005-1-scaled.jpeg")
187+
XCTAssertEqual(uploadedMedia.title, .init(rendered: "img_0005-1"))
188+
XCTAssertEqual(uploadedMedia.details?.sizes["thumbnail"],
189+
.init(fileName: "img_0005-1-150x150.jpeg",
190+
src: "https://ninja.media/wp-content/uploads/2021/11/img_0005-1-150x150.jpeg",
191+
width: 150,
192+
height: 150))
193+
}
194+
195+
/// Verifies that `uploadMedia` properly relays Networking Layer errors.
196+
///
197+
func test_uploadMediaToWordPressSite_properly_relays_networking_errors() {
198+
// Given
199+
let remote = MediaRemote(network: network)
200+
201+
// When
202+
let result = waitFor { promise in
203+
remote.uploadMediaToWordPressSite(siteID: self.sampleSiteID,
204+
productID: self.sampleProductID,
205+
mediaItems: []) { result in
206+
promise(result)
207+
}
208+
}
209+
210+
// Then
211+
XCTAssertTrue(result.isFailure)
212+
}
104213
}

0 commit comments

Comments
 (0)