From ea3f59b595503b339cce20060b1a7c29dbd89c3c Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 28 Nov 2025 11:01:39 -0500 Subject: [PATCH 1/5] Use JsonValue for post type supports field WordPress 6.9 returns post type supports as either bool or array, so we use JsonValue wrapped in PostTypeSupportsValue for flexibility. Changes: - Add PostTypeSupportsValue type wrapping JsonValue - Update PostTypeSupportsMap to use Arc - Update test assertion to use as_json_bool() method --- wp_api/src/post_types.rs | 26 +++++++++++++++++-- .../tests/test_post_types_immut.rs | 8 ++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/wp_api/src/post_types.rs b/wp_api/src/post_types.rs index b905d5c50..370ba0be6 100644 --- a/wp_api/src/post_types.rs +++ b/wp_api/src/post_types.rs @@ -1,7 +1,8 @@ -use crate::impl_as_query_value_from_to_string; +use crate::{JsonValue, impl_as_query_value_from_to_string}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::str::FromStr; +use std::sync::Arc; use wp_contextual::WpContextual; use wp_serde_helper::deserialize_empty_array_or_hashmap; @@ -97,7 +98,28 @@ pub struct PostTypeSupportsMap { #[serde(deserialize_with = "deserialize_empty_array_or_hashmap")] #[serde(flatten)] #[serde(rename = "supports")] - pub map: HashMap, + pub map: HashMap>, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, uniffi::Object)] +#[serde(transparent)] +pub struct PostTypeSupportsValue { + #[serde(flatten)] + pub json_value: JsonValue, +} + +#[uniffi::export] +impl PostTypeSupportsValue { + fn as_json_value(&self) -> JsonValue { + self.json_value.clone() + } + + pub fn as_json_bool(&self) -> Option { + match self.json_value { + JsonValue::Bool(b) => Some(b), + _ => None, + } + } } #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, uniffi::Record)] diff --git a/wp_api_integration_tests/tests/test_post_types_immut.rs b/wp_api_integration_tests/tests/test_post_types_immut.rs index 140cba347..7c142acf8 100644 --- a/wp_api_integration_tests/tests/test_post_types_immut.rs +++ b/wp_api_integration_tests/tests/test_post_types_immut.rs @@ -93,8 +93,12 @@ async fn retrieve_post_types_with_edit_context( // post types might not support `Title` in which case it's perfectly fine to completely // remove this assertion. assert_eq!( - post_type.supports.map.get(&PostTypeSupports::Title), - Some(true).as_ref() + post_type + .supports + .map + .get(&PostTypeSupports::Title) + .and_then(|v| v.as_json_bool()), + Some(true) ); // All post types in our current testing sites have `EditPost` capability, so we use this // assertion to verify that we are able to parse `capabilities` field properly. From d6bc53d50f97b7486d7dc4e3f35f6abfd0c5d7f0 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Fri, 28 Nov 2025 14:27:37 -0500 Subject: [PATCH 2/5] Update Kotlin test to use asJsonBool() for post type supports --- .../kotlin/src/integrationTest/kotlin/PostTypesEndpointTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/kotlin/api/kotlin/src/integrationTest/kotlin/PostTypesEndpointTest.kt b/native/kotlin/api/kotlin/src/integrationTest/kotlin/PostTypesEndpointTest.kt index f954e8037..201d653f4 100644 --- a/native/kotlin/api/kotlin/src/integrationTest/kotlin/PostTypesEndpointTest.kt +++ b/native/kotlin/api/kotlin/src/integrationTest/kotlin/PostTypesEndpointTest.kt @@ -26,7 +26,7 @@ class PostTypesEndpointTest { val postTypesPost = client.request { requestBuilder -> requestBuilder.postTypes().retrieveWithEditContext(PostType.Post) }.assertSuccessAndRetrieveData().data - assert(postTypesPost.supports.map[PostTypeSupports.Title]!!) + assert(postTypesPost.supports.map[PostTypeSupports.Title]!!.asJsonBool()!!) assertFalse(postTypesPost.capabilities[PostTypeCapabilities.EditPosts]!!.isEmpty()) } From 1f1b288b4c69f981f795f2a3fa262ab402c0f867 Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Tue, 9 Dec 2025 13:16:50 -0500 Subject: [PATCH 3/5] Add post_type_supports helper to check feature support Add a `supports` method to `PostTypeSupportsMap` for Rust usage and a `post_type_supports` free function for FFI clients to check if a post type supports a specific feature by key presence. Includes documentation explaining the assumption that key presence implies support, regardless of the associated value. --- wp_api/src/post_types.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/wp_api/src/post_types.rs b/wp_api/src/post_types.rs index 370ba0be6..d8fc6cf31 100644 --- a/wp_api/src/post_types.rs +++ b/wp_api/src/post_types.rs @@ -101,6 +101,28 @@ pub struct PostTypeSupportsMap { pub map: HashMap>, } +impl PostTypeSupportsMap { + /// Check if the post type supports a specific feature by checking if the key is present. + /// + /// Note: This only checks for key presence, not the associated value. WordPress typically + /// includes a feature in the map with a `true` value when supported, and omits it entirely + /// when not supported. The value can also be an object with additional configuration (e.g., + /// `editor` may have nested settings). We assume that if a key is present, the feature is + /// supported, regardless of the actual value. + pub fn supports(&self, feature: &PostTypeSupports) -> bool { + self.map.contains_key(feature) + } +} + +/// Check if a post type supports a specific feature by checking if the key is present. +/// +/// Note: This only checks for key presence, not the associated value. See +/// `PostTypeSupportsMap::supports` for details on this assumption. +#[uniffi::export] +fn post_type_supports(supports_map: &PostTypeSupportsMap, feature: PostTypeSupports) -> bool { + supports_map.supports(&feature) +} + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, uniffi::Object)] #[serde(transparent)] pub struct PostTypeSupportsValue { From 76f7aa69265a95234450d34ed6e27a4c64382f8d Mon Sep 17 00:00:00 2001 From: Oguz Kocer Date: Wed, 17 Dec 2025 16:20:29 -0500 Subject: [PATCH 4/5] Replace PostTypeSupportsValue with JsonValue directly Simplify post type supports by using JsonValue directly instead of the PostTypeSupportsValue wrapper type. Tests now use the supports method on PostTypeSupportsMap to check feature support. Changes: - Change PostTypeSupportsMap.map from HashMap<_, Arc> to HashMap<_, JsonValue> - Remove PostTypeSupportsValue struct and its impl block - Update Rust test to use supports method directly - Update Kotlin test to use postTypeSupports helper --- .../kotlin/PostTypesEndpointTest.kt | 3 ++- wp_api/src/post_types.rs | 24 +------------------ .../tests/test_post_types_immut.rs | 9 +------ 3 files changed, 4 insertions(+), 32 deletions(-) diff --git a/native/kotlin/api/kotlin/src/integrationTest/kotlin/PostTypesEndpointTest.kt b/native/kotlin/api/kotlin/src/integrationTest/kotlin/PostTypesEndpointTest.kt index 201d653f4..7f210cb73 100644 --- a/native/kotlin/api/kotlin/src/integrationTest/kotlin/PostTypesEndpointTest.kt +++ b/native/kotlin/api/kotlin/src/integrationTest/kotlin/PostTypesEndpointTest.kt @@ -6,6 +6,7 @@ import uniffi.wp_api.PostType import uniffi.wp_api.PostTypeCapabilities import uniffi.wp_api.PostTypeSupports import uniffi.wp_api.WpErrorCode +import uniffi.wp_api.postTypeSupports import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertNull @@ -26,7 +27,7 @@ class PostTypesEndpointTest { val postTypesPost = client.request { requestBuilder -> requestBuilder.postTypes().retrieveWithEditContext(PostType.Post) }.assertSuccessAndRetrieveData().data - assert(postTypesPost.supports.map[PostTypeSupports.Title]!!.asJsonBool()!!) + assert(postTypeSupports(postTypesPost.supports, PostTypeSupports.Title)) assertFalse(postTypesPost.capabilities[PostTypeCapabilities.EditPosts]!!.isEmpty()) } diff --git a/wp_api/src/post_types.rs b/wp_api/src/post_types.rs index d8fc6cf31..54f378fe9 100644 --- a/wp_api/src/post_types.rs +++ b/wp_api/src/post_types.rs @@ -2,7 +2,6 @@ use crate::{JsonValue, impl_as_query_value_from_to_string}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::str::FromStr; -use std::sync::Arc; use wp_contextual::WpContextual; use wp_serde_helper::deserialize_empty_array_or_hashmap; @@ -98,7 +97,7 @@ pub struct PostTypeSupportsMap { #[serde(deserialize_with = "deserialize_empty_array_or_hashmap")] #[serde(flatten)] #[serde(rename = "supports")] - pub map: HashMap>, + pub map: HashMap, } impl PostTypeSupportsMap { @@ -123,27 +122,6 @@ fn post_type_supports(supports_map: &PostTypeSupportsMap, feature: PostTypeSuppo supports_map.supports(&feature) } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, uniffi::Object)] -#[serde(transparent)] -pub struct PostTypeSupportsValue { - #[serde(flatten)] - pub json_value: JsonValue, -} - -#[uniffi::export] -impl PostTypeSupportsValue { - fn as_json_value(&self) -> JsonValue { - self.json_value.clone() - } - - pub fn as_json_bool(&self) -> Option { - match self.json_value { - JsonValue::Bool(b) => Some(b), - _ => None, - } - } -} - #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, uniffi::Record)] pub struct PostTypeLabels { pub name: String, diff --git a/wp_api_integration_tests/tests/test_post_types_immut.rs b/wp_api_integration_tests/tests/test_post_types_immut.rs index 7c142acf8..532df4b91 100644 --- a/wp_api_integration_tests/tests/test_post_types_immut.rs +++ b/wp_api_integration_tests/tests/test_post_types_immut.rs @@ -92,14 +92,7 @@ async fn retrieve_post_types_with_edit_context( // It's possible that we might have more test sites in the future and some of their // post types might not support `Title` in which case it's perfectly fine to completely // remove this assertion. - assert_eq!( - post_type - .supports - .map - .get(&PostTypeSupports::Title) - .and_then(|v| v.as_json_bool()), - Some(true) - ); + assert!(post_type.supports.supports(&PostTypeSupports::Title)); // All post types in our current testing sites have `EditPost` capability, so we use this // assertion to verify that we are able to parse `capabilities` field properly. // From 3bd21912fe461a22f5de885256fe78b17c125310 Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Wed, 17 Dec 2025 16:13:27 -0700 Subject: [PATCH 5/5] Add Swift support --- native/swift/Sources/wordpress-api/Extensions.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/native/swift/Sources/wordpress-api/Extensions.swift b/native/swift/Sources/wordpress-api/Extensions.swift index 93c80cf02..30db47e8f 100644 --- a/native/swift/Sources/wordpress-api/Extensions.swift +++ b/native/swift/Sources/wordpress-api/Extensions.swift @@ -122,3 +122,13 @@ extension PostType: ExpressibleByStringLiteral { self.init(stringLiteral) } } + +public extension PostTypeSupportsMap { + func supports(_ feature: PostTypeSupports) -> Bool { + postTypeSupports(supportsMap: self, feature: feature) + } + + func supports(_ feature: String) -> Bool { + postTypeSupports(supportsMap: self, feature: .custom(feature)) + } +}