Passed
Push — master ( cb50cd...7264d5 )
by Chris
37s
created

Configuration   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 228
Duplicated Lines 0 %

Test Coverage

Coverage 13.64%

Importance

Changes 0
Metric Value
dl 0
loc 228
ccs 6
cts 44
cp 0.1364
rs 10
c 0
b 0
f 0
wmc 13

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 1 1
B fromArray() 0 26 3
A getTicketMetadata() 0 3 1
A getCurrency() 0 3 1
A getTaxRate() 0 3 1
A displayTax() 0 3 1
A getTicketTypes() 0 3 1
A getAvailableTickets() 0 3 1
A addTicketInformation() 0 18 1
A getTicketType() 0 3 1
A getDiscountCodes() 0 3 1
1
<?php
2
3
namespace ConferenceTools\Tickets\Domain\Service;
4
5
use ConferenceTools\Tickets\Domain\ValueObject\DiscountCode;
6
use ConferenceTools\Tickets\Domain\ValueObject\Money;
7
use ConferenceTools\Tickets\Domain\ValueObject\Price;
8
use ConferenceTools\Tickets\Domain\ValueObject\TaxRate;
9
use ConferenceTools\Tickets\Domain\ValueObject\TicketMetadata;
10
use ConferenceTools\Tickets\Domain\ValueObject\TicketType;
11
use Zend\Stdlib\ArrayUtils;
12
13
class Configuration
14
{
15
    //@TODO change to private const
16
    private static $defaults = [
17
        'tickets' => [],
18
        'discountCodes' => [],
19
        'financial' => [
20
            'currency' => 'GBP',
21
            'taxRate' => 0,
22
            'displayTax' => false
23
        ]
24
    ];
25
26
    /**
27
     * Defines the currency in use across the app.
28
     *
29
     * Defaults to GBP, should be a proper currency code otherwise you will have issues with display of
30
     * currency values and creating stripe charges.
31
     *
32
     * config key: financial->currency
33
     *
34
     * @var string
35
     */
36
    private $currency;
37
38
    /**
39
     * The tax rate in use across the app.
40
     *
41
     * Defaults to 0% Will be added to all cost values for tickets. The app assumes a single tax rate for all tickets
42
     * and also assumes that tickets are for a physical event. As such the EU VATMOSS rules do not apply. If you are
43
     * selling tickets for a webinar or online conference, you should check with legal advisers if this is appropriate.
44
     *
45
     * config key: financial->taxRate
46
     *
47
     * @var TaxRate
48
     */
49
    private $taxRate;
50
51
    /**
52
     * Should VAT/sales tax be displayed in the app.
53
     *
54
     * Defaults to false. If enabled, this will display sales tax (VAT) in various points in the purchase process. You
55
     * should also update the layout template to include the relevent legal information. There are three ways this app
56
     * can deal with tax:
57
     * - if you are not vat registered or do not need to charge VAT, you can set this to false and the tax rate to 0;
58
     *   the app will not track any tax for you.
59
     * - if you set a tax rate but disable this flag, VAT will be added to purchases and tracked by the app but not
60
     *   made visible to customers. The main purpose of this is for when you have a pending VAT registration; the app
61
     *   will still track the tax and you can turn on the display of this tracking when the registration completes.
62
     *   Another use for this, if you don't need to track VAT would be to add a handling/processing fee to tickets.
63
     * - If you set a tax rate and enable this flag, VAT will be tracked and displayed to your customers at purchase
64
     *   time.
65
     *
66
     *
67
     * config key: financial->displayTax
68
     *
69
     * @var bool
70
     */
71
    private $displayTax;
72
73
    /**
74
     * An array of available ticket types. The app uses this for determining how many tickets are available and their
75
     * prices.
76
     *
77
     * If you change this config, you will need to rebuild the ticket counters projection to get the updated types in
78
     * your app.
79
     *
80
     * config key: tickets
81
     * structure: identifier => [
82
     *      'cost' => Net cost in pence/cents (eg before tax price),
83
     *      'name' => display name shown to customers,
84
     *      'available' => Number available for purchase
85
     * ]
86
     *
87
     * @var TicketType[]
88
     */
89
    private $ticketTypes;
90
91
    /**
92
     * Holds a count of avaliable tickets by type.
93
     *
94
     * @see ticketTypes for how to configure
95
     *
96
     * @var int[]
97
     */
98
    private $avaliableTickets;
99
100
    /**
101
     * An array of discount codes. The app uses this for validating and applying different codes.
102
     *
103
     * If you change this config, you will need to rebuild the discount codes projection
104
     *
105
     * configkey: discountCodes
106
     * structure: identifier => [
107
     *      'type' => The class name of the discount type eg Percentage::class,
108
     *      'name' => User friendly name for the code
109
     *      'options' => An array of options for the type you are using
110
     * ]
111
     *
112
     * @var DiscountCode[]
113
     */
114
    private $discountCodes;
115
116
    /**
117
     * Contains metadata about tickets eg when they are available for sale
118
     *
119
     * configkey: tickets->metadata
120
     * structure: [
121
     *      'availableFrom' => DateTime ticket is to go on sale from,
122
     *      'availableTo' => DateTime after which ticket is no longer on sale
123
     * ]
124
     *
125
     * @var TicketMetadata[]
126
     */
127
    private $ticketMetadata;
128
129
    private function __construct() {}
130
131
    public static function fromArray(array $settings)
132
    {
133
        /** Ensures that all the keys exist @TODO remove dependency on Zend Array Utils for this */
134
        $settings = ArrayUtils::merge(self::$defaults, $settings);
135
        $instance = new static();
136
137
        $instance->currency = (string) $settings['financial']['currency'];
138
        $instance->displayTax = (string) $settings['financial']['displayTax'];
0 ignored issues
show
Documentation Bug introduced by
The property $displayTax was declared of type boolean, but (string)$settings['financial']['displayTax'] is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
139
        $instance->taxRate = new TaxRate($settings['financial']['taxRate']);
140
141
        foreach ($settings['tickets'] as $identifier => $ticket) {
142
            $instance->addTicketInformation($ticket, $identifier);
143
        }
144
145
        foreach ($settings['discountCodes'] as $identifier => $code) {
146
            // Be careful here; configuration object is still under constrcution at the time it is passed in
147
            // Might need to rethink this at some point
148
            $discountType = call_user_func([$code['type'], 'fromArray'], $code['options'], $instance);
149
            $instance->discountCodes[$identifier] = new DiscountCode(
150
                $identifier,
151
                $code['name'],
152
                $discountType
153
            );
154
        }
155
156
        return $instance;
157
    }
158
159
    /**
160
     * @param $ticket
161
     * @param $identifier
162
     */
163
    private function addTicketInformation(array $ticket, string $identifier)
164
    {
165
        $price = Price::fromNetCost(
166
            new Money($ticket['cost'], $this->currency),
167
            $this->taxRate
168
        );
169
170
        $this->ticketTypes[$identifier] = new TicketType(
171
            $identifier,
172
            $price,
173
            $ticket['name']
174
        );
175
176
        $this->avaliableTickets[$identifier] = $ticket['available'];
177
178
        $this->ticketMetadata[$identifier] = TicketMetadata::fromArray(
179
            $this->ticketTypes[$identifier],
180
            $ticket['metadata'] ?? []
181
        );
182
    }
183
184
    /**
185
     * @return string
186
     */
187 10
    public function getCurrency(): string
188
    {
189 10
        return $this->currency;
190
    }
191
192
    /**
193
     * @return TaxRate
194
     */
195 10
    public function getTaxRate(): TaxRate
196
    {
197 10
        return $this->taxRate;
198
    }
199
200
    /**
201
     * @return boolean
202
     */
203
    public function displayTax(): bool
204
    {
205
        return $this->displayTax;
206
    }
207
208
    /**
209
     * @return TicketType[]
210
     */
211
    public function getTicketTypes(): array
212
    {
213
        return $this->ticketTypes;
214
    }
215
216
    /**
217
     * @return TicketType
218
     */
219
    public function getTicketType(string $identifier): TicketType
220
    {
221
        return $this->ticketTypes[$identifier];
222
    }
223
224
    /**
225
     * @param string $identifier
226
     * @return int
227
     */
228
    public function getAvailableTickets(string $identifier): int
229
    {
230
        return $this->avaliableTickets[$identifier];
231
    }
232
233
    public function getDiscountCodes(): array
234
    {
235
        return $this->discountCodes;
236
    }
237
238 4
    public function getTicketMetadata(string $identifier): TicketMetadata
239
    {
240 4
        return $this->ticketMetadata[$identifier];
241
    }
242
}