Skip to content

Commit

Permalink
CIF-2895 - Extend product retriever with hook for product filters (#938)
Browse files Browse the repository at this point in the history
* Extend product retriever with hook for product filters
* Add filter hooks to retrievers
* Update Magento GraphQL schema version
  • Loading branch information
herzog31 authored Jul 13, 2022
1 parent e1923ba commit 1bc2813
Show file tree
Hide file tree
Showing 14 changed files with 406 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.util.Collections;
import java.util.List;
import java.util.function.Function;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -54,6 +55,46 @@ void setProductCount(Integer productCount) {
this.productCount = productCount;
}

/**
* Lambda that allows to replace or extend the category filters.
*/
private Function<CategoryFilterInput, CategoryFilterInput> categoryFilterHook;

/**
* Extends or replaces the category filter with a custom instance defined by a lambda hook.
*
* Example 1 (Extend):
*
* <pre>
* {@code
* productsRetriever.extendCategoryFilterWith(f -> f
* .setCustomFilter("my-attribute", new FilterEqualTypeInput()
* .setEq("my-value")));
* }
* </pre>
*
* Example 2 (Replace):
*
* <pre>
* {@code
* productsRetriever.extendCategoryFilterWith(f -> new CategoryFilterInput()
* .setCategoryUid(new FilterEqualTypeInput()
* .setEq("custom-uid"))
* .setCustomFilter("my-attribute", new FilterEqualTypeInput()
* .setEq("my-value")));
* }
* </pre>
*
* @param categoryFilterHook Lambda that extends or replaces the category filter.
*/
public void extendCategoryFilterWith(Function<CategoryFilterInput, CategoryFilterInput> categoryFilterHook) {
if (this.categoryFilterHook == null) {
this.categoryFilterHook = categoryFilterHook;
} else {
this.categoryFilterHook = this.categoryFilterHook.andThen(categoryFilterHook);
}
}

CategoryInterface fetchCategory() {
fetchProducts();

Expand All @@ -63,9 +104,18 @@ CategoryInterface fetchCategory() {
@Override
protected String generateQuery(List<String> identifiers) {
if (isCategoryQuery()) {
CategoryFilterInput categoryFilter = new CategoryFilterInput();
FilterEqualTypeInput uidFilter = new FilterEqualTypeInput().setEq(categoryUid);
CategoryFilterInput categoryFilter = new CategoryFilterInput().setCategoryUid(uidFilter);
QueryQuery.CategoryListArgumentsDefinition categoryArgs = s -> s.filters(categoryFilter);
categoryFilter.setCategoryUid(uidFilter);

// Apply category filter hook
if (this.categoryFilterHook != null) {
categoryFilter = this.categoryFilterHook.apply(categoryFilter);
}

CategoryFilterInput finalCategoryFilter = categoryFilter;
QueryQuery.CategoryListArgumentsDefinition categoryArgs = s -> s.filters(finalCategoryFilter);

CategoryTreeQuery.ProductsArgumentsDefinition productArgs = s -> s.currentPage(1).pageSize(productCount);
return Operations.query(query -> query.categoryList(categoryArgs, generateCategoryListQuery(productArgs))).toString();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,17 @@ String getText() {

@Override
protected String generateQuery(List<String> identifiers) {
ProductAttributeFilterInput filter = new ProductAttributeFilterInput().setSku(new FilterEqualTypeInput().setEq(identifiers.get(0)));
QueryQuery.ProductsArgumentsDefinition searchArgs = s -> s.filter(filter);
ProductAttributeFilterInput filter = new ProductAttributeFilterInput();
FilterEqualTypeInput skuFilter = new FilterEqualTypeInput().setEq(identifiers.get(0));
filter.setSku(skuFilter);

// Apply product attribute filter hook
if (this.productAttributeFilterHook != null) {
filter = this.productAttributeFilterHook.apply(filter);
}

ProductAttributeFilterInput finalFilter = filter;
QueryQuery.ProductsArgumentsDefinition searchArgs = s -> s.filter(finalFilter);

ProductInterfaceQueryDefinition def;
if (RelationType.UPSELL_PRODUCTS.equals(relationtype)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

import org.apache.commons.collections4.CollectionUtils;

Expand All @@ -43,6 +44,11 @@ public abstract class AbstractCategoriesRetriever extends AbstractRetriever {
*/
protected Consumer<CategoryTreeQuery> categoryQueryHook;

/**
* Lambda that allows to replace or extend the category filters.
*/
protected Function<CategoryFilterInput, CategoryFilterInput> categoryFilterHook;

/**
* List of category instances. Is only available after populate() was called.
*/
Expand Down Expand Up @@ -100,6 +106,41 @@ public void extendCategoryQueryWith(Consumer<CategoryTreeQuery> categoryQueryHoo
this.categoryQueryHook = categoryQueryHook;
}

/**
* Extends or replaces the category filter with a custom instance defined by a lambda hook.
*
* Example 1 (Extend):
*
* <pre>
* {@code
* categoriesRetriever.extendCategoryFilterWith(f -> f
* .setCustomFilter("my-attribute", new FilterEqualTypeInput()
* .setEq("my-value")));
* }
* </pre>
*
* Example 2 (Replace):
*
* <pre>
* {@code
* categoriesRetriever.extendCategoryFilterWith(f -> new CategoryFilterInput()
* .setCategoryUid(new FilterEqualTypeInput()
* .setEq("custom-uid"))
* .setCustomFilter("my-attribute", new FilterEqualTypeInput()
* .setEq("my-value")));
* }
* </pre>
*
* @param categoryFilterHook Lambda that extends or replaces the category filter.
*/
public void extendCategoryFilterWith(Function<CategoryFilterInput, CategoryFilterInput> categoryFilterHook) {
if (this.categoryFilterHook == null) {
this.categoryFilterHook = categoryFilterHook;
} else {
this.categoryFilterHook = this.categoryFilterHook.andThen(categoryFilterHook);
}
}

/**
* Generates the partial CategoryTree query part of the GraphQL category query.
*
Expand All @@ -114,14 +155,22 @@ public void extendCategoryQueryWith(Consumer<CategoryTreeQuery> categoryQueryHoo
* @return GraphQL query as string
*/
protected String generateQuery(List<String> identifiers) {
CategoryFilterInput filter = new CategoryFilterInput();
FilterEqualTypeInput identifiersFilter = new FilterEqualTypeInput().setIn(identifiers);
filter.setCategoryUid(identifiersFilter);

// Apply category filter hook
if (this.categoryFilterHook != null) {
filter = this.categoryFilterHook.apply(filter);
}

CategoryFilterInput finalFilter = filter;
QueryQuery.CategoryListArgumentsDefinition searchArgs = s -> s.filters(finalFilter);

CategoryTreeQueryDefinition queryArgs = generateCategoryQuery();
return Operations.query(query -> {
FilterEqualTypeInput identifiersFilter = new FilterEqualTypeInput().setIn(identifiers);
CategoryFilterInput filter = new CategoryFilterInput().setCategoryUid(identifiersFilter);

QueryQuery.CategoryListArgumentsDefinition searchArgs = s -> s.filters(filter);
query.categoryList(searchArgs, queryArgs);
}).toString();
return Operations.query(query -> query
.categoryList(searchArgs, queryArgs)).toString();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
Expand Down Expand Up @@ -47,6 +48,11 @@ public abstract class AbstractCategoryRetriever extends AbstractRetriever {
*/
protected Consumer<ProductInterfaceQuery> productQueryHook;

/**
* Lambda that allows to replace or extend the category filters.
*/
protected Function<CategoryFilterInput, CategoryFilterInput> categoryFilterHook;

/**
* Category instance. Is only available after populate() was called.
*/
Expand Down Expand Up @@ -137,6 +143,41 @@ public void extendCategoryQueryWith(Consumer<CategoryTreeQuery> categoryQueryHoo
}
}

/**
* Extends or replaces the category filter with a custom instance defined by a lambda hook.
*
* Example 1 (Extend):
*
* <pre>
* {@code
* categoryRetriever.extendCategoryFilterWith(f -> f
* .setCustomFilter("my-attribute", new FilterEqualTypeInput()
* .setEq("my-value")));
* }
* </pre>
*
* Example 2 (Replace):
*
* <pre>
* {@code
* categoryRetriever.extendCategoryFilterWith(f -> new CategoryFilterInput()
* .setCategoryUid(new FilterEqualTypeInput()
* .setEq("custom-uid"))
* .setCustomFilter("my-attribute", new FilterEqualTypeInput()
* .setEq("my-value")));
* }
* </pre>
*
* @param categoryFilterHook Lambda that extends or replaces the category filter.
*/
public void extendCategoryFilterWith(Function<CategoryFilterInput, CategoryFilterInput> categoryFilterHook) {
if (this.categoryFilterHook == null) {
this.categoryFilterHook = categoryFilterHook;
} else {
this.categoryFilterHook = this.categoryFilterHook.andThen(categoryFilterHook);
}
}

/**
* @return The extended category query part if it was set with {@link AbstractCategoryRetriever#extendCategoryQueryWith(Consumer)}
*/
Expand Down Expand Up @@ -204,10 +245,17 @@ public String generateQuery(String identifier) {
* @return GraphQL query as string
*/
public Pair<CategoryListArgumentsDefinition, CategoryTreeQueryDefinition> generateCategoryQueryArgs(String identifier) {
CategoryFilterInput filter = new CategoryFilterInput();
FilterEqualTypeInput identifierFilter = new FilterEqualTypeInput().setEq(identifier);
CategoryFilterInput filter = new CategoryFilterInput().setCategoryUid(identifierFilter);
filter.setCategoryUid(identifierFilter);

// Apply category filter hook
if (this.categoryFilterHook != null) {
filter = this.categoryFilterHook.apply(filter);
}

CategoryListArgumentsDefinition searchArgs = q -> q.filters(filter);
CategoryFilterInput finalFilter = filter;
CategoryListArgumentsDefinition searchArgs = q -> q.filters(finalFilter);
CategoryTreeQueryDefinition queryArgs = generateCategoryQuery();

return new ImmutablePair<>(searchArgs, queryArgs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;

import org.apache.commons.collections4.CollectionUtils;

Expand All @@ -35,6 +36,7 @@
import com.adobe.cq.commerce.magento.graphql.QueryQuery;
import com.adobe.cq.commerce.magento.graphql.SimpleProductQuery;
import com.adobe.cq.commerce.magento.graphql.gson.Error;
import com.shopify.graphql.support.Input;

/**
* Abstract implementation of product retriever that loads product data using GraphQL.
Expand All @@ -51,6 +53,11 @@ public abstract class AbstractProductRetriever extends AbstractRetriever {
*/
protected Consumer<SimpleProductQuery> variantQueryHook;

/**
* Lambda that allows to replace or extend the product attribute filters.
*/
protected Function<ProductAttributeFilterInput, ProductAttributeFilterInput> productAttributeFilterHook;

/**
* Product instance. Is only available after populate() was called.
*/
Expand Down Expand Up @@ -138,17 +145,59 @@ public void extendVariantQueryWith(Consumer<SimpleProductQuery> variantQueryHook
}
}

/**
* Extends or replaces the product attribute filter with a custom instance defined by a lambda hook.
*
* Example 1 (Extend):
*
* <pre>
* {@code
* productRetriever.extendProductFilterWith(f -> f
* .setCustomFilter("my-attribute", new FilterEqualTypeInput()
* .setEq("my-value")));
* }
* </pre>
*
* Example 2 (Replace):
*
* <pre>
* {@code
* productRetriever.extendProductFilterWith(f -> new ProductAttributeFilterInput()
* .setSku(new FilterEqualTypeInput()
* .setEq("custom-sku"))
* .setCustomFilter("my-attribute", new FilterEqualTypeInput()
* .setEq("my-value")));
* }
* </pre>
*
* @param productAttributeFilterHook Lambda that extends or replaces the product attribute filter.
*/
public void extendProductFilterWith(Function<ProductAttributeFilterInput, ProductAttributeFilterInput> productAttributeFilterHook) {
if (this.productAttributeFilterHook == null) {
this.productAttributeFilterHook = productAttributeFilterHook;
} else {
this.productAttributeFilterHook = this.productAttributeFilterHook.andThen(productAttributeFilterHook);
}
}

/**
* Generate a complete product GraphQL query with a filter for the given product identifier.
*
* @param identifier Product identifier, usually SKU or slug
* @return GraphQL query as string
*/
protected String generateQuery(String identifier) {
ProductAttributeFilterInput filter = new ProductAttributeFilterInput();
FilterEqualTypeInput identifierFilter = new FilterEqualTypeInput().setEq(identifier);
ProductAttributeFilterInput filter = new ProductAttributeFilterInput().setSku(identifierFilter);
filter.setSkuInput(Input.optional(identifierFilter));

// Apply product attribute filter hook
if (this.productAttributeFilterHook != null) {
filter = this.productAttributeFilterHook.apply(filter);
}

QueryQuery.ProductsArgumentsDefinition searchArgs = s -> s.filter(filter);
ProductAttributeFilterInput finalFilter = filter;
QueryQuery.ProductsArgumentsDefinition searchArgs = s -> s.filter(finalFilter);

ProductsQueryDefinition queryArgs = q -> q.items(generateProductQuery());
return Operations.query(query -> query
Expand Down
Loading

0 comments on commit 1bc2813

Please sign in to comment.