Skip to content

Commit

Permalink
Merge pull request #198 from woocommerce/develop
Browse files Browse the repository at this point in the history
Merging Mark 0.4 into Master
  • Loading branch information
jleandroperez authored Jul 30, 2018
2 parents af3bd9e + e2cdc45 commit ccda6d3
Show file tree
Hide file tree
Showing 116 changed files with 5,256 additions and 448 deletions.
12 changes: 12 additions & 0 deletions Networking/Networking.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
B56C1EB620EA757B00D749F9 /* SiteListMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56C1EB520EA757B00D749F9 /* SiteListMapper.swift */; };
B56C1EB820EA76F500D749F9 /* Site.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56C1EB720EA76F500D749F9 /* Site.swift */; };
B56C1EBA20EA7D2C00D749F9 /* sites.json in Resources */ = {isa = PBXBuildFile; fileRef = B56C1EB920EA7D2C00D749F9 /* sites.json */; };
B58E5BEA20FFB3D0003C986E /* CodingUserInfoKey+Woo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58E5BE920FFB3D0003C986E /* CodingUserInfoKey+Woo.swift */; };
B5969E1520A47F99005E9DF1 /* RemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5969E1420A47F99005E9DF1 /* RemoteTests.swift */; };
B5BB1D0C20A2050300112D92 /* DateFormatter+Woo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BB1D0B20A2050300112D92 /* DateFormatter+Woo.swift */; };
B5BB1D1020A237FB00112D92 /* Address.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BB1D0F20A237FB00112D92 /* Address.swift */; };
Expand All @@ -60,6 +61,8 @@
B5C6FCD420A373BB00A4F8E4 /* OrderMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C6FCD320A373BA00A4F8E4 /* OrderMapper.swift */; };
B5C6FCD620A3768900A4F8E4 /* order.json in Resources */ = {isa = PBXBuildFile; fileRef = B5C6FCD520A3768900A4F8E4 /* order.json */; };
CE20179320E3EFA7005B4C18 /* broken-orders.json in Resources */ = {isa = PBXBuildFile; fileRef = CE20179220E3EFA7005B4C18 /* broken-orders.json */; };
CE21B3E72106811000A259D5 /* new-order-note.json in Resources */ = {isa = PBXBuildFile; fileRef = CE21B3E62106811000A259D5 /* new-order-note.json */; };
CE583A0E2109154500D73C1C /* OrderNoteMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE583A0D2109154500D73C1C /* OrderNoteMapper.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -119,6 +122,7 @@
B56C1EB520EA757B00D749F9 /* SiteListMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteListMapper.swift; sourceTree = "<group>"; };
B56C1EB720EA76F500D749F9 /* Site.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Site.swift; sourceTree = "<group>"; };
B56C1EB920EA7D2C00D749F9 /* sites.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = sites.json; sourceTree = "<group>"; };
B58E5BE920FFB3D0003C986E /* CodingUserInfoKey+Woo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CodingUserInfoKey+Woo.swift"; sourceTree = "<group>"; };
B5969E1420A47F99005E9DF1 /* RemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteTests.swift; sourceTree = "<group>"; };
B5BB1D0B20A2050300112D92 /* DateFormatter+Woo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateFormatter+Woo.swift"; sourceTree = "<group>"; };
B5BB1D0F20A237FB00112D92 /* Address.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Address.swift; sourceTree = "<group>"; };
Expand All @@ -131,6 +135,8 @@
BD9439D9B8F2C1ED2EADAA51 /* Pods-NetworkingTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NetworkingTests.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-NetworkingTests/Pods-NetworkingTests.debug.xcconfig"; sourceTree = "<group>"; };
C8F9A8CC6F90A8C9B5EF2EE2 /* Pods-Networking.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Networking.release.xcconfig"; path = "../Pods/Target Support Files/Pods-Networking/Pods-Networking.release.xcconfig"; sourceTree = "<group>"; };
CE20179220E3EFA7005B4C18 /* broken-orders.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "broken-orders.json"; sourceTree = "<group>"; };
CE21B3E62106811000A259D5 /* new-order-note.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "new-order-note.json"; sourceTree = "<group>"; };
CE583A0D2109154500D73C1C /* OrderNoteMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderNoteMapper.swift; sourceTree = "<group>"; };
F3F25DC15EC1D7C631169CB5 /* Pods_Networking.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Networking.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F6CEE1CA2AD376C0C28AE9F6 /* Pods-NetworkingTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NetworkingTests.release.xcconfig"; path = "../Pods/Target Support Files/Pods-NetworkingTests/Pods-NetworkingTests.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -312,6 +318,7 @@
B559EBA820A0B5B100836CD4 /* Responses */ = {
isa = PBXGroup;
children = (
CE21B3E62106811000A259D5 /* new-order-note.json */,
B505F6D420BEE4E600BB1B69 /* me.json */,
B559EBA920A0B5CD00836CD4 /* orders-load-all.json */,
B5C6FCD520A3768900A4F8E4 /* order.json */,
Expand All @@ -333,6 +340,7 @@
B567AF2A20A0FA4200AB6C62 /* OrderListMapper.swift */,
B56C1EB520EA757B00D749F9 /* SiteListMapper.swift */,
74C8F06720EEB7BC00B6EDC9 /* OrderNotesMapper.swift */,
CE583A0D2109154500D73C1C /* OrderNoteMapper.swift */,
);
path = Mapper;
sourceTree = "<group>";
Expand All @@ -341,6 +349,7 @@
isa = PBXGroup;
children = (
B5BB1D0B20A2050300112D92 /* DateFormatter+Woo.swift */,
B58E5BE920FFB3D0003C986E /* CodingUserInfoKey+Woo.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -479,6 +488,7 @@
files = (
74C8F06620EEB76400B6EDC9 /* order-notes.json in Resources */,
74C8F06C20EEBD5D00B6EDC9 /* broken-order.json in Resources */,
CE21B3E72106811000A259D5 /* new-order-note.json in Resources */,
B505F6D520BEE4E700BB1B69 /* me.json in Resources */,
B5C6FCD620A3768900A4F8E4 /* order.json in Resources */,
B559EBAA20A0B5CD00836CD4 /* orders-load-all.json in Resources */,
Expand Down Expand Up @@ -556,6 +566,7 @@
files = (
B56C1EB620EA757B00D749F9 /* SiteListMapper.swift in Sources */,
B557DA1A20979D66005962F4 /* Settings.swift in Sources */,
B58E5BEA20FFB3D0003C986E /* CodingUserInfoKey+Woo.swift in Sources */,
741B950120EBC8A700DD6E2D /* OrderCouponLine.swift in Sources */,
74C8F06420EEB44800B6EDC9 /* OrderNote.swift in Sources */,
B5BB1D0C20A2050300112D92 /* DateFormatter+Woo.swift in Sources */,
Expand All @@ -571,6 +582,7 @@
B518662220A097C200037A38 /* Network.swift in Sources */,
B518662420A099BF00037A38 /* AlamofireNetwork.swift in Sources */,
B557DA1820979D51005962F4 /* Credentials.swift in Sources */,
CE583A0E2109154500D73C1C /* OrderNoteMapper.swift in Sources */,
B5C6FCCF20A3592900A4F8E4 /* OrderItem.swift in Sources */,
B505F6EC20BEFDC200BB1B69 /* Loader.swift in Sources */,
B5BB1D1220A255EC00112D92 /* OrderStatus.swift in Sources */,
Expand Down
11 changes: 11 additions & 0 deletions Networking/Networking/Extensions/CodingUserInfoKey+Woo.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Foundation


/// WooCommerce CodingUserInfoKey(s)
///
extension CodingUserInfoKey {

/// Used to store the SiteID within a Coder/Decoder's userInfo dictionary.
///
public static let siteID = CodingUserInfoKey(rawValue: "siteID")!
}
12 changes: 11 additions & 1 deletion Networking/Networking/Mapper/OrderListMapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,23 @@ import Foundation

/// Mapper: OrderList
///
class OrderListMapper: Mapper {
struct OrderListMapper: Mapper {

/// Site Identifier associated to the orders that will be parsed.
/// We're injecting this field via `JSONDecoder.userInfo` because the remote endpoints don't really return the SiteID in any of the
/// Order Endpoints.
///
let siteID: Int


/// (Attempts) to convert a dictionary into [Order].
///
func map(response: Data) throws -> [Order] {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(DateFormatter.Defaults.dateTimeFormatter)
decoder.userInfo = [
.siteID: siteID
]

return try decoder.decode(OrderListEnvelope.self, from: response).orders
}
Expand Down
12 changes: 11 additions & 1 deletion Networking/Networking/Mapper/OrderMapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,23 @@ import Foundation

/// Mapper: Order
///
class OrderMapper: Mapper {
struct OrderMapper: Mapper {

/// Site Identifier associated to the orders that will be parsed.
/// We're injecting this field via `JSONDecoder.userInfo` because the remote endpoints don't really return the SiteID in any of the
/// Order Endpoints.
///
let siteID: Int


/// (Attempts) to convert a dictionary into [Order].
///
func map(response: Data) throws -> Order {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(DateFormatter.Defaults.dateTimeFormatter)
decoder.userInfo = [
.siteID: siteID
]

return try decoder.decode(OrderEnvelope.self, from: response).order
}
Expand Down
29 changes: 29 additions & 0 deletions Networking/Networking/Mapper/OrderNoteMapper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Foundation


/// Mapper: OrderNote (Singular)
///
class OrderNoteMapper: Mapper {

/// (Attempts) to convert a dictionary into a single OrderNote
///
func map(response: Data) throws -> OrderNote {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(DateFormatter.Defaults.dateTimeFormatter)

return try decoder.decode(OrderNoteEnvelope.self, from: response).orderNote
}
}


/// OrderNote Disposable Entity:
/// `Add Order Note` endpoint the single added note within the `data` key. This entity
/// allows us to parse all the things with JSONDecoder.
///
private struct OrderNoteEnvelope: Decodable {
let orderNote: OrderNote

private enum CodingKeys: String, CodingKey {
case orderNote = "data"
}
}
44 changes: 40 additions & 4 deletions Networking/Networking/Model/Order.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Foundation
/// Represents an Order Entity.
///
public struct Order: Decodable {
public let siteID: Int
public let orderID: Int
public let parentID: Int
public let customerID: Int
Expand Down Expand Up @@ -32,8 +33,30 @@ public struct Order: Decodable {

/// Order struct initializer.
///
public init(orderID: Int, parentID: Int, customerID: Int, number: String, status: OrderStatus, currency: String, customerNote: String?, dateCreated: Date, dateModified: Date, datePaid: Date?, discountTotal: String, discountTax: String, shippingTotal: String, shippingTax: String, total: String, totalTax: String, paymentMethodTitle: String, items: [OrderItem], billingAddress: Address, shippingAddress: Address, coupons: [OrderCouponLine]) {

public init(siteID: Int,
orderID: Int,
parentID: Int,
customerID: Int,
number: String,
status: OrderStatus,
currency: String,
customerNote: String?,
dateCreated: Date,
dateModified: Date,
datePaid: Date?,
discountTotal: String,
discountTax: String,
shippingTotal: String,
shippingTax: String,
total: String,
totalTax: String,
paymentMethodTitle: String,
items: [OrderItem],
billingAddress: Address,
shippingAddress: Address,
coupons: [OrderCouponLine]) {

self.siteID = siteID
self.orderID = orderID
self.parentID = parentID
self.customerID = customerID
Expand Down Expand Up @@ -65,7 +88,12 @@ public struct Order: Decodable {
/// The public initializer for Order.
///
public init(from decoder: Decoder) throws {
guard let siteID = decoder.userInfo[.siteID] as? Int else {
throw OrderDecodingError.missingSiteID
}

let container = try decoder.container(keyedBy: CodingKeys.self)

let orderID = try container.decode(Int.self, forKey: .orderID)
let parentID = try container.decode(Int.self, forKey: .parentID)
let customerID = try container.decode(Int.self, forKey: .customerID)
Expand All @@ -92,7 +120,7 @@ public struct Order: Decodable {
let billingAddress = try container.decode(Address.self, forKey: .billingAddress)
let coupons = try container.decode([OrderCouponLine].self, forKey: .couponLines)

self.init(orderID: orderID, parentID: parentID, customerID: customerID, number: number, status: status, currency: currency, customerNote: customerNote, dateCreated: dateCreated, dateModified: dateModified, datePaid: datePaid, discountTotal: discountTotal, discountTax: discountTax, shippingTotal: shippingTotal, shippingTax: shippingTax, total: total, totalTax: totalTax, paymentMethodTitle: paymentMethodTitle, items: items, billingAddress: billingAddress, shippingAddress: shippingAddress, coupons: coupons) // initialize the struct
self.init(siteID: siteID, orderID: orderID, parentID: parentID, customerID: customerID, number: number, status: status, currency: currency, customerNote: customerNote, dateCreated: dateCreated, dateModified: dateModified, datePaid: datePaid, discountTotal: discountTotal, discountTax: discountTax, shippingTotal: shippingTotal, shippingTax: shippingTax, total: total, totalTax: totalTax, paymentMethodTitle: paymentMethodTitle, items: items, billingAddress: billingAddress, shippingAddress: shippingAddress, coupons: coupons) // initialize the struct
}
}

Expand Down Expand Up @@ -135,7 +163,8 @@ private extension Order {
//
extension Order: Comparable {
public static func == (lhs: Order, rhs: Order) -> Bool {
return lhs.orderID == rhs.orderID &&
return lhs.siteID == rhs.siteID &&
lhs.orderID == rhs.orderID &&
lhs.parentID == rhs.parentID &&
lhs.customerID == rhs.customerID &&
lhs.number == rhs.number &&
Expand Down Expand Up @@ -163,3 +192,10 @@ extension Order: Comparable {
(lhs.orderID == rhs.orderID && lhs.dateCreated == rhs.dateCreated && lhs.dateModified < rhs.dateModified)
}
}


// MARK: - Decoding Errors
//
enum OrderDecodingError: Error {
case missingSiteID
}
14 changes: 7 additions & 7 deletions Networking/Networking/Model/OrderNote.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import Foundation
/// Represents an Order's Note Entity.
///
public struct OrderNote: Decodable {
public let noteId: Int
public let noteID: Int
public let dateCreated: Date
public let note: String
public let isCustomerNote: Bool

/// OrderNote struct initializer.
///
init(noteId: Int, dateCreated: Date, note: String, isCustomerNote: Bool) {
self.noteId = noteId
public init(noteId: Int, dateCreated: Date, note: String, isCustomerNote: Bool) {
self.noteID = noteId
self.dateCreated = dateCreated
self.note = note
self.isCustomerNote = isCustomerNote
Expand Down Expand Up @@ -49,15 +49,15 @@ private extension OrderNote {
//
extension OrderNote: Comparable {
public static func == (lhs: OrderNote, rhs: OrderNote) -> Bool {
return lhs.noteId == rhs.noteId &&
return lhs.noteID == rhs.noteID &&
lhs.dateCreated == rhs.dateCreated &&
lhs.note == rhs.note &&
lhs.isCustomerNote == rhs.isCustomerNote
}

public static func < (lhs: OrderNote, rhs: OrderNote) -> Bool {
return lhs.noteId < rhs.noteId ||
(lhs.noteId == rhs.noteId && lhs.dateCreated < rhs.dateCreated) ||
(lhs.noteId == rhs.noteId && lhs.dateCreated == rhs.dateCreated && lhs.note < rhs.note)
return lhs.noteID < rhs.noteID ||
(lhs.noteID == rhs.noteID && lhs.dateCreated < rhs.dateCreated) ||
(lhs.noteID == rhs.noteID && lhs.dateCreated == rhs.dateCreated && lhs.note < rhs.note)
}
}
9 changes: 8 additions & 1 deletion Networking/Networking/Model/Site.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ public struct Site: Decodable {
///
public let url: String

/// Indicates if there is a WooCommerce Store Active.
///
public let isWooCommerceActive: Bool

/// Indicates if this site hosts a WordPress Store.
///
public let isWordPressStore: Bool
Expand All @@ -38,16 +42,18 @@ public struct Site: Decodable {

let optionsContainer = try siteContainer.nestedContainer(keyedBy: OptionKeys.self, forKey: .options)
isWordPressStore = try optionsContainer.decode(Bool.self, forKey: .isWordPressStore)
isWooCommerceActive = try optionsContainer.decode(Bool.self, forKey: .isWooCommerceActive)
}

/// Designated Initializer.
///
public init(siteID: Int, name: String, description: String, url: String, isWordPressStore: Bool) {
public init(siteID: Int, name: String, description: String, url: String, isWooCommerceActive: Bool, isWordPressStore: Bool) {
self.siteID = siteID
self.name = name
self.description = description
self.url = url
self.isWordPressStore = isWordPressStore
self.isWooCommerceActive = isWooCommerceActive
}
}

Expand All @@ -66,5 +72,6 @@ private extension Site {

enum OptionKeys: String, CodingKey {
case isWordPressStore = "is_wpcom_store"
case isWooCommerceActive = "woocommerce_is_active"
}
}
34 changes: 28 additions & 6 deletions Networking/Networking/Remote/OrdersRemote.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class OrdersRemote: Remote {
let parameters = [ParameterKeys.page: String(page),
ParameterKeys.perPage: String(Constants.defaultPageSize)]
let request = JetpackRequest(wooApiVersion: .mark2, method: .get, siteID: siteID, path: path, parameters: parameters)
let mapper = OrderListMapper()
let mapper = OrderListMapper(siteID: siteID)

enqueue(request, mapper: mapper, completion: completion)
}
Expand All @@ -32,7 +32,7 @@ public class OrdersRemote: Remote {
public func loadOrder(for siteID: Int, orderID: Int, completion: @escaping (Order?, Error?) -> Void) {
let path = "\(Constants.ordersPath)/\(orderID)"
let request = JetpackRequest(wooApiVersion: .mark2, method: .get, siteID: siteID, path: path, parameters: nil)
let mapper = OrderMapper()
let mapper = OrderMapper(siteID: siteID)

enqueue(request, mapper: mapper, completion: completion)
}
Expand Down Expand Up @@ -63,7 +63,27 @@ public class OrdersRemote: Remote {
public func updateOrder(from siteID: Int, orderID: Int, status: String, completion: @escaping (Order?, Error?) -> Void) {
let path = "\(Constants.ordersPath)/" + String(orderID)
let parameters = [ParameterKeys.status: status]
let mapper = OrderMapper()
let mapper = OrderMapper(siteID: siteID)

let request = JetpackRequest(wooApiVersion: .mark2, method: .post, siteID: siteID, path: path, parameters: parameters)
enqueue(request, mapper: mapper, completion: completion)
}

/// Adds an order note to a specific Order.
///
/// - Parameters:
/// - siteID: Site which hosts the Order.
/// - orderID: Identifier of the Order to be updated.
/// - isCustomerNote: if true, the note will be shown to customers and they will be notified.
/// if false, the note will be for admin reference only. Default is false.
/// - note: The note to be posted.
/// - completion: Closure to be executed upon completion.
///
public func addOrderNote(for siteID: Int, orderID: Int, isCustomerNote: Bool, with note: String, completion: @escaping (OrderNote?, Error?) -> Void) {
let path = "\(Constants.ordersPath)/" + String(orderID) + "/" + "\(Constants.notesPath)"
let parameters = [ParameterKeys.note: note,
ParameterKeys.customerNote: String(isCustomerNote)]
let mapper = OrderNoteMapper()

let request = JetpackRequest(wooApiVersion: .mark2, method: .post, siteID: siteID, path: path, parameters: parameters)
enqueue(request, mapper: mapper, completion: completion)
Expand All @@ -81,8 +101,10 @@ private extension OrdersRemote {
}

enum ParameterKeys {
static let status: String = "status"
static let page: String = "page"
static let perPage: String = "per_page"
static let customerNote: String = "customer_note"
static let note: String = "note"
static let page: String = "page"
static let perPage: String = "per_page"
static let status: String = "status"
}
}
Loading

0 comments on commit ccda6d3

Please sign in to comment.