IssueFreeTicket::reserveTickets()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 3
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace ConferenceTools\Tickets\Cli\Command;
4
5
use Carnage\Cqrs\MessageBus\MessageBusInterface;
6
use Carnage\Cqrs\Service\EventCatcher;
7
use ConferenceTools\Tickets\Domain\Command\Ticket\CompletePurchase;
8
use ConferenceTools\Tickets\Domain\Command\Ticket\ReserveTickets;
9
use ConferenceTools\Tickets\Domain\Event\Ticket\TicketPurchaseCreated;
10
use ConferenceTools\Tickets\Domain\Service\Configuration;
11
use ConferenceTools\Tickets\Domain\ValueObject\Delegate;
12
use ConferenceTools\Tickets\Domain\ValueObject\DiscountCode;
13
use ConferenceTools\Tickets\Domain\ValueObject\TicketReservationRequest;
14
use ConferenceTools\Tickets\Domain\ValueObject\TicketType;
15
use Symfony\Component\Console\Command\Command;
16
use Symfony\Component\Console\Input\InputArgument;
17
use Symfony\Component\Console\Input\InputInterface;
18
use Symfony\Component\Console\Input\InputOption;
19
use Symfony\Component\Console\Output\OutputInterface;
20
21
class IssueFreeTicket extends Command
22
{
23
    /**
24
     * @var MessageBusInterface
25
     */
26
    private $commandBus;
27
28
    /**
29
     * @var Configuration
30
     */
31
    private $config;
32
33
    /**
34
     * @var EventCatcher
35
     */
36
    private $eventCatcher;
37
38
    public static function build(MessageBusInterface $commandBus, Configuration $config, EventCatcher $eventCatcher)
39
    {
40
        $instance = new static();
41
        $instance->commandBus = $commandBus;
42
        $instance->eventCatcher = $eventCatcher;
43
        $instance->config = $config;
44
45
        return $instance;
46
    }
47
48
    protected function configure()
49
    {
50
        $this->setName('tickets:issue-free-ticket')
51
            ->setDescription('Creates a free ticket purchase record for a given email address')
52
            ->setDefinition([
53
                new InputArgument('ticketType', InputArgument::REQUIRED, 'Ticket type to issue'),
54
                new InputArgument('email', InputArgument::REQUIRED, 'Email address to send ticket to'),
55
                new InputOption('number', '', InputOption::VALUE_OPTIONAL, 'Number of tickets to add to purchase', 1),
56
                new InputOption('discountCode', '', InputOption::VALUE_OPTIONAL, 'Discount code to apply to the purchase')
57
            ]);
58
    }
59
60
    protected function execute(InputInterface $input, OutputInterface $output)
61
    {
62
        $email = $input->getArgument('email');
63
        $numberOfTickets = $input->getOption('number');
64
        $ticketType = $this->getTicketType($input->getArgument('ticketType'));
65
        $discountCode = $this->getDiscountcode($input->getOption('discountCode'));
66
67
        $purchaseId = $this->reserveTickets($ticketType, $numberOfTickets, $discountCode);
68
        $delegateInfo = $this->createDelegates($numberOfTickets);
69
70
        $this->commandBus->dispatch(new CompletePurchase($purchaseId, $email, ...$delegateInfo));
71
72
        $output->writeln(sprintf('Tickets created. PurchaseId: %s', $purchaseId));
73
    }
74
75
    /**
76
     * @param $numberOfTickets
77
     * @return Delegate[]
78
     */
79
    private function createDelegates($numberOfTickets): array
80
    {
81
        $delegateInfo = [];
82
83
        for ($i = 0; $i < $numberOfTickets; $i++) {
84
            $delegateInfo[] = Delegate::emptyObject();
85
        }
86
        return $delegateInfo;
87
    }
88
89
    /**
90
     * @param $ticketType
91
     * @param $numberOfTickets
92
     * @return string
93
     */
94
    private function reserveTickets($ticketType, $numberOfTickets, $discountCode): string
95
    {
96
        if ($discountCode === null) {
97
            $command = ReserveTickets::withoutDiscountCode(
98
                new TicketReservationRequest($ticketType, $numberOfTickets)
99
            );
100
        } else {
101
            $command = ReserveTickets::withDiscountCode(
102
                $discountCode,
103
                new TicketReservationRequest($ticketType, $numberOfTickets)
104
            );
105
        }
106
107
        $this->commandBus->dispatch($command);
108
109
        /** @var TicketPurchaseCreated $event */
110
        $event = $this->eventCatcher->getEventsByType(TicketPurchaseCreated::class)[0];
111
        return $event->getId();
112
    }
113
114
    /**
115
     * @param $issueTicketType
116
     * @return TicketType
117
     * @throws \Exception
118
     */
119
    private function getTicketType($issueTicketType): TicketType
120
    {
121
        $ticketTypes = $this->config->getTicketTypes();
122
123
        if (!isset($ticketTypes[$issueTicketType])) {
124
            throw new \Exception('Invalid ticket type');
125
        }
126
127
        $ticketType = $ticketTypes[$issueTicketType];
128
        return $ticketType;
129
    }
130
131
    private function getDiscountCode($type) /* : ?DiscountCode*/
132
    {
133
        if (empty($type)) {
134
            return null;
135
        }
136
137
        $discountCodes = $this->config->getDiscountCodes();
138
139
        if (!isset($discountCodes[$type])) {
140
            throw new \Exception('Invalid discount code');
141
        }
142
143
        $ticketType = $discountCodes[$type];
144
        return $ticketType;
145
    }
146
}