AbstractEntityService   B
last analyzed

Complexity

Total Complexity 51

Size/Duplication

Total Lines 519
Duplicated Lines 6.74 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 51
lcom 1
cbo 8
dl 35
loc 519
ccs 173
cts 173
cp 1
rs 7.92
c 0
b 0
f 0

27 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A getRepository() 0 4 1
A getEvent() 0 10 2
A getEventManager() 0 8 2
A setEventManager() 0 20 4
B attach() 35 77 6
A getEntityServiceName() 0 4 1
A delete() 0 10 2
A deleteBy() 0 10 2
A countBy() 0 10 2
A find() 0 10 2
A findAll() 0 8 2
A findBy() 0 10 2
A findOneBy() 0 10 2
A persist() 0 10 2
A multiPersist() 0 10 2
A trigger() 0 14 3
A beginTransaction() 0 11 2
A commitTransaction() 0 11 2
A rollbackTransaction() 0 11 2
A isTransactionEnabled() 0 4 1
A isRepositoryWritable() 0 4 1
A isRepositoryReadable() 0 4 1
A isRepositoryDeletable() 0 4 1
A createNotDeletableException() 0 7 1
A createNotReadableException() 0 7 1
A createNotWritableException() 0 7 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

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:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like AbstractEntityService often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AbstractEntityService, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Polder Knowledge / entityservice (https://polderknowledge.com)
4
 *
5
 * @link https://github.com/polderknowledge/entityservice for the canonical source repository
6
 * @copyright Copyright (c) 2016 Polder Knowledge (https://polderknowledge.com)
7
 * @license https://github.com/polderknowledge/entityservice/blob/master/LICENSE.md MIT
8
 */
9
10
namespace PolderKnowledge\EntityService;
11
12
use Doctrine\Common\Collections\Collection;
13
use Doctrine\Common\Collections\Criteria;
14
use PolderKnowledge\EntityService\Event\EntityEvent;
15
use PolderKnowledge\EntityService\Exception\RuntimeException;
16
use PolderKnowledge\EntityService\Exception\ServiceException;
17
use PolderKnowledge\EntityService\Feature\TransactionAwareInterface;
18
use PolderKnowledge\EntityService\Repository\EntityRepositoryInterface;
19
use PolderKnowledge\EntityService\Repository\Feature\DeletableInterface;
20
use PolderKnowledge\EntityService\Repository\Feature\FlushableInterface;
21
use PolderKnowledge\EntityService\Repository\Feature\ReadableInterface;
22
use PolderKnowledge\EntityService\Repository\Feature\WritableInterface;
23
use Traversable;
24
use Zend\EventManager\AbstractListenerAggregate;
25
use Zend\EventManager\EventManager;
26
use Zend\EventManager\EventManagerInterface;
27
28
/**
29
 * Base class for application specific EntityServices. This is a fully event driven class.
30
 * Each method trigger a method for extendability.
31
 */
32
abstract class AbstractEntityService extends AbstractListenerAggregate implements
33
    EntityServiceInterface,
34
    TransactionAwareInterface
35
{
36
    /**
37
     * The repository that is used for this entity service.
38
     *
39
     * @var EntityRepositoryInterface
40
     */
41
    private $repository;
42
43
    /**
44
     * EventManager handling all events triggered by this service
45
     *
46
     * @var EventManagerInterface
47
     */
48
    private $eventManager;
49
50
    /**
51
     * Initialized Event
52
     *
53
     * @var EntityEvent
54
     */
55
    private $event;
56
57
    /**
58
     * Initializes a new instance of this class.
59
     *
60
     * @param EntityRepositoryInterface $repository The repository that is used to communicate with.
61
     * @param string $entityClassName The FQCN of the entity.
62
     * @throws \PolderKnowledge\EntityService\Exception\RuntimeException
63
     */
64 108
    public function __construct(EntityRepositoryInterface $repository, $entityClassName)
65
    {
66 108
        $this->repository = $repository;
67 108
        $this->listeners = [];
68
69 108
        $this->getEvent()->setEntityClassName($entityClassName);
70 108
    }
71
72
    /**
73
     * Gets the repository that is used by the service.
74
     *
75
     * @return EntityRepositoryInterface
76
     */
77 93
    protected function getRepository()
78
    {
79 93
        return $this->repository;
80
    }
81
82
    /**
83
     * Get the pre initialized event object
84
     *
85
     * @return EntityEvent
86
     */
87 108
    protected function getEvent()
88
    {
89 108
        if (null === $this->event) {
90 108
            $this->event = $event = new EntityEvent;
91
92 108
            $event->setTarget($this);
93
        }
94
95 108
        return $this->event;
96
    }
97
98
    /**
99
     * Will create an EventManager when no EventManager was provided.
100
     * The returned EventManager is used to handle events triggered by this service instance.
101
     *
102
     * @return EventManagerInterface
103
     */
104 63
    public function getEventManager()
105
    {
106 63
        if (null === $this->eventManager) {
107 54
            $this->setEventManager(new EventManager);
108
        }
109
110 63
        return $this->eventManager;
111
    }
112
113
    /**
114
     * Set the EventManager used by this service instance to handle its events.
115
     * It will take care of disabling the old EventManager and will subscribe the internal
116
     * listeners to the new EventManager
117
     *
118
     * @param EventManagerInterface $eventManager
119
     */
120 63
    public function setEventManager(EventManagerInterface $eventManager)
121
    {
122 63
        if ($this->eventManager === $eventManager || $eventManager === null) {
123 3
            return;
124
        }
125
126 63
        if ($this->eventManager !== null) {
127 3
            $this->detach($this->eventManager);
128
        }
129
130 63
        $this->eventManager = $eventManager;
131 63
        $this->eventManager->addIdentifiers([
132 63
            'EntityService',
133 63
            'PolderKnowledge\EntityService\Service\EntityService',
134 63
            $this->getEntityServiceName(),
135 63
            trim($this->getEntityServiceName(), '\\'),
136
        ]);
137
138 63
        $this->attach($this->eventManager);
139 63
    }
140
141
    /**
142
     * {@inheritDoc}
143
     */
144
    public function attach(EventManagerInterface $events, $priority = 1)
145
    {
146 63 View Code Duplication
        $callback = function (EntityEvent $event) {
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...
147 33
            $repository = $event->getTarget()->getRepository();
148
149 33
            $event->setResult(call_user_func_array(
150 33
                [$repository, $event->getName()],
151 33
                $event->getParams()
152
            ));
153 63
        };
154
155 63
        $this->listeners[] = $events->attach('countBy', $callback, 0);
156 63
        $this->listeners[] = $events->attach('find', $callback, 0);
157 63
        $this->listeners[] = $events->attach('findAll', $callback, 0);
158 63
        $this->listeners[] = $events->attach('findBy', $callback, 0);
159 63
        $this->listeners[] = $events->attach('findOneBy', $callback, 0);
160 63
        $this->listeners[] = $events->attach(
161 63
            'delete',
162 63 View Code Duplication
            function (EntityEvent $event) {
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...
163 3
                $repository = $event->getTarget()->getRepository();
164
165 3
                call_user_func_array([$repository, 'delete'], $event->getParams());
166
167 3
                if ($repository instanceof FlushableInterface) {
168 3
                    $repository->flush();
169
                }
170 63
            },
171
            0
172
        );
173 63
        $this->listeners[] = $events->attach(
174 63
            'deleteBy',
175 63 View Code Duplication
            function (EntityEvent $event) {
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...
176 3
                $repository = $event->getTarget()->getRepository();
177
178 3
                call_user_func_array([$repository, 'deleteBy'], $event->getParams());
179
180 3
                if ($repository instanceof FlushableInterface) {
181 3
                    $repository->flush();
182
                }
183 63
            },
184
            0
185
        );
186 63
        $this->listeners[] = $events->attach(
187 63
            'persist',
188 63 View Code Duplication
            function (EntityEvent $event) {
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...
189 15
                $repository = $event->getTarget()->getRepository();
190
191 15
                call_user_func_array([$repository, 'persist'], $event->getParams());
192
193 15
                if ($repository instanceof FlushableInterface) {
194 3
                    $repository->flush();
195
                }
196 63
            },
197
            0
198
        );
199 63
        $this->listeners[] = $events->attach(
200 63
            'multiPersist',
201 63
            function (EntityEvent $event) {
202 3
                $repository = $event->getTarget()->getRepository();
203
204 3
                $entities = current($event->getParams());
205
206 3
                foreach ($entities as $entity) {
207 3
                    call_user_func_array([$repository, 'persist'], [$entity]);
208
                }
209
210 3
                if ($repository instanceof FlushableInterface) {
211 3
                    $repository->flush();
212
                }
213 63
            },
214
            0
215
        );
216
217 63
        $this->listeners[] = $events->attach('*', function (EntityEvent $event) {
218 45
            $event->disableStoppingOfPropagation();
219 63
        }, -1);
220 63
    }
221
222
    /**
223
     * Returns the FQCN of the entity handled by this service.
224
     *
225
     * @return string
226
     */
227 99
    protected function getEntityServiceName()
228
    {
229 99
        return $this->getEvent()->getEntityClassName();
230
    }
231
232
    /**
233
     * Deletes the given object from the repository
234
     *
235
     * @param object $entity The entity to delete.
236
     * @return mixed
237
     * @throws \Zend\EventManager\Exception\InvalidArgumentException
238
     * @throws \PolderKnowledge\EntityService\Exception\RuntimeException
239
     */
240 6
    public function delete($entity)
241
    {
242 6
        if (!$this->isRepositoryDeletable()) {
243 3
            throw $this->createNotDeletableException();
244
        }
245
246 3
        return $this->trigger(__FUNCTION__, [
247 3
            'entity' => $entity,
248
        ]);
249
    }
250
251
    /**
252
     * Deletes all objects matching the criteria from the repository
253
     *
254
     * @param array|Criteria $criteria The criteria values to match on.
255
     * @return mixed
256
     * @throws \Zend\EventManager\Exception\InvalidArgumentException
257
     * @throws \PolderKnowledge\EntityService\Exception\RuntimeException
258
     */
259 6
    public function deleteBy($criteria)
260
    {
261 6
        if (!$this->isRepositoryDeletable()) {
262 3
            throw $this->createNotDeletableException();
263
        }
264
265 3
        return $this->trigger(__FUNCTION__, [
266 3
            'criteria' => $criteria,
267
        ]);
268
    }
269
270
    /**
271
     * Count the objects matching the criteria respecting the order, limit and offset.
272
     *
273
     * @param array|Criteria $criteria The criteria values to match on.
274
     * @return int
275
     * @throws \Zend\EventManager\Exception\InvalidArgumentException
276
     * @throws \PolderKnowledge\EntityService\Exception\RuntimeException
277
     */
278 12
    public function countBy($criteria)
279
    {
280 12
        if (!$this->isRepositoryReadable()) {
281 3
            throw $this->createNotReadableException();
282
        }
283
284 9
        return $this->trigger(__FUNCTION__, [
285 9
            'criteria' => $criteria,
286
        ]);
287
    }
288
289
    /**
290
     * Find one object in the repository matching the $id
291
     *
292
     * @param mixed $id The id of the entity.
293
     * @return object|null
294
     * @throws \Zend\EventManager\Exception\InvalidArgumentException
295
     * @throws \PolderKnowledge\EntityService\Exception\RuntimeException
296
     */
297 12
    public function find($id)
298
    {
299 12
        if (!$this->isRepositoryReadable()) {
300 3
            throw $this->createNotReadableException();
301
        }
302
303 9
        return $this->trigger(__FUNCTION__, [
304 9
            'id' => $id,
305
        ]);
306
    }
307
308
    /**
309
     * Finds all entities in the repository.
310
     *
311
     * @return array Returns the entities that exist.
312
     * @throws \Zend\EventManager\Exception\InvalidArgumentException
313
     * @throws \PolderKnowledge\EntityService\Exception\RuntimeException
314
     */
315 15
    public function findAll()
316
    {
317 15
        if (!$this->isRepositoryReadable()) {
318 3
            throw $this->createNotReadableException();
319
        }
320
321 12
        return $this->trigger(__FUNCTION__, []);
322
    }
323
324
    /**
325
     * Find one or more objects in the repository matching the criteria respecting the order, limit and offset
326
     *
327
     * @param array|Criteria $criteria The array with criteria to search on.
328
     * @return array
329
     * @throws \Zend\EventManager\Exception\InvalidArgumentException
330
     * @throws \PolderKnowledge\EntityService\Exception\RuntimeException
331
     */
332 9
    public function findBy($criteria)
333
    {
334 9
        if (!$this->isRepositoryReadable()) {
335 3
            throw $this->createNotReadableException();
336
        }
337
338 6
        return $this->trigger(__FUNCTION__, [
339 6
            'criteria' => $criteria,
340
        ]);
341
    }
342
343
    /**
344
     * Find one object in the repository matching the criteria
345
     *
346
     * @param array|Criteria $criteria The criteria values to match on.
347
     * @return object|null
348
     * @throws \Zend\EventManager\Exception\InvalidArgumentException
349
     * @throws \PolderKnowledge\EntityService\Exception\RuntimeException
350
     */
351 6
    public function findOneBy($criteria)
352
    {
353 6
        if (!$this->isRepositoryReadable()) {
354 3
            throw $this->createNotReadableException();
355
        }
356
357 3
        return $this->trigger(__FUNCTION__, [
358 3
            'criteria' => $criteria,
359
        ]);
360
    }
361
362
    /**
363
     * Persist the given entity
364
     *
365
     * @param object $entity
366
     * @return mixed
367
     * @throws \Zend\EventManager\Exception\InvalidArgumentException
368
     * @throws RuntimeException
369
     */
370 18
    public function persist($entity)
371
    {
372 18
        if (!$this->isRepositoryWritable()) {
373 3
            throw $this->createNotWritableException();
374
        }
375
376 15
        return $this->trigger(__FUNCTION__, [
377 15
            'entity' => $entity,
378
        ]);
379
    }
380
381
    /**
382
     * Persist the given object and flushes it to the storage device.
383
     *
384
     * @param array|Collection|Traversable $entities The entities to persist.
385
     * @return mixed
386
     * @throws RuntimeException
387
     */
388 6
    public function multiPersist($entities)
389
    {
390 6
        if (!$this->isRepositoryWritable()) {
391 3
            throw $this->createNotWritableException();
392
        }
393
394 3
        return $this->trigger(__FUNCTION__, [
395 3
            'entities' => $entities,
396
        ]);
397
    }
398
399
    /**
400
     * will prepare the event object and trigger the event using the internal EventManager
401
     *
402
     * @param  string $name
403
     * @param  array $params
404
     * @return mixed
405
     * @throws \Zend\EventManager\Exception\InvalidArgumentException
406
     * @throws \PolderKnowledge\EntityService\Exception\RuntimeException
407
     */
408 48
    protected function trigger($name, array $params)
409
    {
410 48
        $event = clone $this->getEvent();
411 48
        $event->setName($name);
412 48
        $event->setParams($params);
413
414 48
        $responseCollection = $this->getEventManager()->triggerEvent($event);
415
416 48
        if ($responseCollection->stopped() && $event->isError()) {
417 3
            throw new RuntimeException($event->getError(), $event->getErrorNr());
418
        }
419
420 45
        return $event->getResult();
421
    }
422
423
    /**
424
     * Starts a new transaction.
425
     *
426
     * @throws ServiceException
427
     */
428 6
    public function beginTransaction()
429
    {
430 6
        if ($this->isTransactionEnabled() === false) {
431 3
            throw new ServiceException(sprintf(
432 3
                'The repository for %s doesn\'t support Transactions',
433 3
                $this->getEntityServiceName()
434
            ));
435
        }
436
437 3
        $this->getRepository()->beginTransaction();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface PolderKnowledge\EntitySe...tityRepositoryInterface as the method beginTransaction() does only exist in the following implementations of said interface: PolderKnowledge\EntitySe...\Doctrine\ORMRepository.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
438 3
    }
439
440
    /**
441
     * Commits a started transaction.
442
     *
443
     * @throws ServiceException
444
     */
445 6
    public function commitTransaction()
446
    {
447 6
        if ($this->isTransactionEnabled() === false) {
448 3
            throw new ServiceException(sprintf(
449 3
                'The repository for %s doesn\'t support Transactions',
450 3
                $this->getEntityServiceName()
451
            ));
452
        }
453
454 3
        $this->getRepository()->commitTransaction();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface PolderKnowledge\EntitySe...tityRepositoryInterface as the method commitTransaction() does only exist in the following implementations of said interface: PolderKnowledge\EntitySe...\Doctrine\ORMRepository.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
455 3
    }
456
457
    /**
458
     * Rolls back a started transaction.
459
     *
460
     * @throws ServiceException
461
     */
462 6
    public function rollbackTransaction()
463
    {
464 6
        if ($this->isTransactionEnabled() === false) {
465 3
            throw new ServiceException(sprintf(
466 3
                'The repository for %s doesn\'t support Transactions',
467 3
                $this->getEntityServiceName()
468
            ));
469
        }
470
471 3
        $this->getRepository()->rollbackTransaction();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface PolderKnowledge\EntitySe...tityRepositoryInterface as the method rollbackTransaction() does only exist in the following implementations of said interface: PolderKnowledge\EntitySe...\Doctrine\ORMRepository.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
472 3
    }
473
474
    /**
475
     * Returns true when possible to start an transaction
476
     */
477 18
    public function isTransactionEnabled()
478
    {
479 18
        return $this->getRepository() instanceof TransactionAwareInterface;
480
    }
481
482
    /**
483
     * Returns true when the repository for $entityName is writable
484
     *
485
     * @return bool
486
     */
487 24
    protected function isRepositoryWritable()
488
    {
489 24
        return $this->getRepository() instanceof WritableInterface;
490
    }
491
492
    /**
493
     * Returns true when the repository for $entityName is readable
494
     *
495
     * @return bool
496
     */
497 51
    protected function isRepositoryReadable()
498
    {
499 51
        return $this->getRepository() instanceof ReadableInterface;
500
    }
501
502
    /**
503
     * Returns true when the repository for $entityName has delete behavior
504
     *
505
     * @return bool
506
     */
507 12
    protected function isRepositoryDeletable()
508
    {
509 12
        return $this->getRepository() instanceof DeletableInterface;
510
    }
511
512
    /**
513
     * Throws an exception for cases where it's not possible to delete from the repository.
514
     *
515
     * @throws RuntimeException
516
     */
517 6
    private function createNotDeletableException()
518
    {
519 6
        throw new RuntimeException(sprintf(
520 6
            'The entities of type "%s" cannot be deleted from its repository.',
521 6
            $this->getEntityServiceName()
522
        ));
523
    }
524
525
    /**
526
     * Throws an exception for cases where it's not possible to read from the repository.
527
     *
528
     * @throws RuntimeException
529
     */
530 15
    private function createNotReadableException()
531
    {
532 15
        throw new RuntimeException(sprintf(
533 15
            'It is not possible to read entities of type "%s" from its repository.',
534 15
            $this->getEntityServiceName()
535
        ));
536
    }
537
538
    /**
539
     * Throws an exception for cases where it's not possible to write to the repository.
540
     *
541
     * @throws RuntimeException
542
     */
543 6
    private function createNotWritableException()
544
    {
545 6
        throw new RuntimeException(sprintf(
546 6
            'The entities of type "%s" cannot be written to its repository.',
547 6
            $this->getEntityServiceName()
548
        ));
549
    }
550
}
551