Completed
Push — master ( dead21...224450 )
by Bram
02:17
created

Reservation::getState()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/**
3
 * Reservation.php
4
 *
5
 * @author Bram de Leeuw
6
 * Date: 09/03/17
7
 */
8
9
namespace Broarm\EventTickets;
10
11
use CalendarEvent;
12
use CalendarEvent_Controller;
13
use DataObject;
14
use Director;
15
use Dompdf\Dompdf;
16
use FieldList;
17
use File;
18
use Folder;
19
use GridField;
20
use GridFieldConfig_RecordViewer;
21
use HasManyList;
22
use ManyManyList;
23
use Member;
24
use ReadonlyField;
25
use SiteConfig;
26
use SSViewer;
27
use Tab;
28
use TabSet;
29
use ViewableData;
30
31
/**
32
 * Class Reservation
33
 *
34
 * @package Broarm\EventTickets
35
 *
36
 * @property string Status
37
 * @property string Title
38
 * @property float  Total
39
 * @property string FirstName
40
 * @property string Surname
41
 * @property string Email
42
 * @property string Comments
43
 * @property string ReservationCode
44
 * @property string Gateway
45
 *
46
 * @property int    EventID
47
 * @property int    TicketFileID
48
 * @property int    MainContactID
49
 *
50
 * @method File TicketFile
51
 * @method CalendarEvent|TicketExtension Event
52
 * @method Attendee MainContact
53
 * @method HasManyList Payments
54
 * @method HasManyList Attendees
55
 * @method ManyManyList PriceModifiers
56
 */
57
class Reservation extends DataObject
58
{
59
    /**
60
     * Time to wait before deleting the discarded cart
61
     * Give a string that is parsable by strtotime
62
     *
63
     * @var string
64
     */
65
    private static $delete_after = '+1 week';
1 ignored issue
show
Unused Code introduced by
The property $delete_after is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
66
67
    private static $db = array(
2 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $db is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
68
        'Status' => 'Enum("CART,PENDING,PAID,CANCELED","CART")',
69
        'Title' => 'Varchar(255)',
70
        'Total' => 'Currency',
71
        'Email' => 'Varchar(255)',
72
        'Gateway' => 'Varchar(255)',
73
        'Comments' => 'Text',
74
        'ReservationCode' => 'Varchar(255)'
75
    );
76
77
    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...
Unused Code introduced by
The property $has_one is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
78
        'Event' => 'CalendarEvent',
79
        'TicketFile' => 'File',
80
        'MainContact' => 'Broarm\EventTickets\Attendee'
81
    );
82
83
    private static $has_many = array(
1 ignored issue
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $has_many is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
84
        'Payments' => 'Payment',
85
        'Attendees' => 'Broarm\EventTickets\Attendee.Reservation'
86
    );
87
88
    private static $belongs_many_many = 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...
Unused Code introduced by
The property $belongs_many_many is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
89
        'PriceModifiers' => 'Broarm\EventTickets\PriceModifier'
90
    );
91
92
    private static $indexes = array(
2 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $indexes is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
93
        'ReservationCode' => 'unique("ReservationCode")'
94
    );
95
96
    private static $summary_fields = array(
1 ignored issue
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $summary_fields is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
97
        'Title' => 'Customer',
98
        'Total.Nice' => 'Total',
99
        'State' => 'Status'
100
    );
101
102
    public function getCMSFields()
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...
103
    {
104
        $fields = new FieldList(new TabSet('Root', $mainTab = new Tab('Main')));
105
        $gridFieldConfig = GridFieldConfig_RecordViewer::create();
106
        $fields->addFieldsToTab('Root.Main', array(
107
            ReadonlyField::create('ReservationCode', _t('Reservation.Code', 'Code')),
108
            ReadonlyField::create('Title', _t('Reservation.MainContact', 'Main contact')),
109
            ReadonlyField::create('Gateway', _t('Reservation.Gateway', 'Gateway')),
110
            ReadonlyField::create('Total', _t('Reservation.Total', 'Total')),
111
            ReadonlyField::create('Comments', _t('Reservation.Comments', 'Comments')),
112
            $reservationFileField = ReadonlyField::create(
113
                'ReservationFile',
114
                _t('Attendee.Reservation', 'Reservation'),
115
                "<a class='readonly' href='{$this->TicketFile()->Link()}' target='_blank'>Download reservation PDF</a>"
0 ignored issues
show
Bug introduced by
The method TicketFile() does not exist on Broarm\EventTickets\Reservation. Did you maybe mean createTicketFile()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
116
            ),
117
            GridField::create('Attendees', 'Attendees', $this->Attendees(), $gridFieldConfig),
0 ignored issues
show
Documentation Bug introduced by
The method Attendees does not exist on object<Broarm\EventTickets\Reservation>? 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...
118
            GridField::create('Payments', 'Payments', $this->Payments(), $gridFieldConfig)
0 ignored issues
show
Documentation Bug introduced by
The method Payments does not exist on object<Broarm\EventTickets\Reservation>? 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...
119
        ));
120
        $reservationFileField->dontEscape = true;
121
        $fields->addFieldsToTab('Root.Main', array());
122
        $this->extend('updateCMSFields', $fields);
123
        return $fields;
124
    }
