Completed
Pull Request — experimental/sf (#3412)
by Kentaro
14:51 queued 07:29
created

AdminController::changePassword()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 54

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 7.5801

Importance

Changes 0
Metric Value
cc 4
nc 3
nop 1
dl 0
loc 54
ccs 11
cts 28
cp 0.3929
crap 7.5801
rs 9.0036
c 0
b 0
f 0

How to fix   Long Method   

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\Controller\Admin;
15
16
use Doctrine\ORM\NoResultException;
17
use Doctrine\ORM\Query\ResultSetMapping;
18
use Doctrine\ORM\QueryBuilder;
19
use Eccube\Controller\AbstractController;
20
use Eccube\Entity\Master\OrderStatus;
21
use Eccube\Entity\ProductStock;
22
use Eccube\Event\EccubeEvents;
23
use Eccube\Event\EventArgs;
24
use Eccube\Form\Type\Admin\ChangePasswordType;
25
use Eccube\Form\Type\Admin\LoginType;
26
use Eccube\Form\Type\Admin\SearchCustomerType;
27
use Eccube\Form\Type\Admin\SearchOrderType;
28
use Eccube\Form\Type\Admin\SearchProductType;
29
use Eccube\Repository\MemberRepository;
30
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
31
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
32
use Symfony\Component\Form\Form;
33
use Symfony\Component\HttpFoundation\Request;
34
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
35
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
36
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
37
38
class AdminController extends AbstractController
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
39
{
40
    /**
41
     * @var AuthorizationCheckerInterface
42
     */
43
    protected $authorizationChecker;
44
45
    /**
46
     * @var AuthenticationUtils
47
     */
48
    protected $helper;
49
50
    /**
51
     * @var MemberRepository
52
     */
53
    protected $memberRepository;
54
55
    /**
56
     * @var EncoderFactoryInterface
57
     */
58
    protected $encoderFactory;
59
60
    /**
61
     * AdminController constructor.
62
     *
63
     * @param AuthorizationCheckerInterface $authorizationChecker
64
     * @param AuthenticationUtils $helper
0 ignored issues
show
introduced by
Expected 11 spaces after parameter type; 1 found
Loading history...
65
     * @param MemberRepository $memberRepository
0 ignored issues
show
introduced by
Expected 14 spaces after parameter type; 1 found
Loading history...
66
     * @param EncoderFactoryInterface $encoderFactory
0 ignored issues
show
introduced by
Expected 7 spaces after parameter type; 1 found
Loading history...
67
     */
68 9
    public function __construct(
69
        AuthorizationCheckerInterface $authorizationChecker,
70
        AuthenticationUtils $helper,
71
        MemberRepository $memberRepository,
72
        EncoderFactoryInterface $encoderFactory
73
    ) {
74 9
        $this->authorizationChecker = $authorizationChecker;
75 9
        $this->helper = $helper;
76 9
        $this->memberRepository = $memberRepository;
77 9
        $this->encoderFactory = $encoderFactory;
78
    }
79
80
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$request" missing
Loading history...
81
     * @Route("/%eccube_admin_route%/login", name="admin_login")
82
     * @Template("@admin/login.twig")
83
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
84 2
    public function login(Request $request)
85
    {
86 2
        if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) {
87
            return $this->redirectToRoute('admin_homepage');
88
        }
89
90
        /* @var $form \Symfony\Component\Form\FormInterface */
91 2
        $builder = $this->formFactory->createNamedBuilder('', LoginType::class);
92
93 2
        $event = new EventArgs(
94
            [
95 2
                'builder' => $builder,
96
            ],
97 2
            $request
98
        );
99 2
        $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_ADMIM_LOGIN_INITIALIZE, $event);
100
101 2
        $form = $builder->getForm();
102
103
        return [
104 2
            'error' => $this->helper->getLastAuthenticationError(),
105 2
            'form' => $form->createView(),
106
        ];
107
    }
