Failed Conditions
Pull Request — experimental/sf (#29)
by Kentaro
50:12 queued 39:05
created

ProductRepository::getQueryBuilderBySearchData()   C

Complexity

Conditions 15
Paths 36

Size

Total Lines 75

Duplication

Lines 11
Ratio 14.67 %

Code Coverage

Tests 43
CRAP Score 15.0196

Importance

Changes 0
Metric Value
cc 15
nc 36
nop 1
dl 11
loc 75
ccs 43
cts 45
cp 0.9556
crap 15.0196
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 Eccube\Common\EccubeConfig;
17
use Eccube\Doctrine\Query\Queries;
18
use Eccube\Entity\Product;
19
use Eccube\Entity\ProductStock;
20
use Eccube\Util\StringUtil;
21
use Symfony\Bridge\Doctrine\RegistryInterface;
22
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
    /**
37
     * @var EccubeConfig
38
     */
39
    protected $eccubeConfig;
40
41
    /**
42
     * ProductRepository constructor.
43
     *
44
     * @param RegistryInterface $registry
45
     * @param Queries $queries
46
     * @param EccubeConfig $eccubeConfig
47
     */
48 198
    public function __construct(
49
        RegistryInterface $registry,
50
        Queries $queries,
51
        EccubeConfig $eccubeConfig
52
    ) {
53 198
        parent::__construct($registry, Product::class);
54 198
        $this->queries = $queries;
55 198
        $this->eccubeConfig = $eccubeConfig;
56
    }
57
58
    /**
59
     * Find the Product with sorted ClassCategories.
60
     *
61
     * @param integer $productId
62
     *
63
     * @return Product
64
     */
65 11
    public function findWithSortedClassCategories($productId)
66
    {
67 11
        $qb = $this->createQueryBuilder('p');
68 11
        $qb->addSelect(['pc', 'cc1', 'cc2', 'pi', 'ps'])
69 11
            ->innerJoin('p.ProductClasses', 'pc')
70 11
            ->leftJoin('pc.ClassCategory1', 'cc1')
71 11
            ->leftJoin('pc.ClassCategory2', 'cc2')
72 11
            ->leftJoin('p.ProductImage', 'pi')
73 11
            ->innerJoin('pc.ProductStock', 'ps')
74 11
            ->where('p.id = :id')
75 11
            ->orderBy('cc1.sort_no', 'DESC')
76 11
            ->addOrderBy('cc2.sort_no', 'DESC');
77
        $product = $qb
78 11
            ->setParameters([
79 11
                'id' => $productId,
80
            ])
81 11
            ->getQuery()
82 11
            ->getSingleResult();
83
84 11
        return $product;
85
    }
86
87
    /**
88
     * get query builder.
89
     *
90
     * @param  array $searchData
91
     *
92
     * @return \Doctrine\ORM\QueryBuilder
93
     */
94 17
    public function getQueryBuilderBySearchData($searchData)
95
    {
96 17
        $qb = $this->createQueryBuilder('p')
97 17
            ->andWhere('p.Status = 1');
98
99
        // category
100 17
        $categoryJoin = false;
101 17 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...
102 3
            $Categories = $searchData['category_id']->getSelfAndDescendants();
103 3
            if ($Categories) {
104
                $qb
105 3
                    ->innerJoin('p.ProductCategories', 'pct')
106 3
                    ->innerJoin('pct.Category', 'c')
107 3
                    ->andWhere($qb->expr()->in('pct.Category', ':Categories'))
108 3
                    ->setParameter('Categories', $Categories);
109 3
                $categoryJoin = true;
110
            }
111
        }
112
113
        // name
114 17
        if (isset($searchData['name']) && StringUtil::isNotBlank($searchData['name'])) {
115 2
            $keywords = preg_split('/[\s ]+/u', str_replace(['%', '_'], ['\\%', '\\_'], $searchData['name']), -1, PREG_SPLIT_NO_EMPTY);
116
117 2
            foreach ($keywords as $index => $keyword) {
118 2
                $key = sprintf('keyword%s', $index);
119
                $qb
120 2
                    ->andWhere(sprintf('NORMALIZE(p.name) LIKE NORMALIZE(:%s) OR 
121
                        NORMALIZE(p.search_word) LIKE NORMALIZE(:%s) OR 
122
                        EXISTS (SELECT wpc%d FROM \Eccube\Entity\ProductClass wpc%d WHERE p = wpc%d.Product AND NORMALIZE(wpc%d.code) LIKE NORMALIZE(:%s))',
123 2
                        $key, $key, $index, $index, $index, $index, $key))
124 2
                    ->setParameter($key, '%'.$keyword.'%');
125
            }
126
        }
127
128
        // Order By
129
        // 価格低い順
130 17
        $config = $this->eccubeConfig;
131 17
        if (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_lower']) {
132
            //@see http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html
133 5
            $qb->addSelect('MIN(pc.price02) as HIDDEN price02_min');
134 5
            $qb->innerJoin('p.ProductClasses', 'pc');
135 5
            $qb->andWhere('pc.visible = true');
136 5
            $qb->groupBy('p.id');
137 5
            $qb->orderBy('price02_min', 'ASC');
138 5
            $qb->addOrderBy('p.id', 'DESC');
139
        // 価格高い順
140 12
        } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_price_higher']) {
141 1
            $qb->addSelect('MAX(pc.price02) as HIDDEN price02_max');
142 1
            $qb->innerJoin('p.ProductClasses', 'pc');
143 1
            $qb->andWhere('pc.visible = true');
144 1
            $qb->groupBy('p.id');
145 1
            $qb->orderBy('price02_max', 'DESC');
146 1
            $qb->addOrderBy('p.id', 'DESC');
147
        // 新着順
148 11
        } elseif (!empty($searchData['orderby']) && $searchData['orderby']->getId() == $config['eccube_product_order_newer']) {
149
            // 在庫切れ商品非表示の設定が有効時対応
150
            // @see https://github.com/EC-CUBE/ec-cube/issues/1998
151 4
            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...
152
                $qb->innerJoin('p.ProductClasses', 'pc');
153
                $qb->andWhere('pc.visible = true');
154
            }
