Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ PODS:
- OHHTTPStubs/Swift (6.1.0):
- OHHTTPStubs/Default
- UIDeviceIdentifier (1.1.4)
- WordPressKit (2.0.0-beta.3):
- WordPressKit (2.0.0-beta.4):
- Alamofire (~> 4.7.3)
- CocoaLumberjack (= 3.4.2)
- NSObject-SafeExpectations (= 0.0.3)
Expand Down Expand Up @@ -70,7 +70,7 @@ SPEC CHECKSUMS:
OCMock: 43565190abc78977ad44a61c0d20d7f0784d35ab
OHHTTPStubs: 1e21c7d2c084b8153fc53d48400d8919d2d432d0
UIDeviceIdentifier: 8f8a24b257a4d978c8d40ad1e7355b944ffbfa8c
WordPressKit: 7978809060775c2301d1c0f83215b34dc4aaba2e
WordPressKit: c08da00b4a479cd52cda11d085e78b99a741e202
WordPressShared: a2fc2db66c210a05d317ae9678b5823dd6a4d708
wpxmlrpc: 6ba55c773cfa27083ae4a2173e69b19f46da98e2

Expand Down
2 changes: 1 addition & 1 deletion WordPressKit.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "WordPressKit"
s.version = "2.0.0-beta.3"
s.version = "2.0.0-beta.4"
s.summary = "WordPressKit offers a clean and simple WordPress.com and WordPress.org API."

s.description = <<-DESC
Expand Down
4 changes: 4 additions & 0 deletions WordPressKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
7328420421CD786C00126755 /* WordPressComServiceRemote+SiteCreation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7328420321CD786C00126755 /* WordPressComServiceRemote+SiteCreation.swift */; };
7328420621CD798A00126755 /* WordPressComServiceRemoteTests+SiteCreation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7328420521CD798A00126755 /* WordPressComServiceRemoteTests+SiteCreation.swift */; };
736C971021E80D48007A4200 /* SiteVerticalsPromptResponseDecodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 736C970F21E80D48007A4200 /* SiteVerticalsPromptResponseDecodingTests.swift */; };
7397F01A220A072500C723F3 /* ActivityServiceRemote_ApiVersion1_0.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7397F019220A072500C723F3 /* ActivityServiceRemote_ApiVersion1_0.swift */; };
73A2F38A21E7F81E00388609 /* WordPressComServiceRemote+SiteVerticalsPrompt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73A2F38921E7F81E00388609 /* WordPressComServiceRemote+SiteVerticalsPrompt.swift */; };
73A2F38D21E7FC8200388609 /* WordPressComServiceRemoteTests+SiteVerticalsPrompt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73A2F38C21E7FC8200388609 /* WordPressComServiceRemoteTests+SiteVerticalsPrompt.swift */; };
73A2F38E21E7FD9B00388609 /* site-verticals-prompt.json in Resources */ = {isa = PBXBuildFile; fileRef = 73A2F38B21E7FC2A00388609 /* site-verticals-prompt.json */; };
Expand Down Expand Up @@ -508,6 +509,7 @@
7328420321CD786C00126755 /* WordPressComServiceRemote+SiteCreation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WordPressComServiceRemote+SiteCreation.swift"; sourceTree = "<group>"; };
7328420521CD798A00126755 /* WordPressComServiceRemoteTests+SiteCreation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WordPressComServiceRemoteTests+SiteCreation.swift"; sourceTree = "<group>"; };
736C970F21E80D48007A4200 /* SiteVerticalsPromptResponseDecodingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteVerticalsPromptResponseDecodingTests.swift; sourceTree = "<group>"; };
7397F019220A072500C723F3 /* ActivityServiceRemote_ApiVersion1_0.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityServiceRemote_ApiVersion1_0.swift; sourceTree = "<group>"; };
73A2F38921E7F81E00388609 /* WordPressComServiceRemote+SiteVerticalsPrompt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WordPressComServiceRemote+SiteVerticalsPrompt.swift"; sourceTree = "<group>"; };
73A2F38B21E7FC2A00388609 /* site-verticals-prompt.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "site-verticals-prompt.json"; sourceTree = "<group>"; };
73A2F38C21E7FC8200388609 /* WordPressComServiceRemoteTests+SiteVerticalsPrompt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WordPressComServiceRemoteTests+SiteVerticalsPrompt.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1237,6 +1239,7 @@
93BD273A1EE73282002BB00B /* AccountServiceRemoteREST.m */,
7403A2E31EF06ED500DED7DC /* AccountSettingsRemote.swift */,
826016F01F9FA13A00533B6C /* ActivityServiceRemote.swift */,
7397F019220A072500C723F3 /* ActivityServiceRemote_ApiVersion1_0.swift */,
40247DF92120D8E100AE1C3C /* AutomatedTransferService.swift */,
82FFBF551F460DD400F4573F /* BlogJetpackSettingsServiceRemote.swift */,
74B5F0DB1EF829B800B411E7 /* BlogServiceRemote.h */,
Expand Down Expand Up @@ -2214,6 +2217,7 @@
93BD27831EE73944002BB00B /* WordPressRSDParser.swift in Sources */,
7328420421CD786C00126755 /* WordPressComServiceRemote+SiteCreation.swift in Sources */,
826016F31F9FA17B00533B6C /* Activity.swift in Sources */,
7397F01A220A072500C723F3 /* ActivityServiceRemote_ApiVersion1_0.swift in Sources */,
7E3E7A4A20E443890075D159 /* Scanner+extensions.swift in Sources */,
742362E31F1025B400BD0A7F /* RemoteMenuLocation.m in Sources */,
82FFBF561F460DD400F4573F /* BlogJetpackSettingsServiceRemote.swift in Sources */,
Expand Down
31 changes: 0 additions & 31 deletions WordPressKit/ActivityServiceRemote.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,39 +97,8 @@ public class ActivityServiceRemote: ServiceRemoteWordPressComREST {
})
}

