Skip to content
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
2 changes: 1 addition & 1 deletion native/swift/Sources/wordpress-api/Exports.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ public typealias PluginListParams = WordPressAPIInternal.PluginListParams
public typealias PluginUpdateParams = WordPressAPIInternal.PluginUpdateParams
public typealias PluginCreateParams = WordPressAPIInternal.PluginCreateParams
public typealias PluginDeleteResponse = WordPressAPIInternal.PluginDeleteResponse
public typealias PluginsRequestBuilder = WordPressAPIInternal.PluginsRequestBuilder
public typealias PluginsRequestExecutor = WordPressAPIInternal.PluginsRequestExecutor

#endif
2 changes: 1 addition & 1 deletion native/swift/Sources/wordpress-api/WordPressAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public struct WordPressAPI {
self.requestBuilder.users()
}

public var plugins: PluginsRequestBuilder {
public var plugins: PluginsRequestExecutor {
self.requestBuilder.plugins()
}

Expand Down
13 changes: 8 additions & 5 deletions wp_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use request::{
application_passwords_endpoint::{
ApplicationPasswordsRequestBuilder2, ApplicationPasswordsRequestExecutor,
},
plugins_endpoint::{PluginsRequestBuilder2, PluginsRequestExecutor},
users_endpoint::{UsersRequestBuilder2, UsersRequestExecutor},
ApiBaseUrl,
},
plugins_request_builder::PluginsRequestBuilder,
RequestExecutor, WpNetworkResponse,
};
use std::sync::Arc;
Expand Down Expand Up @@ -71,7 +71,7 @@ impl WpApiRequestBuilder {
pub struct WpRequestBuilder {
application_passwords: Arc<ApplicationPasswordsRequestExecutor>,
users: Arc<UsersRequestExecutor>,
plugins: Arc<PluginsRequestBuilder>,
plugins: Arc<PluginsRequestExecutor>,
}

#[uniffi::export]
Expand Down Expand Up @@ -106,8 +106,11 @@ impl WpRequestBuilder {
request_executor.clone(),
)
.into(),
plugins: PluginsRequestBuilder::new(api_base_url.clone(), request_builder.clone())
.into(),
plugins: PluginsRequestExecutor::new(
PluginsRequestBuilder2::new(api_base_url.clone(), request_builder.clone()),
request_executor.clone(),
)
.into(),
})
}

Expand All @@ -119,7 +122,7 @@ impl WpRequestBuilder {
self.users.clone()
}

pub fn plugins(&self) -> Arc<PluginsRequestBuilder> {
pub fn plugins(&self) -> Arc<PluginsRequestExecutor> {
self.plugins.clone()
}
}
Expand Down
8 changes: 8 additions & 0 deletions wp_api/src/plugins.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::fmt::Display;

use serde::{Deserialize, Serialize};
use wp_contextual::WpContextual;

Expand Down Expand Up @@ -132,6 +134,12 @@ impl From<&str> for PluginSlug {
}
}

