Code Duplication    Length = 101-102 lines in 2 locations

src/Gica/Cqrs/Command/CommandTester/DefaultCommandTester.php 1 location

@@ 24-125 (lines=102) @@
21
use Gica\Cqrs\Scheduling\ScheduledCommand;
22
use Gica\Types\Guid;
23
24
class DefaultCommandTester implements CommandTester
25
{
26
    /**
27
     * @var CommandSubscriber
28
     */
29
    private $commandSubscriber;
30
    /**
31
     * @var CommandApplier
32
     */
33
    private $commandApplier;
34
    /**
35
     * @var AggregateRepository
36
     */
37
    private $aggregateRepository;
38
    /**
39
     * @var EventsApplierOnAggregate
40
     */
41
    private $eventsApplierOnAggregate;
42
    /**
43
     * @var EventMetadataFactory
44
     */
45
    private $eventMetadataFactory;
46
    /**
47
     * @var CommandMetadataFactory
48
     */
49
    private $commandMetadataFactory;
50
51
    public function __construct(
52
        CommandSubscriber $commandSubscriber,
53
        CommandApplier $commandApplier,
54
        AggregateRepository $aggregateRepository,
55
        EventsApplierOnAggregate $eventsApplier,
56
        EventMetadataFactory $eventMetadataFactory,
57
        CommandMetadataFactory $commandMetadataFactory
58
    )
59
    {
60
        $this->commandSubscriber = $commandSubscriber;
61
        $this->commandApplier = $commandApplier;
62
        $this->aggregateRepository = $aggregateRepository;
63
        $this->eventsApplierOnAggregate = $eventsApplier;
64
        $this->eventMetadataFactory = $eventMetadataFactory;
65
        $this->commandMetadataFactory = $commandMetadataFactory;
66
    }
67
68
    public function canExecuteCommand(Command $command): bool
69
    {
70
        try {
71
            $command = $this->commandMetadataFactory->wrapCommandWithMetadata($command, null);
72
            $this->applyCommand($command, $this->loadCommandHandlerAndAggregate($command));
73
            return true;
74
        } catch (\Exception $exception) {
75
            return false;
76
        }
77
    }
78
79
    private function loadCommandHandlerAndAggregate(CommandWithMetadata $command): CommandHandlerAndAggregate
80
    {
81
        return new CommandHandlerAndAggregate(
82
            $this->commandSubscriber->getHandlerForCommand($command->getCommand()),
83
            $this->aggregateRepository->loadAggregate($this->commandSubscriber->getHandlerForCommand($command->getCommand())->getHandlerClass(), $command->getAggregateId())
84
        );
85
    }
86
87
    private function decorateEventWithMetaData($event, MetaData $metaData): EventWithMetaData
88
    {
89
        return new EventWithMetaData($event, $metaData->withEventId(Guid::generate()));
90
    }
91
92
    /**
93
     * @param CommandWithMetadata $command
94
     * @param CommandHandlerAndAggregate $handlerAndAggregate
95
     * @return void
96
     */
97
    private function applyCommand(CommandWithMetadata $command, CommandHandlerAndAggregate $handlerAndAggregate)
98
    {
99
        $aggregate = $handlerAndAggregate->getAggregate();
100
        $handler = $handlerAndAggregate->getCommandHandler();
101
102
        $metaData = $this->eventMetadataFactory->factoryEventMetadata($command, $aggregate);
103
104
        $newMessageGenerator = $this->commandApplier->applyCommand($aggregate, $command->getCommand(), $handler->getMethodName());
105
106
        foreach ($newMessageGenerator as $message) {
107
            if (!$this->isScheduledCommand($message)) {
108
                $eventWithMetaData = $this->decorateEventWithMetaData($message, $metaData);
109
                if (!$this->isScheduledEvent($message)) {
110
                    $this->eventsApplierOnAggregate->applyEventsOnAggregate($aggregate, [$eventWithMetaData]);
111
                }
112
            }
113
        }
114
    }
115
116
    private function isScheduledEvent($event): bool
117
    {
118
        return $event instanceof ScheduledEvent;
119
    }
120
121
    private function isScheduledCommand($message): bool
122
    {
123
        return $message instanceof ScheduledCommand;
124
    }
125
}

