Skip to content

Commit 5205e94

Browse files
authored
/navigation/<parent>/revisions & /navigation/<parent>/autosaves endpoints (#942)
* `/navigation/<parent>/revisions` immutable integration tests * `/navigation/<parent>/autosaves` immutable integration tests * Error tests for navigation revisions & autosaves * Mutable tests for navigation revisions & autosaves * Adds navigation revision & autosave specific types & endpoints
1 parent 1b8b845 commit 5205e94

21 files changed

+1038
-18
lines changed

native/swift/Sources/wordpress-api/Exports.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,11 @@ public typealias NavigationWithEditContext = WordPressAPIInternal.NavigationWith
205205
public typealias NavigationWithViewContext = WordPressAPIInternal.NavigationWithViewContext
206206
public typealias NavigationWithEmbedContext = WordPressAPIInternal.NavigationWithEmbedContext
207207

208+
public typealias NavigationRevisionListParams = WordPressAPIInternal.NavigationRevisionListParams
209+
public typealias NavigationRevisionWithEditContext = WordPressAPIInternal.NavigationRevisionWithEditContext
210+
public typealias NavigationRevisionWithViewContext = WordPressAPIInternal.NavigationRevisionWithViewContext
211+
public typealias NavigationRevisionWithEmbedContext = WordPressAPIInternal.NavigationRevisionWithEmbedContext
212+
208213
// MARK: - Menus
209214
public typealias SparseNavMenu = WordPressAPIInternal.SparseNavMenu
210215
public typealias NavMenuListParams = WordPressAPIInternal.NavMenuListParams

native/swift/Sources/wordpress-api/Pagination.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,36 @@ extension CommentsRequestExecutor: PaginationAwareExecutor {
530530
}
531531

532532
// MARK: Menus
533+
extension NavigationsRequestFilterListWithEditContextResponse: PaginatableResponse {
534+
public typealias ParamsType = NavigationListParams
535+
public typealias DataType = SparseNavigationWithEditContext
536+
}
537+
538+
extension NavigationsRequestFilterListWithViewContextResponse: PaginatableResponse {
539+
public typealias ParamsType = NavigationListParams
540+
public typealias DataType = SparseNavigationWithViewContext
541+
}
542+
543+
extension NavigationsRequestFilterListWithEmbedContextResponse: PaginatableResponse {
544+
public typealias ParamsType = NavigationListParams
545+
public typealias DataType = SparseNavigationWithEmbedContext
546+
}
547+
548+
extension NavigationRevisionsRequestFilterListWithEditContextResponse: PaginatableResponse {
549+
public typealias ParamsType = NavigationRevisionListParams
550+
public typealias DataType = SparseNavigationRevisionWithEditContext
551+
}
552+
553+
extension NavigationRevisionsRequestFilterListWithViewContextResponse: PaginatableResponse {
554+
public typealias ParamsType = NavigationRevisionListParams
555+
public typealias DataType = SparseNavigationRevisionWithViewContext
556+
}
557+
558+
extension NavigationRevisionsRequestFilterListWithEmbedContextResponse: PaginatableResponse {
559+
public typealias ParamsType = NavigationRevisionListParams
560+
public typealias DataType = SparseNavigationRevisionWithEmbedContext
561+
}
562+
533563
extension NavMenuItemsRequestListWithEditContextResponse: PaginatableResponse {
534564
public typealias ParamsType = NavMenuItemListParams
535565
public typealias DataType = NavMenuItemWithEditContext

scripts/setup-test-site.sh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,20 @@ create_nav_menu_item_autosave() {
138138
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"
139139
}
140140

141+
create_navigation_revision() {
142+
local revision_number="$1"
143+
local navigation_id="$2"
144+
145+
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
146+
}
147+
148+
create_navigation_autosave() {
149+
local autosave_number="$1"
150+
local navigation_id="$2"
151+
152+
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"
153+
}
154+
141155
create_test_credentials () {
142156
local SITE_URL
143157
local ADMIN_USERNAME
@@ -243,6 +257,22 @@ create_test_credentials () {
243257
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)"
244258
NAVIGATION_ID="$(echo "$NAVIGATION_RESPONSE" | jq -r '.id')"
245259

260+
echo "Setting up navigation with 10 revisions for integration tests.."
261+
# Create revisions for the navigation
262+
for i in {1..10};
263+
do
264+
create_navigation_revision "$i" "$NAVIGATION_ID"
265+
done
266+
# Generating revisions don't return an id, but since we just created the `NAVIGATION_ID`, we can use it to calculate the revision id
267+
REVISION_ID_FOR_NAVIGATION_ID=$((NAVIGATION_ID + 1))
268+
269+
echo "Setting up navigation with autosave for integration tests.."
270+
# Create navigation as author user to enable proper autosave behavior (same requirement as posts/pages)
271+
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)"
272+
# Create autosave as admin user (different from navigation author) and capture its ID
273+
AUTOSAVE_NAVIGATION_RESPONSE="$(create_navigation_autosave "1" "$AUTOSAVED_NAVIGATION_ID")"
274+
AUTOSAVE_ID_FOR_AUTOSAVED_NAVIGATION_ID="$(echo "$AUTOSAVE_NAVIGATION_RESPONSE" | jq -r '.id')"
275+
246276
rm -rf /app/test_credentials.json
247277
jo -p \
248278
site_url="$SITE_URL" \
@@ -281,6 +311,9 @@ create_test_credentials () {
281311
nav_menu_item_id="$NAV_MENU_ITEM_ID" \
282312
autosave_id_for_nav_menu_item_id="$AUTOSAVE_ID_FOR_NAV_MENU_ITEM_ID" \
283313
navigation_id="$NAVIGATION_ID" \
314+
revision_id_for_navigation_id="$REVISION_ID_FOR_NAVIGATION_ID" \
315+
autosaved_navigation_id="$AUTOSAVED_NAVIGATION_ID" \
316+
autosave_id_for_autosaved_navigation_id="$AUTOSAVE_ID_FOR_AUTOSAVED_NAVIGATION_ID" \
284317
> /app/test_credentials.json
285318
}
286319
create_test_credentials

wp_api/src/api_client.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ use crate::{
1919
},
2020
nav_menu_items_endpoint::{NavMenuItemsRequestBuilder, NavMenuItemsRequestExecutor},
2121
nav_menus_endpoint::{NavMenusRequestBuilder, NavMenusRequestExecutor},
22+
navigation_autosaves_endpoint::{
23+
NavigationAutosavesRequestBuilder, NavigationAutosavesRequestExecutor,
24+
},
25+
navigation_revisions_endpoint::{
26+
NavigationRevisionsRequestBuilder, NavigationRevisionsRequestExecutor,
27+
},
2228
navigations_endpoint::{NavigationsRequestBuilder, NavigationsRequestExecutor},
2329
plugins_endpoint::{PluginsRequestBuilder, PluginsRequestExecutor},
2430
post_autosaves_endpoint::{AutosavesRequestBuilder, AutosavesRequestExecutor},
@@ -54,6 +60,8 @@ pub struct WpApiRequestBuilder {
5460
nav_menu_item_autosaves: Arc<NavMenuItemAutosavesRequestBuilder>,
5561
nav_menu_items: Arc<NavMenuItemsRequestBuilder>,
5662
nav_menus: Arc<NavMenusRequestBuilder>,
63+
navigation_autosaves: Arc<NavigationAutosavesRequestBuilder>,
64+
navigation_revisions: Arc<NavigationRevisionsRequestBuilder>,
5765
navigations: Arc<NavigationsRequestBuilder>,
5866
plugins: Arc<PluginsRequestBuilder>,
5967
post_revisions: Arc<PostRevisionsRequestBuilder>,
@@ -90,6 +98,8 @@ impl WpApiRequestBuilder {
9098
nav_menu_item_autosaves,
9199
nav_menu_items,
92100
nav_menus,
101+
navigation_autosaves,
102+
navigation_revisions,
93103
navigations,
94104
plugins,
95105
post_revisions,
@@ -136,6 +146,8 @@ pub struct WpApiClient {
136146
nav_menu_item_autosaves: Arc<NavMenuItemAutosavesRequestExecutor>,
137147
nav_menu_items: Arc<NavMenuItemsRequestExecutor>,
138148
nav_menus: Arc<NavMenusRequestExecutor>,
149+
navigation_autosaves: Arc<NavigationAutosavesRequestExecutor>,
150+
navigation_revisions: Arc<NavigationRevisionsRequestExecutor>,
139151
navigations: Arc<NavigationsRequestExecutor>,
140152
plugins: Arc<PluginsRequestExecutor>,
141153
post_revisions: Arc<PostRevisionsRequestExecutor>,
@@ -169,6 +181,8 @@ impl WpApiClient {
169181
nav_menu_item_autosaves,
170182
nav_menu_items,
171183
nav_menus,
184+
navigation_autosaves,
185+
navigation_revisions,
172186
navigations,
173187
plugins,
174188
post_revisions,
@@ -212,6 +226,8 @@ api_client_generate_endpoint_impl!(WpApi, menu_locations);
212226
api_client_generate_endpoint_impl!(WpApi, nav_menu_item_autosaves);
213227
api_client_generate_endpoint_impl!(WpApi, nav_menu_items);
214228
api_client_generate_endpoint_impl!(WpApi, nav_menus);
229+
api_client_generate_endpoint_impl!(WpApi, navigation_autosaves);
230+
api_client_generate_endpoint_impl!(WpApi, navigation_revisions);
215231
api_client_generate_endpoint_impl!(WpApi, navigations);
216232
api_client_generate_endpoint_impl!(WpApi, plugins);
217233
api_client_generate_endpoint_impl!(WpApi, post_revisions);

wp_api/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub mod middleware;
2222
pub mod nav_menu_item_revisions;
2323
pub mod nav_menu_items;
2424
pub mod nav_menus;
25+
pub mod navigation_revisions;
2526
pub mod navigations;
2627
pub mod parsed_url;
2728
pub mod plugins;

wp_api/src/navigation_revisions.rs

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
use crate::{
2+
UserId, WpApiParamOrder,
3+
date::WpGmtDateTime,
4+
impl_as_query_value_from_to_string,
5+
navigations::NavigationId,
6+
url_query::{
7+
AppendUrlQueryPairs, FromUrlQueryPairs, QueryPairs, QueryPairsExtension, UrlQueryPairsMap,
8+
},
9+
wp_content_i64_id,
10+
};
11+
use serde::{Deserialize, Serialize};
12+
use wp_contextual::WpContextual;
13+
use wp_derive::WpDeriveParamsField;
14+
15+
wp_content_i64_id!(NavigationRevisionId);
16+
17+
#[derive(
18+
Debug,
19+
Default,
20+
Clone,
21+
Copy,
22+
PartialEq,
23+
Eq,
24+
uniffi::Enum,
25+
strum_macros::EnumString,
26+
strum_macros::Display,
27+
)]
28+
#[strum(serialize_all = "snake_case")]
29+
pub enum WpApiParamNavigationRevisionsOrderBy {
30+
#[default]
31+
Date,
32+
Id,
33+
Include,
34+
IncludeSlugs,
35+
Relevance,
36+
Slug,
37+
Title,
38+
}
39+
40+
impl_as_query_value_from_to_string!(WpApiParamNavigationRevisionsOrderBy);
41+
42+
#[derive(Debug, Default, PartialEq, Eq, uniffi::Record, WpDeriveParamsField)]
43+
#[supports_pagination(true)]
44+
pub struct NavigationRevisionListParams {
45+
/// Current page of the collection.
46+
/// Default: `1`
47+
#[uniffi(default = None)]
48+
pub page: Option<u32>,
49+
/// Maximum number of items to be returned in result set.
50+
#[uniffi(default = None)]
51+
pub per_page: Option<u32>,
52+
/// Limit results to those matching a string.
53+
#[uniffi(default = None)]
54+
pub search: Option<String>,
55+
/// Ensure result set excludes specific IDs.
56+
#[uniffi(default = [])]
57+
pub exclude: Vec<NavigationRevisionId>,
58+
/// Limit result set to specific IDs.
59+
#[uniffi(default = [])]
60+
pub include: Vec<NavigationRevisionId>,
61+
/// Offset the result set by a specific number of items.
62+
#[uniffi(default = None)]
63+
pub offset: Option<u32>,
64+
/// Order sort attribute ascending or descending.
65+
/// Default: desc
66+
/// One of: asc, desc
67+
#[uniffi(default = None)]
68+
pub order: Option<WpApiParamOrder>,
69+
/// Sort collection by object attribute.
70+
/// Default: date
71+
/// One of: date, id, include, relevance, slug, include_slugs, title
72+
#[uniffi(default = None)]
73+
#[field_name("orderby")]
74+
pub orderby: Option<WpApiParamNavigationRevisionsOrderBy>,
75+
}
76+
77+
#[derive(Debug, Serialize, Deserialize, uniffi::Record, WpContextual)]
78+
pub struct SparseNavigationRevision {
79+
#[WpContext(edit, embed, view)]
80+
pub id: Option<NavigationRevisionId>,
81+
#[WpContext(edit, embed, view)]
82+
pub author: Option<UserId>,
83+
#[WpContext(edit, embed, view)]
84+
pub date: Option<String>,
85+
#[WpContext(edit, view)]
86+
pub date_gmt: Option<WpGmtDateTime>,
87+
#[WpContext(edit, view)]
88+
pub modified: Option<String>,
89+
#[WpContext(edit, view)]
90+
pub modified_gmt: Option<WpGmtDateTime>,
91+
#[WpContext(edit, embed, view)]
92+
pub parent: Option<NavigationId>,
93+
#[WpContext(edit, embed, view)]
94+
pub slug: Option<String>,
95+
#[WpContext(edit, view)]
96+
#[WpContextualField]
97+
pub guid: Option<crate::navigations::SparseNavigationGuid>,
98+
#[WpContext(edit, embed, view)]
99+
#[WpContextualField]
100+
pub title: Option<crate::navigations::SparseNavigationTitle>,
101+
#[WpContext(edit, view)]
102+
#[WpContextualField]
103+
pub content: Option<crate::navigations::SparseNavigationContent>,
104+
// meta field omitted for now
105+
}
106+
107+
#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
108+
pub struct NavigationRevisionDeleteResponse {
109+
pub deleted: bool,
110+
pub previous: NavigationRevisionWithEditContext,
111+
}

wp_api/src/post_revisions.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ pub struct SparseAnyPostRevision {
105105
#[WpContextualOption]
106106
pub excerpt: Option<crate::posts::SparsePostExcerpt>,
107107
#[WpContext(edit, view)]
108+
#[WpContextualOption]
108109
pub meta: Option<crate::posts::PostMeta>,
109110
}
110111

wp_api/src/posts.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
};
1212
use serde::{Deserialize, Serialize};
1313
use wp_contextual::WpContextual;
14-
use wp_derive::WpDeriveParamsField;
14+
use wp_derive::{WpDeriveParamsField, WpDeserialize};
1515
use wp_serde_helper::{deserialize_from_string_of_json_array, serialize_as_json_string};
1616

1717
#[derive(
@@ -474,11 +474,11 @@ pub struct SparsePostExcerpt {
474474
pub protected: Option<bool>,
475475
}
476476

477-
#[derive(Debug, Serialize, Deserialize, uniffi::Record)]
477+
#[derive(Debug, Serialize, WpDeserialize, uniffi::Record)]
478478
pub struct PostMeta {
479479
#[serde(deserialize_with = "deserialize_from_string_of_json_array")]
480480
#[serde(serialize_with = "serialize_as_json_string")]
481-
pub footnotes: Vec<PostFootnote>,
481+
pub footnotes: Option<Vec<PostFootnote>>,
482482
}
483483

484484
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, uniffi::Record)]

wp_api/src/request/endpoint.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ pub mod menu_locations_endpoint;
1111
pub mod nav_menu_item_autosaves_endpoint;
1212
pub mod nav_menu_items_endpoint;
1313
pub mod nav_menus_endpoint;
14+
pub mod navigation_autosaves_endpoint;
15+
pub mod navigation_revisions_endpoint;
1416
pub mod navigations_endpoint;
1517
pub mod plugins_endpoint;
1618
pub mod post_autosaves_endpoint;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use super::{AsNamespace, DerivedRequest, WpNamespace};
2+
use crate::{navigation_revisions::NavigationRevisionId, navigations::NavigationId};
3+
use wp_derive_request_builder::WpDerivedRequest;
4+
5+
#[derive(WpDerivedRequest)]
6+
enum NavigationAutosavesRequest {
7+
#[contextual_get(url = "/navigation/<navigation_id>/autosaves", output = Vec<crate::navigation_revisions::SparseNavigationRevision>, filter_by = crate::navigation_revisions::SparseNavigationRevisionField)]
8+
List,
9+
#[contextual_get(url = "/navigation/<navigation_id>/autosaves/<navigation_revision_id>", output = crate::navigation_revisions::SparseNavigationRevision, filter_by = crate::navigation_revisions::SparseNavigationRevisionField)]
10+
Retrieve,
11+
#[post(url = "/navigation/<navigation_id>/autosaves", params = &crate::navigations::NavigationCreateParams, output = crate::navigation_revisions::NavigationRevisionWithEditContext)]
12+
Create,
13+
}
14+
15+
impl DerivedRequest for NavigationAutosavesRequest {
16+
fn namespace() -> impl AsNamespace {
17+
WpNamespace::WpV2
18+
}
19+
}

0 commit comments

Comments
 (0)