Completed
Push — improve-lists ( 44b468 )
by Kiyotaka
08:29 queued 01:18
created

ProductRepository::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 3
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of EC-CUBE
5
 *
6
 * Copyright(c) LOCKON CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.lockon.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
     */
49
    public function __construct(
50
        RegistryInterface $registry,
51
        Queries $queries,
52
        EccubeConfig $eccubeConfig
53
    ) {
54
        parent::__construct($registry, Product::class);
55
        $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
     */
66
    public function findWithSortedClassCategories($productId)
67
    {
68
        $qb = $this->createQueryBuilder('p');
69
        $qb->addSelect(['pc', 'cc1', 'cc2', 'pi', 'pt'])
70
            ->innerJoin('p.ProductClasses', 'pc')
71
            ->leftJoin('pc.ClassCategory1', 'cc1')
72
            ->leftJoin('pc.ClassCategory2', 'cc2')
73
            ->leftJoin('p.ProductImage', 'pi')
74
            ->leftJoin('p.ProductTag', 'pt')
75
            ->where('p.id = :id')
76
            ->andWhere('pc.visible = :visible')
77
            ->setParameter('id', $productId)
78
            ->setParameter('visible', true)
79
            ->orderBy('cc1.sort_no', 'DESC')
80
            ->addOrderBy('cc2.sort_no', 'DESC');
81
82
        $product = $qb
83
            ->getQuery()
84
            ->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
     *
95
     * @return ArrayCollection|array
96
     */
97
    public function findProductsWithSortedClassCategories(array $ids, $indexBy = null)
98
    {
99
        if (count($ids) < 1) {
100
            return [];
101
        }
102
        $qb = $this->createQueryBuilder('p', $indexBy);
103
        $qb->addSelect(['pc', 'cc1', 'cc2', 'pi', 'pt', 'tr', 'ps'])
104
            ->innerJoin('p.ProductClasses', 'pc')
105
            // XXX Joined 'TaxRule' and 'ProductStock' to prevent lazy loading
106
            ->leftJoin('pc.TaxRule', 'tr')
107
            ->innerJoin('pc.ProductStock', 'ps')
108
            ->leftJoin('pc.ClassCategory1', 'cc1')
109
            ->leftJoin('pc.ClassCategory2', 'cc2')
110
            ->leftJoin('p.ProductImage', 'pi')
111
            ->leftJoin('p.ProductTag', 'pt')
112
            ->where($qb->expr()->in('p.id', $ids))
113
            ->andWhere($qb->expr()->in('pc.Product', $ids))
114
            ->andWhere($qb->expr()->in('pi.Product', $ids))
115
            ->andWhere('pc.visible = :visible')
116
            ->setParameter('visible', true)
117
            ->orderBy('cc1.sort_no', 'DESC')
118
            ->addOrderBy('cc2.sort_no', 'DESC');
119
120
        $products = $qb
121
            ->getQuery()
122
            ->getResult();
123
124
        return $products;
125
    }
126
127
    /**
128
     * get query builder.
129
     *
130
     * @param  array $searchData
131
     *
132
     * @return \Doctrine\ORM\QueryBuilder
133
     */
134
    public function getQueryBuilderBySearchData($searchData)
135
    {
136
        $qb = $this->createQueryBuilder('p')
137
            ->andWhere('p.Status = 1');
138
139
        // category
140
        $categoryJoin = false;
141 View Code Duplication
        if (!empty($searchData['category_id']) && $searchData['category_id']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
142
            $Categories = $searchData['category_id']->getSelfAndDescendants();
143
            if ($Categories) {
144
                $qb
145
                    ->innerJoin('p.ProductCategories', 'pct')
146
                    ->innerJoin('pct.Category', 'c')
147
                    ->andWhere($qb->expr()->in('pct.Category', ':Categories'))
148
                    ->setParameter('Categories', $Categories);
149
                $categoryJoin = true;
150
            }
151
        }
152
153
        // name
154
        if (isset($searchData['name']) && StringUtil::isNotBlank($searchData['name'])) {
155
            $keywords = preg_split('/[\s ]+/u', str_replace(['%', '_'], ['\\%', '\\_'], $searchData['name']), -1, PREG_SPLIT_NO_EMPTY);
156
157
            foreach ($keywords as $index => $keyword) {
158
                $key = sprintf('keyword%s', $index);
159
                $qb
160
                    ->andWhere(sprintf('NORMALIZE(p.name) LIKE NORMALIZE(:%s) OR 
161
                        NORMALIZE(p.search_word) LIKE NORMALIZE(:%s) OR 
162
                        EXISTS (SELECT wpc%d FROM \Eccube\Entity\ProductClass wpc%d WHERE p = wpc%d.Product AND NORMALIZE(wpc%d.code) LIKE NORMALIZE(:%s))',
163
                        $key, $key, $index, $index, $index, $index, $key))
164
                    ->setParameter($key, '%'.$keyword.'%');
165
            }
166
        }
167
168
        // Order By
169
        // 価格低い順
170
        $config = $this->eccubeConfig;
171
        if (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_lower']) {
172
            //@see http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html
173
            $qb->addSelect('MIN(pc.price02) as HIDDEN price02_min');
174
            $qb->innerJoin('p.ProductClasses', 'pc');
175
            $qb->andWhere('pc.visible = true');
176
            $qb->groupBy('p.id');
177
            $qb->orderBy('price02_min', 'ASC');
178
            $qb->addOrderBy('p.id', 'DESC');
179
        // 価格高い順
180
        } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_higher']) {
181
            $qb->addSelect('MAX(pc.price02) as HIDDEN price02_max');
182
            $qb->innerJoin('p.ProductClasses', 'pc');
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) {
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...
192
                $qb->innerJoin('p.ProductClasses', 'pc');
193
                $qb->andWhere('pc.visible = true');
194
            }
195
            $qb->orderBy('p.create_date', 'DESC');
196
            $qb->addOrderBy('p.id', 'DESC');
197
        } else {
198
            if ($categoryJoin === false) {
199
                $qb
200
                    ->leftJoin('p.ProductCategories', 'pct')
201
                    ->leftJoin('pct.Category', 'c');
202
            }
203
            $qb
204
                ->addOrderBy('p.id', 'DESC');
205
        }
206
207
        return $this->queries->customize(QueryKey::PRODUCT_SEARCH, $qb, $searchData);
208
    }
