Completed
Push — 4.0 ( 268f2c...88f012 )
by Hideki
05:48 queued 10s
created

src/Eccube/Repository/ProductRepository.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/*
4
 * This file is part of EC-CUBE
5
 *
6
 * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.ec-cube.co.jp/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Eccube\Repository;
15
16
use Doctrine\Common\Collections\ArrayCollection;
17
use Eccube\Common\EccubeConfig;
18
use Eccube\Doctrine\Query\Queries;
19
use Eccube\Entity\Product;
20
use Eccube\Entity\ProductStock;
21
use Eccube\Util\StringUtil;
22
use Symfony\Bridge\Doctrine\RegistryInterface;
23
24
/**
25
 * ProductRepository
26
 *
27
 * This class was generated by the Doctrine ORM. Add your own custom
28
 * repository methods below.
29
 */
30
class ProductRepository extends AbstractRepository
31
{
32
    /**
33
     * @var Queries
34
     */
35
    protected $queries;
36
37
    /**
38
     * @var EccubeConfig
39
     */
40
    protected $eccubeConfig;
41
42
    /**
43
     * ProductRepository constructor.
44
     *
45
     * @param RegistryInterface $registry
46
     * @param Queries $queries
47
     * @param EccubeConfig $eccubeConfig
48 204
     */
49
    public function __construct(
50
        RegistryInterface $registry,
51
        Queries $queries,
52
        EccubeConfig $eccubeConfig
53 204
    ) {
54 204
        parent::__construct($registry, Product::class);
55 204
        $this->queries = $queries;
56
        $this->eccubeConfig = $eccubeConfig;
57
    }
58
59
    /**
60
     * Find the Product with sorted ClassCategories.
61
     *
62
     * @param integer $productId
63
     *
64
     * @return Product
65 15
     */
66
    public function findWithSortedClassCategories($productId)
67 15
    {
68 15
        $qb = $this->createQueryBuilder('p');
69 15
        $qb->addSelect(['pc', 'cc1', 'cc2', 'pi', 'pt'])
70 15
            ->innerJoin('p.ProductClasses', 'pc')
71 15
            ->leftJoin('pc.ClassCategory1', 'cc1')
72 15
            ->leftJoin('pc.ClassCategory2', 'cc2')
73 15
            ->leftJoin('p.ProductImage', 'pi')
74 15
            ->leftJoin('p.ProductTag', 'pt')
75 15
            ->where('p.id = :id')
76 15
            ->andWhere('pc.visible = :visible')
77
            ->setParameter('id', $productId)
78 15
            ->setParameter('visible', true)
79 15
            ->orderBy('cc1.sort_no', 'DESC')
80
            ->addOrderBy('cc2.sort_no', 'DESC');
81 15
82 15
        $product = $qb
83
            ->getQuery()
84 15
            ->getSingleResult();
85
86
        return $product;
87
    }
88
89
    /**
90
     * Find the Products with sorted ClassCategories.
91
     *
92
     * @param array $ids Product in ids
93
     * @param string $indexBy The index for the from.
94 17
     *
95
     * @return ArrayCollection|array
96 17
     */
97 17
    public function findProductsWithSortedClassCategories(array $ids, $indexBy = null)
98
    {
99
        if (count($ids) < 1) {
100 17
            return [];
101 17
        }
102 3
        $qb = $this->createQueryBuilder('p', $indexBy);
103 3
        $qb->addSelect(['pc', 'cc1', 'cc2', 'pi', 'pt', 'tr', 'ps'])
104
            ->innerJoin('p.ProductClasses', 'pc')
105 3
            // XXX Joined 'TaxRule' and 'ProductStock' to prevent lazy loading
106 3
            ->leftJoin('pc.TaxRule', 'tr')
107 3
            ->innerJoin('pc.ProductStock', 'ps')
108 3
            ->leftJoin('pc.ClassCategory1', 'cc1')
109 3
            ->leftJoin('pc.ClassCategory2', 'cc2')
110
            ->leftJoin('p.ProductImage', 'pi')
111
            ->leftJoin('p.ProductTag', 'pt')
112
            ->where($qb->expr()->in('p.id', $ids))
113
            ->andWhere('pc.visible = :visible')
114 17
            ->setParameter('visible', true)
115 2
            ->orderBy('cc1.sort_no', 'DESC')
116
            ->addOrderBy('cc2.sort_no', 'DESC');
117 2
118 2
        $products = $qb
119
            ->getQuery()
120 2
            ->useResultCache(true, $this->eccubeConfig['eccube_result_cache_lifetime_short'])
121
            ->getResult();
122
123 2
        return $products;
124 2
    }
125
126
    /**
127
     * get query builder.
128
     *
129
     * @param  array $searchData
130 17
     *
131 17
     * @return \Doctrine\ORM\QueryBuilder
132
     */
133 5
    public function getQueryBuilderBySearchData($searchData)
134 5
    {
135 5
        $qb = $this->createQueryBuilder('p')
136 5
            ->andWhere('p.Status = 1');
137 5
138 5
        // category
139
        $categoryJoin = false;
140 12 View Code Duplication
        if (!empty($searchData['category_id']) && $searchData['category_id']) {
141 1
            $Categories = $searchData['category_id']->getSelfAndDescendants();
142 1
            if ($Categories) {
143 1
                $qb
144 1
                    ->innerJoin('p.ProductCategories', 'pct')
145 1
                    ->innerJoin('pct.Category', 'c')
146 1
                    ->andWhere($qb->expr()->in('pct.Category', ':Categories'))
147
                    ->setParameter('Categories', $Categories);
148 11
                $categoryJoin = true;
149
            }
150
        }
151 4
152
        // name
153
        if (isset($searchData['name']) && StringUtil::isNotBlank($searchData['name'])) {
154
            $keywords = preg_split('/[\s ]+/u', str_replace(['%', '_'], ['\\%', '\\_'], $searchData['name']), -1, PREG_SPLIT_NO_EMPTY);
155 4
156 4
            foreach ($keywords as $index => $keyword) {
157
                $key = sprintf('keyword%s', $index);
158 7
                $qb
159
                    ->andWhere(sprintf('NORMALIZE(p.name) LIKE NORMALIZE(:%s) OR 
160 5
                        NORMALIZE(p.search_word) LIKE NORMALIZE(:%s) OR 
161 5
                        EXISTS (SELECT wpc%d FROM \Eccube\Entity\ProductClass wpc%d WHERE p = wpc%d.Product AND NORMALIZE(wpc%d.code) LIKE NORMALIZE(:%s))',
162
                        $key, $key, $index, $index, $index, $index, $key))
163
                    ->setParameter($key, '%'.$keyword.'%');
164 7
            }
165
        }
166
167 17
        // Order By
168
        // 価格低い順
169
        $config = $this->eccubeConfig;
170
        if (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_lower']) {
171
            //@see http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html
172
            $qb->addSelect('MIN(pc.price02) as HIDDEN price02_min');
173
            $qb->innerJoin('p.ProductClasses', 'pc');
174
            $qb->andWhere('pc.visible = true');
175
            $qb->groupBy('p.id');
176
            $qb->orderBy('price02_min', 'ASC');
177 20
            $qb->addOrderBy('p.id', 'DESC');
178
        // 価格高い順
179 20
        } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_higher']) {
180 20
            $qb->addSelect('MAX(pc.price02) as HIDDEN price02_max');
181
            $qb->innerJoin('p.ProductClasses', 'pc');
182
            $qb->andWhere('pc.visible = true');
183 20
            $qb->groupBy('p.id');
184 6
            $qb->orderBy('price02_max', 'DESC');
185
            $qb->addOrderBy('p.id', 'DESC');
186 6
        // 新着順
187 6
        } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_newer']) {
188 6
            // 在庫切れ商品非表示の設定が有効時対応
189
            // @see https://github.com/EC-CUBE/ec-cube/issues/1998
190
            if ($this->getEntityManager()->getFilters()->isEnabled('option_nostock_hidden') == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
191
                $qb->innerJoin('p.ProductClasses', 'pc');
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
206
        return $this->queries->customize(QueryKey::PRODUCT_SEARCH, $qb, $searchData);
207
    }
208
209
    /**
210
     * get query builder.
211
     *
212 20
     * @param  array $searchData
213 2
     *
214 2
     * @return \Doctrine\ORM\QueryBuilder
215
     */
216 2
    public function getQueryBuilderBySearchDataForAdmin($searchData)
217 2
    {
218 2
        $qb = $this->createQueryBuilder('p')
219 2
            ->addSelect('pc', 'pi', 'tr', 'ps')
220
            ->innerJoin('p.ProductClasses', 'pc')
221
            ->leftJoin('p.ProductImage', 'pi')
222
            ->leftJoin('pc.TaxRule', 'tr')
223
            ->leftJoin('pc.ProductStock', 'ps');
224 20
225
        // id
226 2
        if (isset($searchData['id']) && StringUtil::isNotBlank($searchData['id'])) {
227 2
            $id = preg_match('/^\d{0,10}$/', $searchData['id']) ? $searchData['id'] : null;
228
            $qb
229
                ->andWhere('p.id = :id OR p.name LIKE :likeid OR pc.code LIKE :likeid')
230
                ->setParameter('id', $id)
231 20
                ->setParameter('likeid', '%'.str_replace(['%', '_'], ['\\%', '\\_'], $searchData['id']).'%');
232
        }
233 1
234 1
        // code
235
        /*
236
        if (!empty($searchData['code']) && $searchData['code']) {
237
            $qb
238 20
                ->innerJoin('p.ProductClasses', 'pc')
239
                ->andWhere('pc.code LIKE :code')
240
                ->setParameter('code', '%' . $searchData['code'] . '%');
241
        }
242
243
        // name
244
        if (!empty($searchData['name']) && $searchData['name']) {
245 20
            $keywords = preg_split('/[\s ]+/u', $searchData['name'], -1, PREG_SPLIT_NO_EMPTY);
246 3
            foreach ($keywords as $keyword) {
247 3
                $qb
248 1
                    ->andWhere('p.name LIKE :name')
249 1
                    ->setParameter('name', '%' . $keyword . '%');
250 2
            }
251 2
        }
252 2
       */
253
254
        // category
255 View Code Duplication
        if (!empty($searchData['category_id']) && $searchData['category_id']) {
256
            $Categories = $searchData['category_id']->getSelfAndDescendants();
257
            if ($Categories) {
258
                $qb
259 20
                    ->innerJoin('p.ProductCategories', 'pct')
260 1
                    ->innerJoin('pct.Category', 'c')
261
                    ->andWhere($qb->expr()->in('pct.Category', ':Categories'))
262 1
                    ->setParameter('Categories', $Categories);
263 1
            }
264
        }
265
266 20
        // status
267 1 View Code Duplication
        if (!empty($searchData['status']) && $searchData['status']) {
268
            $qb
269 1
                ->andWhere($qb->expr()->in('p.Status', ':Status'))
270
                ->setParameter('Status', $searchData['status']);
271 1
        }
272 1
273
        // link_status
274 View Code Duplication
        if (isset($searchData['link_status']) && !empty($searchData['link_status'])) {
275
            $qb
276 20
                ->andWhere($qb->expr()->in('p.Status', ':Status'))
277 1
                ->setParameter('Status', $searchData['link_status']);
278
        }
279 1
280 1
        // stock status
281
        if (isset($searchData['stock_status'])) {
282 20
            $qb
283 1
                ->andWhere('pc.stock_unlimited = :StockUnlimited AND pc.stock = 0')
284
                ->setParameter('StockUnlimited', $searchData['stock_status']);
285 1
        }
286
287 1
        // stock status
288 1
        if (isset($searchData['stock']) && !empty($searchData['stock'])) {
289
            switch ($searchData['stock']) {
290
                case [ProductStock::IN_STOCK]:
291
                    $qb->andWhere('pc.stock_unlimited = true OR pc.stock > 0');
292
                    break;
293 20
                case [ProductStock::OUT_OF_STOCK]:
294
                    $qb->andWhere('pc.stock_unlimited = false AND pc.stock <= 0');
295 20
                    break;
296
                default:
297
                    // 共に選択された場合は全権該当するので検索条件に含めない
298
            }
299
        }
300
301
        // crate_date
302 View Code Duplication
        if (!empty($searchData['create_date_start']) && $searchData['create_date_start']) {
303
            $date = $searchData['create_date_start'];
304
            $qb
305
                ->andWhere('p.create_date >= :create_date_start')
306
                ->setParameter('create_date_start', $date);
307
        }
308
309 View Code Duplication
        if (!empty($searchData['create_date_end']) && $searchData['create_date_end']) {
310
            $date = clone $searchData['create_date_end'];
311
            $date = $date
312
                ->modify('+1 days');
313
            $qb
314
                ->andWhere('p.create_date < :create_date_end')
315
                ->setParameter('create_date_end', $date);
316
        }
317
318
        // update_date
319 View Code Duplication
        if (!empty($searchData['update_date_start']) && $searchData['update_date_start']) {
320
            $date = $searchData['update_date_start'];
321
            $qb
322
                ->andWhere('p.update_date >= :update_date_start')
323
                ->setParameter('update_date_start', $date);
324
        }
325 View Code Duplication
        if (!empty($searchData['update_date_end']) && $searchData['update_date_end']) {
326
            $date = clone $searchData['update_date_end'];
327
            $date = $date
328
                ->modify('+1 days');
329
            $qb
330
                ->andWhere('p.update_date < :update_date_end')
331
                ->setParameter('update_date_end', $date);
332
        }
333
334
        // Order By
335
        $qb
336
            ->orderBy('p.update_date', 'DESC');
337
338
        return $this->queries->customize(QueryKey::PRODUCT_SEARCH_ADMIN, $qb, $searchData);
339
    }
340
}
341