Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.

Commit ae8f83e

Browse files
authored
Decouple PluginDirectoryServiceRemote from Alamofire (#725)
2 parents dfb2134 + dce3798 commit ae8f83e

File tree

5 files changed

+55
-89
lines changed

5 files changed

+55
-89
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ _None._
3535
### Breaking Changes
3636

3737
- Rewrite `WordPressOrgRestApi` to support self hosted sites and WordPress.com sites. [#724]
38+
- Decouple `PluginDirectoryServiceRemote` from Alamofire. [#725]
39+
- Remove `Endpoint`. [#725]
3840

3941
### New Features
4042

WordPressKit.xcodeproj/project.pbxproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,6 @@
607607
E14694031F344F71004052C8 /* site-plugins-error.json in Resources */ = {isa = PBXBuildFile; fileRef = E14694021F344F71004052C8 /* site-plugins-error.json */; };
608608
E1787DB0200E564B004CB3AF /* timezones.json in Resources */ = {isa = PBXBuildFile; fileRef = E1787DAF200E564B004CB3AF /* timezones.json */; };
609609
E1787DB2200E5690004CB3AF /* TimeZoneServiceRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1787DB1200E5690004CB3AF /* TimeZoneServiceRemoteTests.swift */; };
610-
E182BF6A1FD961810001D850 /* Endpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E182BF691FD961810001D850 /* Endpoint.swift */; };
611610
E194CB731FBDEF6500B0A8B8 /* PluginState.swift in Sources */ = {isa = PBXBuildFile; fileRef = E194CB721FBDEF6400B0A8B8 /* PluginState.swift */; };
612611
E1A6605F1FD694ED00BAC339 /* PluginDirectoryEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A6605E1FD694ED00BAC339 /* PluginDirectoryEntry.swift */; };
613612
E1BD95151FD5A2B800CD5CE3 /* PluginDirectoryServiceRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1BD95141FD5A2B800CD5CE3 /* PluginDirectoryServiceRemote.swift */; };
@@ -1336,7 +1335,6 @@
13361335
E14694021F344F71004052C8 /* site-plugins-error.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "site-plugins-error.json"; sourceTree = "<group>"; };
13371336
E1787DAF200E564B004CB3AF /* timezones.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = timezones.json; sourceTree = "<group>"; };
13381337
E1787DB1200E5690004CB3AF /* TimeZoneServiceRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeZoneServiceRemoteTests.swift; sourceTree = "<group>"; };
1339-
E182BF691FD961810001D850 /* Endpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Endpoint.swift; sourceTree = "<group>"; };
13401338
E194CB721FBDEF6400B0A8B8 /* PluginState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PluginState.swift; sourceTree = "<group>"; };
13411339
E1A6605E1FD694ED00BAC339 /* PluginDirectoryEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginDirectoryEntry.swift; sourceTree = "<group>"; };
13421340
E1BD95141FD5A2B800CD5CE3 /* PluginDirectoryServiceRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginDirectoryServiceRemote.swift; sourceTree = "<group>"; };
@@ -1985,7 +1983,6 @@
19851983
74BA04F11F06DC0A00ED5CD8 /* CommentServiceRemoteXMLRPC.m */,
19861984
8BB5F62027A99A2000B2FFAF /* DashboardServiceRemote.swift */,
19871985
7E0D64FE22D855700092AD10 /* EditorServiceRemote.swift */,
1988-
E182BF691FD961810001D850 /* Endpoint.swift */,
19891986
F9E56DF724EB125600916770 /* FeatureFlagRemote.swift */,
19901987
74650F711F0EA1A700188EDB /* GravatarServiceRemote.swift */,
19911988
1769DEA924729AFF00F42EFC /* HomepageSettingsServiceRemote.swift */,
@@ -3462,7 +3459,6 @@
34623459
F1BB7806240FB90B0030ADDC /* AtomicAuthenticationServiceRemote.swift in Sources */,
34633460
404057CE221C38130060250C /* StatsTopVideosTimeIntervalData.swift in Sources */,
34643461
7E0D64FF22D855700092AD10 /* EditorServiceRemote.swift in Sources */,
3465-
E182BF6A1FD961810001D850 /* Endpoint.swift in Sources */,
34663462
9AF4F2FF2183346B00570E4B /* RemoteRevision.swift in Sources */,
34673463
17D936252475D8AB008B2205 /* RemoteHomepageType.swift in Sources */,
34683464
74BA04F41F06DC0A00ED5CD8 /* CommentServiceRemoteREST.m in Sources */,

WordPressKit/Endpoint.swift

Lines changed: 0 additions & 55 deletions
This file was deleted.

WordPressKit/PluginDirectoryServiceRemote.swift

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import Foundation
2-
import Alamofire
32