/// Makes a request to Restore a site to a previous state.
///
/// - Parameters:
/// - siteID: The target site's ID.
/// - rewindID: The rewindID to restore to.
/// - success: Closure to be executed on success
/// - failure: Closure to be executed on error.
///
/// - Returns: A restoreID to check the status of the rewind request.
///
@objc public func restoreSite(_ siteID: Int,
rewindID: String,
success: @escaping (_ restoreID: String) -> Void,
failure: @escaping (Error) -> Void) {
let endpoint = "activity-log/\(siteID)/rewind/to/\(rewindID)"
let path = self.path(forEndpoint: endpoint, withVersion: ._1_0)

wordPressComRestApi.POST(path,
parameters: nil,
success: { response, _ in
guard let restoreID = response["restore_id"] as? Int else {
failure(ResponseError.decodingFailure)
return
}
success(String(restoreID))
},
failure: { error, _ in
failure(error)
})
}

}

private extension ActivityServiceRemote {

func mapActivitiesResponse(_ response: AnyObject) throws -> ([Activity], Int) {
Expand Down
38 changes: 38 additions & 0 deletions WordPressKit/ActivityServiceRemote_ApiVersion1_0.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

@objc public class ActivityServiceRemote_ApiVersion1_0: ServiceRemoteWordPressComREST {

public enum ResponseError: Error {
case decodingFailure
}

/// Makes a request to Restore a site to a previous state.
///
/// - Parameters:
/// - siteID: The target site's ID.
/// - rewindID: The rewindID to restore to.
/// - success: Closure to be executed on success
/// - failure: Closure to be executed on error.
///
/// - Returns: A restoreID to check the status of the rewind request.
///
@objc public func restoreSite(_ siteID: Int,
rewindID: String,
success: @escaping (_ restoreID: String) -> Void,
failure: @escaping (Error) -> Void) {
let endpoint = "activity-log/\(siteID)/rewind/to/\(rewindID)"
let path = self.path(forEndpoint: endpoint, withVersion: ._1_0)

wordPressComRestApi.POST(path,
parameters: nil,
success: { response, _ in
guard let restoreID = response["restore_id"] as? Int else {
failure(ResponseError.decodingFailure)
return
}
success(String(restoreID))
},
failure: { error, _ in
failure(error)
})
}
}
65 changes: 48 additions & 17 deletions WordPressKit/WordPressComRestApi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import Foundation
import WordPressShared
import Alamofire

// MARK: - WordPressComRestApiError

/**
Error constants for the WordPress.com REST API

Expand All @@ -24,10 +26,19 @@ import Alamofire
case preconditionFailure
}

open class WordPressComRestApi: NSObject {
@objc public static let ErrorKeyErrorCode: String = "WordPressComRestApiErrorCodeKey"
@objc public static let ErrorKeyErrorMessage: String = "WordPressComRestApiErrorMessageKey"
@objc public static let SessionTaskKey: String = "WordPressComRestAPI.sessionTask"
// MARK: - WordPressComRestApi

open class WordPressComRestApi: NSObject {

// MARK: Properties

@objc public static let ErrorKeyErrorCode = "WordPressComRestApiErrorCodeKey"
@objc public static let ErrorKeyErrorMessage = "WordPressComRestApiErrorMessageKey"

@objc public static let LocaleKeyDefault = "locale" // locale is specified with this for v1 endpoints
@objc public static let LocaleKeyV2 = "_locale" // locale is prefixed with an underscore for v2

@objc public static let SessionTaskKey = "WordPressComRestAPI.sessionTask"

public typealias RequestEnqueuedBlock = (_ taskID : NSNumber) -> Void
public typealias SuccessResponseBlock = (_ responseObject: AnyObject, _ httpResponse: HTTPURLResponse?) -> ()
Expand All @@ -37,23 +48,24 @@ open class WordPressComRestApi: NSObject {

@objc public static let defaultBackgroundSessionIdentifier = "org.wordpress.wpcomrestapi"

private let oAuthToken: String?

private let userAgent: String?

@objc public let backgroundSessionIdentifier: String

@objc public let sharedContainerIdentifier: String?

fileprivate let backgroundUploads: Bool

static let localeKey = "locale"
private let backgroundUploads: Bool

fileprivate let oAuthToken: String?
fileprivate let userAgent: String?
private let localeKey: String

/**
Configure whether or not the user's preferred language locale should be appended. Defaults to true.
*/
@objc open var appendsPreferredLanguageLocale = true

fileprivate lazy var sessionManager: Alamofire.SessionManager = {
private lazy var sessionManager: Alamofire.SessionManager = {
let sessionConfiguration = URLSessionConfiguration.default
let sessionManager = self.makeSessionManager(configuration: sessionConfiguration)
return sessionManager
Expand All @@ -67,7 +79,7 @@ open class WordPressComRestApi: NSObject {
return result
}

fileprivate lazy var uploadSessionManager: Alamofire.SessionManager = {
private lazy var uploadSessionManager: Alamofire.SessionManager = {
if self.backgroundUploads {
let sessionConfiguration = URLSessionConfiguration.background(withIdentifier: self.backgroundSessionIdentifier)
sessionConfiguration.sharedContainerIdentifier = self.sharedContainerIdentifier
Expand All @@ -78,7 +90,7 @@ open class WordPressComRestApi: NSObject {
return self.sessionManager
}()

fileprivate func makeSessionManager(configuration sessionConfiguration: URLSessionConfiguration) -> Alamofire.SessionManager {
private func makeSessionManager(configuration sessionConfiguration: URLSessionConfiguration) -> Alamofire.SessionManager {
var additionalHeaders: [String : AnyObject] = [:]
if let oAuthToken = self.oAuthToken {
additionalHeaders["Authorization"] = "Bearer \(oAuthToken)" as AnyObject?
Expand All @@ -92,6 +104,8 @@ open class WordPressComRestApi: NSObject {

return sessionManager
}

// MARK: WordPressComRestApi

@objc convenience public init(oAuthToken: String? = nil, userAgent: String? = nil) {
self.init(oAuthToken: oAuthToken, userAgent: userAgent, backgroundUploads: false, backgroundSessionIdentifier: WordPressComRestApi.defaultBackgroundSessionIdentifier)
Expand All @@ -105,6 +119,7 @@ open class WordPressComRestApi: NSObject {
/// - backgroundUploads: If this value is true the API object will use a background session to execute uploads requests when using the `multipartPOST` function. The default value is false.
/// - backgroundSessionIdentifier: The session identifier to use for the background session. This must be unique in the system.
/// - sharedContainerIdentifier: An optional string used when setting up background sessions for use in an app extension. Default is nil.
/// - localeKey: The key with which to specify locale in the parameters of a request.
///
/// - Discussion: When backgroundUploads are activated any request done by the multipartPOST method will use background session. This background session is shared for all multipart
/// requests and the identifier used must be unique in the system, Apple recomends to use invert DNS base on your bundle ID. Keep in mind these requests will continue even
Expand All @@ -114,12 +129,15 @@ open class WordPressComRestApi: NSObject {
@objc public init(oAuthToken: String? = nil, userAgent: String? = nil,
backgroundUploads: Bool = false,
backgroundSessionIdentifier: String = WordPressComRestApi.defaultBackgroundSessionIdentifier,
sharedContainerIdentifier: String? = nil) {
sharedContainerIdentifier: String? = nil,
localeKey: String = WordPressComRestApi.LocaleKeyDefault) {
self.oAuthToken = oAuthToken
self.userAgent = userAgent
self.backgroundUploads = backgroundUploads
self.backgroundSessionIdentifier = backgroundSessionIdentifier
self.sharedContainerIdentifier = sharedContainerIdentifier
self.localeKey = localeKey

super.init()
}

Expand All @@ -136,7 +154,7 @@ open class WordPressComRestApi: NSObject {
uploadSessionManager.session.invalidateAndCancel()
}

// MARK: - Network requests
// MARK: Network requests

private func request(method: HTTPMethod,
urlString: String,
Expand Down Expand Up @@ -309,10 +327,9 @@ open class WordPressComRestApi: NSObject {
/// - Parameters:
/// - path: the path for the request, which might include `locale`
/// - parameters: the request parameters, which could conceivably include `locale`
/// - localeKey: the locale key to search for (`locale` in v1 endpoints, `_locale` for v2)
/// - Returns: a request URL if successful, `nil` otherwise.
///
func buildRequestURLFor(path: String, parameters: [String: AnyObject]? = [:], localeKey: String = WordPressComRestApi.localeKey) -> String? {
func buildRequestURLFor(path: String, parameters: [String: AnyObject]? = [:]) -> String? {

let baseURL = URL(string: WordPressComRestApi.apiBaseURLString)

Expand Down Expand Up @@ -355,6 +372,8 @@ open class WordPressComRestApi: NSObject {
}
}

// MARK: - FilePart

/// FilePart represents the infomartion needed to encode a file on a multipart form request
public final class FilePart: NSObject {
@objc let parameterName: String
Expand All @@ -370,6 +389,8 @@ public final class FilePart: NSObject {
}
}

// MARK: - Error processing

extension WordPressComRestApi {

/// A custom error processor to handle error responses when status codes are betwen 400 and 500
Expand Down Expand Up @@ -447,15 +468,25 @@ extension WordPressComRestApi {
return errorWithLocalizedMessage
}
}
// MARK: - Anonymous API support

extension WordPressComRestApi {

/// Returns an Api object without an oAuthtoken defined and with the userAgent set for the WordPress App user agent
/// Returns an API object without an OAuth token defined & with the userAgent set for the WordPress App user agent
///
@objc class public func anonymousApi(userAgent: String) -> WordPressComRestApi {
return WordPressComRestApi(oAuthToken: nil, userAgent: userAgent)
}

/// Returns an API object without an OAuth token defined & with both the userAgent & localeKey set for the WordPress App user agent
///
@objc class public func anonymousApi(userAgent: String, localeKey: String) -> WordPressComRestApi {
return WordPressComRestApi(oAuthToken: nil, userAgent: userAgent, localeKey: localeKey)
}
}

// MARK: - Progress

@objc extension Progress {

@objc var sessionTask: URLSessionTask? {
Expand Down
8 changes: 6 additions & 2 deletions WordPressKitTests/ActivityServiceRemoteTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,18 @@ class ActivityServiceRemoteTests: RemoteTestCase, RESTTestable {
var restoreEndpoint: String { return "activity-log/\(siteID)/rewind/to/\(rewindID)" }
var rewindStatusEndpoint: String { return "sites/\(siteID)/rewind" }

var remoteV1: ActivityServiceRemote_ApiVersion1_0!
var remote: ActivityServiceRemote!

/// MARK: - Overridden Methods

override func setUp() {
super.setUp()

remote = ActivityServiceRemote(wordPressComRestApi: getRestApi())
remoteV1 = ActivityServiceRemote_ApiVersion1_0(wordPressComRestApi: getRestApi())

let v2RestApi = WordPressComRestApi(localeKey: WordPressComRestApi.LocaleKeyV2)
remote = ActivityServiceRemote(wordPressComRestApi: v2RestApi)
}

override func tearDown() {
Expand Down Expand Up @@ -142,7 +146,7 @@ class ActivityServiceRemoteTests: RemoteTestCase, RESTTestable {

stubRemoteResponse(restoreEndpoint, filename: restoreSuccessMockFilename, contentType: .ApplicationJSON)

remote.restoreSite(siteID,
remoteV1.restoreSite(siteID,
rewindID: rewindID,
success: { (restoreID) in
XCTAssertEqual(restoreID, self.restoreID)
Expand Down
Loading