src/Eccube/Repository/ProductRepository.php line 65

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