Failed Conditions
Pull Request — experimental/3.1 (#2512)
by chihiro
12:14
created

CustomerRepository::getQueryBuilderBySearchData()   F

Complexity

Conditions 41
Paths > 20000

Size

Total Lines 150
Code Lines 99

Duplication

Lines 60
Ratio 40 %

Code Coverage

Tests 80
CRAP Score 41

Importance

Changes 0
Metric Value
cc 41
eloc 99
nc 786432
nop 1
dl 60
loc 150
ccs 80
cts 80
cp 1
crap 41
rs 2
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
 * This file is part of EC-CUBE
4
 *
5
 * Copyright(c) 2000-2015 LOCKON CO.,LTD. All Rights Reserved.
6
 *
7
 * http://www.lockon.co.jp/
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation; either version 2
12
 * of the License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
 */
23
24
25
namespace Eccube\Repository;
26
27
use Doctrine\ORM\EntityManager;
28
use Eccube\Annotation\Inject;
29
use Eccube\Annotation\Repository;
30
use Eccube\Common\Constant;
31
use Eccube\Doctrine\Query\Queries;
32
use Eccube\Entity\Customer;
33
use Eccube\Entity\Master\CustomerStatus;
34
use Eccube\Util\Str;
35
use Symfony\Component\Security\Core\Encoder\EncoderFactory;
36
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
37
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
38
use Symfony\Component\Security\Core\User\UserInterface;
39
use Symfony\Component\Security\Core\User\UserProviderInterface;
40
41
/**
42
 * CustomerRepository
43
 *
44
 * This class was generated by the Doctrine ORM. Add your own custom
45
 * repository methods below.
46
 *
47
 * @Repository
48
 */
49
class CustomerRepository extends AbstractRepository implements UserProviderInterface
50
{
51
    /**
52
     * @Inject("eccube.queries")
53
     * @var Queries
54
     */
55
    protected $queries;
56
57
    /**
58
     * @Inject("orm.em")
59
     * @var EntityManager
60
     */
61
    protected $entityManager;
62
63
    /**
64
     * @Inject(OrderRepository::class)
65
     * @var OrderRepository
66
     */
67
    protected $orderRepository;
68
69
    /**
70
     * @Inject("config")
71
     * @var array
72
     */
73
    protected $appConfig;
74
75
    /**
76
     * @Inject("security.encoder_factory")
77
     * @var EncoderFactory
78
     */
79
    protected $encoderFactory;
80
81 8
    public function newCustomer()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
82
    {
83 8
        $Customer = new \Eccube\Entity\Customer();
84 8
        $Status = $this->getEntityManager()
85 8
            ->getRepository('Eccube\Entity\Master\CustomerStatus')
86 8
            ->find(1);
87
88
        $Customer
89 8
            ->setStatus($Status);
90
91 8
        return $Customer;
92
    }
93
94
    /**
95
     * Loads the user for the given username.
96
     *
97
     * This method must throw UsernameNotFoundException if the user is not
98
     * found.
99
     *
100
     * @param string $username The username
101
     *
102
     * @return UserInterface
103
     *
104
     * @see UsernameNotFoundException
105
     *
106
     * @throws UsernameNotFoundException if the user is not found
107
     */
108 38
    public function loadUserByUsername($username)
109
    {
110
        // 本会員ステータスの会員のみ有効.
111 38
        $query = $this->createQueryBuilder('c')
112 38
            ->where('c.email = :email')
113 38
            ->leftJoin('c.Status', 's')
114 38
            ->andWhere('s.id = :status')
115 38
            ->setParameters(array(
116 38
                'email' => $username,
117
                'status' => CustomerStatus::REGULAR,
118
            ))
119 38
            ->setMaxResults(1)
120 38
            ->getQuery();
121 38
        $Customer = $query->getOneOrNullResult();
122 38
        if (!$Customer) {
123 1
            throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
124
        }
125
126 37
        return $Customer;
127
    }
128
129
    /**
130
     * Refreshes the user for the account interface.
131
     *
132
     * It is up to the implementation to decide if the user data should be
133
     * totally reloaded (e.g. from the database), or if the UserInterface
134
     * object can just be merged into some internal array of users / identity
135
     * map.
136
     *
137
     * @param UserInterface $user
138
     *
139
     * @return UserInterface
140
     *
141
     * @throws UnsupportedUserException if the account is not supported
142
     */
143 35 View Code Duplication
    public function refreshUser(UserInterface $user)
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...
144
    {
145 35
        if (!$user instanceof Customer) {
146 1
            throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
147
        }
148
149 34
        return $this->loadUserByUsername($user->getUsername());
150
    }
151
152
    /**
153
     * Whether this provider supports the given user class.
154
     *
155
     * @param string $class
156
     *
157
     * @return bool
158
     */
159 1
    public function supportsClass($class)
160
    {
161 1
        return $class === 'Eccube\Entity\Customer';
162
    }
163
164 39
    public function getQueryBuilderBySearchData($searchData)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
165
    {
166 39
        $qb = $this->createQueryBuilder('c')
167 39
            ->select('c');
168
169 39
        if (isset($searchData['multi']) && Str::isNotBlank($searchData['multi'])) {
170
            //スペース除去
171 16
            $clean_key_multi = preg_replace('/\s+|[ ]+/u', '', $searchData['multi']);
172 16
            $id = preg_match('/^\d+$/', $clean_key_multi) ? $clean_key_multi : null;
173
            $qb
174 16
                ->andWhere('c.id = :customer_id OR CONCAT(c.name01, c.name02) LIKE :name OR CONCAT(c.kana01, c.kana02) LIKE :kana OR c.email LIKE :email')
175 16
                ->setParameter('customer_id', $id)
176 16
                ->setParameter('name', '%' . $clean_key_multi . '%')
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
177 16
                ->setParameter('kana', '%' . $clean_key_multi . '%')
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
178 16
                ->setParameter('email', '%' . $clean_key_multi . '%');
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
179
        }
180
181
        // Pref
182 39 View Code Duplication
        if (!empty($searchData['pref']) && $searchData['pref']) {
183
            $qb
184 1
                ->andWhere('c.Pref = :pref')
185 1
                ->setParameter('pref', $searchData['pref']->getId());
186
        }
187
188
        // sex
189 39
        if (!empty($searchData['sex']) && count($searchData['sex']) > 0) {
190 2
            $sexs = array();
191 2
            foreach ($searchData['sex'] as $sex) {
192 2
                $sexs[] = $sex->getId();
193
            }
194
195
            $qb
196 2
                ->andWhere($qb->expr()->in('c.Sex', ':sexs'))
197 2
                ->setParameter('sexs', $sexs);
198
        }
199
200 39
        if (!empty($searchData['birth_month']) && $searchData['birth_month']) {
201
            $qb
202 1
                ->andWhere('EXTRACT(MONTH FROM c.birth) = :birth_month')
203 1
                ->setParameter('birth_month', $searchData['birth_month']);
204
        }
205
206
        // birth
207 39
        if (!empty($searchData['birth_start']) && $searchData['birth_start']) {
208
            $qb
209 2
                ->andWhere('c.birth >= :birth_start')
210 2
                ->setParameter('birth_start', $searchData['birth_start']);
211
        }
212 39 View Code Duplication
        if (!empty($searchData['birth_end']) && $searchData['birth_end']) {
213 2
            $date = clone $searchData['birth_end'];
214 2
            $date->modify('+1 days');
215
            $qb
216 2
                ->andWhere('c.birth < :birth_end')
217 2
                ->setParameter('birth_end', $date);
218
        }
219
220
        // tel
221 39 View Code Duplication
        if (isset($searchData['tel']) && Str::isNotBlank($searchData['tel'])) {
222
            $qb
223 1
                ->andWhere('CONCAT(c.tel01, c.tel02, c.tel03) LIKE :tel')
224 1
                ->setParameter('tel', '%' . $searchData['tel'] . '%');
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
225
        }
226
227
        // buy_total
228 39 View Code Duplication
        if (isset($searchData['buy_total_start']) && Str::isNotBlank($searchData['buy_total_start'])) {
229
            $qb
230 1
                ->andWhere('c.buy_total >= :buy_total_start')
231 1
                ->setParameter('buy_total_start', $searchData['buy_total_start']);
232
        }
233 39 View Code Duplication
        if (isset($searchData['buy_total_end']) && Str::isNotBlank($searchData['buy_total_end'])) {
234
            $qb
235 1
                ->andWhere('c.buy_total <= :buy_total_end')
236 1
                ->setParameter('buy_total_end', $searchData['buy_total_end']);
237
        }
238
239
        // buy_times
240 39
        if (!empty($searchData['buy_times_start']) && $searchData['buy_times_start']) {
241
            $qb
242 1
                ->andWhere('c.buy_times >= :buy_times_start')
243 1
                ->setParameter('buy_times_start', $searchData['buy_times_start']);
244
        }
245 39
        if (!empty($searchData['buy_times_end']) && $searchData['buy_times_end']) {
246
            $qb
247 1
                ->andWhere('c.buy_times <= :buy_times_end')
248 1
                ->setParameter('buy_times_end', $searchData['buy_times_end']);
249
        }
250
251
        // create_date
252 39
        if (!empty($searchData['create_date_start']) && $searchData['create_date_start']) {
253
            $qb
254 1
                ->andWhere('c.create_date >= :create_date_start')
255 1
                ->setParameter('create_date_start', $searchData['create_date_start']);
256
        }
257 39 View Code Duplication
        if (!empty($searchData['create_date_end']) && $searchData['create_date_end']) {
258 1
            $date = clone $searchData['create_date_end'];
259 1
            $date->modify('+1 days');
260
            $qb
261 1
                ->andWhere('c.create_date < :create_date_end')
262 1
                ->setParameter('create_date_end', $date);
263
        }
264
265
        // update_date
266 39
        if (!empty($searchData['update_date_start']) && $searchData['update_date_start']) {
267
            $qb
268 1
                ->andWhere('c.update_date >= :update_date_start')
269 1
                ->setParameter('update_date_start', $searchData['update_date_start']);
270
        }
271 39 View Code Duplication
        if (!empty($searchData['update_date_end']) && $searchData['update_date_end']) {
272 1
            $date = clone $searchData['update_date_end'];
273 1
            $date->modify('+1 days');
274
            $qb
275 1
                ->andWhere('c.update_date < :update_date_end')
276 1
                ->setParameter('update_date_end', $date);
277
        }
278
279
        // last_buy
280 39 View Code Duplication
        if (!empty($searchData['last_buy_start']) && $searchData['last_buy_start']) {
281
            $qb
282 1
                ->andWhere('c.last_buy_date >= :last_buy_start')
283 1
                ->setParameter('last_buy_start', $searchData['last_buy_start']);
284
        }
285 39 View Code Duplication
        if (!empty($searchData['last_buy_end']) && $searchData['last_buy_end']) {
286 1
            $date = clone $searchData['last_buy_end'];
287 1
            $date->modify('+1 days');
288
            $qb
289 1
                ->andWhere('c.last_buy_date < :last_buy_end')
290 1
                ->setParameter('last_buy_end', $date);
291
        }
292
293
        // status
294 39
        if (!empty($searchData['customer_status']) && count($searchData['customer_status']) > 0) {
295
            $qb
296 2
                ->andWhere($qb->expr()->in('c.Status', ':statuses'))
297 2
                ->setParameter('statuses', $searchData['customer_status']);
298
        }
299
300
        // buy_product_name、buy_product_code
301 39 View Code Duplication
        if (isset($searchData['buy_product_code']) && Str::isNotBlank($searchData['buy_product_code'])) {
302
            $qb
303 1
                ->leftJoin('c.Orders', 'o')
304 1
                ->leftJoin('o.OrderDetails', 'od')
305 1
                ->andWhere('od.product_name LIKE :buy_product_name OR od.product_code LIKE :buy_product_name')
306 1
                ->setParameter('buy_product_name', '%' . $searchData['buy_product_code'] . '%');
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
307
        }
308
309
        // Order By
310 39
        $qb->addOrderBy('c.update_date', 'DESC');
311
312 39
        return $this->queries->customize(QueryKey::CUSTOMER_SEARCH, $qb, $searchData);
313
    }
314
315
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$app" missing
Loading history...
316
     * ユニークなシークレットキーを返す
317
     * @param $app
0 ignored issues
show
introduced by
Missing parameter name
Loading history...
318
     * @return string
319
     */
320 237 View Code Duplication
    public function getUniqueSecretKey($app)
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...
321
    {
322 237
        $unique = Str::random(32);
323 237
        $Customer = $this->findBy(array(
324 237
            'secret_key' => $unique,
325
        ));
326 237
        if (count($Customer) == 0) {
327 237
            return $unique;
328
        } else {
329
            return $this->getUniqueSecretKey($app);
330
        }
331
    }
332
333
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$app" missing
Loading history...
334
     * ユニークなパスワードリセットキーを返す
335
     * @param $app
0 ignored issues
show
introduced by
Missing parameter name
Loading history...
336
     * @return string
337
     */
338 1 View Code Duplication
    public function getUniqueResetKey($app)
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...
339
    {
340 1
        $unique = Str::random(32);
341 1
        $Customer = $this->findBy(array(
342 1
                        'reset_key' => $unique,
343
        ));
344 1
        if (count($Customer) == 0) {
345 1
            return $unique;
346
        } else {
347
            return $this->getUniqueResetKey($app);
348
        }
349
    }
350
351
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$byte" missing
Loading history...
352
     * saltを生成する
353
     *
354
     * @param $byte
0 ignored issues
show
introduced by
Missing parameter name
Loading history...
355
     * @return string
356
     */
357 237
    public function createSalt($byte)
358
    {
359 237
        return bin2hex(openssl_random_pseudo_bytes($byte));
360
    }
361
362
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$app" missing
Loading history...
363
     * 入力されたパスワードをSaltと暗号化する
364
     *
365
     * @param $app
0 ignored issues
show
introduced by
Missing parameter name
Loading history...
366
     * @param  Customer $Customer
367
     * @return mixed
368
     */
369 237
    public function encryptPassword($app, \Eccube\Entity\Customer $Customer)
0 ignored issues
show
Unused Code introduced by
The parameter $app is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
370
    {
371 237
        $encoder = $this->encoderFactory->getEncoder($Customer);
372
373 237
        return $encoder->encodePassword($Customer->getPassword(), $Customer->getSalt());
374
    }
375
376 4
    public function getProvisionalCustomerBySecretKey($secret_key)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
377
    {
378 4
        $qb = $this->createQueryBuilder('c')
379 4
            ->where('c.secret_key = :secret_key')
380 4
            ->leftJoin('c.Status', 's')
381 4
            ->andWhere('s.id = :status')
382 4
            ->setParameter('secret_key', $secret_key)
383 4
            ->setParameter('status', CustomerStatus::PROVISIONAL);
384 4
        $query = $qb->getQuery();
385
386 4
        return $query->getSingleResult();
387
    }
388
389 2
    public function getRegularCustomerByEmail($email)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
390
    {
391 2
        $query = $this->createQueryBuilder('c')
392 2
            ->where('c.email = :email AND c.Status = :status')
393 2
            ->setParameter('email', $email)
394 2
            ->setParameter('status', CustomerStatus::REGULAR)
395 2
            ->setMaxResults(1)
396 2
            ->getQuery();
397
398 2
        $Customer = $query->getOneOrNullResult();
399
400 2
        return $Customer;
401
    }
402
403 4
    public function getRegularCustomerByResetKey($reset_key)
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
404
    {
405 4
        $query = $this->createQueryBuilder('c')
406 4
            ->where('c.reset_key = :reset_key AND c.Status = :status AND c.reset_expire >= :reset_expire')
407 4
            ->setParameter('reset_key', $reset_key)
408 4
            ->setParameter('status', CustomerStatus::REGULAR)
409 4
            ->setParameter('reset_expire', new \DateTime())
410 4
            ->getQuery();
411
412 4
        $Customer = $query->getSingleResult();
413
414 2
        return $Customer;
415
    }
416
417 3
    public function getResetPassword()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
418
    {
419 3
        return Str::random(8);
420
    }
421
422
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$orderStatusId" missing
Loading history...
introduced by
Doc comment for parameter "$app" missing
Loading history...
423
     * 会員の初回購入時間、購入時間、購入回数、購入金額を更新する
424
     *
425
     * @param $app
0 ignored issues
show
introduced by
Missing parameter name
Loading history...
426
     * @param  Customer $Customer
0 ignored issues
show
introduced by
Expected 6 spaces after parameter type; 1 found
Loading history...
427
     * @param  $orderStatusId
0 ignored issues
show
introduced by
Missing parameter name
Loading history...
428
     */
429 2
    public function updateBuyData($app, Customer $Customer, $orderStatusId)
0 ignored issues
show
Unused Code introduced by
The parameter $app is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
430
    {
431
        // 会員の場合、初回購入時間・購入時間・購入回数・購入金額を更新
432
433 2
        $arr = array($this->appConfig['order_new'],
434 2
                                $this->appConfig['order_pay_wait'],
435 2
                                $this->appConfig['order_back_order'],
436 2
                                $this->appConfig['order_deliv'],
437 2
                                $this->appConfig['order_pre_end'],
438
                        );
439
440 2
        $result = $this->orderRepository->getCustomerCount($Customer, $arr);
441
442 2
        if (!empty($result)) {
443 1
            $data = $result[0];
444
445 1
            $now = new \DateTime();
446
447 1
            $firstBuyDate = $Customer->getFirstBuyDate();
448 1
            if (empty($firstBuyDate)) {
449 1
                $Customer->setFirstBuyDate($now);
450
            }
451
452 1
            if ($orderStatusId == $this->appConfig['order_cancel'] ||
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
453 1
                    $orderStatusId == $this->appConfig['order_pending'] ||
454 1
                    $orderStatusId == $this->appConfig['order_processing']) {
455
                // キャンセル、決済処理中、購入処理中は購入時間は更新しない
456
            } else {
457 1
                $Customer->setLastBuyDate($now);
458
            }
459
460 1
            $Customer->setBuyTimes($data['buy_times']);
461 1
            $Customer->setBuyTotal($data['buy_total']);
462
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
463
        } else {
464
            // 受注データが存在しなければ初期化
465 2
            $Customer->setFirstBuyDate(null);
466 2
            $Customer->setLastBuyDate(null);
467 2
            $Customer->setBuyTimes(0);
468 2
            $Customer->setBuyTotal(0);
469
        }
470
471 2
        $this->entityManager->persist($Customer);
472 2
        $this->entityManager->flush();
473
    }
474
475
    /**
476
     * 仮会員, 本会員の会員を返す.
477
     * Eccube\Entity\CustomerのUniqueEntityバリデーションで使用しています.
478
     *
479
     * @param array $criteria
480
     * @return Customer[]
481
     */
482 46
    public function getNonWithdrawingCustomers(array $criteria = [])
483
    {
484 46
        $criteria['Status'] = [
485
            CustomerStatus::PROVISIONAL,
486
            CustomerStatus::REGULAR,
487
        ];
488
489 46
        return $this->findBy($criteria);
490
    }
491
}
492