Completed
Push — master ( 88abf3...f2da4c )
by Joachim
03:15
created

StockMovementSubscriber::onFlush()   C

Complexity

Conditions 12
Paths 72

Size

Total Lines 60
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 156

Importance

Changes 0
Metric Value
dl 0
loc 60
ccs 0
cts 32
cp 0
rs 6.366
c 0
b 0
f 0
cc 12
eloc 34
nc 72
nop 1
crap 156

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
declare(strict_types=1);
4
5
namespace Loevgaard\DandomainStockBundle\EventListener;
6
7
use Doctrine\Common\EventSubscriber;
8
use Doctrine\ORM\EntityManager;
9
use Doctrine\ORM\Event\OnFlushEventArgs;
10
use Doctrine\ORM\Events;
11
use Doctrine\ORM\Mapping\ClassMetadata;
12
use Doctrine\ORM\ORMException;
13
use Doctrine\ORM\UnitOfWork;
14
use Loevgaard\DandomainFoundation\Entity\Generated\OrderLineInterface;
15
use Loevgaard\DandomainStock\Entity\Generated\StockMovementInterface;
16
use Loevgaard\DandomainStock\Entity\StockMovement;
17
use Loevgaard\DandomainStock\Exception\CurrencyMismatchException;
18
use Loevgaard\DandomainStock\Exception\StockMovementProductMismatchException;
19
use Loevgaard\DandomainStock\Exception\UndefinedPriceForCurrencyException;
20
use Loevgaard\DandomainStock\Exception\UnsetCurrencyException;
21
use Loevgaard\DandomainStock\Exception\UnsetProductException;
22
23
class StockMovementSubscriber implements EventSubscriber
24
{
25
    /**
26
     * @var array
27
     */
28
    private $orderStateIds;
29
30
    /**
31
     * @param array $orderStateIds An array of external ids for order states (use the id in the Dandomain interface)
32
     */
33 1
    public function __construct(array $orderStateIds)
34
    {
35 1
        $this->orderStateIds = $orderStateIds;
36 1
    }
37
38 1
    public function getSubscribedEvents()
39
    {
40
        return [
41 1
            Events::onFlush,
42
        ];
43
    }
44
45
    /**
46
     * @param OnFlushEventArgs $args
47
     * @throws CurrencyMismatchException
48
     * @throws ORMException
49
     * @throws StockMovementProductMismatchException
50
     * @throws UndefinedPriceForCurrencyException
51
     * @throws UnsetCurrencyException
52
     * @throws UnsetProductException
53
     */
54
    public function onFlush(OnFlushEventArgs $args)
55
    {
56
        $em = $args->getEntityManager();
57
        $uow = $em->getUnitOfWork();
58
59
        foreach ($uow->getScheduledEntityInsertions() as $entity) {
60
            /** @var OrderLineInterface $entity */
61
            if(!$this->isOrderLine($entity) || !$this->isValidState($entity)) {
62
                continue;
63
            }
64
65
            $stockMovement = $this->stockMovementFromOrderLine($entity);
66
67
            $this->persistStockMovement($stockMovement, $em, $uow);
68
        }
69
70
        foreach ($uow->getScheduledEntityUpdates() as $entity) {
71
            /** @var OrderLineInterface $entity */
72
            if(!$this->isOrderLine($entity) || !$this->isValidState($entity)) {
73
                continue;
74
            }
75
76
            $stockMovement = $this->stockMovementFromOrderLine($entity);
77
            $effectiveStockMovement = $entity->computeEffectiveStockMovement();
78
            if ($effectiveStockMovement) {
79
                $stockMovement = $effectiveStockMovement->diff($stockMovement);
80
                $stockMovement->setType(StockMovement::TYPE_REGULATION);
81
            }
82
83
            $this->persistStockMovement($stockMovement, $em, $uow);
84
        }
85
86
        foreach ($uow->getScheduledEntityDeletions() as $entity) {
87
            /** @var OrderLineInterface $entity */
88
            if(!$this->isOrderLine($entity)) {
89
                continue;
90
            }
91
92
            $effectiveStockMovement = $entity->computeEffectiveStockMovement();
93
94
            if ($effectiveStockMovement) {
95
                $stockMovement = $effectiveStockMovement->inverse();
96
                $stockMovement
97
                    ->setType(StockMovement::TYPE_REGULATION) // we set the type as regulation since it is not a sale now
98
                    ->setOrderLineRemoved(true)
99
                    ->setOrderLine(null);
100
101
                $this->persistStockMovement($stockMovement, $em, $uow);
102
            }
103
104
            foreach ($entity->getStockMovements() as $stockMovement) {
105
                $stockMovement
106
                    ->setOrderLineRemoved(true)
107
                    ->setOrderLine(null);
108
109
                $md = $this->metaData($em, $stockMovement);
110
                $uow->recomputeSingleEntityChangeSet($md, $stockMovement);
111
            }
112
        }
113
    }
114
115
    private function isOrderLine($entity) : bool
116
    {
117
        return $entity instanceof OrderLineInterface;
0 ignored issues
show
Bug introduced by
The class Loevgaard\DandomainFound...ated\OrderLineInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
118
    }
119
120
    private function isValidState(OrderLineInterface $orderLine) : bool
121
    {
122
        return $orderLine->getOrder()
123
            && $orderLine->getOrder()->getState()
124
            && in_array($orderLine->getOrder()->getState()->getExternalId(), $this->orderStateIds);
125
    }
126
127
    /**
128
     * @param OrderLineInterface $orderLine
129
     * @return StockMovement
130
     * @throws CurrencyMismatchException
131
     * @throws UndefinedPriceForCurrencyException
132
     * @throws UnsetProductException
133
     */
134
    private function stockMovementFromOrderLine(OrderLineInterface $orderLine) : StockMovement
135
    {
136
        $stockMovement = new StockMovement();
137
        $stockMovement->populateFromOrderLine($orderLine);
138
139
        return $stockMovement;
140
    }
141
142
    private function metaData(EntityManager $entityManager, $entity) : ClassMetadata
143
    {
144
        return $entityManager->getClassMetadata(get_class($entity));
145
    }
146
147
    /**
148
     * @param StockMovementInterface $stockMovement
149
     * @param EntityManager $entityManager
150
     * @param UnitOfWork $unitOfWork
151
     * @return boolean
152
     * @throws ORMException
153
     */
154
    private function persistStockMovement(StockMovementInterface $stockMovement, EntityManager $entityManager, UnitOfWork $unitOfWork) : bool
155
    {
156
        // if the quantity is 0 we don't want to add a stock movement since this will just pollute the stock movement table
157
        if($stockMovement->getQuantity() === 0) {
158
            return false;
159
        }
160
161
        $stockMovement->validate();
162
        $entityManager->persist($stockMovement);
163
        $md = $this->metaData($entityManager, $stockMovement);
164
        $unitOfWork->computeChangeSet($md, $stockMovement);
165
166
        return true;
167
    }
168
}
169