108
109
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$request" missing
Loading history...
110
     * @Route("/%eccube_admin_route%/", name="admin_homepage")
111
     * @Template("@admin/index.twig")
112
     */
0 ignored issues
show
introduced by
Missing @return tag in function comment
Loading history...
113 4
    public function index(Request $request)
114
    {
115
        // install.phpのチェック.
116 4
        if (isset($this->eccubeConfig['eccube_install']) && $this->eccubeConfig['eccube_install'] == 1) {
117
            $file = $this->eccubeConfig['root_dir'].'/html/install.php';
118 View Code Duplication
            if (file_exists($file)) {
119
                $message = trans('admin.install.warning', ['installphpPath' => 'html/install.php']);
120
                $this->addWarning($message, 'admin');
121
            }
122
            $fileOnRoot = $this->eccubeConfig['root_dir'].'/install.php';
123 View Code Duplication
            if (file_exists($fileOnRoot)) {
124
                $message = trans('admin.install.warning', ['installphpPath' => 'install.php']);
125
                $this->addWarning($message, 'admin');
126
            }
127
        }
128
129
        // 受注マスター検索用フォーム
130 4
        $searchOrderBuilder = $this->formFactory->createBuilder(SearchOrderType::class);
131
        // 商品マスター検索用フォーム
132 4
        $searchProductBuilder = $this->formFactory->createBuilder(SearchProductType::class);
133
        // 会員マスター検索用フォーム
134 4
        $searchCustomerBuilder = $this->formFactory->createBuilder(SearchCustomerType::class);
135
136 4
        $event = new EventArgs(
137
            [
138 4
                'searchOrderBuilder' => $searchOrderBuilder,
139 4
                'searchProductBuilder' => $searchProductBuilder,
140 4
                'searchCustomerBuilder' => $searchCustomerBuilder,
141
            ],
142 4
            $request
143
        );
144 4
        $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_ADMIM_INDEX_INITIALIZE, $event);
145
146
        // 受注マスター検索用フォーム
147 4
        $searchOrderForm = $searchOrderBuilder->getForm();
148
149
        // 商品マスター検索用フォーム
150 4
        $searchProductForm = $searchProductBuilder->getForm();
151
152
        // 会員マスター検索用フォーム
153 4
        $searchCustomerForm = $searchCustomerBuilder->getForm();
154
155
        /**
156
         * 受注状況.
157
         */
158 4
        $excludes = [];
159 4
        $excludes[] = OrderStatus::PENDING;
160 4
        $excludes[] = OrderStatus::PROCESSING;
161 4
        $excludes[] = OrderStatus::CANCEL;
162 4
        $excludes[] = OrderStatus::DELIVERED;
163
164 4
        $event = new EventArgs(
165
            [
166 4
                'excludes' => $excludes,
167
            ],
168 4
            $request
169
        );
170 4
        $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_ADMIM_INDEX_ORDER, $event);
171 4
        $excludes = $event->getArgument('excludes');
172
173
        // 受注ステータスごとの受注件数.
174 4
        $Orders = $this->getOrderEachStatus($this->entityManager, $excludes);
175
        // 受注ステータスの一覧.
176 4
        $OrderStatuses = $this->findOrderStatus($this->entityManager, $excludes);
177
178
        /**
179
         * 売り上げ状況
180
         */
181 4
        $excludes = [];
182 4
        $excludes[] = OrderStatus::PROCESSING;
183 4
        $excludes[] = OrderStatus::CANCEL;
184 4
        $excludes[] = OrderStatus::PENDING;
185
186 4
        $event = new EventArgs(
187
            [
188 4
                'excludes' => $excludes,
189
            ],
190 4
            $request
191
        );
192 4
        $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_ADMIM_INDEX_SALES, $event);
193 4
        $excludes = $event->getArgument('excludes');
194
195
        // 今日の売上/件数
196 4
        $salesToday = $this->getSalesByDay($this->entityManager, new \DateTime(), $excludes);
197
        // 昨日の売上/件数
