diff --git a/src/Api/Models/Product/ProductVariantSkuAccessor.php b/src/Api/Models/Product/ProductVariantSkuAccessor.php new file mode 100644 index 00000000000..e5455047f5e --- /dev/null +++ b/src/Api/Models/Product/ProductVariantSkuAccessor.php @@ -0,0 +1,68 @@ + + */ + private $skuIndex = []; + + /** + * @psalm-assert ProductProjection|ProductData $product + * @psalm-param mixed $product + * @param $product + * @throws InvalidArgumentException + */ + private function __construct($product) + { + if (!($product instanceof ProductProjection || $product instanceof ProductData)) { + throw new InvalidArgumentException(""); + } + $variants = $product->getVariants(); + $variants = $variants != null ? $variants->toArray() ?? [] : []; + $masterVariant = $product->getMasterVariant(); + if ($masterVariant != null) { + array_unshift($variants, $masterVariant); + } + + /** + * @var array $variants + */ + $this->variants = new ProductVariantCollection($variants); + + /** + * @var ProductVariant $variant + */ + foreach ($this->variants as $index => $variant) { + $this->skuIndex[(string)$variant->getSku()] = (int)$index; + } + } + + public function getBySku(string $sku): ?ProductVariant + { + if (!isset($this->skuIndex[$sku])) { + return null; + } + return $this->variants->at($this->skuIndex[$sku]); + } + + /** + * @psalm-return callable(ProductProjection|ProductData): self + */ + public static function of() + { + return function ($productProjection): ProductVariantSkuAccessor { + return new self($productProjection); + }; + } +} diff --git a/test/unit/ProductProjectionsTest.php b/test/unit/ProductProjectionsTest.php index 2324548cad9..baaec35e6c2 100644 --- a/test/unit/ProductProjectionsTest.php +++ b/test/unit/ProductProjectionsTest.php @@ -2,14 +2,11 @@ namespace Commercetools\UnitTest; -use Commercetools\Api\Client\ApiRequestBuilder; -use Commercetools\Api\Models\Product\Attribute; use Commercetools\Api\Models\Product\AttributeAccessor; use Commercetools\Api\Models\Product\ProductProjection; -use Commercetools\Api\Models\Product\ProductProjectionModel; -use Commercetools\Api\Models\Product\ProductProjectionPagedQueryResponse; use Commercetools\Api\Models\Product\ProductProjectionPagedQueryResponseModel; -use GuzzleHttp\ClientInterface; +use Commercetools\Api\Models\Product\ProductProjectionVariantSkuAccessor; +use Commercetools\Api\Models\Product\ProductVariantSkuAccessor; use PHPUnit\Framework\TestCase; class ProductProjectionsTest extends TestCase @@ -19,12 +16,7 @@ public function testAttributeMapping() $productsJson = json_decode(file_get_contents(__DIR__ . "/products.json")); $products = ProductProjectionPagedQueryResponseModel::fromStdClass($productsJson)->getResults(); -// /** @var ClientInterface $client */ -// $builder = new ApiRequestBuilder($client); -// $productResponse = $builder->withProjectKey("")->productProjections()->get()->execute(); -// $products = $productResponse->getResults(); - -// /** @var ProductProjection $product */ + /** @var ProductProjection $product */ foreach ($products as $product) { foreach ($product->getMasterVariant()->getAttributes() as $attribute) { /** @var AttributeAccessor $attrAccessor */ @@ -39,4 +31,19 @@ public function testAttributeMapping() } } } + + public function testSkuMapping() + { + $productsJson = json_decode(file_get_contents(__DIR__ . "/products.json")); + $products = ProductProjectionPagedQueryResponseModel::fromStdClass($productsJson)->getResults(); + + $variantsAccessor = $products[0]->with(ProductVariantSkuAccessor::of()); + self::assertSame(1, $variantsAccessor->getBySku("prod1-abc")->getId()); + self::assertNull($variantsAccessor->getBySku("non-existant")); + self::assertSame(2, $variantsAccessor->getBySku("prod1-def")->getId()); + + $variantsAccessor = $products[1]->with(ProductVariantSkuAccessor::of()); + self::assertSame(1, $variantsAccessor->getBySku("prod2-abc")->getId()); + self::assertSame(2, $variantsAccessor->getBySku("prod2-def")->getId()); + } } diff --git a/test/unit/products.json b/test/unit/products.json index 6c420e1ae8e..07e0d552e8c 100644 --- a/test/unit/products.json +++ b/test/unit/products.json @@ -20,6 +20,7 @@ }, "masterVariant": { "id": 1, + "sku": "prod1-abc", "prices": [], "images": [], "attributes": [ @@ -33,7 +34,24 @@ } ] }, - "variants": [], + "variants": [ + { + "id": 2, + "sku": "prod1-def", + "prices": [], + "images": [], + "attributes": [ + { + "name": "text1", + "value": { + "it": "italian1", + "de": "german1", + "en": "englisch1" + } + } + ] + } + ], "searchKeywords": {}, "hasStagedChanges": false, "published": true, @@ -62,6 +80,7 @@ "masterVariant": { "id": 1, "prices": [], + "sku": "prod2-abc", "images": [], "attributes": [ { @@ -70,7 +89,20 @@ } ] }, - "variants": [], + "variants": [ + { + "id": 2, + "prices": [], + "sku": "prod2-def", + "images": [], + "attributes": [ + { + "name": "aboolean", + "value": true + } + ] + } + ], "searchKeywords": {}, "hasStagedChanges": true, "published": true,