Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
39 | class TransactionalInterceptor implements MethodInterceptorInterface, ContainerAwareInterface |
||
40 | { |
||
41 | use ContainerAwareTrait; |
||
42 | |||
43 | /** |
||
44 | * Doctrine's entity manager registry. |
||
45 | * @var RegistryInterface |
||
46 | */ |
||
47 | private $entityManagerRegistry; |
||
48 | /** |
||
49 | * Annotations reader. |
||
50 | * @var Reader |
||
51 | */ |
||
52 | private $reader; |
||
53 | /** |
||
54 | * Logger. |
||
55 | * @var LoggerInterface |
||
56 | */ |
||
57 | private $logger; |
||
58 | |||
59 | /** |
||
60 | * Creates a method interceptor managing the @Transactional annotation. |
||
61 | * |
||
62 | * @param RegistryInterface $entityManagerRegistry Doctrine's entity manager registry. |
||
63 | * @param Reader $reader Doctrine Annotation reader. |
||
64 | * @param LoggerInterface $logger Logger. |
||
65 | */ |
||
66 | 13 | public function __construct(RegistryInterface $entityManagerRegistry, Reader $reader, LoggerInterface $logger) |
|
72 | |||
73 | /** |
||
74 | * {@inheritDoc} |
||
75 | * |
||
76 | * @param MethodInvocation $method Current method invocation. |
||
77 | */ |
||
78 | 13 | public function intercept(MethodInvocation $method) |
|
141 | |||
142 | /** |
||
143 | * Get the entity manager |
||
144 | * |
||
145 | * @return EntityManagerInterface |
||
146 | */ |
||
147 | 11 | protected function getEntityManager() |
|
151 | |||
152 | /** |
||
153 | * Performs additional process after the intercepted method call was performed with a failure. |
||
154 | * |
||
155 | * @param boolean $transactionRequired If a new transaction was required. |
||
156 | * @param Exception $e Exception to throw at the end of the additional process. |
||
157 | * @param string[] $noRollbackExceptions An array of exceptions that shall not lead to a transaction rollback. |
||
158 | * @throws Exception At the end of the additional process (given exception). |
||
159 | */ |
||
160 | 6 | protected function afterMethodInvocationFailure( |
|
180 | |||
181 | /** |
||
182 | * Performs additional process after the intercepted method call was performed successfully. |
||
183 | * |
||
184 | * @param boolean $transactionRequired If a new transaction was required. |
||
185 | */ |
||
186 | 7 | protected function afterMethodInvocationSuccess($transactionRequired) |
|
193 | |||
194 | /** |
||
195 | * Performs additional process before the intercepted method call is performed. |
||
196 | * |
||
197 | * @param boolean $transactionRequired If a new transaction is required. |
||
198 | */ |
||
199 | 13 | protected function beforeMethodInvocation($transactionRequired) |
|
206 | |||
207 | /** |
||
208 | * Starts a transaction on the underlying database connection of a Doctrine's entity manager. |
||
209 | */ |
||
210 | 9 | protected function beginTransaction() |
|
215 | |||
216 | /** |
||
217 | * Commits the pending transaction on the underlying database connection of a Doctrine's entity manager. |
||
218 | */ |
||
219 | 7 | protected function commit() |
|
225 | |||
226 | /** |
||
227 | * Closes the entity manager, and rollbacks the pending transaction on the underlying database connection of a |
||
228 | * Doctrine's entity manager with the given name. This method also resets the manager, so as it can be recreated for |
||
229 | * a new transaction, when needed. |
||
230 | */ |
||
231 | 2 | protected function rollback() |
|
242 | |||
243 | /** |
||
244 | * Gets the Transactional annotation, if any, looking at method level as a priority, then at class level. |
||
245 | * |
||
246 | * @param ReflectionMethod $method Method definition. |
||
247 | * @return Transactional The transaction annotation, or <code>null</code> if not found. |
||
248 | */ |
||
249 | 13 | protected function getTransactionalAnnotation(ReflectionMethod $method) |
|
258 | |||
259 | /** |
||
260 | * Tells whether a transaction must be started, depending on the configured policy and the current TX status. |
||
261 | * |
||
262 | * @param int $policy One of the policy defined in the Transactional annotation. |
||
263 | * @param boolean $isTransactionActive Whether a transaction is already active when invoking a method. |
||
264 | * @return boolean <code>true</code> if a new transaction is required, <code>false</code> otherwise. |
||
265 | */ |
||
266 | 11 | protected function isTransactionRequired($policy, $isTransactionActive) |
|
270 | |||
271 | /** |
||
272 | * Checks whether a rollback shall be executed for a given exception. |
||
273 | * |
||
274 | * @param Exception $e An exception. |
||
275 | * @param string[] $noRollbackExceptions An array of exceptions that shall not lead to a transaction rollback. |
||
276 | * @return boolean <code>true</code> if the rollback must be executed, e.g. this exception shall not be "ignored" by |
||
277 | * the current transactional context. |
||
278 | */ |
||
279 | 5 | protected function isRollbackEnabled(Exception $e, array $noRollbackExceptions = null) |
|
293 | } |
||
294 |
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.