Ticket::canView()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * Ticket.php
4
 *
5
 * @author Bram de Leeuw
6
 * Date: 09/03/17
7
 */
8
9
namespace Broarm\EventTickets;
10
11
use CalendarDateTime;
12
use CalendarEvent;
13
use CalendarEvent_Controller;
14
use DataObject;
15
use Date;
16
use DateField;
17
use DatetimeField;
18
use FieldList;
19
use LiteralField;
20
use NumericField;
21
use SS_Datetime;
22
use Tab;
23
use TabSet;
24
use TextField;
25
26
/**
27
 * Class Ticket
28
 *
29
 * @package Broarm\EventTickets
30
 *
31
 * @property string       Title
32
 * @property float        Price
33
 * @property int          OrderMin
34
 * @property int          OrderMax
35
 * @property string       AvailableFromDate
36
 * @property string       AvailableTillDate
37
 * @property NumericField AmountField the amount field is set on the TicketForm
38
 *
39
 * @method CalendarEvent|TicketExtension Event
40
 */
41
class Ticket extends DataObject
42
{
43
    /**
44
     * The default sale start date
45
     * This defaults to the event start date '-1 week'
46
     *
47
     * @var string
48
     */
49
    private static $sale_start_threshold = '-1 week';
50
51
    /**
52
     * The default sale end date
53
     * This defaults to the event start date time '-12 hours'
54
     *
55
     * @var string
56
     */
57
    private static $sale_end_threshold = '-12 hours';
58
59
    private static $db = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
60
        'Title' => 'Varchar(255)',
61
        'Price' => 'Currency',
62
        'AvailableFromDate' => 'SS_DateTime',
63
        'AvailableTillDate' => 'SS_DateTime',
64
        'OrderMin' => 'Int',
65
        'OrderMax' => 'Int',
66
        'Sort' => 'Int'
67
    );
68
69
    private static $default_sort = 'Sort ASC, AvailableFromDate DESC';
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
70
71
    private static $has_one = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
72
        'Event' => 'CalendarEvent'
73
    );
74
75
    private static $defaults = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
76
        'OrderMin' => 1,
77
        'OrderMax' => 5
78
    );
79
80
    private static $summary_fields = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
81
        'Title' => 'Title',
82
        'Price.NiceDecimalPoint' => 'Price',
83
        'AvailableFrom' => 'Available from',
84
        'AvailableTill' => 'Available till',
85
        'AvailableSummary' => 'Available'
86
    );
87
88
    private static $translate = array(
89
        'Title'
90
    );
91
92
    public function getCMSFields()
