Skip to content
Draft
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class PostTypesEndpointTest {
val postTypesPost = client.request { requestBuilder ->
requestBuilder.postTypes().retrieveWithEditContext(PostType.Post)
}.assertSuccessAndRetrieveData().data
assert(postTypesPost.supports[PostTypeSupports.Title]!!)
assert(postTypesPost.supports.map[PostTypeSupports.Title]!!)
assertFalse(postTypesPost.capabilities[PostTypeCapabilities.EditPosts]!!.isEmpty())
}

Expand All @@ -35,7 +35,7 @@ class PostTypesEndpointTest {
val postTypesPost = client.request { requestBuilder ->
requestBuilder.postTypes().retrieveWithEditContext(PostType.WpFontFace)
}.assertSuccessAndRetrieveData().data
assertNull(postTypesPost.supports[PostTypeSupports.Author])
assertNull(postTypesPost.supports.map[PostTypeSupports.Author])
}

@Test
Expand Down
2 changes: 1 addition & 1 deletion native/swift/Example/Example/ExampleApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ struct ExampleApp: App {
.postTypes
.map(\.value)
.filter { $0.visibility.showInNavMenus }
.filter { $0.supports.keys.contains(allOf: [.title, .author, .customFields]) }
.filter { $0.supports.map.keys.contains(allOf: [.title, .author, .customFields]) }

for type in postTypes {
baseData.append(RootListData(name: type.name, sequence: {
Expand Down
33 changes: 33 additions & 0 deletions scripts/setup-test-site.sh
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ create_nav_menu_item_autosave() {
curl --silent --user "$ADMIN_USERNAME":"$ADMIN_PASSWORD" -H "Content-Type: application/json" -d "{\"title\":\"nav_menu_item_autosave_$autosave_number\", \"author\": $ADMIN_USER_ID}" "http://localhost/wp-json/wp/v2/menu-items/$nav_menu_item_id/autosaves"
}

create_navigation_revision() {
local revision_number="$1"
local navigation_id="$2"

curl --silent --user "$ADMIN_USERNAME":"$ADMIN_PASSWORD" -H "Content-Type: application/json" -d "{\"content\":\"content_revision_$revision_number\", \"author\": $ADMIN_USER_ID}" "http://localhost/wp-json/wp/v2/navigation/$navigation_id" > /dev/null
}

create_navigation_autosave() {
local autosave_number="$1"
local navigation_id="$2"

curl --silent --user "$ADMIN_USERNAME":"$ADMIN_PASSWORD" -H "Content-Type: application/json" -d "{\"content\":\"content_autosave_$autosave_number\", \"author\": $ADMIN_USER_ID}" "http://localhost/wp-json/wp/v2/navigation/$navigation_id/autosaves"
}

create_test_credentials () {
local SITE_URL
local ADMIN_USERNAME
Expand Down Expand Up @@ -241,6 +255,22 @@ create_test_credentials () {
NAVIGATION_RESPONSE="$(curl --silent --user "$ADMIN_USERNAME":"$ADMIN_PASSWORD" -H "Content-Type: application/json" -d '{"title":"Integration Test Navigation","content":"<!-- wp:navigation --><!-- /wp:navigation -->","status":"publish"}' http://localhost/wp-json/wp/v2/navigation)"
NAVIGATION_ID="$(echo "$NAVIGATION_RESPONSE" | jq -r '.id')"

echo "Setting up navigation with 10 revisions for integration tests.."
# Create revisions for the navigation
for i in {1..10};
do
create_navigation_revision "$i" "$NAVIGATION_ID"
done
# Generating revisions don't return an id, but since we just created the `NAVIGATION_ID`, we can use it to calculate the revision id
REVISION_ID_FOR_NAVIGATION_ID=$((NAVIGATION_ID + 1))

echo "Setting up navigation with autosave for integration tests.."
# Create navigation as author user to enable proper autosave behavior (same requirement as posts/pages)
AUTOSAVED_NAVIGATION_ID="$(wp post create --post_type=wp_navigation --post_title='Autosaved Navigation FOR INTEGRATION TESTS' --post_content='<!-- wp:navigation --><!-- /wp:navigation -->' --post_status=publish --post_author="$AUTHOR_USER_ID" --porcelain)"
# Create autosave as admin user (different from navigation author) and capture its ID
AUTOSAVE_NAVIGATION_RESPONSE="$(create_navigation_autosave "1" "$AUTOSAVED_NAVIGATION_ID")"
AUTOSAVE_ID_FOR_AUTOSAVED_NAVIGATION_ID="$(echo "$AUTOSAVE_NAVIGATION_RESPONSE" | jq -r '.id')"

rm -rf /app/test_credentials.json
jo -p \
site_url="$SITE_URL" \
Expand Down Expand Up @@ -279,6 +309,9 @@ create_test_credentials () {
nav_menu_item_id="$NAV_MENU_ITEM_ID" \
autosave_id_for_nav_menu_item_id="$AUTOSAVE_ID_FOR_NAV_MENU_ITEM_ID" \
navigation_id="$NAVIGATION_ID" \
revision_id_for_navigation_id="$REVISION_ID_FOR_NAVIGATION_ID" \
autosaved_navigation_id="$AUTOSAVED_NAVIGATION_ID" \
autosave_id_for_autosaved_navigation_id="$AUTOSAVE_ID_FOR_AUTOSAVED_NAVIGATION_ID" \
> /app/test_credentials.json
}
create_test_credentials
Expand Down
29 changes: 16 additions & 13 deletions wp_api/src/api_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ use crate::{
},
nav_menu_items_endpoint::{NavMenuItemsRequestBuilder, NavMenuItemsRequestExecutor},
nav_menus_endpoint::{NavMenusRequestBuilder, NavMenusRequestExecutor},
navigation_autosaves_endpoint::{
NavigationAutosavesRequestBuilder, NavigationAutosavesRequestExecutor,
},
navigation_revisions_endpoint::{
NavigationRevisionsRequestBuilder, NavigationRevisionsRequestExecutor,
},
navigations_endpoint::{NavigationsRequestBuilder, NavigationsRequestExecutor},
plugins_endpoint::{PluginsRequestBuilder, PluginsRequestExecutor},
post_autosaves_endpoint::{AutosavesRequestBuilder, AutosavesRequestExecutor},
Expand All @@ -44,11 +50,6 @@ use crate::{
};
use std::sync::Arc;

#[derive(uniffi::Object)]
struct UniffiWpApiRequestBuilder {
inner: WpApiRequestBuilder,
}

pub struct WpApiRequestBuilder {
api_root: Arc<ApiRootRequestBuilder>,
application_passwords: Arc<ApplicationPasswordsRequestBuilder>,
Expand All @@ -59,6 +60,8 @@ pub struct WpApiRequestBuilder {
nav_menu_item_autosaves: Arc<NavMenuItemAutosavesRequestBuilder>,
nav_menu_items: Arc<NavMenuItemsRequestBuilder>,
nav_menus: Arc<NavMenusRequestBuilder>,
navigation_autosaves: Arc<NavigationAutosavesRequestBuilder>,
navigation_revisions: Arc<NavigationRevisionsRequestBuilder>,
navigations: Arc<NavigationsRequestBuilder>,
plugins: Arc<PluginsRequestBuilder>,
post_revisions: Arc<PostRevisionsRequestBuilder>,
Expand Down Expand Up @@ -95,6 +98,8 @@ impl WpApiRequestBuilder {
nav_menu_item_autosaves,
nav_menu_items,
nav_menus,
navigation_autosaves,
navigation_revisions,
navigations,
plugins,
post_revisions,
Expand Down Expand Up @@ -141,6 +146,8 @@ pub struct WpApiClient {
nav_menu_item_autosaves: Arc<NavMenuItemAutosavesRequestExecutor>,
nav_menu_items: Arc<NavMenuItemsRequestExecutor>,
nav_menus: Arc<NavMenusRequestExecutor>,
navigation_autosaves: Arc<NavigationAutosavesRequestExecutor>,
navigation_revisions: Arc<NavigationRevisionsRequestExecutor>,
navigations: Arc<NavigationsRequestExecutor>,
plugins: Arc<PluginsRequestExecutor>,
post_revisions: Arc<PostRevisionsRequestExecutor>,
Expand Down Expand Up @@ -174,6 +181,8 @@ impl WpApiClient {
nav_menu_item_autosaves,
nav_menu_items,
nav_menus,
navigation_autosaves,
navigation_revisions,
navigations,
plugins,
post_revisions,
Expand Down Expand Up @@ -217,6 +226,8 @@ api_client_generate_endpoint_impl!(WpApi, menu_locations);
api_client_generate_endpoint_impl!(WpApi, nav_menu_item_autosaves);
api_client_generate_endpoint_impl!(WpApi, nav_menu_items);
api_client_generate_endpoint_impl!(WpApi, nav_menus);
api_client_generate_endpoint_impl!(WpApi, navigation_autosaves);
api_client_generate_endpoint_impl!(WpApi, navigation_revisions);
api_client_generate_endpoint_impl!(WpApi, navigations);
api_client_generate_endpoint_impl!(WpApi, plugins);
api_client_generate_endpoint_impl!(WpApi, post_revisions);
Expand All @@ -239,14 +250,6 @@ api_client_generate_endpoint_impl!(WpApi, wp_site_health_tests);
macro_rules! api_client_generate_endpoint_impl {
($client_name_prefix: ident, $feature:ident) => {
paste::paste! {
#[uniffi::export]

impl [<Uniffi $client_name_prefix RequestBuilder>] {
fn $feature(&self) -> Arc<[<$feature:camel RequestBuilder>]> {
self.inner.$feature.clone()
}
}

impl [<$client_name_prefix RequestBuilder>] {
pub fn $feature(&self) -> &[<$feature:camel RequestBuilder>] {
self.$feature.as_ref()
Expand Down
26 changes: 0 additions & 26 deletions wp_api/src/jetpack/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,6 @@ use crate::{
};
use std::sync::Arc;

#[derive(uniffi::Object)]
struct UniffiJetpackApiRequestBuilder {
inner: JetpackApiRequestBuilder,
}

#[uniffi::export]
impl UniffiJetpackApiRequestBuilder {
#[uniffi::constructor]
pub fn new(
api_url_resolver: Arc<dyn ApiUrlResolver>,
auth_provider: Arc<WpAuthenticationProvider>,
) -> Self {
Self {
inner: JetpackApiRequestBuilder::new(api_url_resolver, auth_provider),
}
}

#[uniffi::constructor]
pub fn with_api_root_url(
api_root_url: Arc<ParsedUrl>,
auth_provider: Arc<WpAuthenticationProvider>,
) -> Self {
Self::new(jetpack_api_url_resolver(api_root_url), auth_provider)
}
}

pub struct JetpackApiRequestBuilder {
connection: Arc<ConnectionRequestBuilder>,
}
Expand Down
1 change: 1 addition & 0 deletions wp_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod middleware;
pub mod nav_menu_item_revisions;
pub mod nav_menu_items;
pub mod nav_menus;
pub mod navigation_revisions;
pub mod navigations;
pub mod parsed_url;
pub mod plugins;
Expand Down
111 changes: 111 additions & 0 deletions wp_api/src/navigation_revisions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
use crate::{
UserId, WpApiParamOrder,
date::WpGmtDateTime,
impl_as_query_value_from_to_string,
navigations::NavigationId,
url_query::{
AppendUrlQueryPairs, FromUrlQueryPairs, QueryPairs, QueryPairsExtension, UrlQueryPairsMap,
},
wp_content_i64_id,
};
use serde::{Deserialize, Serialize};
use wp_contextual::WpContextual;
use wp_derive::WpDeriveParamsField;

wp_content_i64_id!(NavigationRevisionId);

#[derive(
Debug,
Default,
Clone,
Copy,
PartialEq,
Eq,
uniffi::Enum,
strum_macros::EnumString,
strum_macros::Display,
)]
#[strum(serialize_all = "snake_case")]
pub enum WpApiParamNavigationRevisionsOrderBy {
#[default]
Date,
Id,
Include,
IncludeSlugs,
Relevance,
Slug,
Title,
}

impl_as_query_value_from_to_string!(WpApiParamNavigationRevisionsOrderBy);

#[derive(Debug, Default, PartialEq, Eq, uniffi::Record, WpDeriveParamsField)]
#[supports_pagination(true)]
pub struct NavigationRevisionListParams {
/// Current page of the collection.
/// Default: `1`
#[uniffi(default = None)]
pub page: Option<u32>,
/// Maximum number of items to be returned in result set.
#[uniffi(default = None)]
pub per_page: Option<u32>,
/// Limit results to those matching a string.
#[uniffi(default = None)]
pub search: Option<String>,
/// Ensure result set excludes specific IDs.
#[uniffi(default = [])]
pub exclude: Vec<NavigationRevisionId>,
/// Limit result set to specific IDs.
#[uniffi(default = [])]
pub include: Vec<NavigationRevisionId>,
/// Offset the result set by a specific number of items.
#[uniffi(default = None)]
pub offset: Option<u32>,
/// Order sort attribute ascending or descending.
/// Default: desc
/// One of: asc, desc
#[uniffi(default = None)]
pub order: Option<WpApiParamOrder>,
/// Sort collection by object attribute.
/// Default: date
/// One of: date, id, include, relevance, slug, include_slugs, title
#[uniffi(default = None)]
#[field_name("orderby")]
pub orderby: Option<WpApiParamNavigationRevisionsOrderBy>,
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record, WpContextual)]
pub struct SparseNavigationRevision {
#[WpContext(edit, embed, view)]
pub id: Option<NavigationRevisionId>,
#[WpContext(edit, embed, view)]
pub author: Option<UserId>,
#[WpContext(edit, embed, view)]
pub date: Option<String>,
#[WpContext(edit, view)]
pub date_gmt: Option<WpGmtDateTime>,
#[WpContext(edit, view)]
pub modified: Option<String>,
#[WpContext(edit, view)]
pub modified_gmt: Option<WpGmtDateTime>,
#[WpContext(edit, embed, view)]
pub parent: Option<NavigationId>,
#[WpContext(edit, embed, view)]
pub slug: Option<String>,
#[WpContext(edit, view)]
#[WpContextualField]
pub guid: Option<crate::navigations::SparseNavigationGuid>,
#[WpContext(edit, embed, view)]
#[WpContextualField]
pub title: Option<crate::navigations::SparseNavigationTitle>,
#[WpContext(edit, view)]
#[WpContextualField]
pub content: Option<crate::navigations::SparseNavigationContent>,
// meta field omitted for now
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
pub struct NavigationRevisionDeleteResponse {
pub deleted: bool,
pub previous: NavigationRevisionWithEditContext,
}
1 change: 1 addition & 0 deletions wp_api/src/post_revisions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ pub struct SparseAnyPostRevision {
#[WpContextualOption]
pub excerpt: Option<crate::posts::SparsePostExcerpt>,
#[WpContext(edit, view)]
#[WpContextualOption]
pub meta: Option<crate::posts::PostMeta>,
}

Expand Down
12 changes: 11 additions & 1 deletion wp_api/src/post_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::str::FromStr;
use wp_contextual::WpContextual;
use wp_serde_helper::deserialize_empty_array_or_hashmap;

#[derive(
Debug,
Expand Down Expand Up @@ -74,7 +75,7 @@ pub struct SparsePostTypeDetails {
#[WpContext(edit, embed, view)]
pub slug: Option<String>,
#[WpContext(edit)]
pub supports: Option<HashMap<PostTypeSupports, bool>>,
pub supports: Option<PostTypeSupportsMap>,
#[WpContext(edit, view)]
pub has_archive: Option<bool>,
#[WpContext(edit, view)]
Expand All @@ -90,6 +91,15 @@ pub struct SparsePostTypeDetails {
pub icon: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, uniffi::Record)]
#[serde(transparent)]
pub struct PostTypeSupportsMap {
#[serde(deserialize_with = "deserialize_empty_array_or_hashmap")]
#[serde(flatten)]
#[serde(rename = "supports")]
pub map: HashMap<PostTypeSupports, bool>,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, uniffi::Record)]
pub struct PostTypeLabels {
pub name: String,
Expand Down
6 changes: 3 additions & 3 deletions wp_api/src/posts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
};
use serde::{Deserialize, Serialize};
use wp_contextual::WpContextual;
use wp_derive::WpDeriveParamsField;
use wp_derive::{WpDeriveParamsField, WpDeserialize};
use wp_serde_helper::{deserialize_from_string_of_json_array, serialize_as_json_string};

#[derive(
Expand Down Expand Up @@ -474,11 +474,11 @@ pub struct SparsePostExcerpt {
pub protected: Option<bool>,
}

#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
#[derive(Debug, Serialize, WpDeserialize, uniffi::Record)]
pub struct PostMeta {
#[serde(deserialize_with = "deserialize_from_string_of_json_array")]
#[serde(serialize_with = "serialize_as_json_string")]
pub footnotes: Vec<PostFootnote>,
pub footnotes: Option<Vec<PostFootnote>>,
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, uniffi::Record)]
Expand Down
2 changes: 2 additions & 0 deletions wp_api/src/request/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub mod menu_locations_endpoint;
pub mod nav_menu_item_autosaves_endpoint;
pub mod nav_menu_items_endpoint;
pub mod nav_menus_endpoint;
pub mod navigation_autosaves_endpoint;
pub mod navigation_revisions_endpoint;
pub mod navigations_endpoint;
pub mod plugins_endpoint;
pub mod post_autosaves_endpoint;
Expand Down
1 change: 0 additions & 1 deletion wp_api/src/request/endpoint/media_endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ impl NetworkRequestAccessor for MediaUploadRequest {
}
}

#[uniffi::export]
impl MediaRequestBuilder {
pub fn create(
&self,
Expand Down
Loading