43
private struct PluginDirectoryRemoteConstants {
54
static let dateFormatter: DateFormatter = {
@@ -47,7 +46,7 @@ public enum PluginDirectoryFeedType: Hashable {
4746
}
4847
}
4948

50-
public struct PluginDirectoryGetInformationEndpoint: Endpoint {
49+
public struct PluginDirectoryGetInformationEndpoint {
5150
public enum Error: Swift.Error {
5251
case pluginNotFound
5352
}
@@ -57,20 +56,18 @@ public struct PluginDirectoryGetInformationEndpoint: Endpoint {
5756
self.slug = slug
5857
}
5958

60-
public func buildRequest() throws -> URLRequest {
61-
let url = PluginDirectoryRemoteConstants.getInformationEndpoint
62-
.appendingPathComponent(slug)
63-
.appendingPathExtension("json")
64-
let request = URLRequest(url: url)
65-
let encodedRequest = try URLEncoding.default.encode(request, with: ["fields": "icons,banners"])
66-
return encodedRequest
59+
func buildRequest() throws -> URLRequest {
60+
try HTTPRequestBuilder(url: PluginDirectoryRemoteConstants.getInformationEndpoint)
61+
.append(percentEncodedPath: "\(slug).json")
62+
.query(name: "fields", value: "icons,banners")
63+
.build()
6764
}
6865

69-
public func parseResponse(data: Data) throws -> PluginDirectoryEntry {
66+
func parseResponse(data: Data) throws -> PluginDirectoryEntry {
7067
return try PluginDirectoryRemoteConstants.jsonDecoder.decode(PluginDirectoryEntry.self, from: data)
7168
}
7269

73-
public func validate(request: URLRequest?, response: HTTPURLResponse, data: Data?) throws {
70+
func validate(response: HTTPURLResponse, data: Data?) throws {
7471
// api.wordpress.org has an odd way of responding to plugin info requests for
7572
// plugins not in the directory: it will return `null` with an HTTP 200 OK.
7673
// This turns that case into a `.pluginNotFound` error.
@@ -83,20 +80,20 @@ public struct PluginDirectoryGetInformationEndpoint: Endpoint {
8380
}
8481
}
8582

86-
public struct PluginDirectoryFeedEndpoint: Endpoint {
83+
public struct PluginDirectoryFeedEndpoint {
8784
public enum Error: Swift.Error {
8885
case genericError
8986
}
9087

9188
let feedType: PluginDirectoryFeedType
9289
let pageNumber: Int
9390

94-
public init(feedType: PluginDirectoryFeedType) {
91+
init(feedType: PluginDirectoryFeedType) {
9592
self.feedType = feedType
9693
self.pageNumber = 1
9794
}
9895

99-
public func buildRequest() throws -> URLRequest {
96+
func buildRequest() throws -> URLRequest {
10097
var parameters: [String: Any] = ["action": "query_plugins",
10198
"request[per_page]": PluginDirectoryRemoteConstants.pluginsPerPage,
10299
"request[fields][icons]": 1,
@@ -113,17 +110,16 @@ public struct PluginDirectoryFeedEndpoint: Endpoint {
113110

114111
}
115112

116-
let request = URLRequest(url: PluginDirectoryRemoteConstants.feedEndpoint)
117-
let encodedRequest = try URLEncoding.default.encode(request, with: parameters)
118-
119-
return encodedRequest
113+
return try HTTPRequestBuilder(url: PluginDirectoryRemoteConstants.feedEndpoint)
114+
.query(parameters)
115+
.build()
120116
}
121117

122-
public func parseResponse(data: Data) throws -> PluginDirectoryFeedPage {
118+
func parseResponse(data: Data) throws -> PluginDirectoryFeedPage {
123119
return try PluginDirectoryRemoteConstants.jsonDecoder.decode(PluginDirectoryFeedPage.self, from: data)
124120
}
125121

126-
public func validate(request: URLRequest?, response: HTTPURLResponse, data: Data?) throws {
122+
func validate(response: HTTPURLResponse, data: Data?) throws {
127123
if response.statusCode != 200 { throw Error.genericError}
128124
}
129125
}
@@ -132,13 +128,19 @@ public struct PluginDirectoryServiceRemote {
132128

133129
public init() {}
134130

135-
public func getPluginFeed(_ feedType: PluginDirectoryFeedType,
136-
pageNumber: Int = 1,
137-
completion: @escaping (Result<PluginDirectoryFeedPage>) -> Void) {
138-
PluginDirectoryFeedEndpoint(feedType: feedType).request(completion: completion)
131+
public func getPluginFeed(_ feedType: PluginDirectoryFeedType, pageNumber: Int = 1) async throws -> PluginDirectoryFeedPage {
132+
let endpoint = PluginDirectoryFeedEndpoint(feedType: feedType)
133+
let (data, response) = try await URLSession.shared.data(for: endpoint.buildRequest())
134+
let httpResponse = response as! HTTPURLResponse
135+
try endpoint.validate(response: httpResponse, data: data)
136+
return try endpoint.parseResponse(data: data)
139137
}
140138

141-
public func getPluginInformation(slug: String, completion: @escaping (Result<PluginDirectoryEntry>) -> Void) {
142-
PluginDirectoryGetInformationEndpoint(slug: slug).request(completion: completion)
139+
public func getPluginInformation(slug: String) async throws -> PluginDirectoryEntry {
140+
let endpoint = PluginDirectoryGetInformationEndpoint(slug: slug)
141+
let (data, response) = try await URLSession.shared.data(for: endpoint.buildRequest())
142+
let httpResponse = response as! HTTPURLResponse
143+
try endpoint.validate(response: httpResponse, data: data)
144+
return try endpoint.parseResponse(data: data)
143145
}
144146
}

WordPressKitTests/PluginDirectoryTests.swift

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import XCTest
2+
import OHHTTPStubs
23
@testable import WordPressKit
34

45
class PluginDirectoryTests: XCTestCase {
@@ -51,13 +52,33 @@ class PluginDirectoryTests: XCTestCase {
5152
}
5253
}
5354

55+
func testGetPluginInformation() async throws {
56+
let data = try MockPluginDirectoryProvider.getPluginDirectoryMockData(with: "plugin-directory-rename-xml-rpc", sender: type(of: self))
57+
stub(condition: isHost("api.wordpress.org")) { _ in
58+
HTTPStubsResponse(data: data, statusCode: 200, headers: ["Content-Type": "application/json"])
59+
}
60+
61+
let plugin = try await PluginDirectoryServiceRemote().getPluginInformation(slug: "rename-xml-rpc")
62+
XCTAssertEqual(plugin.name, "Rename XMLRPC")
63+
}
64+
65+
func testGetDirectoryFeed() async throws {
66+
let data = try MockPluginDirectoryProvider.getPluginDirectoryMockData(with: "plugin-directory-popular", sender: type(of: self))
67+
stub(condition: isHost("api.wordpress.org")) { _ in
68+
HTTPStubsResponse(data: data, statusCode: 200, headers: ["Content-Type": "application/json"])
69+
}
70+
71+
let feed = try await PluginDirectoryServiceRemote().getPluginFeed(.popular)
72+
XCTAssertEqual(feed.plugins.first?.name, "Contact Form 7")
73+
}
74+
5475
func testValidateResponseFound() {
5576
let data = try! MockPluginDirectoryProvider.getPluginDirectoryMockData(with: "plugin-directory-rename-xml-rpc", sender: type(of: self))
5677
let endpoint = PluginDirectoryGetInformationEndpoint(slug: "jetpack")
5778
do {
5879
let request = try endpoint.buildRequest()
5980
let response = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: "1.1", headerFields: nil)!
60-
XCTAssertNoThrow(try endpoint.validate(request: request, response: response, data: data))
81+
XCTAssertNoThrow(try endpoint.validate(response: response, data: data))
6182
} catch {
6283
XCTFail(error.localizedDescription)
6384
}
@@ -70,7 +91,7 @@ class PluginDirectoryTests: XCTestCase {
7091
let request = try! endpoint.buildRequest()
7192
let response = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: "1.1", headerFields: nil)!
7293

73-
XCTAssertThrowsError(try endpoint.validate(request: request, response: response, data: "null".data(using: .utf8)))
94+
XCTAssertThrowsError(try endpoint.validate(response: response, data: "null".data(using: .utf8)))
7495
}
7596

7697
func testValidatePluginDirectoryFeedResponseSucceeds() throws {
@@ -79,7 +100,7 @@ class PluginDirectoryTests: XCTestCase {
79100
let request = try endpoint.buildRequest()
80101
let response = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: "1.1", headerFields: nil)!
81102

82-
XCTAssertNoThrow(try endpoint.validate(request: request, response: response, data: "null".data(using: .utf8)))
103+
XCTAssertNoThrow(try endpoint.validate(response: response, data: "null".data(using: .utf8)))
83104
}
84105

85106
func testValidatePluginDirectoryFeedResponseFails() {
@@ -88,7 +109,7 @@ class PluginDirectoryTests: XCTestCase {
88109
let request = try! endpoint.buildRequest()
89110
let response = HTTPURLResponse(url: request.url!, statusCode: 403, httpVersion: "1.1", headerFields: nil)!
90111

91-
XCTAssertThrowsError(try endpoint.validate(request: request, response: response, data: "null".data(using: .utf8)))
112+
XCTAssertThrowsError(try endpoint.validate(response: response, data: "null".data(using: .utf8)))
92113
}
93114

94115
func testNewDirectoryFeedRequest() {

0 commit comments

Comments
 (0)