93
    {
94
        $fields = new FieldList(new TabSet('Root', $mainTab = new Tab('Main')));
95
96
        $fields->addFieldsToTab('Root.Main', array(
97
            TextField::create('Title', _t('Ticket.TITLE_LABEL', 'Title for the ticket')),
98
            NumericField::create('Price', _t('Ticket.PRICE_LABEL', 'Ticket price')),
99
            $saleStart = DatetimeField::create('AvailableFromDate',
100
                _t('Ticket.SALE_START_LABEL', 'Ticket sale starts from')),
101
            $saleEnd = DatetimeField::create('AvailableTillDate', _t('Ticket.SALE_END_LABEL', 'Ticket sale ends on')),
102
            NumericField::create('OrderMin', _t('Ticket.OrderMin', 'Minimum allowed amount of tickets from this type')),
103
            NumericField::create('OrderMax', _t('Ticket.OrderMax', 'Maximum allowed amount of tickets from this type'))
104
        ));
105
106
        $saleStart->getDateField()->setConfig('showcalendar', true);
107
        $saleStart->setDescription(_t(
108
            'Ticket.SALE_START_DESCRIPTION',
109
            'If no date is given the following date will be used: {date}', null,
110
            array('date' => $this->getAvailableFrom()->Nice())
0 ignored issues
show
Documentation introduced by
array('date' => $this->g...vailableFrom()->Nice()) is of type array<string,?,{"date":"?"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
111
        ));
112
113
        $saleEnd->getDateField()->setConfig('showcalendar', true);
114
        $saleEnd->setDescription(_t(
115
            'Ticket.SALE_END_DESCRIPTION',
116
            'If no date is given the event start date will be used: {date}', null,
117
            array('date' => $this->getEventStartDate()->Nice())
0 ignored issues
show
Documentation introduced by
array('date' => $this->g...entStartDate()->Nice()) is of type array<string,?,{"date":"?"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
118
        ));
119
120
        $this->extend('updateCMSFields', $fields);
121
        return $fields;
122
    }
123
124
    /**
125
     * Returns the singular name without the namespaces
126
     *
127
     * @return string
128
     */
129
    public function singular_name()
130
    {
131
        $name = explode('\\', parent::singular_name());
132
        return trim(end($name));
133
    }
134
135
    /**
136
     * Get the available form date if it is set,
137
     * otherwise get it from the parent
138
     *
139
     * @return \SS_DateTime|Date|\DBField|null
140
     */
141
    public function getAvailableFrom()
142
    {
143
        if ($this->AvailableFromDate) {
144
            return $this->dbObject('AvailableFromDate');
145
        } elseif ($startDate = $this->getEventStartDate()) {
146
            $lastWeek = new Date();
147
            $lastWeek->setValue(strtotime(self::config()->get('sale_start_threshold'), strtotime($startDate->value)));
148
            return $lastWeek;
149
        }
150
151
        return null;
152
    }
153
154
    /**
155
     * Get the available till date if it is set,
156
     * otherwise get it from the parent
157
     * Use the event start date as last sale possibility
158
     *
159
     * @return \SS_DateTime|Date|\DBField|null
160
     */
161
    public function getAvailableTill()
162
    {
163
        if ($this->AvailableTillDate) {
164
            return $this->dbObject('AvailableTillDate');
165
        } elseif ($startDate = $this->getEventStartDate()) {
166
            $till = strtotime(self::config()->get('sale_end_threshold'), strtotime($startDate->Nice()));
167
            $date = SS_Datetime::create();
168
            $date->setValue(date('Y-m-d H:i:s', $till));
169
            return $date;
170
        }
171
172
        return null;
173
    }
174
175
    /**
176
     * Validate if the start and end date are in the past and the future
177
     * todo check start time and treshhold
178
     *
179
     * @return bool
180
     */
181
    public function validateDate()
182
    {
183
        if (
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return ($from = $this->g...) && $till->InFuture();.
Loading history...
184
            ($from = $this->getAvailableFrom()) &&
185
            ($till = $this->getAvailableTill()) &&
186
            $from->InPast() &&
187
            $till->InFuture()
188
        ) {
189
            return true;
190
        }
191
192
        return false;
193
    }
194
195
    /**
196
     * Validate the available capacity
197
     *
198
     * @return bool
199
     */
200
    private function validateAvailability()
201
    {
202
        return $this->Event()->getAvailability() > 0;
0 ignored issues
show
Documentation Bug introduced by
The method Event does not exist on object<Broarm\EventTickets\Ticket>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
203
    }
204
205
    /**
206
     * Return if the ticket is available or not
207
     *
208
     * @return bool
209
     */
210
    public function getAvailable()
211
    {
212
        if (!$this->getAvailableFrom() && !$this->getAvailableTill()) {
213
            return false;
214
        } elseif ($this->validateDate() && $this->validateAvailability()) {
215
            return true;
216
        }
217
218
        return false;
219
    }
220
221
    /**
222
     * Return availability for use in grid fields
223
     *
224
     * @return LiteralField
225
     */
226
    public function getAvailableSummary()
227
    {
228
        $available = $this->getAvailable()
229
            ? '<span style="color: #3adb76;">' . _t('Ticket.AVAILABLE', 'Tickets available') . '</span>'
230
            : '<span style="color: #cc4b37;">' . _t('Ticket.UNAVAILABLE', 'Not for sale') . '</span>';
231
232
        return new LiteralField('Available', $available);
233
    }
234
235
    /**
236
     * Get the event start date
237
     *
238
     * @return Date
0 ignored issues
show
Documentation introduced by
Should the return type not be SS_Datetime|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
239
     */
240
    private function getEventStartDate()
241
    {
242
        $currentDate = $this->Event()->getController()->CurrentDate();
0 ignored issues
show
Documentation Bug introduced by
The method Event does not exist on object<Broarm\EventTickets\Ticket>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
243
        if ($currentDate && $currentDate->exists()) {
244
            $date = $currentDate->obj('StartDate')->Format('Y-m-d');
245
            $time = $currentDate->obj('StartTime')->Format('H:i:s');
246
            $dateTime = SS_Datetime::create();
247
            $dateTime->setValue("$date $time");
248
            return $dateTime;
249
        } else {
250
            return null;
251
        }
252
    }
253
254
    public function canView($member = null)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
255
    {
256
        return $this->Event()->canView($member);
0 ignored issues
show
Documentation Bug introduced by
The method Event does not exist on object<Broarm\EventTickets\Ticket>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
257
    }
258
259
    public function canEdit($member = null)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
260
    {
261
        return $this->Event()->canEdit($member);
0 ignored issues
show
Documentation Bug introduced by
The method Event does not exist on object<Broarm\EventTickets\Ticket>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
262
    }
263
264
    public function canDelete($member = null)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
265
    {
266
        return $this->Event()->canDelete($member);
0 ignored issues
show
Documentation Bug introduced by
The method Event does not exist on object<Broarm\EventTickets\Ticket>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
267
    }
268
269
    public function canCreate($member = null)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
270
    {
271
        return $this->Event()->canCreate($member);
0 ignored issues
show
Documentation Bug introduced by
The method Event does not exist on object<Broarm\EventTickets\Ticket>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
272
    }
273
}
274