Failed Conditions
Push — dev/local-plugin-cache ( 16070e )
by Kiyotaka
08:36 queued 47s
created

ProductRepository::getQueryBuilderBySearchData()   C

Complexity

Conditions 15
Paths 36

Size

Total Lines 75

Duplication

Lines 11
Ratio 14.67 %

Importance

Changes 0
Metric Value
cc 15
nc 36
nop 1
dl 11
loc 75
rs 5.2787
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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('pc.visible = :visible')
114
            ->setParameter('visible', true)
115
            ->orderBy('cc1.sort_no', 'DESC')
116
            ->addOrderBy('cc2.sort_no', 'DESC');
117
118
        $products = $qb
119
            ->getQuery()
120
            ->useResultCache(true, $this->eccubeConfig['eccube_result_cache_lifetime_short'])
121
            ->getResult();
122
123
        return $products;
124
    }
125
126
    /**
127
     * get query builder.
128
     *
129
     * @param  array $searchData
130
     *
131
     * @return \Doctrine\ORM\QueryBuilder
132
     */
133
    public function getQueryBuilderBySearchData($searchData)
134
    {
135
        $qb = $this->createQueryBuilder('p')
136
            ->andWhere('p.Status = 1');
137
138
        // category
139
        $categoryJoin = false;
140 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...
141
            $Categories = $searchData['category_id']->getSelfAndDescendants();
142
            if ($Categories) {
143
                $qb
144
                    ->innerJoin('p.ProductCategories', 'pct')
145
                    ->innerJoin('pct.Category', 'c')
146
                    ->andWhere($qb->expr()->in('pct.Category', ':Categories'))
147
                    ->setParameter('Categories', $Categories);
148
                $categoryJoin = true;
149
            }
150
        }
151
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
156
            foreach ($keywords as $index => $keyword) {
157
                $key = sprintf('keyword%s', $index);
158
                $qb
159
                    ->andWhere(sprintf('NORMALIZE(p.name) LIKE NORMALIZE(:%s) OR 
160
                        NORMALIZE(p.search_word) LIKE NORMALIZE(:%s) OR 
161
                        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
            }
165
        }
166
167
        // 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
            $qb->addOrderBy('p.id', 'DESC');
178
        // 価格高い順
179
        } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_higher']) {
180
            $qb->addSelect('MAX(pc.price02) as HIDDEN price02_max');
181
            $qb->innerJoin('p.ProductClasses', 'pc');
182
            $qb->andWhere('pc.visible = true');
183
            $qb->groupBy('p.id');
184
            $qb->orderBy('price02_max', 'DESC');
185
            $qb->addOrderBy('p.id', 'DESC');
186
        // 新着順
187
        } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_newer']) {
188
            // 在庫切れ商品非表示の設定が有効時対応
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
     * @param  array $searchData
213
     *
214
     * @return \Doctrine\ORM\QueryBuilder
215
     */
216
    public function getQueryBuilderBySearchDataForAdmin($searchData)
217
    {
218
        $qb = $this->createQueryBuilder('p')
219
            ->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
225
        // id
226
        if (isset($searchData['id']) && StringUtil::isNotBlank($searchData['id'])) {
227
            $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
                ->setParameter('likeid', '%'.str_replace(['%', '_'], ['\\%', '\\_'], $searchData['id']).'%');
232
        }
233
234
        // code
235
        /*
236
        if (!empty($searchData['code']) && $searchData['code']) {
237
            $qb
238
                ->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
            $keywords = preg_split('/[\s ]+/u', $searchData['name'], -1, PREG_SPLIT_NO_EMPTY);
246
            foreach ($keywords as $keyword) {
247
                $qb
248
                    ->andWhere('p.name LIKE :name')
249
                    ->setParameter('name', '%' . $keyword . '%');
250
            }
251
        }
252
       */
253
254
        // category
255 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...
256
            $Categories = $searchData['category_id']->getSelfAndDescendants();
257
            if ($Categories) {
258
                $qb
259
                    ->innerJoin('p.ProductCategories', 'pct')
260
                    ->innerJoin('pct.Category', 'c')
261
                    ->andWhere($qb->expr()->in('pct.Category', ':Categories'))
262
                    ->setParameter('Categories', $Categories);
263
            }
264
        }
265
266
        // status
267 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...
268
            $qb
269
                ->andWhere($qb->expr()->in('p.Status', ':Status'))
270
                ->setParameter('Status', $searchData['status']);
271
        }
272
273
        // link_status
274 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...
275
            $qb
276
                ->andWhere($qb->expr()->in('p.Status', ':Status'))
277
                ->setParameter('Status', $searchData['link_status']);
278
        }
279
280
        // stock status
281
        if (isset($searchData['stock_status'])) {
282
            $qb
283
                ->andWhere('pc.stock_unlimited = :StockUnlimited AND pc.stock = 0')
284
                ->setParameter('StockUnlimited', $searchData['stock_status']);
285
        }
286
287
        // stock status
288
        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
                case [ProductStock::OUT_OF_STOCK]:
294
                    $qb->andWhere('pc.stock_unlimited = false AND pc.stock <= 0');
295
                    break;
296
                default:
297
                    // 共に選択された場合は全権該当するので検索条件に含めない
298
            }
299
        }
300
301
        // crate_date
302 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...
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']) {
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...
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']) {
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...
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']) {
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...
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