src/Eccube/Repository/ProductRepository.php line 54

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of EC-CUBE
  4.  *
  5.  * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  6.  *
  7.  * http://www.ec-cube.co.jp/
  8.  *
  9.  * For the full copyright and license information, please view the LICENSE
  10.  * file that was distributed with this source code.
  11.  */
  12. namespace Eccube\Repository;
  13. use Doctrine\Common\Collections\ArrayCollection;
  14. use Eccube\Common\EccubeConfig;
  15. use Eccube\Doctrine\Query\Queries;
  16. use Eccube\Entity\Product;
  17. use Eccube\Entity\ProductStock;
  18. use Eccube\Util\StringUtil;
  19. use Symfony\Bridge\Doctrine\RegistryInterface;
  20. /**
  21.  * ProductRepository
  22.  *
  23.  * This class was generated by the Doctrine ORM. Add your own custom
  24.  * repository methods below.
  25.  */
  26. class ProductRepository extends AbstractRepository
  27. {
  28.     /**
  29.      * @var Queries
  30.      */
  31.     protected $queries;
  32.     /**
  33.      * @var EccubeConfig
  34.      */
  35.     protected $eccubeConfig;
  36.     /**
  37.      * ProductRepository constructor.
  38.      *
  39.      * @param RegistryInterface $registry
  40.      * @param Queries $queries
  41.      * @param EccubeConfig $eccubeConfig
  42.      */
  43.     public function __construct(
  44.         RegistryInterface $registry,
  45.         Queries $queries,
  46.         EccubeConfig $eccubeConfig
  47.     ) {
  48.         parent::__construct($registryProduct::class);
  49.         $this->queries $queries;
  50.         $this->eccubeConfig $eccubeConfig;
  51.     }
  52.     /**
  53.      * Find the Product with sorted ClassCategories.
  54.      *
  55.      * @param integer $productId
  56.      *
  57.      * @return Product
  58.      */
  59.     public function findWithSortedClassCategories($productId)
  60.     {
  61.         $qb $this->createQueryBuilder('p');
  62.         $qb->addSelect(['pc''cc1''cc2''pi''pt'])
  63.             ->innerJoin('p.ProductClasses''pc')
  64.             ->leftJoin('pc.ClassCategory1''cc1')
  65.             ->leftJoin('pc.ClassCategory2''cc2')
  66.             ->leftJoin('p.ProductImage''pi')
  67.             ->leftJoin('p.ProductTag''pt')
  68.             ->where('p.id = :id')
  69.             ->andWhere('pc.visible = :visible')
  70.             ->setParameter('id'$productId)
  71.             ->setParameter('visible'true)
  72.             ->orderBy('cc1.sort_no''DESC')
  73.             ->addOrderBy('cc2.sort_no''DESC');
  74.         $product $qb
  75.             ->getQuery()
  76.             ->getSingleResult();
  77.         return $product;
  78.     }
  79.     /**
  80.      * Find the Products with sorted ClassCategories.
  81.      *
  82.      * @param array $ids Product in ids
  83.      * @param string $indexBy The index for the from.
  84.      *
  85.      * @return ArrayCollection|array
  86.      */
  87.     public function findProductsWithSortedClassCategories(array $ids$indexBy null)
  88.     {
  89.         if (count($ids) < 1) {
  90.             return [];
  91.         }
  92.         $qb $this->createQueryBuilder('p'$indexBy);
  93.         $qb->addSelect(['pc''cc1''cc2''pi''pt''tr''ps'])
  94.             ->innerJoin('p.ProductClasses''pc')
  95.         // XXX Joined 'TaxRule' and 'ProductStock' to prevent lazy loading
  96.             ->leftJoin('pc.TaxRule''tr')
  97.             ->innerJoin('pc.ProductStock''ps')
  98.             ->leftJoin('pc.ClassCategory1''cc1')
  99.             ->leftJoin('pc.ClassCategory2''cc2')
  100.             ->leftJoin('p.ProductImage''pi')
  101.             ->leftJoin('p.ProductTag''pt')
  102.             ->where($qb->expr()->in('p.id'$ids))
  103.             ->andWhere('pc.visible = :visible')
  104.             ->setParameter('visible'true)
  105.             ->orderBy('cc1.sort_no''DESC')
  106.             ->addOrderBy('cc2.sort_no''DESC');
  107.         $products $qb
  108.             ->getQuery()
  109.             ->useResultCache(true$this->eccubeConfig['eccube_result_cache_lifetime_short'])
  110.             ->getResult();
  111.         return $products;
  112.     }
  113.     /**
  114.      * get query builder.
  115.      *
  116.      * @param  array $searchData
  117.      *
  118.      * @return \Doctrine\ORM\QueryBuilder
  119.      */
  120.     public function getQueryBuilderBySearchData($searchData)
  121.     {
  122.         $qb $this->createQueryBuilder('p')
  123.             ->andWhere('p.Status = 1')
  124.             ->andWhere('p.published_at is NULL OR p.published_at <= :now')
  125.             ->setParameter('now', new \DateTime());
  126.         // category
  127.         $categoryJoin false;
  128.         if (!empty($searchData['category_id']) && $searchData['category_id']) {
  129.             $Categories $searchData['category_id']->getSelfAndDescendants();
  130.             if ($Categories) {
  131.                 $qb
  132.                     ->innerJoin('p.ProductCategories''pct')
  133.                     ->innerJoin('pct.Category''c')
  134.                     ->andWhere($qb->expr()->in('pct.Category'':Categories'))
  135.                     ->setParameter('Categories'$Categories);
  136.                 $categoryJoin true;
  137.             }
  138.         }
  139.         if (isset($searchData['freeword']) && StringUtil::isNotBlank($searchData['freeword'])) {
  140.             $id preg_match('/^\d{0,10}$/'$searchData['freeword']) ? $searchData['freeword'] : null;
  141.             $qb
  142.                 ->leftJoin('p.ProductCategories''pct2')
  143.                 ->leftJoin('pct2.Category''c2');
  144.             $qb
  145.                 ->andWhere('p.id = :id OR p.name LIKE :likeid OR pc.code LIKE :likeid OR c2.name LIKE :likeid OR p.search_word LIKE :likeid')
  146.                 ->setParameter('id'$id)
  147.                 ->setParameter('likeid''%' str_replace(['%''_'], ['\\%''\\_'], $searchData['freeword']) . '%');
  148.         }
  149.         // name
  150.         if (isset($searchData['name']) && StringUtil::isNotBlank($searchData['name'])) {
  151.             $keywords preg_split('/[\s ]+/u'str_replace(['%''_'], ['\\%''\\_'], $searchData['name']), -1PREG_SPLIT_NO_EMPTY);
  152.             foreach ($keywords as $index => $keyword) {
  153.                 $key sprintf('keyword%s'$index);
  154.                 $qb
  155.                     ->andWhere(sprintf('NORMALIZE(p.name) LIKE NORMALIZE(:%s) OR
  156.                         NORMALIZE(p.search_word) LIKE NORMALIZE(:%s) OR
  157.                         EXISTS (SELECT wpc%d FROM \Eccube\Entity\ProductClass wpc%d WHERE p = wpc%d.Product AND NORMALIZE(wpc%d.code) LIKE NORMALIZE(:%s))',
  158.                         $key$key$index$index$index$index$key))
  159.                     ->setParameter($key'%' $keyword '%');
  160.             }
  161.         }
  162.         if (!empty($searchData['is_special_sort'])) {
  163.             $qb->addSelect("(CASE WHEN (CASE WHEN MAX(pc.stock) IS NULL THEN 0 ELSE MAX(pc.stock) END) + (CASE WHEN MAX(pc.stock_unlimited) IS NULL THEN 0 ELSE  MAX(pc.stock_unlimited) END) = 0 THEN '0000-00-00 00:00:00_0000-00-00 00:00:00' ELSE CONCAT(CASE WHEN p.published_at IS NULL THEN '0000-00-00 00:00:00' ELSE p.published_at END, '_', p.create_date) END) AS HIDDEN sort_field")
  164.                 ->andWhere('p.published_at is NULL OR p.published_at <= :now')
  165.                 ->setParameter('now', new \DateTime())
  166.                 ->andWhere('pc.visible = :visible')
  167.                 ->setParameter('visible'true)
  168.                 ->innerJoin('p.ProductClasses''pc')
  169.                 ->groupBy('p.id')
  170.                 ->addOrderBy('sort_field''DESC')
  171.                 ->addOrderBy('p.id''DESC');
  172.         } else {
  173.             // Order By
  174.             // 価格低い順
  175.             $config $this->eccubeConfig;
  176.             if (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_lower']) {
  177.                 //@see http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html
  178.                 $qb->addSelect('MIN(pc.price02) as HIDDEN price02_min');
  179.                 $qb->innerJoin('p.ProductClasses''pc');
  180.                 $qb->andWhere('pc.visible = true');
  181.                 $qb->groupBy('p.id');
  182.                 $qb->orderBy('price02_min''ASC');
  183.                 $qb->addOrderBy('p.id''DESC');
  184.                 // 価格高い順
  185.             } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_higher']) {
  186.                 $qb->addSelect('MAX(pc.price02) as HIDDEN price02_max');
  187.                 $qb->innerJoin('p.ProductClasses''pc');
  188.                 $qb->andWhere('pc.visible = true');
  189.                 $qb->groupBy('p.id');
  190.                 $qb->orderBy('price02_max''DESC');
  191.                 $qb->addOrderBy('p.id''DESC');
  192.                 // 新着順
  193.             } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_newer']) {
  194.                 // 在庫切れ商品非表示の設定が有効時対応
  195.                 // @see https://github.com/EC-CUBE/ec-cube/issues/1998
  196.                 if ($this->getEntityManager()->getFilters()->isEnabled('option_nostock_hidden') == true) {
  197.                     $qb->innerJoin('p.ProductClasses''pc');
  198.                     $qb->andWhere('pc.visible = true');
  199.                 }
  200.                 $qb->orderBy('p.create_date''DESC');
  201.                 $qb->addOrderBy('p.id''DESC');
  202.             } else {
  203.                 if ($categoryJoin === false) {
  204.                     $qb
  205.                         ->leftJoin('p.ProductCategories''pct')
  206.                         ->leftJoin('pct.Category''c');
  207.                 }
  208.                 $qb
  209.                     ->addOrderBy('p.id''DESC');
  210.             }
  211.         }
  212.         return $this->queries->customize(QueryKey::PRODUCT_SEARCH$qb$searchData);
  213.     }
  214.     /**
  215.      * get query builder.
  216.      *
  217.      * @param  array $searchData
  218.      *
  219.      * @return \Doctrine\ORM\QueryBuilder
  220.      */
  221.     public function getQueryBuilderBySearchDataForAdmin($searchData)
  222.     {
  223.         $qb $this->createQueryBuilder('p')
  224.             ->addSelect('pc''pi''tr''ps')
  225.             ->innerJoin('p.ProductClasses''pc')
  226.             ->leftJoin('p.ProductImage''pi')
  227.             ->leftJoin('pc.TaxRule''tr')
  228.             ->leftJoin('pc.ProductStock''ps');
  229.         // id
  230.         if (isset($searchData['id']) && StringUtil::isNotBlank($searchData['id'])) {
  231.             $id preg_match('/^\d{0,10}$/'$searchData['id']) ? $searchData['id'] : null;
  232.             $qb
  233.                 ->andWhere('p.id = :id OR p.name LIKE :likeid OR pc.code LIKE :likeid')
  234.                 ->setParameter('id'$id)
  235.                 ->setParameter('likeid''%' str_replace(['%''_'], ['\\%''\\_'], $searchData['id']) . '%');
  236.         }
  237.         // code
  238.         /*
  239.         if (!empty($searchData['code']) && $searchData['code']) {
  240.         $qb
  241.         ->innerJoin('p.ProductClasses', 'pc')
  242.         ->andWhere('pc.code LIKE :code')
  243.         ->setParameter('code', '%' . $searchData['code'] . '%');
  244.         }
  245.         // name
  246.         if (!empty($searchData['name']) && $searchData['name']) {
  247.         $keywords = preg_split('/[\s ]+/u', $searchData['name'], -1, PREG_SPLIT_NO_EMPTY);
  248.         foreach ($keywords as $keyword) {
  249.         $qb
  250.         ->andWhere('p.name LIKE :name')
  251.         ->setParameter('name', '%' . $keyword . '%');
  252.         }
  253.         }
  254.          */
  255.         // category
  256.         if (!empty($searchData['category_id']) && $searchData['category_id']) {
  257.             $Categories $searchData['category_id']->getSelfAndDescendants();
  258.             if ($Categories) {
  259.                 $qb
  260.                     ->innerJoin('p.ProductCategories''pct')
  261.                     ->innerJoin('pct.Category''c')
  262.                     ->andWhere($qb->expr()->in('pct.Category'':Categories'))
  263.                     ->setParameter('Categories'$Categories);
  264.             }
  265.         }
  266.         // status
  267.         if (!empty($searchData['status']) && $searchData['status']) {
  268.             $qb
  269.                 ->andWhere($qb->expr()->in('p.Status'':Status'))
  270.                 ->setParameter('Status'$searchData['status']);
  271.         }
  272.         // link_status
  273.         if (isset($searchData['link_status']) && !empty($searchData['link_status'])) {
  274.             $qb
  275.                 ->andWhere($qb->expr()->in('p.Status'':Status'))
  276.                 ->setParameter('Status'$searchData['link_status']);
  277.         }
  278.         // stock status
  279.         if (isset($searchData['stock_status'])) {
  280.             $qb
  281.                 ->andWhere('pc.stock_unlimited = :StockUnlimited AND pc.stock = 0')
  282.                 ->setParameter('StockUnlimited'$searchData['stock_status']);
  283.         }
  284.         // stock status
  285.         if (isset($searchData['stock']) && !empty($searchData['stock'])) {
  286.             switch ($searchData['stock']) {
  287.                 case [ProductStock::IN_STOCK]:
  288.                     $qb->andWhere('( pc.stock_unlimited = true OR pc.stock > 0 ) AND pc.visible=1');
  289.                     break;
  290.                 case [ProductStock::OUT_OF_STOCK]:
  291.                     $qb->andWhere('pc.stock_unlimited = false AND pc.stock <= 0 AND pc.visible=1');
  292.                     break;
  293.                 default:
  294.                     // 共に選択された場合は全権該当するので検索条件に含めない
  295.             }
  296.         }
  297.         // crate_date
  298.         if (!empty($searchData['create_date_start']) && $searchData['create_date_start']) {
  299.             $date $searchData['create_date_start'];
  300.             $qb
  301.                 ->andWhere('p.create_date >= :create_date_start')
  302.                 ->setParameter('create_date_start'$date);
  303.         }
  304.         if (!empty($searchData['create_date_end']) && $searchData['create_date_end']) {
  305.             $date = clone $searchData['create_date_end'];
  306.             $date $date
  307.                 ->modify('+1 days');
  308.             $qb
  309.                 ->andWhere('p.create_date < :create_date_end')
  310.                 ->setParameter('create_date_end'$date);
  311.         }
  312.         // update_date
  313.         if (!empty($searchData['update_date_start']) && $searchData['update_date_start']) {
  314.             $date $searchData['update_date_start'];
  315.             $qb
  316.                 ->andWhere('p.update_date >= :update_date_start')
  317.                 ->setParameter('update_date_start'$date);
  318.         }
  319.         if (!empty($searchData['update_date_end']) && $searchData['update_date_end']) {
  320.             $date = clone $searchData['update_date_end'];
  321.             $date $date
  322.                 ->modify('+1 days');
  323.             $qb
  324.                 ->andWhere('p.update_date < :update_date_end')
  325.                 ->setParameter('update_date_end'$date);
  326.         }
  327.         // Order By
  328.         $qb
  329.             ->orderBy('p.update_date''DESC');
  330.         return $this->queries->customize(QueryKey::PRODUCT_SEARCH_ADMIN$qb$searchData);
  331.     }
  332. }