Skip to content

Commit

Permalink
Add getPost(withID)
Browse files Browse the repository at this point in the history
  • Loading branch information
kean committed Apr 10, 2024
1 parent d25e7f9 commit c57db04
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 31 deletions.
12 changes: 9 additions & 3 deletions Sources/WordPressKit/Services/PostServiceRemoteExtended.swift
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
import Foundation

public protocol PostServiceRemoteExtended: PostServiceRemote {
/// Returns a post with the given ID.
///
/// - throws: ``PostServiceRemoteError`` or oher underlying errors
/// (see ``WordPressAPIError``)
func getPost(withID postID: Int) async throws -> RemotePost

/// Creates a new post with the given parameters.
func createPost(with parameters: RemotePostCreateParameters) async throws -> RemotePost

/// Performs a partial update to the existing post.
///
/// - throws: ``PostServiceRemoteUpdatePostError`` or oher underlying errors
/// - throws: ``PostServiceRemoteError`` or oher underlying errors
/// (see ``WordPressAPIError``)
func patchPost(withID postID: Int, parameters: RemotePostUpdateParameters) async throws -> RemotePost

/// Permanently deletes a post with the given ID.
///
/// - throws: ``PostServiceRemoteUpdatePostError`` or oher underlying errors
/// - throws: ``PostServiceRemoteError`` or oher underlying errors
/// (see ``WordPressAPIError``)
func deletePost(withID postID: Int) async throws
}