155 4
            $qb->orderBy('p.create_date', 'DESC');
156 4
            $qb->addOrderBy('p.id', 'DESC');
157
        } else {
158 7
            if ($categoryJoin === false) {
159
                $qb
160 5
                    ->leftJoin('p.ProductCategories', 'pct')
161 5
                    ->leftJoin('pct.Category', 'c');
162
            }
163
            $qb
164 7
                ->addOrderBy('p.id', 'DESC');
165
        }
166
167 17
        return $this->queries->customize(QueryKey::PRODUCT_SEARCH, $qb, $searchData);
168
    }
169
170
    /**
171
     * get query builder.
172
     *
173
     * @param  array $searchData
174
     *
175
     * @return \Doctrine\ORM\QueryBuilder
176
     */
177 20
    public function getQueryBuilderBySearchDataForAdmin($searchData)
178
    {
179 20
        $qb = $this->createQueryBuilder('p')
180 20
            ->innerJoin('p.ProductClasses', 'pc');
181
182
        // id
183 20
        if (isset($searchData['id']) && StringUtil::isNotBlank($searchData['id'])) {
184 6
            $id = preg_match('/^\d{0,10}$/', $searchData['id']) ? $searchData['id'] : null;
185
            $qb
186 6
                ->andWhere('p.id = :id OR p.name LIKE :likeid OR pc.code LIKE :likeid')
187 6
                ->setParameter('id', $id)
188 6
                ->setParameter('likeid', '%'.str_replace(['%', '_'], ['\\%', '\\_'], $searchData['id']).'%');
189
        }
190
191
        // code
192
        /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
193
        if (!empty($searchData['code']) && $searchData['code']) {
194
            $qb
195
                ->innerJoin('p.ProductClasses', 'pc')
196
                ->andWhere('pc.code LIKE :code')
197
                ->setParameter('code', '%' . $searchData['code'] . '%');
198
        }
199
200
        // name
201
        if (!empty($searchData['name']) && $searchData['name']) {
202
            $keywords = preg_split('/[\s ]+/u', $searchData['name'], -1, PREG_SPLIT_NO_EMPTY);
203
            foreach ($keywords as $keyword) {
204
                $qb
205
                    ->andWhere('p.name LIKE :name')
206
                    ->setParameter('name', '%' . $keyword . '%');
207
            }
208
        }
209
       */
210
211
        // category
212 20 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...
213 2
            $Categories = $searchData['category_id']->getSelfAndDescendants();
214 2
            if ($Categories) {
215
                $qb
216 2
                    ->innerJoin('p.ProductCategories', 'pct')
217 2
                    ->innerJoin('pct.Category', 'c')
218 2
                    ->andWhere($qb->expr()->in('pct.Category', ':Categories'))
219 2
                    ->setParameter('Categories', $Categories);
220
            }
221
        }