198 4
        $salesYesterday = $this->getSalesByDay($this->entityManager, new \DateTime('-1 day'), $excludes);
199
        // 今月の売上/件数
200 4
        $salesThisMonth = $this->getSalesByMonth($this->entityManager, new \DateTime(), $excludes);
201
202
        /**
203
         * ショップ状況
204
         */
205
        // 在庫切れ商品数
206 4
        $countNonStockProducts = $this->countNonStockProducts($this->entityManager);
207
        // 本会員数
208 4
        $countCustomers = $this->countCustomers($this->entityManager);
209
210 4
        $event = new EventArgs(
211
            [
212 4
                'Orders' => $Orders,
213 4
                'OrderStatuses' => $OrderStatuses,
214 4
                'salesThisMonth' => $salesThisMonth,
215 4
                'salesToday' => $salesToday,
216 4
                'salesYesterday' => $salesYesterday,
217 4
                'countNonStockProducts' => $countNonStockProducts,
218 4
                'countCustomers' => $countCustomers,
219
            ],
220 4
            $request
221
        );
222 4
        $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_ADMIM_INDEX_COMPLETE, $event);
223
224
        return [
225 4
            'searchOrderForm' => $searchOrderForm->createView(),
226 4
            'searchProductForm' => $searchProductForm->createView(),
227 4
            'searchCustomerForm' => $searchCustomerForm->createView(),
228 4
            'Orders' => $Orders,
229 4
            'OrderStatuses' => $OrderStatuses,
230 4
            'salesThisMonth' => $salesThisMonth,
231 4
            'salesToday' => $salesToday,
232 4
            'salesYesterday' => $salesYesterday,
233 4
            'countNonStockProducts' => $countNonStockProducts,
234 4
            'countCustomers' => $countCustomers,
235
        ];
236
    }
237
238
    /**
239
     * パスワード変更画面
240
     *
241
     * @Route("/%eccube_admin_route%/change_password", name="admin_change_password")
242
     * @Template("@admin/change_password.twig")
243
     *
244
     * @param Request $request
245
     *
246
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|array
247
     */
248 2
    public function changePassword(Request $request)
249
    {
250 2
        $builder = $this->formFactory
251 2
            ->createBuilder(ChangePasswordType::class);
252
253 2
        $event = new EventArgs(
254
            [
255 2
                'builder' => $builder,
256
            ],
257 2
            $request
258
        );
259 2
        $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_ADMIM_CHANGE_PASSWORD_INITIALIZE, $event);
260
261 2
        $form = $builder->getForm();
262 2
        $form->handleRequest($request);
263
264 2
        if ($form->isSubmitted() && $form->isValid()) {
265
            $Member = $this->getUser();
266
            $salt = $Member->getSalt();
267
            $password = $form->get('change_password')->getData();
268
269
            $encoder = $this->encoderFactory->getEncoder($Member);
0 ignored issues
show
Documentation introduced by
$Member is of type null|object, but the function expects a object<Symfony\Component...r\UserInterface>|string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
270
271
            // 2系からのデータ移行でsaltがセットされていない場合はsaltを生成.
272
            if (empty($salt)) {
273
                $salt = $encoder->createSalt();
274
            }
275
276
            $password = $encoder->encodePassword($password, $salt);
277
278
            $Member
279
                ->setPassword($password)
280
                ->setSalt($salt);
281
282
            $this->memberRepository->save($Member);
0 ignored issues
show
Documentation introduced by
$Member is of type null|object, but the function expects a object<Eccube\Entity\Member>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
283
284
            $event = new EventArgs(
285
                [
286
                    'form' => $form,
287
                    'Member' => $Member,
288
                ],
289
                $request
290
            );
291
            $this->eventDispatcher->dispatch(EccubeEvents::ADMIN_ADMIN_CHANGE_PASSWORD_COMPLETE, $event);
292
293
            $this->addSuccess('admin.change_password.save.complete', 'admin');
294
295
            return $this->redirectToRoute('admin_change_password');
296
        }
