app/Customize/Repository/ProductRepository.php line 107

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