125
126
    public function onBeforeWrite()
127
    {
128
        // Set the title to the name of the reservation holder
129
        $this->Title = $this->getName();
130
131
        // Create a validation code to be used for confirmation and in the barcode
132
        if ($this->exists() && empty($this->ReservationCode)) {
133
            $this->ReservationCode = $this->createReservationCode();
134
        }
135
136
        parent::onBeforeWrite();
137
    }
138
139
    public function onBeforeDelete()
140
    {
141
        // If a reservation is deleted remove the names from the guest list
142
        foreach ($this->Attendees() as $attendee) {
0 ignored issues
show
Documentation Bug introduced by
The method Attendees does not exist on object<Broarm\EventTickets\Reservation>? 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...
143
            /** @var Attendee $attendee */
144
            if ($attendee->exists()) {
145
                $attendee->delete();
146
            }
147
        }
148
149
        // Make sure the ticket file is not downloadable
150
        if ($this->TicketFile()->exists()) {
0 ignored issues
show
Bug introduced by
The method TicketFile() does not exist on Broarm\EventTickets\Reservation. Did you maybe mean createTicketFile()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
151
            $this->TicketFile()->delete();
0 ignored issues
show
Bug introduced by
The method TicketFile() does not exist on Broarm\EventTickets\Reservation. Did you maybe mean createTicketFile()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
152
        }
153
154
        // Remove the folder
155
        if ($this->fileFolder()->exists()) {
156
            $this->fileFolder()->delete();
157
        }
158
159
        parent::onBeforeDelete();
160
    }
161
162
    public function singular_name()
163
    {
164
        $name = explode('\\', parent::singular_name());
165
        return trim(end($name));
166
    }
167
168
    /**
169
     * Check if the cart is still in cart state and the delete_after time period has been exceeded
170
     *
171
     * @return bool
172
     */
173
    public function isDiscarded()
174
    {
175
        $deleteAfter = strtotime(self::config()->get('delete_after'), strtotime($this->Created));
176
        return ($this->Status === 'CART') && (time() > $deleteAfter);
177
    }
178
179
    /**
180
     * Get the full name
181
     *
182
     * @return string
183
     */
184
    public function getName()
185
    {
186
        /** @var Attendee $attendee */
187
        if ($this->MainContact()->exists()) {
0 ignored issues
show
Bug introduced by
The method MainContact() does not exist on Broarm\EventTickets\Reservation. Did you maybe mean setMainContact()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
188
            return $this->MainContact()->getName();
0 ignored issues
show
Bug introduced by
The method MainContact() does not exist on Broarm\EventTickets\Reservation. Did you maybe mean setMainContact()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
189
        } else {
190
            return 'new reservation';
191
        }
192
    }
193
194
    /**
195
     * Return the translated state
196
     * @return string
197
     */
198
    public function getState()
199
    {
200
        return _t("Reservation.{$this->Status}", $this->Status);
201
    }
202
203
    /**
204
     * Get the total by querying the sum of attendee ticket prices
205
     *
206
     * @return float
207
     */
208
    public function calculateTotal()
209
    {
210
        $total = $this->Attendees()->leftJoin(
0 ignored issues
show
Documentation Bug introduced by
The method Attendees does not exist on object<Broarm\EventTickets\Reservation>? 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...
211
            'Broarm\EventTickets\Ticket',
212
            '`Broarm\EventTickets\Attendee`.`TicketID` = `Broarm\EventTickets\Ticket`.`ID`'
213
        )->sum('Price');
214
        
215
        // Calculate any price modifications if added
216
        if ($this->PriceModifiers()->exists()) {
0 ignored issues
show
Documentation Bug introduced by
The method PriceModifiers does not exist on object<Broarm\EventTickets\Reservation>? 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...
217
            foreach ($this->PriceModifiers() as $priceModifier) {
0 ignored issues
show
Documentation Bug introduced by
The method PriceModifiers does not exist on object<Broarm\EventTickets\Reservation>? 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...
218
                $priceModifier->updateTotal($total);
219
            }
220
        }
221
222
        return $this->Total = $total;
223
    }
224
225
    /**
226
     * Safely change to a state
227
     *
228
     * @param $state
229
     */
230
    public function changeState($state)