297
298
        return [
299 2
            'form' => $form->createView(),
300
        ];
301
    }
302
303
    /**
304
     * 在庫なし商品の検索結果を表示する.
305
     *
306
     * @Route("/%eccube_admin_route%/nonstock", name="admin_homepage_nonstock")
307
     *
308
     * @param Request $request
309
     *
310
     * @return \Symfony\Component\HttpFoundation\Response
311
     */
312 2
    public function searchNonStockProducts(Request $request)
313
    {
314
        // 商品マスター検索用フォーム
315
        /* @var Form $form */
316 2
        $form = $this->formFactory
317 2
            ->createBuilder(SearchProductType::class)
318 2
            ->getForm();
319
320 2
        $form->handleRequest($request);
321 2
        if ($form->isSubmitted() && $form->isValid()) {
322
            // 在庫なし商品の検索条件をセッションに付与し, 商品マスタへリダイレクトする.
323 1
            $searchData = [];
324 1
            $searchData['stock'] = [ProductStock::OUT_OF_STOCK];
325 1
            $session = $request->getSession();
326 1
            $session->set('eccube.admin.product.search', $searchData);
327
328 1
            return $this->redirectToRoute('admin_product_page', [
329 1
                'page_no' => 1,
330 1
                'status' => $this->eccubeConfig['eccube_admin_product_stock_status'], ]);
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 12 spaces, but found 16.
Loading history...
331
        }
332
333 1
        return $this->redirectToRoute('admin_homepage');
334
    }
335
336
    /**
337
     * @param $em
338
     * @param array $excludes
339
     *
340
     * @return array
341
     */
342 4
    protected function findOrderStatus($em, array $excludes)
343
    {
344
        /* @var $qb QueryBuilder */
345
        $qb = $em
346 4
            ->getRepository('Eccube\Entity\Master\OrderStatus')
347 4
            ->createQueryBuilder('os');
348
349
        return $qb
350 4
            ->where($qb->expr()->notIn('os.id', $excludes))
351 4
            ->orderBy('os.sort_no', 'ASC')
352 4
            ->getQuery()
353 4
            ->getResult();
354
    }
355
356
    /**
357
     * @param $em
358
     * @param array $excludes
359
     *
360
     * @return array
361
     */
362 4
    protected function getOrderEachStatus($em, array $excludes)
363
    {
364 4
        $sql = 'SELECT
365
                    t1.order_status_id as status,
366
                    COUNT(t1.id) as count
367
                FROM
368
                    dtb_order t1
369
                WHERE
370
                    t1.order_status_id NOT IN (:excludes)
371
                GROUP BY
372
                    t1.order_status_id
373
                ORDER BY
374
                    t1.order_status_id';
375 4
        $rsm = new ResultSetMapping();
376 4
        $rsm->addScalarResult('status', 'status');
377 4
        $rsm->addScalarResult('count', 'count');
378 4
        $query = $em->createNativeQuery($sql, $rsm);
379 4
        $query->setParameters([':excludes' => $excludes]);
380 4
        $result = $query->getResult();
381 4
        $orderArray = [];
382 4
        foreach ($result as $row) {
383 1
            $orderArray[$row['status']] = $row['count'];
384
        }
385
386 4
        return $orderArray;
387
    }
388
389
    /**
390
     * @param $em
391
     * @param $dateTime
392
     * @param array $excludes
393
     *
394
     * @return array
395
     */