public enum PostServiceRemoteUpdatePostError: Error {
public enum PostServiceRemoteError: Error {
/// 409 (Conflict)
case conflict
/// 404 (Not Found)
Expand Down
20 changes: 17 additions & 3 deletions Sources/WordPressKit/Services/PostServiceRemoteREST+Extended.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
import Foundation

extension PostServiceRemoteREST: PostServiceRemoteExtended {
public func getPost(withID postID: Int) async throws -> RemotePost {
let path = self.path(forEndpoint: "sites/\(siteID)/posts/\(postID)?context=edit", withVersion: ._1_1)
let result = await wordPressComRestApi.perform(.post, URLString: path)
switch result {
case .success(let response):
return try await decodePost(from: response.body)
case .failure(let error):
if case .endpointError(let error) = error, error.apiErrorCode == "unknown_post" {
throw PostServiceRemoteError.notFound
}
throw error
}
}

public func createPost(with parameters: RemotePostCreateParameters) async throws -> RemotePost {
let path = self.path(forEndpoint: "sites/\(siteID)/posts/new?context=edit", withVersion: ._1_2)
let parameters = try makeParameters(from: RemotePostCreateParametersWordPressComEncoder(parameters: parameters))
Expand All @@ -22,8 +36,8 @@ extension PostServiceRemoteREST: PostServiceRemoteExtended {
throw error
}
switch error.apiErrorCode ?? "" {
case "unknown_post": throw PostServiceRemoteUpdatePostError.notFound
case "old-revision": throw PostServiceRemoteUpdatePostError.conflict
case "unknown_post": throw PostServiceRemoteError.notFound
case "old-revision": throw PostServiceRemoteError.conflict
default: throw error
}
}
Expand All @@ -40,7 +54,7 @@ extension PostServiceRemoteREST: PostServiceRemoteExtended {
throw error
}
switch error.apiErrorCode ?? "" {
case "unknown_post": throw PostServiceRemoteUpdatePostError.notFound
case "unknown_post": throw PostServiceRemoteError.notFound
default: throw error
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,28 @@ import Foundation
import wpxmlrpc

extension PostServiceRemoteXMLRPC: PostServiceRemoteExtended {
public func getPost(withID postID: Int) async throws -> RemotePost {
let parameters = xmlrpcArguments(withExtra: postID) as [AnyObject]
let result = await api.call(method: "wp.getPost", parameters: parameters)
switch result {
case .success(let response):
return try await decodePost(from: response.body)
case .failure(let error):
if case .endpointError(let error) = error, error.code == 404 {
throw PostServiceRemoteError.notFound
}
throw error
}
}

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: "metaWeblog.newPost", parameters: parameters).get()
guard let postID = (response.body as? NSObject)?.numericValue() else {
throw URLError(.unknown) // Should never happen
}
return try await getPost(withID: postID)
return try await getPost(withID: postID.intValue)
}

public func patchPost(withID postID: Int, parameters: RemotePostUpdateParameters) async throws -> RemotePost {
Expand All @@ -21,14 +35,14 @@ extension PostServiceRemoteXMLRPC: PostServiceRemoteExtended {
let result = await api.call(method: "metaWeblog.editPost", parameters: parameters)
switch result {
case .success:
return try await getPost(withID: postID as NSNumber)
return try await getPost(withID: postID)
case .failure(let error):
guard case .endpointError(let error) = error else {
throw error
}
switch error.code ?? 0 {
case 404: throw PostServiceRemoteUpdatePostError.notFound
case 409: throw PostServiceRemoteUpdatePostError.conflict
case 404: throw PostServiceRemoteError.notFound
case 409: throw PostServiceRemoteError.conflict
default: throw error
}
}
Expand All @@ -41,28 +55,19 @@ extension PostServiceRemoteXMLRPC: PostServiceRemoteExtended {
case .success:
return
case .failure(let error):
guard case .endpointError(let error) = error else {
throw error
}
switch error.code ?? 0 {
case 404: throw PostServiceRemoteUpdatePostError.notFound
default: throw error
if case .endpointError(let error) = error, error.code == 404 {
throw PostServiceRemoteError.notFound
}
throw error
}
}
}

private func getPost(withID postID: NSNumber) async throws -> RemotePost {
try await withUnsafeThrowingContinuation { continuation in
getPostWithID(postID) { post in
guard let post else {
return continuation.resume(throwing: URLError(.unknown)) // Should never happen
}
continuation.resume(returning: post)
} failure: { error in
continuation.resume(throwing: error ?? URLError(.unknown))
}
}
private func decodePost(from object: AnyObject) async throws -> RemotePost {
guard let dictionary = object as? [AnyHashable: Any] else {
throw WordPressAPIError<WordPressComRestApiEndpointError>.unparsableResponse(response: nil, body: nil)
}
return PostServiceRemoteXMLRPC.remotePost(fromXMLRPCDictionary: dictionary)
}

private func makeParameters<T: Encodable>(from value: T) throws -> [String: AnyObject] {
Expand Down
2 changes: 2 additions & 0 deletions Sources/WordPressKit/Services/PostServiceRemoteXMLRPC.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@

@interface PostServiceRemoteXMLRPC : ServiceRemoteWordPressXMLRPC <PostServiceRemote>

+ (RemotePost *)remotePostFromXMLRPCDictionary:(NSDictionary *)xmlrpcDictionary;

@end
12 changes: 8 additions & 4 deletions Sources/WordPressKit/Services/PostServiceRemoteXMLRPC.m
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,10 @@ - (NSDictionary *)dictionaryWithRemoteOptions:(id <PostServiceRemoteOptions>)opt
}

- (RemotePost *)remotePostFromXMLRPCDictionary:(NSDictionary *)xmlrpcDictionary {
return [PostServiceRemoteXMLRPC remotePostFromXMLRPCDictionary:xmlrpcDictionary];
}

+ (RemotePost *)remotePostFromXMLRPCDictionary:(NSDictionary *)xmlrpcDictionary {
RemotePost *post = [RemotePost new];

post.postID = [xmlrpcDictionary numberForKey:@"post_id"];
Expand Down Expand Up @@ -339,7 +343,7 @@ - (RemotePost *)remotePostFromXMLRPCDictionary:(NSDictionary *)xmlrpcDictionary
return post;
}

- (NSString *)statusForPostStatus:(NSString *)status andDate:(NSDate *)date
+ (NSString *)statusForPostStatus:(NSString *)status andDate:(NSDate *)date
{
// Scheduled posts are synced with a post_status of 'publish' but we want to
// work with a status of 'future' from within the app.
Expand All @@ -349,20 +353,20 @@ - (NSString *)statusForPostStatus:(NSString *)status andDate:(NSDate *)date
return status;
}

- (NSArray *)tagsFromXMLRPCTermsArray:(NSArray *)terms {
+ (NSArray *)tagsFromXMLRPCTermsArray:(NSArray *)terms {
NSArray *tags = [terms filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"taxonomy = 'post_tag' AND name != NIL"]];
return [tags valueForKey:@"name"];
}

- (NSArray *)remoteCategoriesFromXMLRPCTermsArray:(NSArray *)terms {
+ (NSArray *)remoteCategoriesFromXMLRPCTermsArray:(NSArray *)terms {
return [[terms wp_filter:^BOOL(NSDictionary *category) {
return [[category stringForKey:@"taxonomy"] isEqualToString:@"category"];
}] wp_map:^id(NSDictionary *category) {
return [self remoteCategoryFromXMLRPCDictionary:category];
}];
}

- (RemotePostCategory *)remoteCategoryFromXMLRPCDictionary:(NSDictionary *)xmlrpcCategory {
+ (RemotePostCategory *)remoteCategoryFromXMLRPCDictionary:(NSDictionary *)xmlrpcCategory {
RemotePostCategory *category = [RemotePostCategory new];
category.categoryID = [xmlrpcCategory numberForKey:@"term_id"];
category.name = [xmlrpcCategory stringForKey:@"name"];
Expand Down

0 comments on commit c57db04

Please sign in to comment.