app/Customize/Repository/ProductRepository.php line 456

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