app/Customize/Repository/CustomProductRepository.php line 230

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 Customize\Repository;
  13. use Doctrine\Common\Collections\ArrayCollection;
  14. use Doctrine\Persistence\ManagerRegistry as RegistryInterface;
  15. use Eccube\Common\EccubeConfig;
  16. use Eccube\Doctrine\Query\Queries;
  17. use Eccube\Entity\Category;
  18. use Eccube\Entity\Master\ProductListMax;
  19. use Eccube\Entity\Master\ProductListOrderBy;
  20. use Eccube\Entity\Master\ProductStatus;
  21. use Eccube\Entity\Product;
  22. use Eccube\Entity\ProductStock;
  23. use Eccube\Entity\Tag;
  24. use Eccube\Util\StringUtil;
  25. use Eccube\Repository\AbstractRepository;
  26. use Eccube\Repository\QueryKey;
  27. use Symfony\Component\HttpFoundation\RequestStack;
  28. /**
  29.  * ProductRepository
  30.  *
  31.  * This class was generated by the Doctrine ORM. Add your own custom
  32.  * repository methods below.
  33.  */
  34. class CustomProductRepository extends AbstractRepository
  35. {
  36.     /**
  37.      * @var Queries
  38.      */
  39.     protected $queries;
  40.     /**
  41.      * @var EccubeConfig
  42.      */
  43.     protected $eccubeConfig;
  44.     /**
  45.      * @var RequestStack
  46.      */
  47.     protected $requestStack;
  48.     public const COLUMNS = [
  49.         'product_id' => 'p.id''name' => 'p.name''product_code' => 'pc.code''stock' => 'pc.stock''status' => 'p.Status''create_date' => 'p.create_date''update_date' => 'p.update_date',
  50.     ];
  51.     /**
  52.      * ProductRepository constructor.
  53.      *
  54.      * @param RegistryInterface $registry
  55.      * @param Queries $queries
  56.      * @param EccubeConfig $eccubeConfig
  57.      * @param RequestStack $requestStack
  58.      *
  59.      */
  60.     public function __construct(
  61.         RegistryInterface $registry,
  62.         Queries $queries,
  63.         EccubeConfig $eccubeConfig,
  64.         RequestStack $requestStack
  65.     ) {
  66.         parent::__construct($registryProduct::class);
  67.         $this->queries $queries;
  68.         $this->eccubeConfig $eccubeConfig;
  69.         $this->requestStack $requestStack;
  70.     }
  71.     /**
  72.      * Find the Product with sorted ClassCategories.
  73.      *
  74.      * @param integer $productId
  75.      *
  76.      * @return Product
  77.      */
  78.     public function findWithSortedClassCategories($productId)
  79.     {
  80.         $qb $this->createQueryBuilder('p');
  81.         $qb->addSelect(['pc''cc1''cc2''pi''pt'])
  82.             ->innerJoin('p.ProductClasses''pc')
  83.             ->leftJoin('pc.ClassCategory1''cc1')
  84.             ->leftJoin('pc.ClassCategory2''cc2')
  85.             ->leftJoin('p.ProductImage''pi')
  86.             ->leftJoin('p.ProductTag''pt')
  87.             ->where('p.id = :id')
  88.             ->andWhere('pc.visible = :visible')
  89.             ->setParameter('id'$productId)
  90.             ->setParameter('visible'true)
  91.             ->orderBy('cc1.sort_no''DESC')
  92.             ->addOrderBy('cc2.sort_no''DESC');
  93.         $product $qb
  94.             ->getQuery()
  95.             ->getSingleResult();
  96.         return $product;
  97.     }
  98.     /**
  99.      * Find the Products with sorted ClassCategories.
  100.      *
  101.      * @param array $ids Product in ids
  102.      * @param string $indexBy The index for the from.
  103.      *
  104.      * @return ArrayCollection|array
  105.      */
  106.     public function findProductsWithSortedClassCategories(array $ids$indexBy null)
  107.     {
  108.         if (count($ids) < 1) {
  109.             return [];
  110.         }
  111.         $qb $this->createQueryBuilder('p'$indexBy);
  112.         $qb->addSelect(['pc''cc1''cc2''pi''pt''tr''ps'])
  113.             ->innerJoin('p.ProductClasses''pc')
  114.             // XXX Joined 'TaxRule' and 'ProductStock' to prevent lazy loading
  115.             ->leftJoin('pc.TaxRule''tr')
  116.             ->innerJoin('pc.ProductStock''ps')
  117.             ->leftJoin('pc.ClassCategory1''cc1')
  118.             ->leftJoin('pc.ClassCategory2''cc2')
  119.             ->leftJoin('p.ProductImage''pi')
  120.             ->leftJoin('p.ProductTag''pt')
  121.             ->where($qb->expr()->in('p.id'$ids))
  122.             ->andWhere('pc.visible = :visible')
  123.             ->setParameter('visible'true)
  124.             ->orderBy('cc1.sort_no''DESC')
  125.             ->addOrderBy('cc2.sort_no''DESC');
  126.         $products $qb
  127.             ->getQuery()
  128.             ->useResultCache(true$this->eccubeConfig['eccube_result_cache_lifetime_short'])
  129.             ->getResult();
  130.         return $products;
  131.     }
  132.     /**
  133.      * get query builder.
  134.      *
  135.      * @param array{
  136.      *         category_id?:Category,
  137.      *         name?:string,
  138.      *         pageno?:string,
  139.      *         disp_number?:ProductListMax,
  140.      *         orderby?:ProductListOrderBy
  141.      *     } $searchData
  142.      *
  143.      * @return \Doctrine\ORM\QueryBuilder
  144.      */
  145.     public function customGetQueryBuilderBySearchData($searchData)
  146.     {
  147.         $qb $this->createQueryBuilder('p')
  148.             ->andWhere('p.Status = 1');
  149.         // category
  150.         $categoryJoin false;
  151.         if (!empty($searchData['category_id']) && $searchData['category_id']) {
  152.             $Categories $searchData['category_id']->getSelfAndDescendants();
  153.             if ($Categories) {
  154.                 $qb
  155.                     ->innerJoin('p.ProductCategories''pct')
  156.                     ->innerJoin('pct.Category''c')
  157.                     ->andWhere($qb->expr()->in('pct.Category'':Categories'))
  158.                     ->setParameter('Categories'$Categories);
  159.                 $categoryJoin true;
  160.             }
  161.         }
  162.         // name
  163.         if (isset($searchData['name']) && StringUtil::isNotBlank($searchData['name'])) {
  164.             $keywords preg_split('/[\s ]+/u'str_replace(['%''_'], ['\\%''\\_'], $searchData['name']), -1PREG_SPLIT_NO_EMPTY);
  165.             foreach ($keywords as $index => $keyword) {
  166.                 $key sprintf('keyword%s'$index);
  167.                 $qb
  168.                     ->andWhere(sprintf('NORMALIZE(p.name) LIKE NORMALIZE(:%s) OR
  169.                         NORMALIZE(p.search_word) LIKE NORMALIZE(:%s) OR
  170.                         EXISTS (SELECT wpc%d FROM \Eccube\Entity\ProductClass wpc%d WHERE p = wpc%d.Product AND NORMALIZE(wpc%d.code) LIKE NORMALIZE(:%s))',
  171.                         $key$key$index$index$index$index$key))
  172.                     ->setParameter($key'%'.$keyword.'%');
  173.             }
  174.         }
  175.         // Order By
  176.         // 価格低い順
  177.         $config $this->eccubeConfig;
  178.         if (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_lower']) {
  179.             // @see http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html
  180.             $qb->addSelect('MIN(pc.price02) as HIDDEN price02_min');
  181.             $qb->innerJoin('p.ProductClasses''pc');
  182.             $qb->andWhere('pc.visible = true');
  183.             $qb->groupBy('p.id');
  184.             $qb->orderBy('price02_min''ASC');
  185.             $qb->addOrderBy('p.id''DESC');
  186.         // 価格高い順
  187.         } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_higher']) {
  188.             $qb->addSelect('MAX(pc.price02) as HIDDEN price02_max');
  189.             $qb->innerJoin('p.ProductClasses''pc');
  190.             $qb->andWhere('pc.visible = true');
  191.             $qb->groupBy('p.id');
  192.             $qb->orderBy('price02_max''DESC');
  193.             $qb->addOrderBy('p.id''DESC');
  194.         // 新着順
  195.         } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_newer']) {
  196.             // 在庫切れ商品非表示の設定が有効時対応
  197.             // @see https://github.com/EC-CUBE/ec-cube/issues/1998
  198.             if ($this->getEntityManager()->getFilters()->isEnabled('option_nostock_hidden') == true) {
  199.                 $qb->innerJoin('p.ProductClasses''pc');
  200.                 $qb->andWhere('pc.visible = true');
  201.             }
  202.             $qb->orderBy('p.create_date''DESC');
  203.             $qb->addOrderBy('p.id''DESC');
  204.         // ランダム順
  205.         } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == 4) {
  206.             $session $this->requestStack->getSession();
  207.             if ($this->getEntityManager()->getFilters()->isEnabled('option_nostock_hidden') == true) {
  208.                 $qb->innerJoin('p.ProductClasses''pc');
  209.                 $qb->andWhere('pc.visible = true');
  210.             }
  211.             if (!$session->has('rand_seed')) {
  212.                 $session->set('rand_seed'random_int(1999999));
  213.             }
  214.             $seed $session->get('rand_seed');
  215.             $qb->addSelect('MOD(p.id * :seed, 1000000) as HIDDEN random_sort');
  216.             $qb->setParameter('seed'$seed);
  217.             $qb->resetDQLPart('orderBy');
  218.             $qb->orderBy('random_sort''ASC');
  219.         } else {
  220.             if ($categoryJoin === false) {
  221.                 $qb
  222.                     ->leftJoin('p.ProductCategories''pct')
  223.                     ->leftJoin('pct.Category''c');
  224.             }
  225.             $qb
  226.                 ->addOrderBy('p.id''DESC');
  227.         }
  228.         return $this->queries->customize(QueryKey::PRODUCT_SEARCH$qb$searchData);
  229.     }
  230.     /**
  231.      * get query builder.
  232.      *
  233.      * @param array{
  234.      *         id?:string|int|null,
  235.      *         category_id?:Category,
  236.      *         status?:ProductStatus[],
  237.      *         link_status?:ProductStatus[],
  238.      *         stock_status?:int,
  239.      *         stock?:ProductStock::IN_STOCK|ProductStock::OUT_OF_STOCK,
  240.      *         tag_id?:Tag,
  241.      *         create_datetime_start?:\DateTime,
  242.      *         create_datetime_end?:\DateTime,
  243.      *         create_date_start?:\DateTime,
  244.      *         create_date_end?:\DateTime,
  245.      *         update_datetime_start?:\DateTime,
  246.      *         update_datetime_end?:\DateTime,
  247.      *         update_date_start?:\DateTime,
  248.      *         update_date_end?:\DateTime,
  249.      *         sortkey?:string,
  250.      *         sorttype?:string
  251.      *     } $searchData
  252.      *
  253.      * @return \Doctrine\ORM\QueryBuilder
  254.      */
  255.     public function getQueryBuilderBySearchDataForAdmin($searchData)
  256.     {
  257.         $qb $this->createQueryBuilder('p')
  258.             ->addSelect('pc''pi''tr''ps')
  259.             ->innerJoin('p.ProductClasses''pc')
  260.             ->leftJoin('p.ProductImage''pi')
  261.             ->leftJoin('pc.TaxRule''tr')
  262.             ->leftJoin('pc.ProductStock''ps')
  263.             ->andWhere('pc.visible = :visible')
  264.             ->setParameter('visible'true);
  265.         // id
  266.         if (isset($searchData['id']) && StringUtil::isNotBlank($searchData['id'])) {
  267.             $id preg_match('/^\d{0,10}$/'$searchData['id']) ? $searchData['id'] : null;
  268.             if ($id && $id '2147483647' && $this->isPostgreSQL()) {
  269.                 $id null;
  270.             }
  271.             $qb
  272.                 ->andWhere('p.id = :id OR p.name LIKE :likeid OR pc.code LIKE :likeid')
  273.                 ->setParameter('id'$id)
  274.                 ->setParameter('likeid''%'.str_replace(['%''_'], ['\\%''\\_'], $searchData['id']).'%');
  275.         }
  276.         // code
  277.         /*
  278.         if (!empty($searchData['code']) && $searchData['code']) {
  279.             $qb
  280.                 ->innerJoin('p.ProductClasses', 'pc')
  281.                 ->andWhere('pc.code LIKE :code')
  282.                 ->setParameter('code', '%' . $searchData['code'] . '%');
  283.         }
  284.         // name
  285.         if (!empty($searchData['name']) && $searchData['name']) {
  286.             $keywords = preg_split('/[\s ]+/u', $searchData['name'], -1, PREG_SPLIT_NO_EMPTY);
  287.             foreach ($keywords as $keyword) {
  288.                 $qb
  289.                     ->andWhere('p.name LIKE :name')
  290.                     ->setParameter('name', '%' . $keyword . '%');
  291.             }
  292.         }
  293.        */
  294.         // category
  295.         if (!empty($searchData['category_id']) && $searchData['category_id']) {
  296.             $Categories $searchData['category_id']->getSelfAndDescendants();
  297.             if ($Categories) {
  298.                 $qb
  299.                     ->innerJoin('p.ProductCategories''pct')
  300.                     ->innerJoin('pct.Category''c')
  301.                     ->andWhere($qb->expr()->in('pct.Category'':Categories'))
  302.                     ->setParameter('Categories'$Categories);
  303.             }
  304.         }
  305.         // status
  306.         if (!empty($searchData['status']) && $searchData['status']) {
  307.             $qb
  308.                 ->andWhere($qb->expr()->in('p.Status'':Status'))
  309.                 ->setParameter('Status'$searchData['status']);
  310.         }
  311.         // link_status
  312.         if (isset($searchData['link_status']) && !empty($searchData['link_status'])) {
  313.             $qb
  314.                 ->andWhere($qb->expr()->in('p.Status'':Status'))
  315.                 ->setParameter('Status'$searchData['link_status']);
  316.         }
  317.         // stock status
  318.         if (isset($searchData['stock_status'])) {
  319.             $qb
  320.                 ->andWhere('pc.stock_unlimited = :StockUnlimited AND pc.stock = 0')
  321.                 ->setParameter('StockUnlimited'$searchData['stock_status']);
  322.         }
  323.         // stock status
  324.         if (isset($searchData['stock']) && !empty($searchData['stock'])) {
  325.             switch ($searchData['stock']) {
  326.                 case [ProductStock::IN_STOCK]:
  327.                     $qb->andWhere('pc.stock_unlimited = true OR pc.stock > 0');
  328.                     break;
  329.                 case [ProductStock::OUT_OF_STOCK]:
  330.                     $qb->andWhere('pc.stock_unlimited = false AND pc.stock <= 0');
  331.                     break;
  332.                 default:
  333.                     // 共に選択された場合は全権該当するので検索条件に含めない
  334.             }
  335.         }
  336.         // tag
  337.         if (!empty($searchData['tag_id']) && $searchData['tag_id']) {
  338.             $qb
  339.                 ->innerJoin('p.ProductTag''pt')
  340.                 ->andWhere('pt.Tag = :tag_id')
  341.                 ->setParameter('tag_id'$searchData['tag_id']);
  342.         }
  343.         // crate_date
  344.         if (!empty($searchData['create_datetime_start']) && $searchData['create_datetime_start']) {
  345.             $date $searchData['create_datetime_start'];
  346.             $qb
  347.                 ->andWhere('p.create_date >= :create_date_start')
  348.                 ->setParameter('create_date_start'$date);
  349.         } elseif (!empty($searchData['create_date_start']) && $searchData['create_date_start']) {
  350.             $date $searchData['create_date_start'];
  351.             $qb
  352.                 ->andWhere('p.create_date >= :create_date_start')
  353.                 ->setParameter('create_date_start'$date);
  354.         }
  355.         if (!empty($searchData['create_datetime_end']) && $searchData['create_datetime_end']) {
  356.             $date $searchData['create_datetime_end'];
  357.             $qb
  358.                 ->andWhere('p.create_date < :create_date_end')
  359.                 ->setParameter('create_date_end'$date);
  360.         } elseif (!empty($searchData['create_date_end']) && $searchData['create_date_end']) {
  361.             $date = clone $searchData['create_date_end'];
  362.             $date $date
  363.                 ->modify('+1 days');
  364.             $qb
  365.                 ->andWhere('p.create_date < :create_date_end')
  366.                 ->setParameter('create_date_end'$date);
  367.         }
  368.         // update_date
  369.         if (!empty($searchData['update_datetime_start']) && $searchData['update_datetime_start']) {
  370.             $date $searchData['update_datetime_start'];
  371.             $qb
  372.                 ->andWhere('p.update_date >= :update_date_start')
  373.                 ->setParameter('update_date_start'$date);
  374.         } elseif (!empty($searchData['update_date_start']) && $searchData['update_date_start']) {
  375.             $date $searchData['update_date_start'];
  376.             $qb
  377.                 ->andWhere('p.update_date >= :update_date_start')
  378.                 ->setParameter('update_date_start'$date);
  379.         }
  380.         if (!empty($searchData['update_datetime_end']) && $searchData['update_datetime_end']) {
  381.             $date $searchData['update_datetime_end'];
  382.             $qb
  383.                 ->andWhere('p.update_date < :update_date_end')
  384.                 ->setParameter('update_date_end'$date);
  385.         } elseif (!empty($searchData['update_date_end']) && $searchData['update_date_end']) {
  386.             $date = clone $searchData['update_date_end'];
  387.             $date $date
  388.                 ->modify('+1 days');
  389.             $qb
  390.                 ->andWhere('p.update_date < :update_date_end')
  391.                 ->setParameter('update_date_end'$date);
  392.         }
  393.         // Order By
  394.         if (isset($searchData['sortkey']) && !empty($searchData['sortkey'])) {
  395.             $sortOrder = (isset($searchData['sorttype']) && $searchData['sorttype'] == 'a') ? 'ASC' 'DESC';
  396.             $qb->orderBy(self::COLUMNS[$searchData['sortkey']], $sortOrder);
  397.             $qb->addOrderBy('p.update_date''DESC');
  398.             $qb->addOrderBy('p.id''DESC');
  399.         } else {
  400.             $qb->orderBy('p.update_date''DESC');
  401.             $qb->addOrderBy('p.id''DESC');
  402.         }
  403.         return $this->queries->customize(QueryKey::PRODUCT_SEARCH_ADMIN$qb$searchData);
  404.     }
  405. }