From 6f0f3c4e2fc82fa04638527c002c8582f04bd20a Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 08:04:54 +1000 Subject: [PATCH 01/17] Remove an `enum` builder in favor of default associated value --- Sources/WordPressKit/WordPressAPI/WordPressAPIError.swift | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Sources/WordPressKit/WordPressAPI/WordPressAPIError.swift b/Sources/WordPressKit/WordPressAPI/WordPressAPIError.swift index a4680b20..5a6c3d5f 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressAPIError.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressAPIError.swift @@ -18,13 +18,10 @@ public enum WordPressAPIError: Error where EndpointError: Localiz /// The API call returned an status code that's unacceptable to the endpoint. case unacceptableStatusCode(response: HTTPURLResponse, body: Data) /// The API call returned an HTTP response that WordPressKit can't parse. Receiving this error could be an indicator that there is an error response that's not handled properly by WordPressKit. - case unparsableResponse(response: HTTPURLResponse?, body: Data?, underlyingError: Error) + case unparsableResponse(response: HTTPURLResponse?, body: Data?, underlyingError: Error = URLError(.cannotParseResponse)) /// Other error occured. case unknown(underlyingError: Error) - static func unparsableResponse(response: HTTPURLResponse?, body: Data?) -> Self { - return WordPressAPIError.unparsableResponse(response: response, body: body, underlyingError: URLError(.cannotParseResponse)) - } var response: HTTPURLResponse? { switch self { From 465d589b9360bc5b6f701d9548a6b9dbf6834c87 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 08:03:53 +1000 Subject: [PATCH 02/17] Update access control to components called by removed types --- .../Models/RemotePostParameters.swift | 32 ++++++++++++++----- .../DateFormatter+WordPressCom.swift | 2 +- .../WordPressAPI/HTTPRequestBuilder.swift | 4 +-- .../WordPressAPI/WordPressComRestApi.swift | 2 +- .../WordPressAPI/WordPressOrgXMLRPCApi.swift | 2 +- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/Sources/WordPressKit/Models/RemotePostParameters.swift b/Sources/WordPressKit/Models/RemotePostParameters.swift index ba22b6cd..90cda7ba 100644 --- a/Sources/WordPressKit/Models/RemotePostParameters.swift +++ b/Sources/WordPressKit/Models/RemotePostParameters.swift @@ -198,10 +198,14 @@ private enum RemotePostWordPressComCodingKeys: String, CodingKey { static let postTags = "post_tag" } -struct RemotePostCreateParametersWordPressComEncoder: Encodable { +public struct RemotePostCreateParametersWordPressComEncoder: Encodable { let parameters: RemotePostCreateParameters - func encode(to encoder: Encoder) throws { + public init(parameters: RemotePostCreateParameters) { + self.parameters = parameters + } + + public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: RemotePostWordPressComCodingKeys.self) try container.encodeIfPresent(parameters.type, forKey: .type) try container.encodeIfPresent(parameters.status, forKey: .status) @@ -281,10 +285,14 @@ struct RemotePostUpdateParametersWordPressComMetadata: Encodable { } } -struct RemotePostUpdateParametersWordPressComEncoder: Encodable { +public struct RemotePostUpdateParametersWordPressComEncoder: Encodable { let parameters: RemotePostUpdateParameters - func encode(to encoder: Encoder) throws { + public init(parameters: RemotePostUpdateParameters) { + self.parameters = parameters + } + + public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: RemotePostWordPressComCodingKeys.self) try container.encodeIfPresent(parameters.ifNotModifiedSince, forKey: .ifNotModifiedSince) @@ -348,10 +356,14 @@ private enum RemotePostXMLRPCCodingKeys: String, CodingKey { static let postTags = "post_tag" } -struct RemotePostCreateParametersXMLRPCEncoder: Encodable { +public struct RemotePostCreateParametersXMLRPCEncoder: Encodable { let parameters: RemotePostCreateParameters - func encode(to encoder: Encoder) throws { + public init(parameters: RemotePostCreateParameters) { + self.parameters = parameters + } + + public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: RemotePostXMLRPCCodingKeys.self) try container.encode(parameters.type, forKey: .type) try container.encodeIfPresent(parameters.status, forKey: .postStatus) @@ -387,10 +399,14 @@ struct RemotePostCreateParametersXMLRPCEncoder: Encodable { } } -struct RemotePostUpdateParametersXMLRPCEncoder: Encodable { +public struct RemotePostUpdateParametersXMLRPCEncoder: Encodable { let parameters: RemotePostUpdateParameters - func encode(to encoder: Encoder) throws { + public init(parameters: RemotePostUpdateParameters) { + self.parameters = parameters + } + + public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: RemotePostXMLRPCCodingKeys.self) try container.encodeIfPresent(parameters.ifNotModifiedSince, forKey: .ifNotModifiedSince) try container.encodeIfPresent(parameters.status, forKey: .postStatus) diff --git a/Sources/WordPressKit/WordPressAPI/DateFormatter+WordPressCom.swift b/Sources/WordPressKit/WordPressAPI/DateFormatter+WordPressCom.swift index 1bb03baf..a20a1775 100644 --- a/Sources/WordPressKit/WordPressAPI/DateFormatter+WordPressCom.swift +++ b/Sources/WordPressKit/WordPressAPI/DateFormatter+WordPressCom.swift @@ -3,7 +3,7 @@ extension DateFormatter { /// A `DateFormatter` configured to manage dates compatible with the WordPress.com API. /// /// - SeeAlso: [https://developer.wordpress.com/docs/api/](https://developer.wordpress.com/docs/api/) - static let wordPressCom: DateFormatter = { + public static let wordPressCom: DateFormatter = { let formatter = DateFormatter() formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ" formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) as TimeZone diff --git a/Sources/WordPressKit/WordPressAPI/HTTPRequestBuilder.swift b/Sources/WordPressKit/WordPressAPI/HTTPRequestBuilder.swift index c53cf9ca..bb26a907 100644 --- a/Sources/WordPressKit/WordPressAPI/HTTPRequestBuilder.swift +++ b/Sources/WordPressKit/WordPressAPI/HTTPRequestBuilder.swift @@ -5,8 +5,8 @@ import wpxmlrpc /// /// Calling this class's url related functions (the ones that changes path, query, etc) does not modify the /// original URL string. The URL will be perserved in the final result that's returned by the `build` function. -final class HTTPRequestBuilder { - enum Method: String, CaseIterable { +public final class HTTPRequestBuilder { + public enum Method: String, CaseIterable { case get = "GET" case post = "POST" case put = "PUT" diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index a0b9d605..64e875ad 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -360,7 +360,7 @@ open class WordPressComRestApi: NSObject { return configuration } - func perform( + public func perform( _ method: HTTPRequestBuilder.Method, URLString: String, parameters: [String: AnyObject]? = nil, diff --git a/Sources/WordPressKit/WordPressAPI/WordPressOrgXMLRPCApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressOrgXMLRPCApi.swift index 2698c89f..4bb825eb 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressOrgXMLRPCApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressOrgXMLRPCApi.swift @@ -180,7 +180,7 @@ open class WordPressOrgXMLRPCApi: NSObject { /// - Parameters: /// - streaming: set to `true` if there are large data (i.e. uploading files) in given `parameters`. `false` by default. /// - Returns: A `Result` type that contains the XMLRPC success or failure result. - func call(method: String, parameters: [AnyObject]?, fulfilling progress: Progress? = nil, streaming: Bool = false) async -> WordPressAPIResult, WordPressOrgXMLRPCApiFault> { + public func call(method: String, parameters: [AnyObject]?, fulfilling progress: Progress? = nil, streaming: Bool = false) async -> WordPressAPIResult, WordPressOrgXMLRPCApiFault> { let session = streaming ? uploadURLSession : urlSession let builder = HTTPRequestBuilder(url: endpoint) .method(.post) From eb13fb920919ca38b5b09ccb9e00cbb645b23c7a Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 08:30:22 +1000 Subject: [PATCH 03/17] Move `upload(...` definition before `perform(...` This is just a convenience refactor to make future diff clearer --- .../WordPressAPI/WordPressComRestApi.swift | 65 +++++++++---------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index 64e875ad..5fe6d288 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -360,6 +360,38 @@ open class WordPressComRestApi: NSObject { return configuration } + public func upload( + URLString: String, + parameters: [String: AnyObject]?, + fileParts: [FilePart], + requestEnqueued: RequestEnqueuedBlock? = nil, + fulfilling progress: Progress? = nil + ) async -> APIResult { + let builder: HTTPRequestBuilder + do { + let form = try fileParts.map { + try MultipartFormField(fileAtPath: $0.url.path, name: $0.parameterName, filename: $0.fileName, mimeType: $0.mimeType) + } + builder = try requestBuilder(URLString: URLString) + .method(.post) + .body(form: form) + } catch { + return .failure(.requestEncodingFailure(underlyingError: error)) + } + + return await perform( + request: builder.query(parameters ?? [:]), + fulfilling: progress, + decoder: { try JSONSerialization.jsonObject(with: $0) as AnyObject }, + taskCreated: { taskID in + DispatchQueue.main.async { + requestEnqueued?(NSNumber(value: taskID)) + } + }, + session: uploadURLSession + ) + } + public func perform( _ method: HTTPRequestBuilder.Method, URLString: String, @@ -443,39 +475,6 @@ open class WordPressComRestApi: NSObject { } } } - - public func upload( - URLString: String, - parameters: [String: AnyObject]?, - fileParts: [FilePart], - requestEnqueued: RequestEnqueuedBlock? = nil, - fulfilling progress: Progress? = nil - ) async -> APIResult { - let builder: HTTPRequestBuilder - do { - let form = try fileParts.map { - try MultipartFormField(fileAtPath: $0.url.path, name: $0.parameterName, filename: $0.fileName, mimeType: $0.mimeType) - } - builder = try requestBuilder(URLString: URLString) - .method(.post) - .body(form: form) - } catch { - return .failure(.requestEncodingFailure(underlyingError: error)) - } - - return await perform( - request: builder.query(parameters ?? [:]), - fulfilling: progress, - decoder: { try JSONSerialization.jsonObject(with: $0) as AnyObject }, - taskCreated: { taskID in - DispatchQueue.main.async { - requestEnqueued?(NSNumber(value: taskID)) - } - }, - session: uploadURLSession - ) - } - } // MARK: - Error processing From b56f5d344c54ea47bb4222a262160c4c9bddbcf2 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 08:31:38 +1000 Subject: [PATCH 04/17] Make a couple of properties used in `async` API `public` --- .../APIInterface/include/WordPressComRESTAPIInterfacing.h | 6 ++++++ Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Sources/APIInterface/include/WordPressComRESTAPIInterfacing.h b/Sources/APIInterface/include/WordPressComRESTAPIInterfacing.h index 1f652fd6..7901238d 100644 --- a/Sources/APIInterface/include/WordPressComRESTAPIInterfacing.h +++ b/Sources/APIInterface/include/WordPressComRESTAPIInterfacing.h @@ -6,6 +6,12 @@ @property (strong, nonatomic, readonly) NSURL * _Nonnull baseURL; +/// The key with which to specify locale in the parameters of a request. +@property (strong, nonatomic, readonly) NSString * _Nonnull localeKey; + +/// Whether the user's preferred language locale should be appended. +@property (nonatomic, readonly) BOOL appendsPreferredLanguageLocale; + /// - Note: `parameters` has `id` instead of the more common `NSObject *` as its value type so it will convert to `AnyObject` in Swift. /// In Swift, it's simpler to work with `AnyObject` than with `NSObject`. For example `"abc" as AnyObject` over `"abc" as NSObject`. - (NSProgress * _Nullable)get:(NSString * _Nonnull)URLString diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index 5fe6d288..7b81070a 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -95,7 +95,7 @@ open class WordPressComRestApi: NSObject { private let backgroundUploads: Bool - private let localeKey: String + public let localeKey: String @objc public let baseURL: URL From 6f046e151555683d37bf40068db778522736a9e2 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 08:41:22 +1000 Subject: [PATCH 05/17] Remove a stray double new line --- Sources/WordPressKit/WordPressAPI/WordPressAPIError.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/WordPressKit/WordPressAPI/WordPressAPIError.swift b/Sources/WordPressKit/WordPressAPI/WordPressAPIError.swift index 5a6c3d5f..508710f1 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressAPIError.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressAPIError.swift @@ -22,7 +22,6 @@ public enum WordPressAPIError: Error where EndpointError: Localiz /// Other error occured. case unknown(underlyingError: Error) - var response: HTTPURLResponse? { switch self { case .requestEncodingFailure, .connection, .unknown: From 54845218a473d5cbb5d2fe68500d1d705d20b9e0 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 08:41:38 +1000 Subject: [PATCH 06/17] Move `processError` to an extension on `WordPressComRESTAPIInterfacing` --- .../WordPressAPI/WordPressComRestApi.swift | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index 7b81070a..3fb955ef 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -458,7 +458,7 @@ open class WordPressComRestApi: NSObject { return HTTPAPIResponse(response: response.response, body: object) } .mapUnacceptableStatusCodeError { response, body in - if let error = self.processError(response: response, body: body, additionalUserInfo: nil) { + if let error = self.processError(response: response, body: body, additionalUserInfo: nil, invalidTokenHandler: invalidTokenHandler) { return error } @@ -479,9 +479,14 @@ open class WordPressComRestApi: NSObject { // MARK: - Error processing -extension WordPressComRestApi { +extension WordPressComRESTAPIInterfacing { - func processError(response httpResponse: HTTPURLResponse, body data: Data, additionalUserInfo: [String: Any]?) -> WordPressComRestApiEndpointError? { + func processError( + response httpResponse: HTTPURLResponse, + body data: Data, + additionalUserInfo: [String: Any]?, + invalidTokenHandler: (() -> Void)? + ) -> WordPressComRestApiEndpointError? { // Not sure if it's intentional to include 500 status code, but the code seems to be there from the very beginning. // https://github.com/wordpress-mobile/WordPressKit-iOS/blob/1.0.1/WordPressKit/WordPressComRestApi.swift#L374 guard (400...500).contains(httpResponse.statusCode) else { @@ -527,7 +532,7 @@ extension WordPressComRestApi { if mappedError == .invalidToken { // Call `invalidTokenHandler in the main thread since it's typically used by the apps to present an authentication UI. DispatchQueue.main.async { - self.invalidTokenHandler?() + invalidTokenHandler?() } } From 64e769828c21bc0328dbd175af7c4f398738af3e Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 08:42:53 +1000 Subject: [PATCH 07/17] Require `URLSession` in root `async` `perform` method --- Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index 3fb955ef..7713d355 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -440,7 +440,7 @@ open class WordPressComRestApi: NSObject { } } - return await perform(request: builder, fulfilling: progress, decoder: decoder) + return await perform(request: builder, fulfilling: progress, decoder: decoder, session: urlSession) } private func perform( @@ -448,9 +448,9 @@ open class WordPressComRestApi: NSObject { fulfilling progress: Progress?, decoder: @escaping (Data) throws -> T, taskCreated: ((Int) -> Void)? = nil, - session: URLSession? = nil + session: URLSession ) async -> APIResult { - await (session ?? self.urlSession) + await session .perform(request: request, taskCreated: taskCreated, fulfilling: progress, errorType: WordPressComRestApiEndpointError.self) .mapSuccess { response -> HTTPAPIResponse in let object = try decoder(response.body) From 5f2c8fdbd96b08d8b38eeaf080d07d977f46a0b2 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 08:43:46 +1000 Subject: [PATCH 08/17] Move `session` argument before `taskCreated` As per Swift API naming guidelines on arguments with default values --- .../WordPressKit/WordPressAPI/WordPressComRestApi.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index 7713d355..7b00a908 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -383,12 +383,12 @@ open class WordPressComRestApi: NSObject { request: builder.query(parameters ?? [:]), fulfilling: progress, decoder: { try JSONSerialization.jsonObject(with: $0) as AnyObject }, + session: uploadURLSession, taskCreated: { taskID in DispatchQueue.main.async { requestEnqueued?(NSNumber(value: taskID)) } - }, - session: uploadURLSession + } ) } @@ -447,8 +447,8 @@ open class WordPressComRestApi: NSObject { request: HTTPRequestBuilder, fulfilling progress: Progress?, decoder: @escaping (Data) throws -> T, - taskCreated: ((Int) -> Void)? = nil, - session: URLSession + session: URLSession, + taskCreated: ((Int) -> Void)? = nil ) async -> APIResult { await session .perform(request: request, taskCreated: taskCreated, fulfilling: progress, errorType: WordPressComRestApiEndpointError.self) From 38c2e251bb95bbe115ea58f359b12897d907a4ff Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 08:47:25 +1000 Subject: [PATCH 09/17] Require `invalidTokenHandler` in `perform` --- .../WordPressAPI/WordPressComRestApi.swift | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index 7b00a908..0157e6d6 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -384,6 +384,7 @@ open class WordPressComRestApi: NSObject { fulfilling: progress, decoder: { try JSONSerialization.jsonObject(with: $0) as AnyObject }, session: uploadURLSession, + invalidTokenHandler: invalidTokenHandler, taskCreated: { taskID in DispatchQueue.main.async { requestEnqueued?(NSNumber(value: taskID)) @@ -440,7 +441,13 @@ open class WordPressComRestApi: NSObject { } } - return await perform(request: builder, fulfilling: progress, decoder: decoder, session: urlSession) + return await perform( + request: builder, + fulfilling: progress, + decoder: decoder, + session: urlSession, + invalidTokenHandler: invalidTokenHandler + ) } private func perform( @@ -448,6 +455,7 @@ open class WordPressComRestApi: NSObject { fulfilling progress: Progress?, decoder: @escaping (Data) throws -> T, session: URLSession, + invalidTokenHandler: (() -> Void)?, taskCreated: ((Int) -> Void)? = nil ) async -> APIResult { await session From e4f566b5c26a64e97a5df86f183b9ec2ec84be29 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 08:50:27 +1000 Subject: [PATCH 10/17] Move root `perform` definition to `WordPressComRESTAPIInterfacing` --- .../WordPressKit/WordPressAPI/WordPressComRestApi.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index 0157e6d6..d4172bf9 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -449,15 +449,18 @@ open class WordPressComRestApi: NSObject { invalidTokenHandler: invalidTokenHandler ) } +} - private func perform( +extension WordPressComRESTAPIInterfacing { + + func perform( request: HTTPRequestBuilder, fulfilling progress: Progress?, decoder: @escaping (Data) throws -> T, session: URLSession, invalidTokenHandler: (() -> Void)?, taskCreated: ((Int) -> Void)? = nil - ) async -> APIResult { + ) async -> WordPressAPIResult, WordPressComRestApiEndpointError> { await session .perform(request: request, taskCreated: taskCreated, fulfilling: progress, errorType: WordPressComRestApiEndpointError.self) .mapSuccess { response -> HTTPAPIResponse in From 23bc2abba2224564a94e0e07e1616b92d4e3da1a Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 09:05:12 +1000 Subject: [PATCH 11/17] Extract logic to create builder with locale to extension --- .../WordPressAPI/WordPressComRestApi.swift | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index d4172bf9..d3a165cf 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -307,18 +307,14 @@ open class WordPressComRestApi: NSObject { } private func requestBuilder(URLString: String) throws -> HTTPRequestBuilder { - guard let url = URL(string: URLString, relativeTo: baseURL) else { - throw URLError(.badURL) - } - - var builder = HTTPRequestBuilder(url: url) - + let locale: (String, String)? if appendsPreferredLanguageLocale { - let preferredLanguageIdentifier = WordPressComLanguageDatabase().deviceLanguage.slug - builder = builder.query(defaults: [URLQueryItem(name: localeKey, value: preferredLanguageIdentifier)]) + locale = (localeKey, WordPressComLanguageDatabase().deviceLanguage.slug) + } else { + locale = nil } - return builder + return try HTTPRequestBuilder.with(URLString: URLString, relativeTo: baseURL, appendingLocale: locale) } @objc public func temporaryFileURL(withExtension fileExtension: String) -> URL { @@ -579,6 +575,28 @@ extension WordPressComRESTAPIInterfacing { ) } } + +extension HTTPRequestBuilder { + + static func with( + URLString: String, + relativeTo baseURL: URL, + appendingLocale locale: (key: String, value: String)? + ) throws -> HTTPRequestBuilder { + guard let url = URL(string: URLString, relativeTo: baseURL) else { + throw URLError(.badURL) + } + + let builder = Self.init(url: url) + + guard let locale else { + return builder + } + + return builder.query(defaults: [URLQueryItem(name: locale.key, value: locale.value)]) + } + +} // MARK: - Anonymous API support extension WordPressComRestApi { From 8d0d3dfe7289aa7a8cf968164a2b28d3cc966c53 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 09:16:16 +1000 Subject: [PATCH 12/17] Add new `localeValue` property to `WordPressComRESTAPIInterfacing` --- .../include/WordPressComRESTAPIInterfacing.h | 10 ++++++++-- .../WordPressAPI/WordPressComRestApi.swift | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Sources/APIInterface/include/WordPressComRESTAPIInterfacing.h b/Sources/APIInterface/include/WordPressComRESTAPIInterfacing.h index 7901238d..35abe211 100644 --- a/Sources/APIInterface/include/WordPressComRESTAPIInterfacing.h +++ b/Sources/APIInterface/include/WordPressComRESTAPIInterfacing.h @@ -6,11 +6,17 @@ @property (strong, nonatomic, readonly) NSURL * _Nonnull baseURL; +/// Whether the user's preferred language locale should be appended to the request. +/// Should default to `true`. +/// +/// - SeeAlso: `localeKey` and `localeValue` to configure the locale appendend to the request. +@property (nonatomic, readonly) BOOL appendsPreferredLanguageLocale; + /// The key with which to specify locale in the parameters of a request. @property (strong, nonatomic, readonly) NSString * _Nonnull localeKey; -/// Whether the user's preferred language locale should be appended. -@property (nonatomic, readonly) BOOL appendsPreferredLanguageLocale; +/// The value with which to specify locale in the parameters of a request. +@property (strong, nonatomic, readonly) NSString * _Nonnull localeValue; /// - Note: `parameters` has `id` instead of the more common `NSObject *` as its value type so it will convert to `AnyObject` in Swift. /// In Swift, it's simpler to work with `AnyObject` than with `NSObject`. For example `"abc" as AnyObject` over `"abc" as NSObject`. diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index d3a165cf..1bb2976f 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -97,6 +97,10 @@ open class WordPressComRestApi: NSObject { public let localeKey: String + public var localeValue: String { + WordPressComLanguageDatabase().deviceLanguage.slug + } + @objc public let baseURL: URL private var invalidTokenHandler: (() -> Void)? From bc6dcd15ccd81eec64a7a14ae0df1693b9c46278 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 09:16:43 +1000 Subject: [PATCH 13/17] Move request builder to `WordPressComRESTAPIInterfacing` extension --- .../WordPressAPI/WordPressComRestApi.swift | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index 1bb2976f..579b632b 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -310,17 +310,6 @@ open class WordPressComRestApi: NSObject { return "\(String(describing: oAuthToken)),\(String(describing: userAgent))".hashValue } - private func requestBuilder(URLString: String) throws -> HTTPRequestBuilder { - let locale: (String, String)? - if appendsPreferredLanguageLocale { - locale = (localeKey, WordPressComLanguageDatabase().deviceLanguage.slug) - } else { - locale = nil - } - - return try HTTPRequestBuilder.with(URLString: URLString, relativeTo: baseURL, appendingLocale: locale) - } - @objc public func temporaryFileURL(withExtension fileExtension: String) -> URL { assert(!fileExtension.isEmpty, "file Extension cannot be empty") let fileName = "\(ProcessInfo.processInfo.globallyUniqueString)_file.\(fileExtension)" @@ -427,8 +416,7 @@ open class WordPressComRestApi: NSObject { ) async -> APIResult { var builder: HTTPRequestBuilder do { - builder = try requestBuilder(URLString: URLString) - .method(method) + builder = try requestBuilder(URLString: URLString).method(method) } catch { return .failure(.requestEncodingFailure(underlyingError: error)) } @@ -486,6 +474,17 @@ extension WordPressComRESTAPIInterfacing { } } } + + func requestBuilder(URLString: String) throws -> HTTPRequestBuilder { + let locale: (String, String)? + if appendsPreferredLanguageLocale { + locale = (localeKey, localeValue) + } else { + locale = nil + } + + return try HTTPRequestBuilder.with(URLString: URLString, relativeTo: baseURL, appendingLocale: locale) + } } // MARK: - Error processing From f47621a41a17540f4f86a4db20d2a906a9983cae Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 09:20:35 +1000 Subject: [PATCH 14/17] Redefine `APIResult` typealias in the context of `WPComRESTAPIInterfacing` --- Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index 579b632b..3287a956 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -441,6 +441,8 @@ open class WordPressComRestApi: NSObject { extension WordPressComRESTAPIInterfacing { + public typealias APIResult = WordPressAPIResult, WordPressComRestApiEndpointError> + func perform( request: HTTPRequestBuilder, fulfilling progress: Progress?, @@ -448,7 +450,7 @@ extension WordPressComRESTAPIInterfacing { session: URLSession, invalidTokenHandler: (() -> Void)?, taskCreated: ((Int) -> Void)? = nil - ) async -> WordPressAPIResult, WordPressComRestApiEndpointError> { + ) async -> APIResult { await session .perform(request: request, taskCreated: taskCreated, fulfilling: progress, errorType: WordPressComRestApiEndpointError.self) .mapSuccess { response -> HTTPAPIResponse in From 70cbfd016bf91888b7c67fa1574331677689498b Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 09:39:38 +1000 Subject: [PATCH 15/17] Move `urlSession` and `invalidTokenHandler` to API interface protocol --- .../APIInterface/include/WordPressComRESTAPIInterfacing.h | 4 ++++ .../WordPressKit/WordPressAPI/WordPressComRestApi.swift | 7 ++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Sources/APIInterface/include/WordPressComRESTAPIInterfacing.h b/Sources/APIInterface/include/WordPressComRESTAPIInterfacing.h index 35abe211..5590ba14 100644 --- a/Sources/APIInterface/include/WordPressComRESTAPIInterfacing.h +++ b/Sources/APIInterface/include/WordPressComRESTAPIInterfacing.h @@ -18,6 +18,10 @@ /// The value with which to specify locale in the parameters of a request. @property (strong, nonatomic, readonly) NSString * _Nonnull localeValue; +@property (strong, nonatomic, readonly) NSURLSession * _Nonnull urlSession; + +@property (strong, nonatomic, readonly) void (^ _Nullable invalidTokenHandler)(void); + /// - Note: `parameters` has `id` instead of the more common `NSObject *` as its value type so it will convert to `AnyObject` in Swift. /// In Swift, it's simpler to work with `AnyObject` than with `NSObject`. For example `"abc" as AnyObject` over `"abc" as NSObject`. - (NSProgress * _Nullable)get:(NSString * _Nonnull)URLString diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index 3287a956..d5ae17b4 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -103,7 +103,7 @@ open class WordPressComRestApi: NSObject { @objc public let baseURL: URL - private var invalidTokenHandler: (() -> Void)? + public var invalidTokenHandler: (() -> Void)? /** Configure whether or not the user's preferred language locale should be appended. Defaults to true. @@ -177,9 +177,6 @@ open class WordPressComRestApi: NSObject { } } - @objc func setInvalidTokenHandler(_ handler: @escaping () -> Void) { - invalidTokenHandler = handler - } // MARK: Network requests @@ -319,7 +316,7 @@ open class WordPressComRestApi: NSObject { // MARK: - Async - private lazy var urlSession: URLSession = { + public lazy var urlSession: URLSession = { URLSession(configuration: sessionConfiguration(background: false)) }() From 7d8877b7c7f4b9307647305b22c4e57647e8437f Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 10 Apr 2024 09:41:01 +1000 Subject: [PATCH 16/17] Move a couple more `perform` types to API protocol --- .../WordPressAPI/WordPressComRestApi.swift | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index d5ae17b4..c75407ef 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -379,17 +379,6 @@ open class WordPressComRestApi: NSObject { ) } - public func perform( - _ method: HTTPRequestBuilder.Method, - URLString: String, - parameters: [String: AnyObject]? = nil, - fulfilling progress: Progress? = nil - ) async -> APIResult { - await perform(method, URLString: URLString, parameters: parameters, fulfilling: progress) { - try (JSONSerialization.jsonObject(with: $0) as AnyObject) - } - } - func perform( _ method: HTTPRequestBuilder.Method, URLString: String, @@ -403,8 +392,25 @@ open class WordPressComRestApi: NSObject { return try decoder.decode(type, from: $0) } } +} + +extension WordPressComRESTAPIInterfacing { + + public typealias APIResult = WordPressAPIResult, WordPressComRestApiEndpointError> + + public func perform( + _ method: HTTPRequestBuilder.Method, + URLString: String, + parameters: [String: AnyObject]? = nil, + fulfilling progress: Progress? = nil + ) async -> APIResult { + await perform(method, URLString: URLString, parameters: parameters, fulfilling: progress) { + try (JSONSerialization.jsonObject(with: $0) as AnyObject) + } + } - private func perform( + // FIXME: This was private. It became public during the extraction. Consider whether to make it privated once done. + public func perform( _ method: HTTPRequestBuilder.Method, URLString: String, parameters: [String: AnyObject]?, @@ -434,13 +440,9 @@ open class WordPressComRestApi: NSObject { invalidTokenHandler: invalidTokenHandler ) } -} - -extension WordPressComRESTAPIInterfacing { - - public typealias APIResult = WordPressAPIResult, WordPressComRestApiEndpointError> - func perform( + // FIXME: This was private. It became public during the extraction. Consider whether to make it privated once done. + public func perform( request: HTTPRequestBuilder, fulfilling progress: Progress?, decoder: @escaping (Data) throws -> T, From 19357f4ff9ed828f5226b6c884c0b96bcacdc5a7 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Sat, 13 Apr 2024 07:46:42 +1000 Subject: [PATCH 17/17] Remove a stray double new line --- Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift index c75407ef..677834a1 100644 --- a/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift +++ b/Sources/WordPressKit/WordPressAPI/WordPressComRestApi.swift @@ -177,7 +177,6 @@ open class WordPressComRestApi: NSObject { } } - // MARK: Network requests /**