DefaultCommandTesterWithExplanation::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 13
nc 1
nop 6
crap 1
1
<?php
2
/**
3
 * Copyright (c) 2017 Constantin Galbenu <[email protected]>
4
 */
5
6
namespace Gica\Cqrs\Command\CommandTester;
7
8
use Gica\Cqrs\Aggregate\AggregateRepository;
9
use Gica\Cqrs\Command;
10
use Gica\Cqrs\Command\CommandApplier;
11
use Gica\Cqrs\Command\CommandSubscriber;
12
use Gica\Cqrs\Command\CommandWithMetadata;
13
use Gica\Cqrs\Command\MetadataWrapper as CommandMetadataFactory;
14
use Gica\Cqrs\Command\ValueObject\CommandHandlerAndAggregate;
15
use Gica\Cqrs\Event\EventsApplier\EventsApplierOnAggregate;
16
use Gica\Cqrs\Event\EventWithMetaData;
17
use Gica\Cqrs\Event\MetaData;
18
use Gica\Cqrs\Event\MetadataFactory as EventMetadataFactory;
19
use Gica\Cqrs\Event\ScheduledEvent;
20
use Gica\Cqrs\Scheduling\ScheduledCommand;
21
use Gica\Types\Guid;
22
23
class DefaultCommandTesterWithExplanation implements Command\CommandTesterWithExplanation
24
{
25
    /**
26
     * @var CommandSubscriber
27
     */
28
    private $commandSubscriber;
29
    /**
30
     * @var CommandApplier
31
     */
32
    private $commandApplier;
33
    /**
34
     * @var AggregateRepository
35
     */
36
    private $aggregateRepository;
37
    /**
38
     * @var EventsApplierOnAggregate
39
     */
40
    private $eventsApplierOnAggregate;
41
    /**
42
     * @var EventMetadataFactory
43
     */
44
    private $eventMetadataFactory;
45
    /**
46
     * @var CommandMetadataFactory
47
     */
48
    private $commandMetadataFactory;
49
50 2
    public function __construct(
51
        CommandSubscriber $commandSubscriber,
52
        CommandApplier $commandApplier,
53
        AggregateRepository $aggregateRepository,
54
        EventsApplierOnAggregate $eventsApplier,
55
        EventMetadataFactory $eventMetadataFactory,
56
        CommandMetadataFactory $commandMetadataFactory
57
    )
58
    {
59 2
        $this->commandSubscriber = $commandSubscriber;
60 2
        $this->commandApplier = $commandApplier;
61 2
        $this->aggregateRepository = $aggregateRepository;
62 2
        $this->eventsApplierOnAggregate = $eventsApplier;
63 2
        $this->eventMetadataFactory = $eventMetadataFactory;
64 2
        $this->commandMetadataFactory = $commandMetadataFactory;
65 2
    }
66
67 2
    public function whyCantExecuteCommand(Command $command)
68
    {
69
        try {
70 2
            $command = $this->commandMetadataFactory->wrapCommandWithMetadata($command, null);
71 2
            $this->applyCommand($command, $this->loadCommandHandlerAndAggregate($command));
72 1
            return [];
73 1
        } catch (\Exception $exception) {
74 1
            return [$exception];
75
        }
76
    }
77
78 2
    private function loadCommandHandlerAndAggregate(CommandWithMetadata $command): CommandHandlerAndAggregate
79
    {
80 2
        return new CommandHandlerAndAggregate(
81 2
            $this->commandSubscriber->getHandlerForCommand($command->getCommand()),
82 2
            $this->aggregateRepository->loadAggregate($this->commandSubscriber->getHandlerForCommand($command->getCommand())->getHandlerClass(), $command->getAggregateId())
83
        );
84
    }
85
86 1
    private function decorateEventWithMetaData($event, MetaData $metaData): EventWithMetaData
87
    {
88 1
        return new EventWithMetaData($event, $metaData->withEventId(Guid::generate()));
89
    }
90
91
    /**
92
     * @param CommandWithMetadata $command
93
     * @param CommandHandlerAndAggregate $handlerAndAggregate
94
     * @return void
95
     */
96 2
    private function applyCommand(CommandWithMetadata $command, CommandHandlerAndAggregate $handlerAndAggregate)
97
    {
98 2
        $aggregate = $handlerAndAggregate->getAggregate();
99 2
        $handler = $handlerAndAggregate->getCommandHandler();
100
101 2
        $metaData = $this->eventMetadataFactory->factoryEventMetadata($command, $aggregate);
102
103 2
        $newMessageGenerator = $this->commandApplier->applyCommand($aggregate, $command->getCommand(), $handler->getMethodName());
104
105 2
        foreach ($newMessageGenerator as $message) {
106 1
            if (!$this->isScheduledCommand($message)) {
107 1
                $eventWithMetaData = $this->decorateEventWithMetaData($message, $metaData);
108 1
                if (!$this->isScheduledEvent($message)) {
109 1
                    $this->eventsApplierOnAggregate->applyEventsOnAggregate($aggregate, [$eventWithMetaData]);
110
                }
111
            }
112
        }
113 1
    }
114
115 1
    private function isScheduledEvent($event): bool
116
    {
117 1
        return $event instanceof ScheduledEvent;
118
    }
119
120 1
    private function isScheduledCommand($message): bool
121
    {
122 1
        return $message instanceof ScheduledCommand;
123
    }
124
}