impl Display for PluginSlug {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.slug)
}
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
#[serde(transparent)]
pub struct PluginWpOrgDirectorySlug {
Expand Down
1 change: 0 additions & 1 deletion wp_api/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::{api_error::RequestExecutionError, WpApiError, WpAuthentication};
use self::endpoint::WpEndpointUrl;

pub mod endpoint;
pub mod plugins_request_builder;

const CONTENT_TYPE_JSON: &str = "application/json";
const LINK_HEADER_KEY: &str = "Link";
Expand Down
8 changes: 4 additions & 4 deletions wp_api/src/request/endpoint/application_passwords_endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ mod tests {
#[rstest]
fn list_application_passwords_with_edit_context(endpoint: ApplicationPasswordsRequestEndpoint) {
validate_endpoint(
endpoint.list_with_edit_context(UserId(2)),
endpoint.list_with_edit_context(&UserId(2)),
"/users/2/application-passwords?context=edit",
);
}
Expand All @@ -36,15 +36,15 @@ mod tests {
endpoint: ApplicationPasswordsRequestEndpoint,
) {
validate_endpoint(
endpoint.list_with_embed_context(UserId(71)),
endpoint.list_with_embed_context(&UserId(71)),
"/users/71/application-passwords?context=embed",
);
}

#[rstest]
fn list_application_passwords_with_view_context(endpoint: ApplicationPasswordsRequestEndpoint) {
validate_endpoint(
endpoint.list_with_view_context(UserId(9999)),
endpoint.list_with_view_context(&UserId(9999)),
"/users/9999/application-passwords?context=view",
);
}
Expand All @@ -59,7 +59,7 @@ mod tests {
#[case] expected_path: &str,
) {
validate_endpoint(
endpoint.filter_list(UserId(2), context, fields),
endpoint.filter_list(&UserId(2), context, fields),
expected_path,
);
}
Expand Down
181 changes: 72 additions & 109 deletions wp_api/src/request/endpoint/plugins_endpoint.rs
Original file line number Diff line number Diff line change
@@ -1,96 +1,42 @@
use std::sync::Arc;

use url::Url;

use crate::{plugins::PluginListParams, PluginSlug, SparsePluginField, WpContext};

use super::{ApiBaseUrl, ApiEndpointUrl, UrlExtension};

#[derive(Debug)]
pub(crate) struct PluginsEndpoint {
api_base_url: Arc<ApiBaseUrl>,
}

impl PluginsEndpoint {
pub fn new(api_base_url: Arc<ApiBaseUrl>) -> Self {
Self { api_base_url }
}

pub fn create(&self) -> ApiEndpointUrl {
self.plugins_base_url().into()
}

pub fn delete(&self, plugin: &PluginSlug) -> ApiEndpointUrl {
self.plugins_url_with_slug(plugin).into()
}

pub fn list(&self, context: WpContext, params: &PluginListParams) -> ApiEndpointUrl {
let mut url = self.plugins_base_url();
url.query_pairs_mut()
.append_pair("context", context.as_str());
url.query_pairs_mut().extend_pairs(params.query_pairs());
url.into()
}

pub fn filter_list(
&self,
context: WpContext,
params: &PluginListParams,
fields: &[SparsePluginField],
) -> ApiEndpointUrl {
self.list(context, params)
.url
.append_filter_fields(fields)
.into()
}

pub fn retrieve(&self, context: WpContext, plugin: &PluginSlug) -> ApiEndpointUrl {
let mut url = self.plugins_url_with_slug(plugin);
url.query_pairs_mut()
.append_pair("context", context.as_str());
url.into()
}

pub fn filter_retrieve(
&self,
context: WpContext,
plugin: &PluginSlug,
fields: &[SparsePluginField],
) -> ApiEndpointUrl {
self.retrieve(context, plugin)
.url
.append_filter_fields(fields)
.into()
}

pub fn update(&self, plugin: &PluginSlug) -> ApiEndpointUrl {
self.plugins_url_with_slug(plugin).into()
}

fn plugins_base_url(&self) -> Url {
self.api_base_url.by_appending("plugins")
}

fn plugins_url_with_slug(&self, plugin: &PluginSlug) -> Url {
self.api_base_url
// The '/' character has to be preserved and not get encoded
.by_extending(["plugins"].into_iter().chain(plugin.slug.split('/')))
}
use crate::{plugins::PluginListParams, PluginSlug};
use crate::{
PluginCreateParams, PluginDeleteResponse, PluginUpdateParams, PluginWithEditContext,
PluginWithEmbedContext, PluginWithViewContext, SparsePlugin, SparsePluginField,
};
use wp_derive_request_builder::WpDerivedRequest;

#[derive(WpDerivedRequest)]
#[SparseField(SparsePluginField)]
enum PluginsRequest {
#[post(url = "/plugins", params = &PluginCreateParams, output = PluginWithEditContext)]
Create,
#[delete(url = "/plugins/<plugin_slug>", output = PluginDeleteResponse)]
Delete,
#[contextual_get(url = "/plugins", params = &PluginListParams, output = Vec<SparsePlugin>)]
List,
#[contextual_get(url = "/plugins/<plugin_slug>", output = SparsePlugin)]
Retrieve,
#[post(url = "/plugins/<plugin_slug>", params = &PluginUpdateParams, output = PluginWithEditContext)]
Update,
}

#[cfg(test)]
mod tests {
use super::*;
use crate::{
generate,
request::endpoint::tests::{fixture_api_base_url, validate_endpoint},
PluginStatus,
request::endpoint::{
tests::{fixture_api_base_url, validate_endpoint},
ApiBaseUrl,
},
PluginStatus, WpContext,
};
use rstest::*;
use std::sync::Arc;

#[rstest]
fn create_plugin(plugins_endpoint: PluginsEndpoint) {
validate_endpoint(plugins_endpoint.create(), "/plugins");
fn create_plugin(endpoint: PluginsRequestEndpoint) {
validate_endpoint(endpoint.create(), "/plugins");
}

#[rstest]
Expand All @@ -102,25 +48,46 @@ mod tests {
#[case("foo/bar%baz".into(), "/plugins/foo/bar%25baz")]
#[case("foo/です".into(), "/plugins/foo/%E3%81%A7%E3%81%99")]
fn delete_plugin(
plugins_endpoint: PluginsEndpoint,
endpoint: PluginsRequestEndpoint,
#[case] plugin_slug: PluginSlug,
#[case] expected_path: &str,
) {
validate_endpoint(plugins_endpoint.delete(&plugin_slug), expected_path);
validate_endpoint(endpoint.delete(&plugin_slug), expected_path);
}

#[rstest]
#[case(WpContext::Edit, PluginListParams::default(), "/plugins?context=edit")]
#[case(WpContext::Edit, generate!(PluginListParams, (search, Some("foo".to_string()))), "/plugins?context=edit&search=foo")]
#[case(WpContext::Embed, generate!(PluginListParams, (status, Some(PluginStatus::Active))), "/plugins?context=embed&status=active")]
#[case(WpContext::View, generate!(PluginListParams, (search, Some("foo".to_string())), (status, Some(PluginStatus::Inactive))), "/plugins?context=view&search=foo&status=inactive")]
fn list_plugins_with_params(
plugins_endpoint: PluginsEndpoint,
#[case] context: WpContext,
#[case(PluginListParams::default(), "/plugins?context=edit")]
#[case(generate!(PluginListParams, (search, Some("foo".to_string()))), "/plugins?context=edit&search=foo")]
#[case(generate!(PluginListParams, (status, Some(PluginStatus::Active))), "/plugins?context=edit&status=active")]
#[case(generate!(PluginListParams, (search, Some("foo".to_string())), (status, Some(PluginStatus::Inactive))), "/plugins?context=edit&search=foo&status=inactive")]
fn list_plugins_with_edit_context(
endpoint: PluginsRequestEndpoint,
#[case] params: PluginListParams,
#[case] expected_path: &str,
) {
validate_endpoint(endpoint.list_with_edit_context(&params), expected_path);
}

#[rstest]
#[case(PluginListParams::default(), "/plugins?context=embed")]
#[case(generate!(PluginListParams, (search, Some("foo".to_string()))), "/plugins?context=embed&search=foo")]
fn list_plugins_with_embed_context(
endpoint: PluginsRequestEndpoint,
#[case] params: PluginListParams,
#[case] expected_path: &str,
) {
validate_endpoint(plugins_endpoint.list(context, &params), expected_path);
validate_endpoint(endpoint.list_with_embed_context(&params), expected_path);
}

#[rstest]
#[case(PluginListParams::default(), "/plugins?context=view")]
#[case(generate!(PluginListParams, (search, Some("foo".to_string()))), "/plugins?context=view&search=foo")]
fn list_plugins_with_view_context(
endpoint: PluginsRequestEndpoint,
#[case] params: PluginListParams,
#[case] expected_path: &str,
) {
validate_endpoint(endpoint.list_with_view_context(&params), expected_path);
}

#[rstest]
Expand Down Expand Up @@ -150,43 +117,39 @@ mod tests {
"/plugins?context=view&search=foo&status=inactive&_fields=network_only%2Crequires_php%2Ctextdomain"
)]
fn filter_list_plugins_with_params(
plugins_endpoint: PluginsEndpoint,
endpoint: PluginsRequestEndpoint,
#[case] context: WpContext,
#[case] params: PluginListParams,
#[case] fields: &[SparsePluginField],
#[case] expected_path: &str,
) {
validate_endpoint(
plugins_endpoint.filter_list(context, &params, fields),
endpoint.filter_list(context, &params, fields),
expected_path,
);
}

#[rstest]
#[case(
"hello-dolly/hello".into(),
WpContext::View,
"/plugins/hello-dolly/hello?context=view"
)]
#[case(
"classic-editor/classic-editor".into(),
WpContext::Embed,
"/plugins/classic-editor/classic-editor?context=embed"
"/plugins/classic-editor/classic-editor?context=view"
)]
#[case("foo/bar%baz".into(), WpContext::Edit, "/plugins/foo/bar%25baz?context=edit")]
#[case("foo/bar%baz".into(), "/plugins/foo/bar%25baz?context=view")]
#[case(
"foo/です".into(),
WpContext::View,
"/plugins/foo/%E3%81%A7%E3%81%99?context=view"
)]
fn retrieve_plugin(
plugins_endpoint: PluginsEndpoint,
fn retrieve_plugin_with_view_context(
endpoint: PluginsRequestEndpoint,
#[case] plugin_slug: PluginSlug,
#[case] context: WpContext,
#[case] expected_path: &str,
) {
validate_endpoint(
plugins_endpoint.retrieve(context, &plugin_slug),
endpoint.retrieve_with_view_context(&plugin_slug),
expected_path,
);
}
Expand Down Expand Up @@ -217,14 +180,14 @@ mod tests {
"/plugins/foo/%E3%81%A7%E3%81%99?context=view&_fields=network_only%2Crequires_php%2Ctextdomain"
)]
fn filter_retrieve_plugin(
plugins_endpoint: PluginsEndpoint,
endpoint: PluginsRequestEndpoint,
#[case] plugin_slug: PluginSlug,
#[case] context: WpContext,
#[case] fields: &[SparsePluginField],
#[case] expected_path: &str,
) {
validate_endpoint(
plugins_endpoint.filter_retrieve(context, &plugin_slug, fields),
endpoint.filter_retrieve(&plugin_slug, context, fields),
expected_path,
);
}
Expand All @@ -238,15 +201,15 @@ mod tests {
#[case("foo/bar%baz".into(), "/plugins/foo/bar%25baz")]
#[case("foo/です".into(), "/plugins/foo/%E3%81%A7%E3%81%99")]
fn update_plugin(
plugins_endpoint: PluginsEndpoint,
endpoint: PluginsRequestEndpoint,
#[case] plugin_slug: PluginSlug,
#[case] expected_path: &str,
) {
validate_endpoint(plugins_endpoint.update(&plugin_slug), expected_path);
validate_endpoint(endpoint.update(&plugin_slug), expected_path);
}

#[fixture]
fn plugins_endpoint(fixture_api_base_url: Arc<ApiBaseUrl>) -> PluginsEndpoint {
PluginsEndpoint::new(fixture_api_base_url)
fn endpoint(fixture_api_base_url: Arc<ApiBaseUrl>) -> PluginsRequestEndpoint {
PluginsRequestEndpoint::new(fixture_api_base_url)
}
}
Loading