<?php
/*
* This file is part of EC-CUBE
*
* Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
*
* http://www.ec-cube.co.jp/
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Eccube\Controller\Block;
use Eccube\Controller\AbstractController;
use Eccube\Repository\ProductRepository;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Annotation\Route;
class RelatedProductController extends AbstractController
{
/**
* @var ProductRepository
*/
protected $productRepository;
/**
* @var RequestStack
*/
protected $requestStack;
/**
* RelatedProductController constructor.
*/
public function __construct(ProductRepository $productRepository, RequestStack $requestStack)
{
$this->productRepository = $productRepository;
$this->requestStack = $requestStack;
}
/**
* 関連商品ブロック
* 商品詳細ページ:商品情報編集で登録した「関連商品」(RelatedProduct42 プラグイン)を表示。
* プラグイン未使用時は同一カテゴリの商品。それ以外のページでは新着順。
*
* @Route("/block/related_product", name="block_related_product", methods={"GET"})
* @Template("Block/related_product.twig")
*/
public function index(Request $request)
{
$Products = [];
$maxResults = 8;
$mainRequest = $this->requestStack->getMainRequest();
if ($mainRequest && $mainRequest->attributes->get('_route') === 'product_detail') {
$productId = $mainRequest->attributes->get('id');
if ($productId) {
$Product = $this->productRepository->find($productId);
if ($Product) {
// 商品情報編集で登録した「関連商品」(RelatedProduct42 プラグイン)を優先
$Products = $this->getRelatedProductsFromPlugin($Product, $maxResults);
// プラグインで取得できなかった場合は同一カテゴリの商品で補う
if (empty($Products) && $Product->getProductCategories()) {
$categoryIds = [];
foreach ($Product->getProductCategories() as $ProductCategory) {
$Category = $ProductCategory->getCategory();
if ($Category) {
$categoryIds[] = $Category->getId();
}
}
if (!empty($categoryIds)) {
$Products = $this->productRepository->getProductsByCategoryIds(
$categoryIds,
$maxResults + 1
);
$Products = array_values(array_filter($Products, function ($p) use ($Product) {
return $p->getId() !== $Product->getId();
}));
$Products = array_slice($Products, 0, $maxResults);
}
}
}
}
}
if (empty($Products)) {
$qb = $this->productRepository->createQueryBuilder('p')
->addSelect(['pc', 'pi', 'tr', 'ps'])
->innerJoin('p.ProductClasses', 'pc')
->leftJoin('p.ProductImage', 'pi')
->leftJoin('pc.TaxRule', 'tr')
->leftJoin('pc.ProductStock', 'ps')
->andWhere('p.Status = 1')
->andWhere('pc.visible = :visible')
->setParameter('visible', true)
->orderBy('p.create_date', 'DESC')
->setMaxResults($maxResults);
$Products = $qb->getQuery()->getResult();
}
return [
'Products' => $Products,
];
}
/**
* 関連商品プラグイン(RelatedProduct42)で登録された関連商品を取得
*
* @param \Eccube\Entity\Product $Product 表示中商品
* @param int $maxResults 最大件数
* @return \Eccube\Entity\Product[]
*/
private function getRelatedProductsFromPlugin($Product, $maxResults)
{
foreach (['Plugin\RelatedProduct42\Entity\RelatedProduct', 'Plugin\RelatedProduct4\Entity\RelatedProduct'] as $entityClass) {
if (!class_exists($entityClass)) {
continue;
}
try {
$repo = $this->entityManager->getRepository($entityClass);
$orderBy = method_exists($entityClass, 'getSortNo') ? ['sortNo' => 'ASC'] : [];
$relatedEntities = $repo->findBy(
['Product' => $Product],
$orderBy,
$maxResults
);
$products = [];
foreach ($relatedEntities as $Related) {
$child = method_exists($Related, 'getChildProduct') ? $Related->getChildProduct() : null;
if ($child && $child->getId() !== $Product->getId()) {
$products[] = $child;
}
}
return $products;
} catch (\Throwable $e) {
continue;
}
}
return [];
}
}