209
210
    /**
211
     * get query builder.
212
     *
213
     * @param  array $searchData
214
     *
215
     * @return \Doctrine\ORM\QueryBuilder
216
     */
217
    public function getQueryBuilderBySearchDataForAdmin($searchData)
218
    {
219
        $qb = $this->createQueryBuilder('p')
220
            ->addSelect('pc', 'pi', 'tr', 'ps')
221
            ->innerJoin('p.ProductClasses', 'pc')
222
            ->leftJoin('p.ProductImage', 'pi')
223
            ->leftJoin('pc.TaxRule', 'tr')
224
            ->leftJoin('pc.ProductStock', 'ps');
225
226
        // id
227
        if (isset($searchData['id']) && StringUtil::isNotBlank($searchData['id'])) {
228
            $id = preg_match('/^\d{0,10}$/', $searchData['id']) ? $searchData['id'] : null;
229
            $qb
230
                ->andWhere('p.id = :id OR p.name LIKE :likeid OR pc.code LIKE :likeid')
231
                ->setParameter('id', $id)
232
                ->setParameter('likeid', '%'.str_replace(['%', '_'], ['\\%', '\\_'], $searchData['id']).'%');
233
        }
234
235
        // code
236
        /*
237
        if (!empty($searchData['code']) && $searchData['code']) {
238
            $qb
239
                ->innerJoin('p.ProductClasses', 'pc')
240
                ->andWhere('pc.code LIKE :code')
241
                ->setParameter('code', '%' . $searchData['code'] . '%');
242
        }
243
244
        // name
245
        if (!empty($searchData['name']) && $searchData['name']) {
246
            $keywords = preg_split('/[\s ]+/u', $searchData['name'], -1, PREG_SPLIT_NO_EMPTY);
247
            foreach ($keywords as $keyword) {
248
                $qb
249
                    ->andWhere('p.name LIKE :name')
250
                    ->setParameter('name', '%' . $keyword . '%');
251
            }
252
        }
253
       */
254
255
        // category
256 View Code Duplication
        if (!empty($searchData['category_id']) && $searchData['category_id']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
257
            $Categories = $searchData['category_id']->getSelfAndDescendants();
258
            if ($Categories) {
259
                $qb
260
                    ->innerJoin('p.ProductCategories', 'pct')
261
                    ->innerJoin('pct.Category', 'c')
262
                    ->andWhere($qb->expr()->in('pct.Category', ':Categories'))
263
                    ->setParameter('Categories', $Categories);
264
            }
265
        }
266
267
        // status
268 View Code Duplication
        if (!empty($searchData['status']) && $searchData['status']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
269
            $qb
270
                ->andWhere($qb->expr()->in('p.Status', ':Status'))
271
                ->setParameter('Status', $searchData['status']);
272
        }
273
274
        // link_status
275 View Code Duplication
        if (isset($searchData['link_status']) && !empty($searchData['link_status'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
276
            $qb
277
                ->andWhere($qb->expr()->in('p.Status', ':Status'))
278
                ->setParameter('Status', $searchData['link_status']);
279
        }
280
281
        // stock status
282
        if (isset($searchData['stock_status'])) {
283
            $qb
284
                ->andWhere('pc.stock_unlimited = :StockUnlimited AND pc.stock = 0')
285
                ->setParameter('StockUnlimited', $searchData['stock_status']);
286
        }
287
288
        // stock status
289
        if (isset($searchData['stock']) && !empty($searchData['stock'])) {
290
            switch ($searchData['stock']) {
291
                case [ProductStock::IN_STOCK]:
292
                    $qb->andWhere('pc.stock_unlimited = true OR pc.stock > 0');
293
                    break;
294
                case [ProductStock::OUT_OF_STOCK]:
295
                    $qb->andWhere('pc.stock_unlimited = false AND pc.stock <= 0');
296
                    break;
297
                default:
298
                    // 共に選択された場合は全権該当するので検索条件に含めない
299
            }
300
        }
301
302
        // crate_date
303 View Code Duplication
        if (!empty($searchData['create_date_start']) && $searchData['create_date_start']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
304
            $date = $searchData['create_date_start'];
305
            $qb
306
                ->andWhere('p.create_date >= :create_date_start')
307
                ->setParameter('create_date_start', $date);
308
        }
309
310 View Code Duplication
        if (!empty($searchData['create_date_end']) && $searchData['create_date_end']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
311
            $date = clone $searchData['create_date_end'];
312
            $date = $date
313
                ->modify('+1 days');
314
            $qb
315
                ->andWhere('p.create_date < :create_date_end')
316
                ->setParameter('create_date_end', $date);
317
        }
318
319
        // update_date
320 View Code Duplication
        if (!empty($searchData['update_date_start']) && $searchData['update_date_start']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
321
            $date = $searchData['update_date_start'];
322
            $qb
323
                ->andWhere('p.update_date >= :update_date_start')
324
                ->setParameter('update_date_start', $date);
325
        }
326 View Code Duplication
        if (!empty($searchData['update_date_end']) && $searchData['update_date_end']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
327
            $date = clone $searchData['update_date_end'];
328
            $date = $date
329
                ->modify('+1 days');
330
            $qb
331
                ->andWhere('p.update_date < :update_date_end')
332
                ->setParameter('update_date_end', $date);
333
        }
334
335
        // Order By
336
        $qb
337
            ->orderBy('p.update_date', 'DESC');
338
339
        return $this->queries->customize(QueryKey::PRODUCT_SEARCH_ADMIN, $qb, $searchData);
340
    }
341
}
342