Specifying commercetools channels for availability information
By default, Frontastic only gets the isOnStock
information from the first channel returned from commercetools for each variant. In some cases, we might want to get the availability from a specific channel.
This article will use a customer decorator to map the correct value to the variant stock information. We'll decorate the ProductSearchApi
and change the variant's isOnStock
property. See our API decorators article for more information.
First, we create the decorator, which we'll call ProductSearchChannelStockMapper
:
namespace Demo\CustomizationBundle\Domain;
use Frontastic\Common\CartApiBundle\Domain\LineItem\Variant;
use Frontastic\Common\ProductApiBundle\Domain\Product;
use Frontastic\Common\ProductApiBundle\Domain\ProductApi\Query\ProductQuery;
use Frontastic\Common\ProductApiBundle\Domain\ProductApi\Result;
use Frontastic\Common\ProductSearchApiBundle\Domain\ProductSearchApi;
use Frontastic\Common\ProductSearchApiBundle\Domain\ProductSearchApi\LifecycleEventDecorator\BaseImplementation;
class ProductSearchChannelStockMapper extends BaseImplementation {
const STOCK_CHANNEL = "36fc7dda-7c58-47ff-9acf-b21bae890e23";
public function beforeQuery(ProductSearchApi $productSearchApi, ProductQuery $query): ?array
{
// ...
}
public function afterQuery(ProductSearchApi $productSearchApi, ?Result $result): ?Result
{
// ...
}
}
Here, we're extending the corresponding BaseImplementation
for the ProductSearchApi
. We're also defining a constant for the channel we want to use. Depending on your needs, you can use different strategies to get the channel you want.
We need to intercept the ProductQuery
to get the raw response from commercetools later. So we do this in the beforeQuery
method.
public function beforeQuery(ProductSearchApi $productSearchApi, ProductQuery $query): ?array
{
$query->loadDangerousInnerData = true;
return parent::beforeQuery($productSearchApi, $query);
}
With that in place, we'll have the dangerousInner
properties on our product
and variant
objects.
We'll take advantage of this in the afterQuery
method.
public function afterQuery(ProductSearchApi $productSearchApi, ?Result $result): ?Result
{
/* @var Product $product */
foreach ($result->items as $product) {
/* @var Variant $variant */
foreach ($product->variants as $variant) {
if (isset($variant->dangerousInnerVariant["availability"]["channels"][self::STOCK_CHANNEL]["isOnStock"])) {
$variant->isOnStock = $variant->dangerousInnerVariant["availability"]["channels"][self::STOCK_CHANNEL]["isOnStock"];
}
}
}
return $result;
}
Let's break it down:
- We iterate through the results. Those results are already in the Frontastic model. They're
product
objects. - Each of those results has a list of
variant
objects inside. Those variants are also already on the Frontastic model. Those variants already have aisOnStock
value, corresponding to the first channel on which they're in. - We check if that variant is available on
STOCK_CHANNEL
. If so, set the stock value accordingly.
So the result is:
namespace Demo\CustomizationBundle\Domain;
use Frontastic\Common\CartApiBundle\Domain\LineItem\Variant;
use Frontastic\Common\ProductApiBundle\Domain\Product;
use Frontastic\Common\ProductApiBundle\Domain\ProductApi\Query\ProductQuery;
use Frontastic\Common\ProductApiBundle\Domain\ProductApi\Result;
use Frontastic\Common\ProductSearchApiBundle\Domain\ProductSearchApi;
use Frontastic\Common\ProductSearchApiBundle\Domain\ProductSearchApi\LifecycleEventDecorator\BaseImplementation;
class ProductSearchChannelStockMapper extends BaseImplementation
{
const STOCK_CHANNEL = "36fc7dda-7c58-47ff-9acf-b21bae890e23";
public function beforeQuery(ProductSearchApi $productSearchApi, ProductQuery $query): ?array
{
$query->loadDangerousInnerData = true;
return parent::beforeQuery($productSearchApi, $query);
}
public function afterQuery(ProductSearchApi $productSearchApi, ?Result $result): ?Result
{
/* @var Product $product */
foreach ($result->items as $product) {
/* @var Variant $variant */
foreach ($product->variants as $variant) {
if (isset($variant->dangerousInnerVariant["availability"]["channels"][self::STOCK_CHANNEL]["isOnStock"])) {
$variant->isOnStock = $variant->dangerousInnerVariant["availability"]["channels"][self::STOCK_CHANNEL]["isOnStock"];
}
}
}
return $result;
}
}
Updated about 1 year ago