<?php
namespace App\Controller\API\WhiteMark;
use App\Model\Product;
use App\Services\API\VersioningService;
use App\Services\Common\StockService;
use App\Services\DTV\YamlConfig\YamlReader;
use App\Services\Front\Catalogue\JsonCatalogueService;
use App\Services\ProductService;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use JMS\Serializer\SerializerInterface;
use JsonException;
use Nelmio\ApiDocBundle\Annotation\Model;
use OpenApi\Annotations as OA;
use Psr\Cache\InvalidArgumentException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Contracts\Cache\ItemInterface;
use Symfony\Contracts\Cache\TagAwareCacheInterface;
/**
* @Route("/catalogues")
*/
class CatalogueController extends ApiController
{
private JsonCatalogueService $catalogueService;
private YamlReader $yamlReader;
private ProductService $productService;
private StockService $stockService;
public function __construct(
EntityManagerInterface $em,
SerializerInterface $serializer,
UrlGeneratorInterface $urlGenerator,
ValidatorInterface $validator,
TagAwareCacheInterface $cache,
KernelInterface $kernel,
VersioningService $versioningService,
JsonCatalogueService $catalogueService,
ProductService $productService,
YamlReader $yamlReader,
StockService $stockService
) {
parent::__construct( $em, $serializer, $urlGenerator, $validator, $cache, $kernel, $versioningService );
$this->catalogueService = $catalogueService;
$this->yamlReader = $yamlReader;
$this->productService = $productService;
$this->stockService = $stockService;
$this->cacheTagSlug = 'cataloguesCache';
}
/**
* Récupérer l'ensemble des catalogues disponibles.
*
* @OA\Response(
* response=200,
* description="Retourne la liste des catalogues",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* type="array",
* @OA\Items(
* type="string",
* ),
* )
* )
* )
*
* @OA\Tag(name="Catalogues")
*
* @Route("/", name="api_list_catalogue", methods={"GET"})
*
* @return JsonResponse
*/
public function listCatalogue(): JsonResponse
{
$slugs = [];
$catalogues = $this->yamlReader->getShop()[ 'catalogues' ];
foreach ( $catalogues as $k => $catalogue ) {
$catalogueType = $catalogue[ 'slug' ] ?? $k;
// Modification des catalogues depuis la version 1.4.0 : pub.json devient obj_pub.json
if ( $catalogueType === 'pub' ) {
$catalogueType = 'obj_pub';
}
if ( $catalogue[ 'enabled' ] ) {
$slugs[] = $catalogueType;
}
}
return new JsonResponse( [ 'catalogues' => $slugs ], Response::HTTP_OK, [] );
}
/**
* Récupérer l'ensemble des produits d'un catalogue.
*
* @OA\Response(
* response=200,
* description="Retourne la liste des produits.<br>Pour afficher les images, il faut les préfixer avec
* https://cdn.37deux.com/pictures suivis du format (150, 400, large).<br>Exemple :
* https://cdn.37deux.com/pictures/150/pic6076bc07b0620.jpg",
* @OA\JsonContent(
* type="array",
* @OA\Items(ref=@Model(type=Product::class, groups={"api_product:list"}))
* )
* )
* @OA\Parameter(
* name="page",
* in="query",
* description="La page que l'on veut récupérer",
* @OA\Schema(type="int")
* )
*
* @OA\Parameter(
* name="limit",
* in="query",
* description="Le nombre d'éléments que l'on veut récupérer",
* @OA\Schema(type="int")
* )
*
* @OA\Parameter(
* name="slug",
* in="path",
* description="Le nom du catalogue",
* @OA\Schema(type="string")
* )
*
* @OA\Tag(name="Catalogues")
*
* @Route("/{slug}/products", name="api_list_product", methods={"GET"})
*
* @throws InvalidArgumentException
*/
public function listProduct( string $slug, Request $request ): JsonResponse
{
$page = $request->get( 'page', 1 );
$limit = $request->get( 'limit', 15 );
$context = $this->getContext( [ "api_product:list" ] );
$idCache = "listProduct-" . $slug . '-' . $page . "-" . $limit;
$jsonProducts = $this->cache->get( $idCache, function ( ItemInterface $item ) use (
$page,
$limit,
$slug,
$context
) {
$item->tag( $this->cacheTagSlug );
$products = $this->catalogueService->getProductsFromCatalogueWithPagination( $slug, $page, $limit );
$formattedProducts = [];
foreach ( $products[ 'products' ] as $product ) {
$formattedProducts[] = $this->catalogueService->getProductBySkuFromCatalogue( $product[ 'sku' ], $slug );
}
$json = $this->serializer->serialize(
$formattedProducts,
'json',
$context,
);
$jsonProducts = [
'totalProducts' => $products[ 'totalProducts' ],
'products' => '{{json_products_data}}',
];
$jsonProducts = json_encode( $jsonProducts );
return str_replace( '"{{json_products_data}}"', $json, $jsonProducts );
} );
return new JsonResponse( $jsonProducts, Response::HTTP_OK, [], TRUE );
}
/**
* Récupérer un produit depuis son sku.
*
* @OA\Response(
* response=200,
* description="Retourne un produit",
* @OA\JsonContent(
* type="array",
* @OA\Items(ref=@Model(type=Product::class, groups={"api_product:item"}))
* )
* )
* @OA\Tag(name="Catalogues")
*
* @Route("/{slug}/products/{sku}", name="api_show_product", methods={"GET"})
*
* @throws JsonException
*/
public function showProduct( string $slug, string $sku ): JsonResponse
{
$product = $this->catalogueService->findProductBySku( $sku );
$json = $this->serializer->serialize(
$product,
'json',
$this->getContext( [ "api_product:item" ] ),
);
return new JsonResponse( $json, Response::HTTP_OK, [], TRUE );
}
/**
* Récupérer le stock en temps réel d'un produit
*
* @OA\Response(
* response=200,
* description="Retourne un stock",
* @OA\MediaType(
* mediaType="application/json",
* @OA\Schema(
* @OA\Property(
* property="sku",
* type="string"
* ),
* @OA\Property(
* property="quantity",
* type="integer"
* ),
* example={"sku": "12345678Z9", "quantity": 3}
* )
* )
* )
* @OA\Tag(name="Catalogues")
*
* @Route("/{slug}/products/{sku}/stocks", name="api_show_product_stocks", methods={"GET"})
*/
public function showProductStock( string $slug, string $sku ): JsonResponse
{
$response = $this->stockService->getProductStockFromBO( $sku );
return new JsonResponse(
json_encode(
[
'stock' => $response - $this->productService->getStockPending( $sku ),
'date' => ( new DateTime( 'now' ) )->format( 'd-m-Y H:i:s' ),
],
),
Response::HTTP_OK,
[],
TRUE,
);
}
}