Issues (81)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Domain/Service/Configuration.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
        $ticket['metadata'] = ArrayUtils::merge(['private' => false], (isset($ticket['metadata'])?$ticket['metadata']:[]));
179
180
        if (isset($ticket['metadata']['availableFrom']) && isset($ticket['metadata']['availableTo'])) {
181
            $this->ticketMetadata[$identifier] = new TicketMetadata(
182
                $this->ticketTypes[$identifier],
183
                $ticket['metadata']['availableFrom'],
184
                $ticket['metadata']['availableTo'],
185
                $ticket['metadata']['private']
186
            );
187
        } else {
188
            $this->ticketMetadata[$identifier] = TicketMetadata::createWithoutDates(
189
                $this->ticketTypes[$identifier],
190
                $ticket['metadata']['private']
191
            );
192
        }
193
    }
194
195
    /**
196
     * @return string
197
     */
198 6
    public function getCurrency(): string
199
    {
200 6
        return $this->currency;
201
    }
202
203
    /**
204
     * @return TaxRate
205
     */
206 6
    public function getTaxRate(): TaxRate
207
    {
208 6
        return $this->taxRate;
209
    }
210
211
    /**
212
     * @return boolean
213
     */
214
    public function displayTax(): bool
215
    {
216
        return $this->displayTax;
217
    }
218
219
    /**
220
     * @return TicketType[]
221
     */
222 4
    public function getTicketTypes(): array
223
    {
224 4
        return $this->ticketTypes;
225
    }
226
227
    /**
228
     * @return TicketType
229
     */
230
    public function getTicketType(string $identifier): TicketType
231
    {
232
        return $this->ticketTypes[$identifier];
233
    }
234
235
    /**
236
     * @param string $identifier
237
     * @return int
238
     */
239
    public function getAvailableTickets(string $identifier): int
240
    {
241
        return $this->avaliableTickets[$identifier];
242
    }
243
244
    public function getDiscountCodes(): array
245
    {
246
        return $this->discountCodes;
247
    }
248
249 4
    public function getTicketMetadata(string $identifier): TicketMetadata
250
    {
251 4
        return $this->ticketMetadata[$identifier];
252
    }
253
}