Skip to content

Commit 97ba482

Browse files
authored
Merge pull request #2213 from woocommerce/issue/2120-product-visibility-networking
Product Visibility Setting: Yosemite & Networking layers
2 parents 8746068 + 198bf43 commit 97ba482

File tree

13 files changed

+702
-0
lines changed

13 files changed

+702
-0
lines changed

Networking/Networking.xcodeproj/project.pbxproj

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@
4848
4501068F2399B19500E24722 /* TaxClassRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4501068E2399B19500E24722 /* TaxClassRemote.swift */; };
4949
450106912399B2C800E24722 /* TaxClassListMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 450106902399B2C800E24722 /* TaxClassListMapper.swift */; };
5050
4524CD9C242CEFAB00B2F20A /* product-on-sale-with-empty-sale-price.json in Resources */ = {isa = PBXBuildFile; fileRef = 4524CD9B242CEFAB00B2F20A /* product-on-sale-with-empty-sale-price.json */; };
51+
453305E92459DF2100264E50 /* PostMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 453305E82459DF2100264E50 /* PostMapper.swift */; };
52+
453305EB2459E01A00264E50 /* PostMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 453305EA2459E01A00264E50 /* PostMapperTests.swift */; };
53+
453305ED2459E1AA00264E50 /* site-post.json in Resources */ = {isa = PBXBuildFile; fileRef = 453305EC2459E1AA00264E50 /* site-post.json */; };
54+
453305EF2459E46100264E50 /* SitePostsRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 453305EE2459E46000264E50 /* SitePostsRemoteTests.swift */; };
55+
453305F52459ED2700264E50 /* site-post-update.json in Resources */ = {isa = PBXBuildFile; fileRef = 453305F42459ED2700264E50 /* site-post-update.json */; };
56+
4568E2222459ADC60007E478 /* SitePostsRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4568E2212459ADC60007E478 /* SitePostsRemote.swift */; };
57+
4568E2242459D3230007E478 /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4568E2232459D3230007E478 /* Post.swift */; };
5158
457FC68C2382B2FD00B41B02 /* product-update.json in Resources */ = {isa = PBXBuildFile; fileRef = 457FC68B2382B2FD00B41B02 /* product-update.json */; };
5259
45CDAFAB2434CA9300F83C22 /* ProductCatalogVisibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45CDAFAA2434CA9300F83C22 /* ProductCatalogVisibility.swift */; };
5360
45D1CF4923BACA6500945A36 /* ProductTaxStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D1CF4823BACA6500945A36 /* ProductTaxStatus.swift */; };
@@ -369,6 +376,13 @@
369376
4501068E2399B19500E24722 /* TaxClassRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaxClassRemote.swift; sourceTree = "<group>"; };
370377
450106902399B2C800E24722 /* TaxClassListMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaxClassListMapper.swift; sourceTree = "<group>"; };
371378
4524CD9B242CEFAB00B2F20A /* product-on-sale-with-empty-sale-price.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "product-on-sale-with-empty-sale-price.json"; sourceTree = "<group>"; };
379+
453305E82459DF2100264E50 /* PostMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostMapper.swift; sourceTree = "<group>"; };
380+
453305EA2459E01A00264E50 /* PostMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostMapperTests.swift; sourceTree = "<group>"; };
381+
453305EC2459E1AA00264E50 /* site-post.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "site-post.json"; sourceTree = "<group>"; };
382+
453305EE2459E46000264E50 /* SitePostsRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SitePostsRemoteTests.swift; sourceTree = "<group>"; };
383+
453305F42459ED2700264E50 /* site-post-update.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "site-post-update.json"; sourceTree = "<group>"; };
384+
4568E2212459ADC60007E478 /* SitePostsRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SitePostsRemote.swift; sourceTree = "<group>"; };
385+
4568E2232459D3230007E478 /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = "<group>"; };
372386
457FC68B2382B2FD00B41B02 /* product-update.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "product-update.json"; sourceTree = "<group>"; };
373387
45CDAFAA2434CA9300F83C22 /* ProductCatalogVisibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductCatalogVisibility.swift; sourceTree = "<group>"; };
374388
45D1CF4823BACA6500945A36 /* ProductTaxStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductTaxStatus.swift; sourceTree = "<group>"; };
@@ -778,6 +792,7 @@
778792
7412A8F121B6E47A005D182A /* ReportRemoteTests.swift */,
779793
743E84F9221742E300FAC9D7 /* ShipmentsRemoteTests.swift */,
780794
74AB5B5021AF426D00859C12 /* SiteAPIRemoteTests.swift */,
795+
453305EE2459E46000264E50 /* SitePostsRemoteTests.swift */,
781796
74D5BECD217E0F98007B0348 /* SiteSettingsRemoteTests.swift */,
782797
74002D6B2118B88200A63C19 /* SiteVisitStatsRemoteTests.swift */,
783798
45ED4F13239E8F2E004F1BE3 /* TaxClassRemoteTests.swift */,
@@ -890,6 +905,7 @@
890905
7426CA0C21AF27B9004E9FFC /* SiteAPIRemote.swift */,
891906
74046E1A217A684D007DD7BF /* SiteSettingsRemote.swift */,
892907
74A1D26E21189EA000931DFA /* SiteVisitStatsRemote.swift */,
908+
4568E2212459ADC60007E478 /* SitePostsRemote.swift */,
893909
4501068E2399B19500E24722 /* TaxClassRemote.swift */,
894910
74ABA1D0213F22CA00FFAD30 /* TopEarnersStatsRemote.swift */,
895911
026CF61F237D69D6009563D4 /* ProductVariationsRemote.swift */,
@@ -954,6 +970,7 @@
954970
45E3EEBA237009CF00A826AC /* ShippingLine.swift */,
955971
B56C1EB720EA76F500D749F9 /* Site.swift */,
956972
7426CA0E21AF2C90004E9FFC /* SiteAPI.swift */,
973+
4568E2232459D3230007E478 /* Post.swift */,
957974
74046E1C217A6989007DD7BF /* SiteSetting.swift */,
958975
74159624224D4045003C21CF /* SiteSettingGroup.swift */,
959976
CE50345F21B5799F007573C6 /* SitePlan.swift */,
@@ -1045,6 +1062,8 @@
10451062
7426CA1221AF34A3004E9FFC /* site-api.json */,
10461063
74AB5B4E21AF3F0D00859C12 /* site-api-no-woo.json */,
10471064
CE50346621B5DCBE007573C6 /* site-plan.json */,
1065+
453305EC2459E1AA00264E50 /* site-post.json */,
1066+
453305F42459ED2700264E50 /* site-post-update.json */,
10481067
74A1D25F211898F000931DFA /* site-visits-day.json */,
10491068
74A1D260211898F000931DFA /* site-visits-week.json */,
10501069
74A1D261211898F000931DFA /* site-visits-month.json */,
@@ -1098,6 +1117,7 @@
10981117
7426CA1021AF30BD004E9FFC /* SiteAPIMapper.swift */,
10991118
B56C1EB520EA757B00D749F9 /* SiteListMapper.swift */,
11001119
CE50345D21B571A7007573C6 /* SitePlanMapper.swift */,
1120+
453305E82459DF2100264E50 /* PostMapper.swift */,
11011121
74046E1E217A6B70007DD7BF /* SiteSettingsMapper.swift */,
11021122
74A1D26C21189DFE00931DFA /* SiteVisitStatsMapper.swift */,
11031123
B53EF53B21814900003E146F /* SuccessResultMapper.swift */,
@@ -1181,6 +1201,7 @@
11811201
7412A8ED21B6E335005D182A /* ReportOrderMapperTests.swift */,
11821202
743E84F722172E1F00FAC9D7 /* ShipmentTrackingListMapperTests.swift */,
11831203
74AB5B4C21AF354E00859C12 /* SiteAPIMapperTests.swift */,
1204+
453305EA2459E01A00264E50 /* PostMapperTests.swift */,
11841205
74A7B4BB217A807400E85A8B /* SiteSettingsMapperTests.swift */,
11851206
74002D692118B26000A63C19 /* SiteVisitStatsMapperTests.swift */,
11861207
45ED4F0F239E8A54004F1BE3 /* TaxClassListMapperTest.swift */,
@@ -1373,6 +1394,7 @@
13731394
74C8F06620EEB76400B6EDC9 /* order-notes.json in Resources */,
13741395
7426CA1321AF34A3004E9FFC /* site-api.json in Resources */,
13751396
748D424E210FB1F500CF7D1B /* order-stats-day.json in Resources */,
1397+
453305ED2459E1AA00264E50 /* site-post.json in Resources */,
13761398
74749B99224135C4005C4CF2 /* product.json in Resources */,
13771399
CEF88DAF233E9F7E00BED485 /* order-details-partially-refunded.json in Resources */,
13781400
743FDB9E210FB36900AC737F /* order-stats-week.json in Resources */,
@@ -1410,6 +1432,7 @@
14101432
74E30951216E8DCE00ABCE4C /* site-visits-alt.json in Resources */,
14111433
74ABA1C5213F17AA00FFAD30 /* top-performers-day.json in Resources */,
14121434
2683D71024456EE4002A1589 /* categories-extra.json in Resources */,
1435+
453305F52459ED2700264E50 /* site-post-update.json in Resources */,
14131436
CECC759E23D6231A00486676 /* order-560-all-refunds.json in Resources */,
14141437
74ABA1CB213F19FE00FFAD30 /* top-performers-week.json in Resources */,
14151438
B524194721AC643900D6FC0A /* device-settings.json in Resources */,
@@ -1520,6 +1543,7 @@
15201543
B5BB1D0C20A2050300112D92 /* DateFormatter+Woo.swift in Sources */,
15211544
743E84EE2217244C00FAC9D7 /* ShipmentTrackingListMapper.swift in Sources */,
15221545
B567AF2520A0CCA300AB6C62 /* AuthenticatedRequest.swift in Sources */,
1546+
453305E92459DF2100264E50 /* PostMapper.swift in Sources */,
15231547
CE430672234B9EB20073CBFF /* OrderItemTax.swift in Sources */,
15241548
D8736B5C22F083C500A14A29 /* OrderCount.swift in Sources */,
15251549
B505F6EA20BEFC3700BB1B69 /* MockupNetwork.swift in Sources */,
@@ -1568,6 +1592,7 @@
15681592
D823D905223746CE00C90817 /* NewShipmentTrackingMapper.swift in Sources */,
15691593
743057B5218B6ACD00441A76 /* Queue.swift in Sources */,
15701594
74A1D26821189A7100931DFA /* SiteVisitStats.swift in Sources */,
1595+
4568E2242459D3230007E478 /* Post.swift in Sources */,
15711596
B557DA0320975500005962F4 /* Remote.swift in Sources */,
15721597
748D424C210FA34400CF7D1B /* OrderStatsMapper.swift in Sources */,
15731598
B53EF53C21814900003E146F /* SuccessResultMapper.swift in Sources */,
@@ -1589,6 +1614,7 @@
15891614
B53EF5322180F21C003E146F /* Dictionary+Woo.swift in Sources */,
15901615
74A1D26D21189DFF00931DFA /* SiteVisitStatsMapper.swift in Sources */,
15911616
D8FBFF2222D5266E006E3336 /* OrderStatsV4Interval.swift in Sources */,
1617+
4568E2222459ADC60007E478 /* SitePostsRemote.swift in Sources */,
15921618
93D8BBFD226BBEE800AD2EB3 /* AccountSettingsMapper.swift in Sources */,
15931619
74D522B62113607F00042831 /* StatGranularity.swift in Sources */,
15941620
B518662220A097C200037A38 /* Network.swift in Sources */,
@@ -1683,6 +1709,7 @@
16831709
7412A8EE21B6E335005D182A /* ReportOrderMapperTests.swift in Sources */,
16841710
74CF0A8C22414D7800DB993F /* ProductMapperTests.swift in Sources */,
16851711
B505F6D720BEE58800BB1B69 /* AccountRemoteTests.swift in Sources */,
1712+
453305EB2459E01A00264E50 /* PostMapperTests.swift in Sources */,
16861713
CE0A0F1D22398D520075ED8D /* ProductListMapperTests.swift in Sources */,
16871714
025CA2C6238F4F3500B05C81 /* ProductShippingClassRemoteTests.swift in Sources */,
16881715
B554FA8B2180B1D500C54DFF /* NotificationsRemoteTests.swift in Sources */,
@@ -1706,6 +1733,7 @@
17061733
743E84F822172E1F00FAC9D7 /* ShipmentTrackingListMapperTests.swift in Sources */,
17071734
45ED4F14239E8F2E004F1BE3 /* TaxClassRemoteTests.swift in Sources */,
17081735
D88D5A4D230BD010007B6E01 /* ProductReviewsRemoteTests.swift in Sources */,
1736+
453305EF2459E46100264E50 /* SitePostsRemoteTests.swift in Sources */,
17091737
740211E121939908002248DA /* CommentRemoteTests.swift in Sources */,
17101738
B57B1E6A21C925280046E764 /* DotcomValidatorTests.swift in Sources */,
17111739
B567AF3020A0FB8F00AB6C62 /* DotcomRequestTests.swift in Sources */,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Foundation
2+
3+
4+
/// Mapper: Post
5+
///
6+
class PostMapper: Mapper {
7+
8+
/// (Attempts) to convert a dictionary into a Post entity.
9+
///
10+
func map(response: Data) throws -> Post {
11+
let decoder = JSONDecoder()
12+
return try decoder.decode(Post.self, from: response)
13+
}
14+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import Foundation
2+
3+
4+
/// Represents a Post Entity.
5+
///
6+
public struct Post: Codable {
7+
8+
/// WordPress.com Site Identifier.
9+
///
10+
public let siteID: Int64
11+
12+
public let password: String
13+
14+
/// Site Post struct initializer.
15+
///
16+
public init(siteID: Int64, password: String) {
17+
self.siteID = siteID
18+
self.password = password
19+
}
20+
21+
22+
/// The public initializer for Site Post.
23+
///
24+
public init(from decoder: Decoder) throws {
25+
let container = try decoder.container(keyedBy: CodingKeys.self)
26+
27+
let siteID = try container.decode(Int64.self, forKey: .siteID)
28+
let password = try container.decode(String.self, forKey: .password)
29+
30+
self.init(siteID: siteID, password: password)
31+
}
32+
33+
public func encode(to encoder: Encoder) throws {
34+
var container = encoder.container(keyedBy: CodingKeys.self)
35+
36+
try container.encode(password, forKey: .password)
37+
}
38+
}
39+
40+
41+
/// Defines all of the Site Post CodingKeys
42+
///
43+
private extension Post {
44+
enum CodingKeys: String, CodingKey {
45+
case siteID = "site_ID"
46+
case password = "password"
47+
}
48+
}
49+
50+
51+
// MARK: - Comparable Conformance
52+
//
53+
extension Post: Comparable {
54+
public static func == (lhs: Post, rhs: Post) -> Bool {
55+
return lhs.siteID == rhs.siteID &&
56+
lhs.password == rhs.password
57+
}
58+
59+
public static func < (lhs: Post, rhs: Post) -> Bool {
60+
return lhs.siteID < rhs.siteID
61+
}
62+
63+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import Foundation
2+
import Alamofire
3+
4+
5+
/// WP.com Site Posts API: Remote Endpoints
6+
///
7+
public class SitePostsRemote: Remote {
8+
9+
10+
/// Loads the Post by ID from WP.com
11+
/// https://developer.wordpress.com/docs/api/1.1/get/sites/%24site/posts/%24post_ID/
12+
///
13+
/// - Parameters:
14+
/// - siteID: Site for which we'll fetch the post.
15+
/// - postID: Id of the post that we want to fetch.
16+
/// - completion: Closure to be executed upon completion.
17+
///
18+
public func loadSitePost(for siteID: Int64, postID: Int64, completion: @escaping (Post?, Error?) -> Void) {
19+
let path = String(format: "/sites/%d/posts/%d", siteID, postID)
20+
let parameters = ["fields": "site_ID,password"]
21+
let request = DotcomRequest(wordpressApiVersion: .mark1_1, method: .get, path: path, parameters: parameters)
22+
let mapper = PostMapper()
23+
24+
enqueue(request, mapper: mapper, completion: completion)
25+
}
26+
27+
/// Update a post from WP.com
28+
/// https://developer.wordpress.com/docs/api/1.2/post/sites/%24site/posts/%24post_ID/
29+
///
30+
/// - Parameters:
31+
/// - siteID: Site for which we'll update the post.
32+
/// - postID: Id of the post that we want to update.
33+
/// - post: Post that we will use to update the post.
34+
/// - completion: Closure to be executed upon completion.
35+
///
36+
public func updateSitePost(for siteID: Int64, postID: Int64, post: Post, completion: @escaping (Post?, Error?) -> Void) {
37+
do {
38+
var parameters = try post.toDictionary()
39+
let parametersFields = ["fields": "site_ID,password"]
40+
parameters.merge(parametersFields) { (current, _) in current }
41+
let path = String(format: "/sites/%d/posts/%d", siteID, postID)
42+
let request = DotcomRequest(wordpressApiVersion: .mark1_2, method: .post, path: path, parameters: parameters)
43+
let mapper = PostMapper()
44+
45+
enqueue(request, mapper: mapper, completion: completion)
46+
} catch {
47+
completion(nil, error)
48+
}
49+
}
50+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import XCTest
2+
@testable import Networking
3+
4+
5+
/// PostMapper Unit Tests
6+
///
7+
final class PostMapperTests: XCTestCase {
8+
9+
/// Verifies that all of the Post fields are parsed correctly.
10+
///
11+
func testFieldsAreProperlyParsed() {
12+
guard let sitePost = mapSitePost() else {
13+
XCTFail()
14+
return
15+
}
16+
17+
XCTAssertEqual(sitePost.siteID, 3584907)
18+
XCTAssertEqual(sitePost.password, "woooooooo!")
19+
}
20+
}
21+
22+
23+
/// Private Methods.
24+
///
25+
private extension PostMapperTests {
26+
27+
/// Returns the PostMapper output upon receiving `site-post` json (Data Encoded)
28+
///
29+
func mapSitePost() -> Post? {
30+
guard let response = Loader.contentsOf("site-post") else {
31+
return nil
32+
}
33+
34+
return try! PostMapper().map(response: response)
35+
}
36+
}

0 commit comments

Comments
 (0)