Completed
Push — experimental/3.1 ( 24445a...d4772e )
by Yangsin
271:33 queued 265:16
created

TransactionListener::disable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
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
namespace Eccube\EventListener;
25
26
use Doctrine\ORM\EntityManager;
27
use Monolog\Logger;
28
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
29
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
30
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
31
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
32
use Symfony\Component\HttpKernel\KernelEvents;
33
34
/**
35
 * トランザクション制御のためのListener
36
 *
37
 * @package Eccube\EventListener
38
 */
39
class TransactionListener implements EventSubscriberInterface
40
{
41
    /**
42
     * @var EntityManager
43
     */
44
    protected $em;
45
46
    /**
47 1069
     * @var Logger
48
     */
49 1069
    protected $logger;
50
51
    /**
52
     * @var bool
53
     */
54
    protected $isEnabled = true;
55
56
    /**
57 317
     * TransactionListener constructor.
58
     *
59 317
     * @param EntityManager $em
60 58
     * @param Logger $logger
0 ignored issues
show
introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
61
     * @param bool $isEnabled
0 ignored issues
show
introduced by
Expected 10 spaces after parameter type; 1 found
Loading history...
62
     */
63 316
    public function __construct(EntityManager $em, Logger $logger, $isEnabled = true)
0 ignored issues
show
Bug introduced by
You have injected the EntityManager via parameter $em. This is generally not recommended as it might get closed and become unusable. Instead, it is recommended to inject the ManagerRegistry and retrieve the EntityManager via getManager() each time you need it.

The EntityManager might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:

function someFunction(ManagerRegistry $registry) {
    $em = $registry->getManager();
    $em->getConnection()->beginTransaction();
    try {
        // Do something.
        $em->getConnection()->commit();
    } catch (\Exception $ex) {
        $em->getConnection()->rollback();
        $em->close();

        throw $ex;
    }
}

If that code throws an exception and the EntityManager is closed. Any other code which depends on the same instance of the EntityManager during this request will fail.

On the other hand, if you instead inject the ManagerRegistry, the getManager() method guarantees that you will always get a usable manager instance.

Loading history...
64 316
    {
65 9
        $this->em = $em;
66 9
        $this->logger = $logger;
67
        $this->isEnabled = $isEnabled;
68 307
    }
69
70
    /**
71
     * Disable transaction listener.
72
     */
73
    public function disable()
74
    {
75
        $this->isEnabled = false;
76
    }
77 25
78
    /**
79 25
     * Kernel request listener callback.
80
     *
81
     * @param GetResponseEvent $event
82
     */
83 25
    public function onKernelRequest(GetResponseEvent $event)
84 25
    {
85 4
        if (!$this->isEnabled) {
86 4
            $this->logger->debug('Transaction Listener is disabled.');
87
88
            return;
89 21
        }
90
91
        if (!$event->isMasterRequest()) {
92
            return;
93
        }
94
95
        $this->em->getConnection()->setAutoCommit(false);
96
        $this->em->beginTransaction();
97
        $this->logger->debug('Begin Transaction.');
98 298
    }
99
100 298
    /**
101
     * Kernel exception listener callback.
102 298
     *
103 9
     * @param GetResponseForExceptionEvent $event
104 9
     */
105
    public function onKernelException(GetResponseForExceptionEvent $event)
106
    {
107 9
        if (!$this->isEnabled) {
108
            $this->logger->debug('Transaction Listener is disabled.');
109
110
            return;
111 289
        }
112
113
        if (!$event->isMasterRequest()) {
114
            return;
115
        }
116
117
        if ($this->em->getConnection()->isTransactionActive()) {
118
            $this->em->rollback();
119
            $this->logger->debug('Rollback executed.');
120 1069
        } else {
121
            $this->logger->debug('Transaction is not active. Rollback skipped.');
122
        }
123 1069
    }
124 1069
125 1069
    /**
126
     *  Kernel terminate listener callback.
127
     *
128
     * @param PostResponseEvent $event
129
     */
130
    public function onKernelTerminate(PostResponseEvent $event)
0 ignored issues
show
Unused Code introduced by
The parameter $event 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...
131
    {
132
        if (!$this->isEnabled) {
133
            $this->logger->debug('Transaction Listener is disabled.');
134
135
            return;
136
        }
137
        if ($this->em->getConnection()->isTransactionActive()) {
138
            if ($this->em->getConnection()->isRollbackOnly()) {
139
                $this->em->rollback();
140
                $this->logger->debug('Rollback executed.');
141
            } else {
142
                $this->em->commit();
143
                $this->logger->debug('Commit executed.');
144
            }
145
        } else {
146
            $this->logger->debug('Transaction is not active. Rollback skipped.');
147
        }
148
    }
149
150
    /**
151
     * Return the events to subscribe to.
152
     *
153
     * @return array
154
     */
155
    public static function getSubscribedEvents()
156
    {
157
        return array(
158
            KernelEvents::REQUEST => 'onKernelRequest',
159
            KernelEvents::EXCEPTION => 'onKernelException',
160
            KernelEvents::TERMINATE => 'onKernelTerminate',
161
        );
162
    }
163
}
164