<?php
/*
* 2001-2019 Reflet Communication
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0) that is available
* through the world-wide-web at this URL: http://www.opensource.org/licenses/OSL-3.0
* If you are unable to obtain it through the world-wide-web, please send an email
* to agence@reflet-digital.com so we can send you a copy immediately.
*
* @author Reflet Communication
* @copyright 2001-2019 Reflet Communication
* @license http://www.opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace App\Controller;
use App\Entity\Url;
use App\Exception\BadResponseException;
use App\Filter\ProxyFilter;
use App\Manager\Api\Catalog\BrandManager;
use App\Manager\Api\Catalog\CategoryManager;
use App\Manager\Api\Catalog\ProductManager;
use App\Navigation\BreadcrumbNavigation;
use App\Navigation\CategoryNavigation;
use App\Navigation\Page\Route as Page;
use App\Service\ApiService;
use App\Service\ProxyService;
use DateTime;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ServerBag;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Contracts\Cache\TagAwareCacheInterface;
/**
* Class NodeController
*
* @package App\Controller
*
* @Route(
* name = "node_",
* options = {
* "priority" = 2
* }
* )
*/
class NodeController extends ProxyAwareController
{
/**
* @var CategoryManager
*/
private $categoryManager;
/**
* @var ProductManager
*/
private $productManager;
/**
* @var BrandManager
*/
private $brandManager;
/**
* @var ServerBag
*/
private $bag;
/**
* NodeController constructor.
*
* @param RequestStack $stack
* @param ApiService $apiService
* @param ProxyFilter $proxyFilter
* @param ProxyService $proxyService
* @param TagAwareCacheInterface $cache
*/
public function __construct(
RequestStack $stack,
ApiService $apiService,
ProxyFilter $proxyFilter,
ProxyService $proxyService,
TagAwareCacheInterface $cache
) {
parent::__construct($stack, $proxyService, $proxyFilter, $cache);
$bag = $this
->request
->server
;
$this->categoryManager = new CategoryManager($apiService, $bag, $cache);
$this->productManager = new ProductManager($apiService, $bag, $cache);
$this->brandManager = new BrandManager($apiService, $bag, $cache);
}
/**
* @Route(
* "/{path}",
* name = "category",
* requirements = {
* "path" = "^[a-z0-9]+(-[a-z0-9]+)*(\/[a-z0-9]+(-[a-z0-9]+)*)?$",
* }
* )
*
* @param Request $request
* @param string $path
* @param $filters
*
* @throws NotFoundHttpException
*
* @return Response
*/
public function category(Request $request, $path, $filters = null): Response
{
$path = explode('/', $path);
try {
try {
$category = $this
->categoryManager
->getItem(end($path), 'slug')
;
$categoryPath = explode('/', $category->path);
} catch (BadResponseException $e) {
if (count($path) > 1) {
$request->attributes->set('_route', 'node_product');
return $this->forward('App\Controller\NodeController::product', [
'path' => $path[0],
'slug' => $path[1],
'request' => $request,
]);
}
throw new NotFoundHttpException('Page not found');
}
if (
empty($category->enabled)
|| reset($categoryPath) != reset($path)
) {
throw new NotFoundHttpException('Page not found');
}
} catch (NotFoundHttpException $e) {
$request->attributes->set('_route', 'sulu_page_index');
return $this->forward('App\Controller\SuluPageController::index', [
'path' => implode('/', $path),
'request' => $request,
]);
}
try {
$categories = $this
->categoryManager
->getList([
'parent' => $category->id,
'enabled' => true,
'sort' => 'order',
])
;
} catch (BadResponseException $exception) {
// Ignore
}
if (!empty($categories->data)) {
$children = [];
foreach ($categories->data as $child) {
try {
$children[$child->id] = $this
->categoryManager
->getList([
'parent' => $child->id,
'enabled' => true,
'sort' => 'order',
])
;
} catch (BadResponseException $e) {
// Ignore
}
}
return $this->render('controller/node/category/category-list.html.twig', [
'path' => implode('/', $path),
'filters' => $filters,
'category' => $category,
'categories' => $categories,
'children' => $children,
]);
}
try {
$products = $this
->productManager
->getList([
'enabled' => true,
'category' => $category->id,
])
;
} catch (BadResponseException $exception) {
// Ignore
}
if (!empty($products->data)) {
foreach ($products->data as &$product) {
foreach ($product->categories as &$productCategory) {
$productCategory = $this
->categoryManager
->getItem($productCategory)
;
}
unset($productCategory);
if (!empty($product->slug)) {
$product->item_link = new Url($request->server, $this->generateUrl('node_product', [
'path' => implode('/', $path),
'slug' => $product->slug,
]));
$product->picture_path = $this->getMainPicturePath($request->server->get('CATALOG_MEDIA_URL'), $product);
}
try {
if (!empty($product->brand)) {
$product->brand = $this
->brandManager
->getItem($product->brand)
;
}
} catch (BadResponseException $e) {
// Ignore
}
}
unset($product);
try {
$block = $this
->proxyEntityManager
->getContent('/blocks/catalog')
;
$proxyFilter = $this->proxyFilter;
$block = $proxyFilter($request, $block);
} catch (BadResponseException $e) {
// Ignore
}
return $this->render('controller/node/category/product-list.html.twig', [
'path' => implode('/', $path),
'filters' => $filters,
'category' => $category,
'products' => $products,
'block' => $block ?? null,
]);
}
try {
$page = $this
->proxyEntityManager
->getContent($request->getRequestUri())
;
$proxyFilter = $this->proxyFilter;
$page = $proxyFilter($request, $page);
} catch (BadResponseException $exception) {
// Ignore
}
if (!empty($page['body'])) {
return $this->render('controller/node/category/page.html.twig', [
'path' => implode('/', $path),
'filters' => $filters,
'category' => $category,
'page' => $page,
]);
}
// TODO: Should we return a true 404 anyway?
// throw new NotFoundHttpException('Page not found');
$request->attributes->set('_route', 'sulu_page_index');
return $this->forward('App\Controller\SuluPageController::index', [
'path' => implode('/', $path),
'request' => $request,
]);
}
/**
* @Route(
* "/{path}/{slug}",
* name = "product",
* requirements = {
* "path" = "^[a-z0-9]+(-[a-z0-9]+)*(\/[a-z0-9]+(-[a-z0-9]+)*)?$",
* "slug": "^([a-z0-9]+(-[a-z0-9]+)*)$",
* }
* )
*
* @param Request $request
* @param RouterInterface $router
* @param BreadcrumbNavigation $breadcrumbNavigation
* @param CategoryNavigation $categoryNavigation
* @param string $path
* @param string $slug
* @param $filters
*
* @throws NotFoundHttpException
*
* @return Response
*/
public function product(
Request $request,
RouterInterface $router,
BreadcrumbNavigation $breadcrumbNavigation,
CategoryNavigation $categoryNavigation,
$path,
$slug,
$filters = null
): Response
{
$path = explode('/', $path);
try {
try {
$category = $this
->categoryManager
->getItem(end($path), 'slug')
;
$categoryPath = explode('/', $category->path);
} catch (BadResponseException $e) {
throw new NotFoundHttpException('Page not found');
}
if (
empty($category->enabled)
|| reset($categoryPath) != reset($path)
) {
throw new NotFoundHttpException('Page not found');
}
try {
$product = $this
->productManager
->getItem($slug, 'slug')
;
$product->date_published = DateTime::createFromFormat('U', $product->date_published);
} catch (BadResponseException $s) {
throw new NotFoundHttpException('Page not found');
}
if (
empty($product->date_published)
|| $product->date_published > new DateTime()
|| !in_array($category->id, $product->categories)
) {
throw new NotFoundHttpException('Page not found');
}
} catch (NotFoundHttpException $e) {
$request->attributes->set('_route', 'sulu_page_index');
return $this->forward('App\Controller\SuluPageController::index', [
'path' => implode('/', array_merge($path, [
$slug,
])),
'request' => $request,
]);
}
foreach ($product->categories as &$productCategory) {
$productCategory = $this
->categoryManager
->getItem($productCategory)
;
}
unset($productCategory);
$route = $request
->attributes
->get('_route')
;
$breadcrumbNavigation
->findOneBy('name', 'node_category-'.$category->id)
->addPage([
'label' => $product->label,
'name' => $route.'-'.$product->id,
'route' => $route,
'type' => Page::class,
'matched_route' => $request,
'router' => $router,
'params' => [
'path' => implode('/', $path),
'slug' => $product->slug,
],
'active' => true,
])
;
$categoryNavigation
->findOneBy('name', 'node_category-'.$category->id)
->setActive(true)
;
if (!empty($product->brand)) {
try {
$product->brand = $this
->brandManager
->getItem($product->brand)
;
} catch (BadResponseException $e) {
// Ignore
}
}
$product->item_link = new Url($request->server, $this->generateUrl('node_product', [
'path' => implode('/', $path),
'slug' => $slug,
]));
$product->picture_path = $this->getMainPicturePath($request->server->get('CATALOG_MEDIA_URL'), $product);
try {
$blocks = $this
->proxyEntityManager
->getContent('/blocks/push-'.str_replace('_', '-', reset($path)))
;
$proxyFilter = $this->proxyFilter;
$blocks = $proxyFilter($this->request, $blocks);
} catch (BadResponseException $e) {
// Ignore
}
try {
$similarProducts = $this
->productManager
->getSimilarItems($product->id, 'id', 3)
;
foreach ($similarProducts->data as &$similarProduct) {
foreach ($similarProduct->categories as &$similarCategory) {
$similarCategory = $this
->categoryManager
->getItem($similarCategory)
;
}
unset($similarCategory);
$similarCategory = reset($similarProduct->categories);
if (!empty($similarProduct->brand)) {
$similarProduct->brand = $this
->brandManager
->getItem($similarProduct->brand)
;
}
$similarPath = explode('/', $similarCategory->path);
array_splice($similarPath, 1, max(count($similarPath) - 2, 0));
$similarProduct->item_link = new Url($request->server, $this->generateUrl('node_product', [
'path' => implode('/', $similarPath),
'slug' => $similarProduct->slug,
]));
$similarProduct->picture_path = $this->getMainPicturePath($request->server->get('CATALOG_MEDIA_URL'), $product);
}
unset($similarProduct);
} catch (BadResponseException $e) {
// Ignore
}
return $this->render('controller/node/product.html.twig', [
'path' => implode('/', $path),
'filters' => $filters,
'category' => $category,
'product' => $product,
'brand' => $brand ?? null,
'blocks' => $blocks ?? null,
'similarProducts' => $similarProducts ?? null,
]);
}
}