396 4 View Code Duplication
    protected function getSalesByMonth($em, $dateTime, array $excludes)
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...
397
    {
398
        // concat... for pgsql
399
        // http://stackoverflow.com/questions/1091924/substr-does-not-work-with-datatype-timestamp-in-postgres-8-3
400 4
        $dql = 'SELECT
401
                  SUBSTRING(CONCAT(o.order_date, \'\'), 1, 7) AS order_month,
402
                  SUM(o.payment_total) AS order_amount,
403
                  COUNT(o) AS order_count
404
                FROM
405
                  Eccube\Entity\Order o
406
                WHERE
407
                    o.OrderStatus NOT IN (:excludes)
408
                    AND SUBSTRING(CONCAT(o.order_date, \'\'), 1, 7) = SUBSTRING(:targetDate, 1, 7)
409
                GROUP BY
410
                  order_month';
411
412
        $q = $em
413 4
            ->createQuery($dql)
414 4
            ->setParameter(':excludes', $excludes)
415 4
            ->setParameter(':targetDate', $dateTime);
416
417 4
        $result = [];
418
        try {
419 4
            $result = $q->getSingleResult();
420 3
        } catch (NoResultException $e) {
421
            // 結果がない場合は空の配列を返す.
422
        }
423
424 4
        return $result;
425
    }
426
427
    /**
428
     * @param $em
429
     * @param $dateTime
430
     * @param array $excludes
431
     *
432
     * @return array
433
     */
434 4 View Code Duplication
    protected function getSalesByDay($em, $dateTime, array $excludes)
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...
435
    {
436
        // concat... for pgsql
437
        // http://stackoverflow.com/questions/1091924/substr-does-not-work-with-datatype-timestamp-in-postgres-8-3
438 4
        $dql = 'SELECT
439
                  SUBSTRING(CONCAT(o.order_date, \'\'), 1, 10) AS order_day,
440
                  SUM(o.payment_total) AS order_amount,
441
                  COUNT(o) AS order_count
442
                FROM
443
                  Eccube\Entity\Order o
444
                WHERE
445
                    o.OrderStatus NOT IN (:excludes)
446
                    AND SUBSTRING(CONCAT(o.order_date, \'\'), 1, 10) = SUBSTRING(:targetDate, 1, 10)
447
                GROUP BY
448
                  order_day';
449
450
        $q = $em
451 4
            ->createQuery($dql)
452 4
            ->setParameter(':excludes', $excludes)
453 4
            ->setParameter(':targetDate', $dateTime);
454
455 4
        $result = [];
456
        try {
457 4
            $result = $q->getSingleResult();
458 3
        } catch (NoResultException $e) {
459
            // 結果がない場合は空の配列を返す.
460
        }
461
462 4
        return $result;
463
    }
464
465
    /**
466
     * @param $em
467
     *
468
     * @return mixed
469
     *
470
     * @throws NoResultException
471
     * @throws \Doctrine\ORM\NonUniqueResultException
472
     */
473 4
    protected function countNonStockProducts($em)
474
    {
475
        /** @var $qb \Doctrine\ORM\QueryBuilder */
476 4
        $qb = $em->getRepository('Eccube\Entity\Product')
477 4
            ->createQueryBuilder('p')
478 4
            ->select('count(DISTINCT p.id)')
479 4
            ->innerJoin('p.ProductClasses', 'pc')
480 4
            ->where('pc.stock_unlimited = :StockUnlimited AND pc.stock = 0')
481 4
            ->setParameter('StockUnlimited', false);
482
483
        return $qb
484 4
            ->getQuery()
485 4
            ->getSingleScalarResult();
486
    }
487
488
    /**
489
     * @param $em
490
     *
491
     * @return mixed
492
     *
493
     * @throws NoResultException
494
     * @throws \Doctrine\ORM\NonUniqueResultException
495
     */
496 4
    protected function countCustomers($em)
497
    {
498
        $Status = $em
499 4
            ->getRepository('Eccube\Entity\Master\CustomerStatus')
500 4
            ->find(2);
501
502
        /** @var $qb \Doctrine\ORM\QueryBuilder */
503 4
        $qb = $em->getRepository('Eccube\Entity\Customer')
504 4
            ->createQueryBuilder('c')
505 4
            ->select('count(c.id)')
506 4
            ->where('c.Status = :Status')
507 4
            ->setParameter('Status', $Status);
508
509
        return $qb
510 4
            ->getQuery()
511 4
            ->getSingleScalarResult();
512
    }
513
}
514