222
223
        // status
224 20 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...
225
            $qb
226 2
                ->andWhere($qb->expr()->in('p.Status', ':Status'))
227 2
                ->setParameter('Status', $searchData['status']);
228
        }
229
230
        // link_status
231 20 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...
232
            $qb
233 1
                ->andWhere($qb->expr()->in('p.Status', ':Status'))
234 1
                ->setParameter('Status', $searchData['link_status']);
235
        }
236
237
        // stock status
238 20
        if (isset($searchData['stock_status'])) {
239
            $qb
240
                ->andWhere('pc.stock_unlimited = :StockUnlimited AND pc.stock = 0')
241
                ->setParameter('StockUnlimited', $searchData['stock_status']);
242
        }
243
244
        // stock status
245 20
        if (isset($searchData['stock']) && !empty($searchData['stock'])) {
246 3
            switch ($searchData['stock']) {
247 3
                case [ProductStock::IN_STOCK]:
248 1
                    $qb->andWhere('pc.stock_unlimited = true OR pc.stock > 0');
249 1
                    break;
250 2
                case [ProductStock::OUT_OF_STOCK]:
251 2
                    $qb->andWhere('pc.stock_unlimited = false AND pc.stock <= 0');
252 2
                    break;
253
                default:
254
                    // 共に選択された場合は全権該当するので検索条件に含めない
255
            }
256
        }
257
258
        // crate_date
259 20 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...
260 1
            $date = $searchData['create_date_start'];
261
            $qb
262 1
                ->andWhere('p.create_date >= :create_date_start')
263 1
                ->setParameter('create_date_start', $date);
264
        }
265
266 20 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...
267 1
            $date = clone $searchData['create_date_end'];
268
            $date = $date
269 1
                ->modify('+1 days');
270
            $qb
271 1
                ->andWhere('p.create_date < :create_date_end')
272 1
                ->setParameter('create_date_end', $date);
273
        }
274
275
        // update_date
276 20 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...
277 1
            $date = $searchData['update_date_start'];
278
            $qb
279 1
                ->andWhere('p.update_date >= :update_date_start')
280 1
                ->setParameter('update_date_start', $date);
281
        }
282 20 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...
283 1
            $date = clone $searchData['update_date_end'];
284
            $date = $date
285 1
                ->modify('+1 days');
286
            $qb
287 1
                ->andWhere('p.update_date < :update_date_end')
288 1
                ->setParameter('update_date_end', $date);
289
        }
290
291
        // Order By
292
        $qb
293 20
            ->orderBy('p.update_date', 'DESC');
294
295 20
        return $this->queries->customize(QueryKey::PRODUCT_SEARCH_ADMIN, $qb, $searchData);
296
    }
297
298
    /**
299
     * get query builder.
300
     *
301
     * @param $Customer
302
     *
303
     * @return \Doctrine\ORM\QueryBuilder
304
     *
305
     * @see CustomerFavoriteProductRepository::getQueryBuilderByCustomer()
306
     * @deprecated since 3.0.0, to be removed in 3.1
307
     */
308 View Code Duplication
    public function getFavoriteProductQueryBuilderByCustomer($Customer)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
309
    {
310
        $qb = $this->createQueryBuilder('p')
311
            ->innerJoin('p.CustomerFavoriteProducts', 'cfp')
312
            ->where('cfp.Customer = :Customer AND p.Status = 1')
313
            ->setParameter('Customer', $Customer);
314
315
        // Order By
316
        // XXX Paginater を使用した場合に PostgreSQL で正しくソートできない
317
        $qb->addOrderBy('cfp.create_date', 'DESC');
318
319
        return $this->queries->customize(QueryKey::PRODUCT_GET_FAVORITE, $qb, ['customer' => $Customer]);
320
    }
321
}
322