231
    {
232
        $availableStates = $this->dbObject('Status')->enumValues();
233
        if (in_array($state, $availableStates)) {
234
            $this->Status = $state;
235
        } else {
236
            user_error(_t('Reservation.STATE_CHANGE_ERROR', 'Selected state is not available'));
237
        }
238
    }
239
240
    /**
241
     * Set the main contact id
242
     *
243
     * @param $id
244
     */
245
    public function setMainContact($id) {
246
        $this->MainContactID = $id;
247
        $this->write();
248
    }
249
250
    /**
251
     * Create a reservation code
252
     *
253
     * @return string
254
     */
255
    public function createReservationCode()
256
    {
257
        return uniqid($this->ID);
258
    }
259
260
    /**
261
     * Create the folder for the qr code and ticket file
262
     *
263
     * @return Folder|DataObject|null
264
     */
265
    public function fileFolder()
266
    {
267
        return Folder::find_or_make("/event-tickets/{$this->ReservationCode}/");
268
    }
269
270
    /**
271
     * Generate the qr codes and downloadable pdf
272
     */
273
    public function createFiles()
274
    {
275
        $folder = $folder = $this->fileFolder();
276
        /** @var Attendee $attendee */
277
        foreach ($this->Attendees() as $attendee) {
0 ignored issues
show
Documentation Bug introduced by
The method Attendees does not exist on object<Broarm\EventTickets\Reservation>? 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...
278
            $attendee->createQRCode($folder);
279
        }
280
281
        // Create a pdf with the newly create QR codes
282
        $this->createTicketFile($folder);
0 ignored issues
show
Documentation introduced by
$folder is of type null|object<DataObject>, but the function expects a object<Folder>.

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...
283
    }
284
285
    /**
286
     * Create a Printable ticket file
287
     *
288
     * @param Folder $folder
289
     *
290
     * @return File
291
     */
292
    private function createTicketFile(Folder $folder)
293
    {
294
        // Find or make a folder
295
        $relativeFilePath = "/{$folder->Filename}{$this->ReservationCode}.pdf";
296
        $absoluteFilePath = Director::baseFolder() . $relativeFilePath;
297
298
        if (!$file = File::get()->find('Filename', $relativeFilePath)) {
299
            $file = File::create();
300
            $file->ParentID = $folder->ID;
301
            $file->OwnerID = (Member::currentUser()) ? Member::currentUser()->ID : 0;
302
            $file->Title = $this->ReservationCode;
303
            $file->setFilename($relativeFilePath);
304
            $file->write();
305
        }
306
307
        // Set the template and parse the data
308
        $template = new SSViewer('PrintableTicket');
309
        $html = $template->process($this->getViewableData());
310
311
        // Create a DomPDF instance
312
        $domPDF = new Dompdf();
313
        $domPDF->loadHtml($html);
314
        $domPDF->setPaper('A4');
315
        $domPDF->getOptions()->setDpi(250);
316
        $domPDF->render();
317
318
        // Save the pdf stream as a file
319
        file_put_contents($absoluteFilePath, $domPDF->output());
320
321
        // Attach the ticket file to the Attendee
322
        $this->TicketFileID = $file->ID;
323
        $this->write();
324
325
        return $file;
326
    }
327
328
    /**
329
     * Get a viewable data object for this reservation
330
     * For use in the Email and print template
331
     *
332
     * @return ViewableData
333
     */
334
    public function getViewableData()
335
    {
336
        $config = SiteConfig::current_site_config();
337
        $data = $this->Me();
338
        $data->CurrentDate = $this->Event()->getController()->CurrentDate();
0 ignored issues
show
Documentation Bug introduced by
The method Event does not exist on object<Broarm\EventTickets\Reservation>? 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...
339
        //$calendarController = new CalendarEvent_Controller($this->Event());
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
340
        //$data->CurrentDate = $calendarController->CurrentDate();
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
341
        $data->Logo = $config->TicketLogo();
342
        $this->extend('updateViewableData', $data);
343
        return $data;
344
    }
345
346
    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...
347
    {
348
        return $this->Event()->canView($member);
0 ignored issues
show
Documentation Bug introduced by
The method Event does not exist on object<Broarm\EventTickets\Reservation>? 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...
349
    }
350
351
    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...
352
    {
353
        return $this->Event()->canEdit($member);
0 ignored issues
show
Documentation Bug introduced by
The method Event does not exist on object<Broarm\EventTickets\Reservation>? 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...
354
    }
355
356
    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...
357
    {
358
        return $this->Event()->canDelete($member);
0 ignored issues
show
Documentation Bug introduced by
The method Event does not exist on object<Broarm\EventTickets\Reservation>? 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...
359
    }
360
361
    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...
362
    {
363
        return $this->Event()->canCreate($member);
0 ignored issues
show
Documentation Bug introduced by
The method Event does not exist on object<Broarm\EventTickets\Reservation>? 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...
364
    }
365
}
366