src/Gica/Cqrs/Command/CommandTester/DefaultCommandTesterWithSideEffect.php 1 location

@@ 24-124 (lines=101) @@
21
use Gica\Cqrs\Scheduling\ScheduledCommand;
22
use Gica\Types\Guid;
23
24
class DefaultCommandTesterWithSideEffect implements CommandTesterWithSideEffect
25
{
26
    /**
27
     * @var CommandSubscriber
28
     */
29
    private $commandSubscriber;
30
    /**
31
     * @var CommandApplier
32
     */
33
    private $commandApplier;
34
    /**
35
     * @var AggregateRepository
36
     */
37
    private $aggregateRepository;
38
    /**
39
     * @var EventsApplierOnAggregate
40
     */
41
    private $eventsApplierOnAggregate;
42
    /**
43
     * @var EventMetadataFactory
44
     */
45
    private $eventMetadataFactory;
46
    /**
47
     * @var CommandMetadataFactory
48
     */
49
    private $commandMetadataFactory;
50
51
    public function __construct(
52
        CommandSubscriber $commandSubscriber,
53
        CommandApplier $commandApplier,
54
        AggregateRepository $aggregateRepository,
55
        EventsApplierOnAggregate $eventsApplier,
56
        EventMetadataFactory $eventMetadataFactory,
57
        CommandMetadataFactory $commandMetadataFactory
58
    )
59
    {
60
        $this->commandSubscriber = $commandSubscriber;
61
        $this->commandApplier = $commandApplier;
62
        $this->aggregateRepository = $aggregateRepository;
63
        $this->eventsApplierOnAggregate = $eventsApplier;
64
        $this->eventMetadataFactory = $eventMetadataFactory;
65
        $this->commandMetadataFactory = $commandMetadataFactory;
66
    }
67
68
    public function shouldExecuteCommand(Command $command): bool
69
    {
70
        $command = $this->commandMetadataFactory->wrapCommandWithMetadata($command, null);
71
        return $this->applyCommand($command, $this->loadCommandHandlerAndAggregate($command));
72
    }
73
74
    private function loadCommandHandlerAndAggregate(CommandWithMetadata $command): CommandHandlerAndAggregate
75
    {
76
        return new CommandHandlerAndAggregate(
77
            $this->commandSubscriber->getHandlerForCommand($command->getCommand()),
78
            $this->aggregateRepository->loadAggregate($this->commandSubscriber->getHandlerForCommand($command->getCommand())->getHandlerClass(), $command->getAggregateId())
79
        );
80
    }
81
82
    private function decorateEventWithMetaData($event, MetaData $metaData): EventWithMetaData
83
    {
84
        return new EventWithMetaData($event, $metaData->withEventId(Guid::generate()));
85
    }
86
87
    /**
88
     * @param CommandWithMetadata $command
89
     * @param CommandHandlerAndAggregate $handlerAndAggregate
90
     * @return bool
91
     */
92
    private function applyCommand(CommandWithMetadata $command, CommandHandlerAndAggregate $handlerAndAggregate): bool
93
    {
94
        $aggregate = $handlerAndAggregate->getAggregate();
95
        $handler = $handlerAndAggregate->getCommandHandler();
96
97
        $metaData = $this->eventMetadataFactory->factoryEventMetadata($command, $aggregate);
98
99
        $newMessageGenerator = $this->commandApplier->applyCommand($aggregate, $command->getCommand(), $handler->getMethodName());
100
101
        foreach ($newMessageGenerator as $message) {
102
            if (!$this->isScheduledCommand($message)) {
103
                $eventWithMetaData = $this->decorateEventWithMetaData($message, $metaData);
104
                if (!$this->isScheduledEvent($message)) {
105
                    $this->eventsApplierOnAggregate->applyEventsOnAggregate($aggregate, [$eventWithMetaData]);
106
                }
107
            }
108
109
            return true;
110
        }
111
112
        return false;
113
    }
114
115
    private function isScheduledEvent($event): bool
116
    {
117
        return $event instanceof ScheduledEvent;
118
    }
119
120
    private function isScheduledCommand($message): bool
121
    {
122
        return $message instanceof ScheduledCommand;
123
    }
124
}