Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.
Closed
15 changes: 15 additions & 0 deletions Sources/WordPressKit/Exports.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@_exported import WordPressKitModels
@_exported import WordPressKitObjC
@_exported import WordPressKitObjCUtils

extension ServiceRemoteWordPressComREST {
public var wordPressComRestApi: WordPressComRestApi {
self.wordPressComRESTAPI as! WordPressComRestApi
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have to use an interface type in the ServiceRemoteWordPressComREST.h, because the implementation is in the Swift WordPressKit module.

In practice, WordPressComRestApi is the only acceptable instance to create ServiceRemoteWordPressComREST, so, we'll do a little bit hack here to force cast in runtime.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the WordPressOrgXMLRPCApi property below.

}

extension ServiceRemoteWordPressXMLRPC {
public var xmlrpcApi: WordPressOrgXMLRPCApi {
self.api as! WordPressOrgXMLRPCApi
}
}
8 changes: 0 additions & 8 deletions Sources/WordPressKit/NotificationSettingsServiceRemote.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,6 @@ import WordPressKitObjC
/// Here we'll deal mostly with the Settings / Push Notifications API.
///
open class NotificationSettingsServiceRemote: ServiceRemoteWordPressComREST {
/// Designated Initializer. Fails if the remoteApi is nil.
///
/// - Parameter wordPressComRestApi: A Reference to the WordPressComRestApi that should be used to interact with WordPress.com
///
public override init(wordPressComRestApi: WordPressComRestApi) {
super.init(wordPressComRestApi: wordPressComRestApi)
}

/// Retrieves all of the Notification Settings
///
/// - Parameters:
Expand Down
2 changes: 1 addition & 1 deletion Sources/WordPressKit/PostServiceRemoteREST.swift

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to translate this function to Swift, because it's used in a Swift module. I'll explain a little bit more of why this is needed in the upcoming app PR (which would provide a full context).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. We'll just need to make sure we test the features that needed rewrite.

Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ extension PostServiceRemoteREST {
parameters["exclude"] = excludeUserIDs
}

wordPressComRestAPI.get(requestUrl,
wordPressComRESTAPI.get(requestUrl,
parameters: parameters,
success: { (responseObject, httpResponse) in
if let success {
Expand Down
8 changes: 4 additions & 4 deletions Sources/WordPressKit/PostServiceRemoteXMLRPC+Extended.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import WordPressKitObjC
extension PostServiceRemoteXMLRPC: PostServiceRemoteExtended {
public func post(withID postID: Int) async throws -> RemotePost {
let parameters = xmlrpcArguments(withExtra: postID) as [AnyObject]
let result = await api.call(method: "wp.getPost", parameters: parameters)
let result = await xmlrpcApi.call(method: "wp.getPost", parameters: parameters)
switch result {
case .success(let response):
return try await decodePost(from: response.body)
Expand All @@ -20,7 +20,7 @@ extension PostServiceRemoteXMLRPC: PostServiceRemoteExtended {
public func createPost(with parameters: RemotePostCreateParameters) async throws -> RemotePost {
let dictionary = try makeParameters(from: RemotePostCreateParametersXMLRPCEncoder(parameters: parameters))
let parameters = xmlrpcArguments(withExtra: dictionary) as [AnyObject]
let response = try await api.call(method: "wp.newPost", parameters: parameters).get()
let response = try await xmlrpcApi.call(method: "wp.newPost", parameters: parameters).get()
guard let postID = (response.body as? NSObject)?.wpkit_numericValue() else {
throw URLError(.unknown) // Should never happen
}
Expand All @@ -30,7 +30,7 @@ extension PostServiceRemoteXMLRPC: PostServiceRemoteExtended {
public func patchPost(withID postID: Int, parameters: RemotePostUpdateParameters) async throws -> RemotePost {
let dictionary = try makeParameters(from: RemotePostUpdateParametersXMLRPCEncoder(parameters: parameters))
let parameters = xmlrpcArguments(withExtraDefaults: [postID as NSNumber], andExtra: dictionary) as [AnyObject]
let result = await api.call(method: "wp.editPost", parameters: parameters)
let result = await xmlrpcApi.call(method: "wp.editPost", parameters: parameters)
switch result {
case .success:
return try await post(withID: postID)
Expand All @@ -48,7 +48,7 @@ extension PostServiceRemoteXMLRPC: PostServiceRemoteExtended {

public func deletePost(withID postID: Int) async throws {
let parameters = xmlrpcArguments(withExtra: postID) as [AnyObject]
let result = await api.call(method: "wp.deletePost", parameters: parameters)
let result = await xmlrpcApi.call(method: "wp.deletePost", parameters: parameters)
switch result {
case .success:
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ extension ReaderTopicServiceRemote {
public func pathForTopic(slug: String) -> String {
let endpoint = path(forEndpoint: "read/tags/\(slug)/posts", withVersion: ._1_2)

return wordPressComRESTAPI.baseURL.appendingPathComponent(endpoint).absoluteString
return wordPressComRestApi.baseURL.appendingPathComponent(endpoint).absoluteString
}
}
23 changes: 23 additions & 0 deletions Sources/WordPressKit/WordPressComRestApi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -682,4 +682,27 @@ extension WordPressComRestApi: WordPressComRESTAPIInterfacing {
failure: failure as FailureReponseBlock
)
}

@objc public func unknownResponseError() -> any Error {
NSError(
domain: WordPressComRestApiEndpointError.errorDomain,
code: WordPressComRestApiErrorCode.unknown.rawValue,
userInfo: [
WordPressComRestApi.ErrorKeyErrorMessage: NSLocalizedString("Unknown error", comment: "Unknown error"),
NSLocalizedDescriptionKey: NSLocalizedString("Unknown error", comment: "Unknown error")
]
)
}

@objc public func uploadFailedErrorCode() -> Int {
WordPressComRestApiErrorCode.uploadFailed.rawValue
}

@objc public func errorCodeKey() -> String {
Self.ErrorKeyErrorCode
}

@objc public func errorMessageKey() -> String {
Self.ErrorKeyErrorMessage
}
}
27 changes: 15 additions & 12 deletions Sources/WordPressKit/WordPressOrgXMLRPCApi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import Foundation
import wpxmlrpc

/// Class to connect to the XMLRPC API on self hosted sites.
open class WordPressOrgXMLRPCApi: NSObject {
public typealias SuccessResponseBlock = (AnyObject, HTTPURLResponse?) -> Void
public typealias FailureReponseBlock = (_ error: NSError, _ httpResponse: HTTPURLResponse?) -> Void
open class WordPressOrgXMLRPCApi: NSObject, WordPressOrgXMLRPCApiInterfacing {
public typealias SuccessResponseBlock = (Any, HTTPURLResponse?) -> Void
public typealias FailureReponseBlock = (_ error: any Error, _ httpResponse: HTTPURLResponse?) -> Void

@available(*, deprecated, message: "This property is no longer being used because WordPressKit now sends all HTTP requests using `URLSession` directly.")
public static var useURLSession = true
Expand Down Expand Up @@ -126,10 +126,12 @@ open class WordPressOrgXMLRPCApi: NSObject {
returns nil it's because something happened on the request serialization and the network request was not started, but the failure callback
will be invoked with the error specificing the serialization issues.
*/
@objc @discardableResult open func callMethod(_ method: String,
parameters: [AnyObject]?,
success: @escaping SuccessResponseBlock,
failure: @escaping FailureReponseBlock) -> Progress? {
@objc @discardableResult open func callMethod(
_ method: String,
parameters: [Any]?,
success: @escaping (Any, HTTPURLResponse?) -> Void,
failure: @escaping (any Error, HTTPURLResponse?) -> Void
) -> Progress {
let progress = Progress.discreteProgress(totalUnitCount: 100)
Task { @MainActor in
let result = await self.call(method: method, parameters: parameters, fulfilling: progress, streaming: false)
Expand All @@ -156,10 +158,11 @@ open class WordPressOrgXMLRPCApi: NSObject {
returns nil it's because something happened on the request serialization and the network request was not started, but the failure callback
will be invoked with the error specificing the serialization issues.
*/
@objc @discardableResult open func streamCallMethod(_ method: String,
parameters: [AnyObject]?,
success: @escaping SuccessResponseBlock,
failure: @escaping FailureReponseBlock) -> Progress? {
@objc @discardableResult open func streamCallMethod(
_ method: String, parameters: [Any]?,
success: @escaping (Any, HTTPURLResponse?) -> Void,
failure: @escaping (any Error, HTTPURLResponse?) -> Void
) -> Progress {
let progress = Progress.discreteProgress(totalUnitCount: 100)
Task { @MainActor in
let result = await self.call(method: method, parameters: parameters, fulfilling: progress, streaming: true)
Expand All @@ -184,7 +187,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<HTTPAPIResponse<AnyObject>, WordPressOrgXMLRPCApiFault> {
func call(method: String, parameters: [Any]?, fulfilling progress: Progress? = nil, streaming: Bool = false) async -> WordPressAPIResult<HTTPAPIResponse<AnyObject>, WordPressOrgXMLRPCApiFault> {
let session = streaming ? uploadURLSession : urlSession
let builder = HTTPRequestBuilder(url: endpoint)
.method(.post)
Expand Down
4 changes: 2 additions & 2 deletions Sources/WordPressKit/WordPressOrgXMLRPCValidator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ open class WordPressOrgXMLRPCValidator: NSObject {
}, failure: { (error, httpResponse) in
if httpResponse?.url != url {
// we where redirected, let's check the answer content
if let data = error.userInfo[WordPressOrgXMLRPCApi.WordPressOrgXMLRPCApiErrorKeyData as String] as? Data,
if let data = (error as NSError).userInfo[WordPressOrgXMLRPCApi.WordPressOrgXMLRPCApiErrorKeyData as String] as? Data,
let responseString = String(data: data, encoding: String.Encoding.utf8), responseString.range(of: "<meta name=\"GENERATOR\" content=\"www.dudamobile.com\">") != nil
|| responseString.range(of: "dm404Container") != nil {
failure(WordPressOrgXMLRPCValidatorError.mobilePluginRedirectedError as NSError)
Expand All @@ -255,7 +255,7 @@ open class WordPressOrgXMLRPCValidator: NSObject {
case .some(WordPressOrgXMLRPCValidatorError.blocked.rawValue):
failure(WordPressOrgXMLRPCValidatorError.blocked as NSError)
default:
failure(error)
failure(error as NSError)
}
})
}
Expand Down
12 changes: 3 additions & 9 deletions Sources/WordPressKitObjC/MediaServiceRemoteREST.m
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ - (NSError *)processMediaUploadErrors:(NSArray *)errorList {
}
NSDictionary *errorDictionary = @{NSLocalizedDescriptionKey: errorMessage};
error = [[NSError alloc] initWithDomain:WordPressComRestApiErrorDomain
code:WordPressComRestApiErrorCodeUploadFailed
code:self.wordPressComRESTAPI.uploadFailedErrorCode
userInfo:errorDictionary];
}
return error;
Expand Down Expand Up @@ -302,10 +302,7 @@ - (void)deleteMedia:(RemoteMedia *)media
}
} else {
if (failure) {
NSError *error = [[NSError alloc] initWithDomain:WordPressComRestApiErrorDomain
code:WordPressComRestApiErrorCodeUnknown
userInfo:nil];
failure(error);
failure(self.wordPressComRESTAPI.unknownResponseError);
}
}
} failure:^(NSError *error, NSHTTPURLResponse *response) {
Expand Down Expand Up @@ -375,10 +372,7 @@ -(void)getVideoPressToken:(NSString *)videoPressID
}
} else {
if (failure) {
NSError *error = [[NSError alloc] initWithDomain:WordPressComRestApiErrorDomain
code:WordPressComRestApiErrorCodeUnknown
userInfo:nil];
failure(error);
failure(self.wordPressComRESTAPI.unknownResponseError);
}
}
} failure:^(NSError *error, NSHTTPURLResponse *response) {
Expand Down
1 change: 1 addition & 0 deletions Sources/WordPressKitObjC/PostServiceRemoteXMLRPC.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#import "WPMapFilterReduce.h"
#import "DisplayableImageHelper.h"

@import WordPressKitModels;
@import NSObject_SafeExpectations;

const NSInteger HTTP404ErrorCode = 404;
Expand Down
7 changes: 2 additions & 5 deletions Sources/WordPressKitObjC/ServiceRemoteWordPressComREST.m
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
#import "ServiceRemoteWordPressComREST.h"
#import "WordPressComRESTAPIVersionedPathBuilder.h"

@implementation ServiceRemoteWordPressComREST

- (instancetype)initWithWordPressComRestApi:(WordPressComRestApi *)wordPressComRestApi {

NSParameterAssert([wordPressComRestApi isKindOfClass:[WordPressComRestApi class]]);

- (instancetype)initWithWordPressComRestApi:(id<WordPressComRESTAPIInterfacing>)wordPressComRestApi {
self = [super init];
if (self) {
_wordPressComRestApi = wordPressComRestApi;
_wordPressComRESTAPI = wordPressComRestApi;
}
return self;
Expand Down
4 changes: 2 additions & 2 deletions Sources/WordPressKitObjC/ServiceRemoteWordPressXMLRPC.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

@interface ServiceRemoteWordPressXMLRPC()

@property (nonatomic, strong, readwrite) WordPressOrgXMLRPCApi *api;
@property (nonatomic, strong, readwrite) id<WordPressOrgXMLRPCApiInterfacing> api;
@property (nonatomic, copy) NSString *username;
@property (nonatomic, copy) NSString *password;

@end

@implementation ServiceRemoteWordPressXMLRPC

- (id)initWithApi:(WordPressOrgXMLRPCApi *)api username:(NSString *)username password:(NSString *)password
- (id)initWithApi:(id<WordPressOrgXMLRPCApiInterfacing>)api username:(NSString *)username password:(NSString *)password
{
NSParameterAssert(api != nil);
NSParameterAssert(username != nil);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ @interface SiteServiceRemoteWordPressComREST ()

@implementation SiteServiceRemoteWordPressComREST

- (instancetype)initWithWordPressComRestApi:(WordPressComRestApi *)api siteID:(NSNumber *)siteID {
- (instancetype)initWithWordPressComRestApi:(id<WordPressComRESTAPIInterfacing>)api siteID:(NSNumber *)siteID {
self = [super initWithWordPressComRestApi:api];
if (self) {
_siteID = siteID;
Expand Down
20 changes: 6 additions & 14 deletions Sources/WordPressKitObjC/WordPressComServiceRemote.m
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,7 @@ - (void)createWPComBlogWithUrl:(NSString *)blogUrl
void (^successBlock)(id, NSHTTPURLResponse *) = ^(id responseObject, NSHTTPURLResponse *httpResponse) {
NSDictionary *response = responseObject;
if ([response count] == 0) {
// There was an error creating the blog as a successful call yields a dictionary back.
NSString *localizedErrorMessage = NSLocalizedString(@"Unknown error", nil);
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
userInfo[WordPressComRestApi.ErrorKeyErrorMessage] = localizedErrorMessage;
userInfo[NSLocalizedDescriptionKey] = localizedErrorMessage;
NSError *errorWithLocalizedMessage = [[NSError alloc] initWithDomain:WordPressComRestApiErrorDomain
code:WordPressComRestApiErrorCodeUnknown
userInfo:userInfo];
failure(errorWithLocalizedMessage);
failure([self.wordPressComRESTAPI unknownResponseError]);
} else {
success(responseObject);
}
Expand Down Expand Up @@ -230,13 +222,13 @@ - (void)createWPComBlogWithUrl:(NSString *)blogUrl
- (NSError *)errorWithLocalizedMessage:(NSError *)error {
NSError *errorWithLocalizedMessage = error;
if ([error.domain isEqual:WordPressComRestApiErrorDomain] &&
[error.userInfo objectForKey:WordPressComRestApi.ErrorKeyErrorCode] != nil) {
[error.userInfo objectForKey:self.wordPressComRESTAPI.errorCodeKey] != nil) {

NSString *localizedErrorMessage = [self errorMessageForError:error];
NSString *errorCode = [error.userInfo objectForKey:WordPressComRestApi.ErrorKeyErrorCode];
NSString *errorCode = [error.userInfo objectForKey:self.wordPressComRESTAPI.errorCodeKey];
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:error.userInfo];
userInfo[WordPressComRestApi.ErrorKeyErrorCode] = errorCode;
userInfo[WordPressComRestApi.ErrorKeyErrorMessage] = localizedErrorMessage;
userInfo[self.wordPressComRESTAPI.errorCodeKey] = errorCode;
userInfo[self.wordPressComRESTAPI.errorMessageKey] = localizedErrorMessage;
userInfo[NSLocalizedDescriptionKey] = localizedErrorMessage;
errorWithLocalizedMessage = [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:userInfo];
}
Expand All @@ -245,7 +237,7 @@ - (NSError *)errorWithLocalizedMessage:(NSError *)error {

- (NSString *)errorMessageForError:(NSError *)error
{
NSString *errorCode = [error.userInfo stringForKey:WordPressComRestApi.ErrorKeyErrorCode];
NSString *errorCode = [error.userInfo stringForKey:self.wordPressComRESTAPI.errorCodeKey];
NSString *errorMessage = [[error.userInfo stringForKey:NSLocalizedDescriptionKey] wpkit_stringByStrippingHTML];

if ([errorCode isEqualToString:@"username_only_lowercase_letters_and_numbers"]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
#import "WordPressComRESTAPIInterfacing.h"
#import "WordPressComRESTAPIVersion.h"

@class WordPressComRestApi;

NS_ASSUME_NONNULL_BEGIN

/**
Expand All @@ -12,12 +10,6 @@ NS_ASSUME_NONNULL_BEGIN
*/
@interface ServiceRemoteWordPressComREST : NSObject

/**
* @brief The API object to use for communications.
*/
// TODO: This needs to go before being able to put this ObjC in a package.
@property (nonatomic, strong, readonly) WordPressComRestApi *wordPressComRestApi;

/**
* @brief The interface to the WordPress.com API to use for performing REST requests.
* This is meant to gradually replace `wordPressComRestApi`.
Expand All @@ -31,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
*
* @returns The initialized object.
*/
- (instancetype)initWithWordPressComRestApi:(WordPressComRestApi *)api;
- (instancetype)initWithWordPressComRestApi:(id<WordPressComRESTAPIInterfacing>)api;

#pragma mark - Request URL construction

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
#import <Foundation/Foundation.h>

@class WordPressOrgXMLRPCApi;
#import "WordPressOrgXMLRPCApiInterfacing.h"

NS_ASSUME_NONNULL_BEGIN

@interface ServiceRemoteWordPressXMLRPC : NSObject

- (id)initWithApi:(WordPressOrgXMLRPCApi *)api username:(NSString *)username password:(NSString *)password;
- (id)initWithApi:(id<WordPressOrgXMLRPCApiInterfacing>)api username:(NSString *)username password:(NSString *)password;

@property (nonatomic, readonly) WordPressOrgXMLRPCApi *api;
@property (nonatomic, readonly) id<WordPressOrgXMLRPCApiInterfacing> api;

- (NSArray *)defaultXMLRPCArguments;
- (NSArray *)XMLRPCArgumentsWithExtra:(_Nullable id)extra;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ NS_ASSUME_NONNULL_BEGIN

@property (nonatomic, readonly) NSNumber *siteID;

- (instancetype)initWithWordPressComRestApi:(WordPressComRestApi *)api __unavailable;
- (instancetype)initWithWordPressComRestApi:(WordPressComRestApi *)api siteID:(NSNumber *)siteID;
- (instancetype)initWithWordPressComRestApi:(id<WordPressComRESTAPIInterfacing>)api __unavailable;
- (instancetype)initWithWordPressComRestApi:(id<WordPressComRESTAPIInterfacing>)api siteID:(NSNumber *)siteID;

@end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,9 @@
success:(void (^ _Nonnull)(id _Nonnull, NSHTTPURLResponse * _Nullable))success
failure:(void (^ _Nonnull)(NSError * _Nonnull, NSHTTPURLResponse * _Nullable))failure;

- (NSError * _Nonnull)unknownResponseError;
- (NSInteger)uploadFailedErrorCode;
- (NSString * _Nonnull)errorCodeKey;
- (NSString * _Nonnull)errorMessageKey;

@end
Loading