<?php
namespace Millerdigital\EleqPimcore\Controller;
use Millerdigital\EleqPimcore\Attribute\SanityApi;
use Millerdigital\EleqPimcore\Formatter\SanityProductFormatter;
use Pimcore\Model\Asset;
use Pimcore\Model\DataObject\Product;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Contracts\Translation\LocaleAwareInterface;
#[SanityApi(validateApiKey: true, rateLimit: false)]
class SanityController extends AbstractController
{
private TranslatorInterface $translator;
public function __construct(
TranslatorInterface $translator
) {
$this->translator = $translator;
}
/**
* Fetch detailed information about a specific product by its slug.
*
* Returns complete product details including environmental conditions,
* application conditions, variants, documents, contact information, and related products.
*/
#[Route('/api/sanity/product/{slug}', name: 'sanity_product', methods: ['GET'])]
public function fetchProduct(Request $request, string $slug): Response
{
$language = self::getRequestLanguage($request);
$request->setLocale($language);
if ($this->translator instanceof LocaleAwareInterface) {
$this->translator->setLocale($language);
}
$product = Product::getBySlug($slug, $language, 1);
if ($product && $product->getPath() == "/Products/" && $product->getShowOnWebsite($language)) {
$product = SanityProductFormatter::formatProduct($product, $this->translator, $request);
return $this->json($product, 200, ["Content-Type" => "application/json"]);
}
throw $this->createNotFoundException();
}
/**
* Fetch a list of products with pagination.
*
* Returns a list of products with detailed information and total count.
*/
#[Route('/api/sanity/products', name: 'sanity_products', methods: ['GET'])]
public function fetchProducts(Request $request): Response
{
// Get offset and limit from query parameters
$offset = (int)$request->query->get('offset', 0);
$limit = (int)$request->query->get('limit', 20);
$language = self::getRequestLanguage($request);
$request->setLocale($language);
if ($this->translator instanceof LocaleAwareInterface) {
$this->translator->setLocale($language);
}
$productListing = new Product\Listing();
$productListing->setLocale($language);
$productListing->addConditionParam('o_path = ? AND ShowOnWebsite = ?', ['/Products/', 1]);
// sort by Order product-property
$productListing->setOrderKey(
['order', 'oo_id',]
);
$productListing->setOrder(
['desc', 'asc']
);
$products = $productListing->getItems($offset, $limit);
$products = array_map(fn(Product $product) => SanityProductFormatter::formatProduct($product, $this->translator, $request), $products);
$count = $productListing->count();
$result = [
'count' => $count,
'products' => $products
];
return $this->json($result, 200, ["Content-Type" => "application/json"]);
}
/**
* Get all document filenames.
*
* Returns a JSON array of all available document filenames.
*/
#[Route('/api/sanity/documents', name: 'sanity_documents', methods: ['GET'])]
public function fetchDocuments(): Response
{
$assetListing = new Asset\Listing();
$assetListing->addConditionParam('type = ?', 'document');
$assets = $assetListing->load();
$filenames = array_map(fn(Asset $asset) => $asset->getFilename(), $assets);
return $this->json($filenames, 200, ["Content-Type" => "application/json"]);
}
/**
* Download a document by filename.
*
* Returns the document as a streamed response with appropriate headers.
*/
#[Route('/api/sanity/document/{file}/download', name: 'sanity_document', methods: ['GET'])]
public function fetchDocument(string $file): Response
{
$assetListing = new Asset\Listing();
$assetListing->addConditionParam('filename = ?', $file);
$asset = $assetListing->getItems(0, 1)[0] ?? null;
if (!$asset) {
throw $this->createNotFoundException();
}
$stream = $asset->getStream();
return new StreamedResponse(function () use ($stream) {
fpassthru($stream);
}, 200, [
'Content-Type' => $asset->getMimeType(),
'Content-Disposition' => sprintf('attachment; filename="%s"', $asset->getFilename()),
'Content-Length' => $asset->getFileSize(),
]);
}
private static function getRequestLanguage(Request $request): ?string
{
if ($language = $request->query->get('lang')) {
return $language;
}
if ($language = $request->getPreferredLanguage()) {
return substr($language, 0, strrpos($language, '_'));
}
return \Locale::getDefault();
}
}