Skip to content

Commit ed4e15e

Browse files
authored
CIF-2864: support querying category by url_path (#899)
* CIF-2864: support querying category by url_path * format code * fix tests in example bundle * update comment * format code
1 parent ae443e7 commit ed4e15e

9 files changed

Lines changed: 94 additions & 25 deletions

File tree

bundles/core/src/main/java/com/adobe/cq/commerce/core/components/internal/services/UrlProviderImpl.java

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -442,20 +442,28 @@ public String getCategoryIdentifier(SlingHttpServletRequest request) {
442442

443443
if (StringUtils.isNotEmpty(categoryIdentifiers.getUid())) {
444444
identifier = categoryIdentifiers.getUid();
445-
} else if (StringUtils.isNotEmpty(categoryIdentifiers.getUrlKey())) {
446-
// lookup internal product identifier (sku) based on URL product identifier
447-
// (url_key)
445+
} else {
446+
// lookup internal category identifier (uid) based on URL category identifier (url_path or url_key, depending on the
447+
// url format)
448448
MagentoGraphqlClient magentoGraphqlClient = request.adaptTo(MagentoGraphqlClient.class);
449-
if (magentoGraphqlClient != null) {
450-
UrlToCategoryRetriever categoryRetriever = new UrlToCategoryRetriever(magentoGraphqlClient);
449+
if (magentoGraphqlClient == null) {
450+
LOGGER.warn("No backend GraphQL client provided, cannot retrieve category identifier for {}", request.getRequestURL()
451+
.toString());
452+
return null;
453+
}
454+
455+
UrlToCategoryRetriever categoryRetriever = null;
456+
457+
if (StringUtils.isNotEmpty(categoryIdentifiers.getUrlPath())) {
458+
categoryRetriever = new UrlToCategoryRetriever.ByUrlPath(magentoGraphqlClient);
459+
categoryRetriever.setIdentifier(categoryIdentifiers.getUrlPath());
460+
} else if (StringUtils.isNotEmpty(categoryIdentifiers.getUrlKey())) {
461+
categoryRetriever = new UrlToCategoryRetriever.ByUrlKey(magentoGraphqlClient);
451462
categoryRetriever.setIdentifier(categoryIdentifiers.getUrlKey());
452-
CategoryInterface category = categoryRetriever.fetchCategory();
453-
identifier = category != null ? category.getUid().toString() : null;
454-
} else {
455-
LOGGER.warn("No backend GraphQL client provided, cannot retrieve product identifier for {}",
456-
request.getRequestURL()
457-
.toString());
458463
}
464+
465+
CategoryInterface category = categoryRetriever != null ? categoryRetriever.fetchCategory() : null;
466+
identifier = category != null ? category.getUid().toString() : null;
459467
}
460468

461469
if (identifier != null) {

bundles/core/src/main/java/com/adobe/cq/commerce/core/components/internal/services/UrlToCategoryRetriever.java

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,48 @@
2323
import com.adobe.cq.commerce.magento.graphql.Operations;
2424
import com.adobe.cq.commerce.magento.graphql.QueryQuery;
2525

26-
class UrlToCategoryRetriever extends AbstractCategoryRetriever {
26+
abstract class UrlToCategoryRetriever extends AbstractCategoryRetriever {
2727

28-
UrlToCategoryRetriever(MagentoGraphqlClient client) {
28+
private UrlToCategoryRetriever(MagentoGraphqlClient client) {
2929
super(client);
3030
}
3131

32+
@Override
33+
protected CategoryTreeQueryDefinition generateCategoryQuery() {
34+
return q -> q.uid();
35+
}
36+
3237
@Override
3338
public String generateQuery(String identifier) {
3439
CategoryTreeQueryDefinition queryArgs = generateCategoryQuery();
3540
return Operations.query(query -> {
36-
CategoryFilterInput filter = new CategoryFilterInput().setUrlKey(new FilterEqualTypeInput().setEq(identifier));
41+
CategoryFilterInput filter = generateCategoryFilterInput();
3742
QueryQuery.CategoryListArgumentsDefinition searchArgs = s -> s.filters(filter);
3843
query.categoryList(searchArgs, queryArgs);
3944
}).toString();
4045
}
4146

42-
@Override
43-
protected CategoryTreeQueryDefinition generateCategoryQuery() {
44-
return q -> q.uid();
47+
protected abstract CategoryFilterInput generateCategoryFilterInput();
48+
49+
static class ByUrlKey extends UrlToCategoryRetriever {
50+
ByUrlKey(MagentoGraphqlClient client) {
51+
super(client);
52+
}
53+
54+
@Override
55+
protected CategoryFilterInput generateCategoryFilterInput() {
56+
return new CategoryFilterInput().setUrlKey(new FilterEqualTypeInput().setEq(identifier));
57+
}
58+
}
59+
60+
static class ByUrlPath extends UrlToCategoryRetriever {
61+
ByUrlPath(MagentoGraphqlClient client) {
62+
super(client);
63+
}
64+
65+
@Override
66+
protected CategoryFilterInput generateCategoryFilterInput() {
67+
return new CategoryFilterInput().setUrlPath(new FilterEqualTypeInput().setEq(identifier));
68+
}
4569
}
4670
}

bundles/core/src/test/java/com/adobe/cq/commerce/core/components/internal/models/v1/breadcrumb/BreadcrumbImplTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ public void testProductSpecificPageOnLaunch() throws Exception {
290290
@Test
291291
public void testCategoryPage() throws Exception {
292292
Utils.setupHttpResponse("graphql/magento-graphql-category-uid.json", httpClient, HttpStatus.SC_OK,
293-
"{categoryList(filters:{url_key");
293+
"{categoryList(filters:{url_path");
294294
Utils.setupHttpResponse("graphql/magento-graphql-category-breadcrumb-result.json", httpClient, HttpStatus.SC_OK,
295295
"{categoryList(filters:{category_uid");
296296
prepareModel("/content/venia/us/en/products/category-page");
@@ -314,7 +314,7 @@ public void testCategoryPage() throws Exception {
314314
@Test
315315
public void testCategorySpecificPage() throws Exception {
316316
Utils.setupHttpResponse("graphql/magento-graphql-category-uid.json", httpClient, HttpStatus.SC_OK,
317-
"{categoryList(filters:{url_key");
317+
"{categoryList(filters:{url_path");
318318
Utils.setupHttpResponse("graphql/magento-graphql-category-breadcrumb-result.json", httpClient, HttpStatus.SC_OK,
319319
"{categoryList(filters:{category_uid");
320320
prepareModel("/content/venia/us/en/products/category-page/category-specific-page");

bundles/core/src/test/java/com/adobe/cq/commerce/core/components/internal/models/v1/contentfragment/CommerceContentFragmentImplTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public void setup() throws Exception {
115115
Utils.setupHttpResponse("graphql/magento-graphql-product-sku.json", httpClient, HttpStatus.SC_OK, "{products(filter:{url_key");
116116
Utils.setupHttpResponse("graphql/magento-graphql-cf-category.json", httpClient, HttpStatus.SC_OK, "url_key\"}}){uid}}");
117117
Utils.setupHttpResponse("graphql/magento-graphql-category-uid.json", httpClient, HttpStatus.SC_OK,
118-
"{categoryList(filters:{url_key");
118+
"{categoryList(filters:{url_path");
119119

120120
prepareContentFragment(resourceResolver);
121121

bundles/core/src/test/java/com/adobe/cq/commerce/core/components/internal/models/v1/page/PageMetadataImplTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ private void testPageMetadataModelOnCategoryPage(String pagePath) throws Excepti
271271
Utils.setupHttpResponse("graphql/magento-graphql-introspection-result.json", httpClient, HttpStatus.SC_OK, "{__type");
272272
Utils.setupHttpResponse("graphql/magento-graphql-attributes-result.json", httpClient, HttpStatus.SC_OK, "{customAttributeMetadata");
273273
Utils.setupHttpResponse("graphql/magento-graphql-category-uid.json", httpClient, HttpStatus.SC_OK,
274-
"{categoryList(filters:{url_key");
274+
"{categoryList(filters:{url_path");
275275
Utils.setupHttpResponse("graphql/magento-graphql-search-category-result-category.json", httpClient, HttpStatus.SC_OK,
276276
"{categoryList(filters:{category_uid");
277277
Utils.setupHttpResponse("graphql/magento-graphql-search-category-result-products.json", httpClient, HttpStatus.SC_OK,

bundles/core/src/test/java/com/adobe/cq/commerce/core/components/internal/models/v1/productlist/ProductListImplTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ public void setUp() throws Exception {
142142
Utils.setupHttpResponse("graphql/magento-graphql-introspection-result.json", httpClient, HttpStatus.SC_OK, "{__type");
143143
Utils.setupHttpResponse("graphql/magento-graphql-attributes-result.json", httpClient, HttpStatus.SC_OK, "{customAttributeMetadata");
144144
Utils.setupHttpResponse("graphql/magento-graphql-category-uid.json", httpClient, HttpStatus.SC_OK,
145-
"{categoryList(filters:{url_key");
145+
"{categoryList(filters:{url_path");
146146
Utils.setupHttpResponse("graphql/magento-graphql-search-category-result-category.json", httpClient, HttpStatus.SC_OK,
147147
"{categoryList(filters:{category_uid");
148148
Utils.setupHttpResponse("graphql/magento-graphql-search-category-result-products.json", httpClient, HttpStatus.SC_OK, "{products");
@@ -331,7 +331,7 @@ public void testFilterQueriesReturnNull() throws IOException {
331331
Utils.setupHttpResponse("graphql/magento-graphql-empty-data.json", httpClient, HttpStatus.SC_OK, "{customAttributeMetadata");
332332
Utils.setupHttpResponse("graphql/magento-graphql-search-category-result-products.json", httpClient, HttpStatus.SC_OK, "{products");
333333
Utils.setupHttpResponse("graphql/magento-graphql-category-uid.json", httpClient, HttpStatus.SC_OK,
334-
"{categoryList(filters:{url_key");
334+
"{categoryList(filters:{url_path");
335335
Utils.setupHttpResponse("graphql/magento-graphql-search-category-result-category.json", httpClient, HttpStatus.SC_OK,
336336
"{categoryList(filters:{category_uid");
337337

bundles/core/src/test/java/com/adobe/cq/commerce/core/components/internal/services/UrlProviderImplTest.java

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@
3838
import org.junit.Before;
3939
import org.junit.Rule;
4040
import org.junit.Test;
41+
import org.mockito.ArgumentCaptor;
4142
import org.mockito.internal.util.reflection.Whitebox;
4243

4344
import com.adobe.cq.commerce.core.MockHttpClientBuilderFactory;
4445
import com.adobe.cq.commerce.core.components.internal.services.urlformats.CategoryPageWithUrlKey;
46+
import com.adobe.cq.commerce.core.components.internal.services.urlformats.CategoryPageWithUrlPath;
4547
import com.adobe.cq.commerce.core.components.internal.services.urlformats.ProductPageWithCategoryAndUrlKey;
4648
import com.adobe.cq.commerce.core.components.internal.services.urlformats.ProductPageWithSku;
4749
import com.adobe.cq.commerce.core.components.internal.services.urlformats.ProductPageWithSkuAndUrlKey;
@@ -54,6 +56,7 @@
5456
import com.adobe.cq.commerce.core.components.services.urls.UrlProvider.ParamsBuilder;
5557
import com.adobe.cq.commerce.core.testing.Utils;
5658
import com.adobe.cq.commerce.graphql.client.GraphqlClient;
59+
import com.adobe.cq.commerce.graphql.client.GraphqlRequest;
5760
import com.adobe.cq.commerce.graphql.client.impl.GraphqlClientImpl;
5861
import com.adobe.cq.commerce.magento.graphql.UrlRewrite;
5962
import com.day.cq.wcm.api.Page;
@@ -104,6 +107,8 @@ public void setup() throws Exception {
104107
"{categoryList(filters:{category_uid:{eq:\"uid-5\"}}");
105108
Utils.setupHttpResponse("graphql/magento-graphql-empty-data.json", httpClient, HttpStatus.SC_OK,
106109
"{categoryList(filters:{category_uid:{eq:\"uid-99\"}}");
110+
Utils.setupHttpResponse("graphql/magento-graphql-category-uid.json", httpClient, HttpStatus.SC_OK,
111+
"{categoryList(filters:{url_path:{eq:\"men/tops-men/jackets-men\"}}");
107112
// from url_path men/tops-men/jackets-men
108113
Utils.setupHttpResponse("graphql/magento-graphql-category-uid.json", httpClient, HttpStatus.SC_OK,
109114
"{categoryList(filters:{url_key:{eq:\"jackets-men\"}}");
@@ -513,17 +518,44 @@ public void testProductIdentifierParsingInSuffixSKU() {
513518

514519
@Test
515520
public void testCategoryIdentifierParsingUrlPath() {
521+
ArgumentCaptor<GraphqlRequest> reqCaptor = ArgumentCaptor.forClass(GraphqlRequest.class);
516522
context.currentPage("/content/catalog-page");
517523
MockRequestPathInfo requestPathInfo = (MockRequestPathInfo) context.request().getRequestPathInfo();
518524
requestPathInfo.setSuffix("/men/tops-men/jackets-men");
525+
MockOsgi.deactivate(urlProvider, context.bundleContext());
526+
MockOsgi.activate(urlProvider, context.bundleContext(), "categoryPageUrlFormat", CategoryPageWithUrlPath.PATTERN);
519527

520528
String identifier = urlProvider.getCategoryIdentifier(context.request());
521529
assertEquals("MTI==", identifier);
522530
// second access should be cached in request attributes
523531
identifier = urlProvider.getCategoryIdentifier(context.request());
524532
assertEquals("MTI==", identifier);
525533

526-
verify(graphqlClient, times(1)).execute(any(), any(), any(), any());
534+
verify(graphqlClient, times(1)).execute(reqCaptor.capture(), any(), any(), any());
535+
536+
GraphqlRequest gqlReq = reqCaptor.getValue();
537+
assertEquals("{categoryList(filters:{url_path:{eq:\"men/tops-men/jackets-men\"}}){uid}}", gqlReq.getQuery());
538+
}
539+
540+
@Test
541+
public void testCategoryIdentifierParsingUrlKey() {
542+
ArgumentCaptor<GraphqlRequest> reqCaptor = ArgumentCaptor.forClass(GraphqlRequest.class);
543+
context.currentPage("/content/catalog-page");
544+
MockRequestPathInfo requestPathInfo = (MockRequestPathInfo) context.request().getRequestPathInfo();
545+
requestPathInfo.setSuffix("/jackets-men");
546+
MockOsgi.deactivate(urlProvider, context.bundleContext());
547+
MockOsgi.activate(urlProvider, context.bundleContext(), "categoryPageUrlFormat", CategoryPageWithUrlKey.PATTERN);
548+
549+
String identifier = urlProvider.getCategoryIdentifier(context.request());
550+
assertEquals("MTI==", identifier);
551+
// second access should be cached in request attributes
552+
identifier = urlProvider.getCategoryIdentifier(context.request());
553+
assertEquals("MTI==", identifier);
554+
555+
verify(graphqlClient, times(1)).execute(reqCaptor.capture(), any(), any(), any());
556+
557+
GraphqlRequest gqlReq = reqCaptor.getValue();
558+
assertEquals("{categoryList(filters:{url_key:{eq:\"jackets-men\"}}){uid}}", gqlReq.getQuery());
527559
}
528560

529561
@Test

bundles/core/src/test/java/com/adobe/cq/commerce/core/components/internal/servlets/CatalogPageNotFoundFilterTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public void setup() throws IOException {
111111
Utils.setupHttpResponse("graphql/magento-graphql-product-sku.json", httpClient, HttpStatus.SC_OK,
112112
"{products(filter:{url_key:{eq:\"beaumont-summit-kit\"}}");
113113
Utils.setupHttpResponse("graphql/magento-graphql-category-uid.json", httpClient, HttpStatus.SC_OK,
114-
"{categoryList(filters:{url_key:{eq:\"jackets-men\"}}");
114+
"{categoryList(filters:{url_path:{eq:\"men/tops-men/jackets-men\"}}");
115115
Utils.setupHttpResponse("graphql/magento-graphql-category-list-result.json", httpClient, HttpStatus.SC_OK,
116116
"{categoryList(filters:{category_uid:{eq:\"MTI==\"}}");
117117
Utils.setupHttpResponse(null, httpClient, HttpStatus.SC_NOT_FOUND, "url_key:{eq:\"does-not-exist\"}}");

examples/bundle/src/main/java/com/adobe/cq/commerce/core/examples/servlets/GraphqlServlet.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,11 @@ private List<CategoryTree> readCategoryListResponse(DataFetchingEnvironment env)
473473
Map<String, Map<String, Object>> filters = env.getArgument("filters");
474474
DataFetchingFieldSelectionSet selectionSet = env.getSelectionSet();
475475

476+
if (filters.containsKey("url_path") && !filters.containsKey("url_key")) {
477+
// handle the url_path as url_key in order to simplify the query resolution logic
478+
filters.put("url_key", filters.get("url_path"));
479+
}
480+
476481
// Only category the Breadcrumb components selects this field
477482
if (selectionSet.contains("breadcrumbs")) {
478483
graphqlResponse = readGraphqlResponse(CATEGORYLIST_BREADCRUMB_JSON);

0 commit comments

Comments
 (0)