-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #30 from wordpress-mobile/feature/automated-transfer
Support for Automated Transfer.
- Loading branch information
Showing
4 changed files
with
185 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import Foundation | ||
|
||
/// Class encapsualting all requests related to performing Automated Transfer operations. | ||
public class AutomatedTransferService: ServiceRemoteWordPressComREST { | ||
|
||
public enum ResponseError: Error { | ||
case decodingFailure | ||
} | ||
|
||
public enum AutomatedTransferEligibilityError: Error { | ||
case unverifiedEmail | ||
case excessiveDiskSpaceUsage | ||
case noBusinessPlan | ||
case VIPSite | ||
case notAdmin | ||
case notDomainOwner | ||
case noCustomDomain | ||
case greylistedSite | ||
case privateSite | ||
case unknown | ||
} | ||
|
||
public func checkTransferEligibility(siteID: Int, | ||
success: @escaping () -> Void, | ||
failure: @escaping (AutomatedTransferEligibilityError) -> Void) { | ||
let endpoint = "sites/\(siteID)/automated-transfers/eligibility" | ||
let path = self.path(forEndpoint: endpoint, withVersion: ._1_1) | ||
|
||
wordPressComRestApi.GET(path, parameters: nil, success: { (responseObject, httpResponse) in | ||
guard let response = responseObject as? [String: AnyObject] else { | ||
failure(.unknown) | ||
return | ||
} | ||
|
||
guard let isEligible = response["is_eligible"] as? Bool, isEligible == true else { | ||
failure(self.eligibilityError(from: response)) | ||
return | ||
} | ||
|
||
success() | ||
}, failure: { _, _ in | ||
failure(.unknown) | ||
}) | ||
} | ||
|
||
public typealias AutomatedTransferInitationResponse = (transferID: Int, status: AutomatedTransferStatus) | ||
public func initiateAutomatedTransfer(siteID: Int, | ||
pluginSlug: String, | ||
success: @escaping (AutomatedTransferInitationResponse) -> Void, | ||
failure: @escaping (Error) -> Void) { | ||
|
||
let endpoint = "sites/\(siteID)/automated-transfers/initiate" | ||
let path = self.path(forEndpoint: endpoint, withVersion: ._1_1) | ||
let payload = ["plugin": pluginSlug] as [String: AnyObject] | ||
|
||
wordPressComRestApi.POST(path, parameters: payload, success: { (responseObject, httpResponse) in | ||
guard let response = responseObject as? [String: AnyObject] else { | ||
failure(ResponseError.decodingFailure) | ||
return | ||
} | ||
|
||
guard let transferID = response["transfer_id"] as? Int, | ||
let status = response["status"] as? String, | ||
let statusObject = AutomatedTransferStatus(status: status) else { | ||
failure(ResponseError.decodingFailure) | ||
return | ||
} | ||
|
||
success((transferID: transferID, status: statusObject)) | ||
}) { (error, _) in | ||
failure(error) | ||
} | ||
|
||
} | ||
|
||
public func fetchAutomatedTransferStatus(siteID: Int, | ||
success: @escaping (AutomatedTransferStatus) -> Void, | ||
failure: @escaping (Error) -> Void) { | ||
|
||
let endpoint = "sites/\(siteID)/automated-transfers/status" | ||
let path = self.path(forEndpoint: endpoint, withVersion: ._1_1) | ||
|
||
wordPressComRestApi.GET(path, parameters: nil, success: { (responseObject, httpResponse) in | ||
guard let response = responseObject as? [String: AnyObject] else { | ||
failure(ResponseError.decodingFailure) | ||
return | ||
} | ||
|
||
guard let status = response["status"] as? String, | ||
let currentStep = response["step"] as? Int, | ||
let totalSteps = response["total"] as? Int, | ||
let statusObject = AutomatedTransferStatus(status: status, step: currentStep, totalSteps: totalSteps) else { | ||
failure(ResponseError.decodingFailure) | ||
return | ||
} | ||
|
||
success(statusObject) | ||
}) { (error, _) in | ||
failure(error) | ||
} | ||
|
||
} | ||
|
||
private func eligibilityError(from response: [String: AnyObject]) -> AutomatedTransferEligibilityError { | ||
guard let errors = response["errors"] as? [[String: AnyObject]], | ||
let errorType = errors.first?["code"] as? String else { | ||
// The API can potentially return multiple errors here. Since there isn't really an actionable | ||
// way for user to deal with multiple of them at once, we're just picking the first one. | ||
return .unknown | ||
} | ||
|
||
switch errorType { | ||
case "email_unverified": | ||
return .unverifiedEmail | ||
case "excessive_disk_space": | ||
return .excessiveDiskSpaceUsage | ||
case "no_business_plan": | ||
return .noBusinessPlan | ||
case "no_vip_sites": | ||
return .VIPSite | ||
case "non_admin_user": | ||
return .notAdmin | ||
case "not_domain_owner": | ||
return .notDomainOwner | ||
case "not_using_custom_domain": | ||
return .noCustomDomain | ||
case "site_graylisted": | ||
return .greylistedSite | ||
case "site_private": | ||
return .privateSite | ||
default: | ||
return .unknown | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import Foundation | ||
|
||
/// A helper object encapsulating a status of Automated Transfer operation. | ||
public struct AutomatedTransferStatus { | ||
public enum State: String, RawRepresentable { | ||
case active | ||
case backfilling | ||
case complete | ||
case error | ||
case notFound = "not found" | ||
case unknownStatus = "unknown_status" | ||
case uploading | ||
case pending | ||
} | ||
|
||
public let status: State | ||
public let step: Int? | ||
public let totalSteps: Int? | ||
|
||
init?(status statusString: String) { | ||
guard let status = State(rawValue: statusString) else { | ||
return nil | ||
} | ||
|
||
self.status = status | ||
self.step = nil | ||
self.totalSteps = nil | ||
} | ||
|
||
init?(status statusString: String, step: Int, totalSteps: Int) { | ||
guard let status = State(rawValue: statusString) else { | ||
return nil | ||
} | ||
|
||
self.status = status | ||
self.step = step | ||
self.totalSteps = totalSteps | ||
} | ||
|
||
} |