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
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import org.wordpress.android.fluxc.network.rest.wpapi.rs.WpApiClientProvider
import org.wordpress.android.fluxc.store.TaxonomyStore
import org.wordpress.android.fluxc.store.TaxonomyStore.DEFAULT_TAXONOMY_TAG
import org.wordpress.android.fluxc.store.TaxonomyStore.FetchTermsResponsePayload
import org.wordpress.android.fluxc.store.TaxonomyStore.RemoteTermPayload
import org.wordpress.android.fluxc.store.TaxonomyStore.TaxonomyError
import org.wordpress.android.fluxc.store.TaxonomyStore.TaxonomyErrorType
import org.wordpress.android.fluxc.utils.AppLogWrapper
import org.wordpress.android.util.AppLog
import rs.wordpress.api.kotlin.WpRequestResult
import uniffi.wp_api.CategoryCreateParams
import uniffi.wp_api.CategoryListParams
import uniffi.wp_api.TagListParams
import javax.inject.Inject
Expand All @@ -30,6 +32,52 @@ class TaxonomyRsApiRestClient @Inject constructor(
private val appLogWrapper: AppLogWrapper,
private val wpApiClientProvider: WpApiClientProvider,
) {
fun createPostCategory(site: SiteModel, term: TermModel) {
scope.launch {
val client = wpApiClientProvider.getWpApiClient(site)

val categoriesResponse = client.request { requestBuilder ->
requestBuilder.categories().create(
CategoryCreateParams(
name = term.name,
description = term.description,
slug = term.slug,
parent = term.parentRemoteId
)
)
}

when (categoriesResponse) {
is WpRequestResult.Success -> {
val category = categoriesResponse.response.data
appLogWrapper.d(AppLog.T.POSTS, "Created category: ${category.name}")
val payload = RemoteTermPayload(
TermModel(
category.id.toInt(),
site.id,
category.id,
TaxonomyStore.DEFAULT_TAXONOMY_CATEGORY,
category.name,
category.slug,
category.description,
category.parent,
category.count.toInt()
),
site
)
notifyTermCreated(payload)
}

else -> {
appLogWrapper.e(AppLog.T.POSTS, "Failed creating category: $categoriesResponse")
val payload = RemoteTermPayload(term, site)
payload.error = TaxonomyError(TaxonomyErrorType.GENERIC_ERROR, "")
notifyTermCreated(payload)
}
}
}
}

fun fetchPostCategories(site: SiteModel) {
scope.launch {
val client = wpApiClientProvider.getWpApiClient(site)
Expand Down Expand Up @@ -124,6 +172,12 @@ class TaxonomyRsApiRestClient @Inject constructor(
dispatcher.dispatch(TaxonomyActionBuilder.newFetchedTermsAction(payload))
}

private fun notifyTermCreated(
payload: RemoteTermPayload,
) {
dispatcher.dispatch(TaxonomyActionBuilder.newPushedTermAction(payload))
}

private fun createTermsResponsePayload(
terms: List<TermModel>,
site: SiteModel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,10 +426,11 @@ private void handlePushTermCompleted(@NonNull RemoteTermPayload payload) {
}

private void pushTerm(@NonNull RemoteTermPayload payload) {
if (payload.site.isUsingWpComRestApi()) {
if (payload.site.isUsingSelfHostedRestApi() && DEFAULT_TAXONOMY_CATEGORY.equals(payload.term.getTaxonomy())) {
mTaxonomyRsApiRestClient.createPostCategory(payload.site, payload.term);
} else if (payload.site.isUsingWpComRestApi()) {
mTaxonomyRestClient.pushTerm(payload.term, payload.site);
} else {
// TODO: check for WP-REST-API plugin and use it here
mTaxonomyXMLRPCClient.pushTerm(payload.term, payload.site);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@ import org.wordpress.android.fluxc.action.TaxonomyAction
import org.wordpress.android.fluxc.annotations.action.Action
import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.network.rest.wpapi.rs.WpApiClientProvider
import org.wordpress.android.fluxc.model.TermModel
import org.wordpress.android.fluxc.store.TaxonomyStore.FetchTermsResponsePayload
import org.wordpress.android.fluxc.store.TaxonomyStore.RemoteTermPayload
import org.wordpress.android.fluxc.store.TaxonomyStore.TaxonomyErrorType
import org.wordpress.android.fluxc.utils.AppLogWrapper
import rs.wordpress.api.kotlin.WpApiClient
import rs.wordpress.api.kotlin.WpRequestResult
import uniffi.wp_api.CategoryWithEditContext
import uniffi.wp_api.CategoriesRequestCreateResponse
import uniffi.wp_api.CategoriesRequestListWithEditContextResponse
import uniffi.wp_api.TagWithEditContext
import uniffi.wp_api.TagsRequestListWithEditContextResponse
Expand All @@ -56,6 +59,18 @@ class TaxonomyRsApiRestClientTest {
url = "https://test.wordpress.com"
}

private val testTermModel = TermModel(
1, // id
123, // localSiteId
2L, // remoteTermId
"category", // taxonomy
"Test Category", // name
"test-category", // slug
"Test category description", // description
0L, // parentRemoteId
0 // postCount
)

private val testTagTaxonomyName = "post_tag"
private val testCategoryTaxonomyName = "category"

Expand Down Expand Up @@ -199,6 +214,70 @@ class TaxonomyRsApiRestClientTest {
assertNull(payload.error)
}

@Test
fun `createPostCategory with error response dispatches error action`() = runTest {
// Use a concrete error type that we can create - UnknownError requires statusCode and response
val errorResponse = WpRequestResult.UnknownError<Any>(
statusCode = 500u,
response = "Internal Server Error"
)

whenever(wpApiClient.request<Any>(any())).thenReturn(errorResponse)

taxonomyClient.createPostCategory(testSite, testTermModel)

// Verify dispatcher was called with error action
val actionCaptor = ArgumentCaptor.forClass(Action::class.java)
verify(dispatcher).dispatch(actionCaptor.capture())

val capturedAction = actionCaptor.value
val payload = capturedAction.payload as RemoteTermPayload
assertEquals(capturedAction.type, TaxonomyAction.PUSHED_TERM)
assertEquals(testSite, payload.site)
assertEquals(testTermModel, payload.term)
assertNotNull(payload.error)
assertEquals(TaxonomyErrorType.GENERIC_ERROR, payload.error?.type)
}

@Test
fun `createPostCategory with success response dispatches success action`() = runTest {
val categoryWithEditContext = createTestCategoryWithEditContext()

// Create the correct response structure following the MediaRSApiRestClientTest pattern
val categoryResponse = CategoriesRequestCreateResponse(
categoryWithEditContext,
mock<WpNetworkHeaderMap>()
)

val successResponse: WpRequestResult<CategoriesRequestCreateResponse> = WpRequestResult.Success(
response = categoryResponse
)

whenever(wpApiClient.request<CategoriesRequestCreateResponse>(any())).thenReturn(successResponse)

taxonomyClient.createPostCategory(testSite, testTermModel)

// Verify dispatcher was called with success action
val actionCaptor = ArgumentCaptor.forClass(Action::class.java)
verify(dispatcher).dispatch(actionCaptor.capture())

val capturedAction = actionCaptor.value
val payload = capturedAction.payload as RemoteTermPayload
assertEquals(capturedAction.type, TaxonomyAction.PUSHED_TERM)
assertEquals(testSite, payload.site)
assertNotNull(payload.term)
// Verify the created term has the correct properties
assertEquals(categoryWithEditContext.id.toInt(), payload.term.id)
assertEquals(testSite.id, payload.term.localSiteId)
assertEquals(categoryWithEditContext.id, payload.term.remoteTermId)
assertEquals(testCategoryTaxonomyName, payload.term.taxonomy)
assertEquals(categoryWithEditContext.name, payload.term.name)
assertEquals(categoryWithEditContext.slug, payload.term.slug)
assertEquals(categoryWithEditContext.description, payload.term.description)
assertEquals(categoryWithEditContext.count.toInt(), payload.term.postCount)
assertNull(payload.error)
}

private fun createTestCategoryWithEditContext(): CategoryWithEditContext {
return CategoryWithEditContext(
id = 2L,
Expand Down