src/Eccube/Repository/ProductRepository.php line 77

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