This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * TicketExtension.php |
||
4 | * |
||
5 | * @author Bram de Leeuw |
||
6 | * Date: 09/03/17 |
||
7 | */ |
||
8 | |||
9 | namespace Broarm\EventTickets; |
||
10 | |||
11 | use CalendarEvent_Controller; |
||
12 | use DataExtension; |
||
13 | use FieldList; |
||
14 | use GridField; |
||
15 | use GridFieldConfig_RecordEditor; |
||
16 | use HasManyList; |
||
17 | use HtmlEditorField; |
||
18 | use LiteralField; |
||
19 | use NumericField; |
||
20 | use SiteConfig; |
||
21 | |||
22 | /** |
||
23 | * Class TicketExtension |
||
24 | * |
||
25 | * @package Broarm\EventTickets |
||
26 | * |
||
27 | * @property TicketExtension|\CalendarEvent $owner |
||
28 | * @property int Capacity |
||
29 | * @property int OrderMin |
||
30 | * @property int OrderMax |
||
31 | * @property string SuccessMessage |
||
32 | * @property string SuccessMessageMail |
||
33 | * |
||
34 | * @method \HasManyList Tickets() |
||
35 | * @method \HasManyList Reservations() |
||
36 | * @method \HasManyList Attendees() |
||
37 | * @method \HasManyList WaitingList() |
||
38 | * @method \HasManyList Fields() |
||
39 | */ |
||
40 | class TicketExtension extends DataExtension |
||
41 | { |
||
42 | /** |
||
43 | * @var CalendarEvent_Controller |
||
44 | */ |
||
45 | protected $controller; |
||
46 | |||
47 | private static $db = array( |
||
48 | 'Capacity' => 'Int', |
||
49 | 'OrderMin' => 'Int', |
||
50 | 'OrderMax' => 'Int', |
||
51 | 'SuccessMessage' => 'HTMLText', |
||
52 | 'SuccessMessageMail' => 'HTMLText' |
||
53 | ); |
||
54 | |||
55 | private static $has_many = array( |
||
56 | 'Tickets' => 'Broarm\EventTickets\Ticket.Event', |
||
57 | 'Reservations' => 'Broarm\EventTickets\Reservation.Event', |
||
58 | 'Attendees' => 'Broarm\EventTickets\Attendee.Event', |
||
59 | 'WaitingList' => 'Broarm\EventTickets\WaitingListRegistration.Event', |
||
60 | 'Fields' => 'Broarm\EventTickets\UserField.Event' |
||
61 | ); |
||
62 | |||
63 | private static $defaults = array( |
||
64 | 'Capacity' => 50 |
||
65 | ); |
||
66 | |||
67 | private static $translate = array( |
||
68 | 'SuccessMessage', |
||
69 | 'SuccessMessageMail' |
||
70 | ); |
||
71 | |||
72 | protected $cachedGuestList; |
||
73 | |||
74 | public function updateCMSFields(FieldList $fields) |
||
75 | { |
||
76 | $guestListStatusDescription = _t('TicketExtension.GuestListStatusDescription', 'Tickets sold: {guestListStatus}', null, [ |
||
0 ignored issues
–
show
|
|||
77 | 'guestListStatus' => $this->owner->getGuestListStatus() |
||
78 | ]); |
||
79 | $fields->addFieldsToTab('Root.Main', [ |
||
80 | LiteralField::create('GuestListStatus', "<p class='message notice'>{$guestListStatusDescription}</p>") |
||
81 | ], 'Title'); |
||
82 | |||
83 | $ticketLabel = _t('TicketExtension.Tickets', 'Tickets'); |
||
84 | $fields->addFieldsToTab( |
||
85 | "Root.$ticketLabel", array( |
||
86 | GridField::create('Tickets', $ticketLabel, $this->owner->Tickets(), TicketsGridFieldConfig::create($this->canCreateTickets())), |
||
87 | NumericField::create('Capacity', _t('TicketExtension.Capacity', 'Capacity')), |
||
88 | HtmlEditorField::create('SuccessMessage', _t('TicketExtension.SuccessMessage', 'Success message'))->setRows(4), |
||
89 | HtmlEditorField::create('SuccessMessageMail', _t('TicketExtension.MailMessage', 'Mail message'))->setRows(4) |
||
90 | )); |
||
91 | |||
92 | // Create Reservations tab |
||
93 | View Code Duplication | if ($this->owner->Reservations()->exists()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
94 | $reservationLabel = _t('TicketExtension.Reservations', 'Reservations'); |
||
95 | $fields->addFieldToTab( |
||
96 | "Root.$reservationLabel", |
||
97 | GridField::create('Reservations', $reservationLabel, $this->owner->Reservations(), ReservationGridFieldConfig::create()) |
||
98 | ); |
||
99 | } |
||
100 | |||
101 | // Create Attendees tab |
||
102 | View Code Duplication | if ($this->owner->Attendees()->exists()) { |
|
103 | $guestListLabel = _t('TicketExtension.GuestList', 'GuestList'); |
||
104 | $fields->addFieldToTab( |
||
105 | "Root.$guestListLabel", |
||
106 | GridField::create('Attendees', $guestListLabel, $this->owner->Attendees(), GuestListGridFieldConfig::create($this->owner)) |
||
107 | ); |
||
108 | } |
||
109 | |||
110 | // Create WaitingList tab |
||
111 | View Code Duplication | if ($this->owner->WaitingList()->exists()) { |
|
112 | $waitingListLabel = _t('TicketExtension.WaitingList', 'WaitingList'); |
||
113 | $fields->addFieldToTab( |
||
114 | "Root.$waitingListLabel", |
||
115 | GridField::create('WaitingList', $waitingListLabel, $this->owner->WaitingList(), WaitingListGridFieldConfig::create()) |
||
116 | ); |
||
117 | } |
||
118 | |||
119 | // Create Fields tab |
||
120 | $extraFieldsLabel = _t('TicketExtension.ExtraFields', 'Attendee fields'); |
||
121 | $fields->addFieldToTab( |
||
122 | "Root.$extraFieldsLabel", |
||
123 | GridField::create('ExtraFields', $extraFieldsLabel, $this->owner->Fields(), UserFieldsGridFieldConfig::create()) |
||
124 | ); |
||
125 | |||
126 | $this->owner->extend('updateTicketExtensionFields', $fields); |
||
127 | } |
||
128 | |||
129 | /** |
||
130 | * Trigger actions after write |
||
131 | */ |
||
132 | public function onAfterWrite() |
||
133 | { |
||
134 | $this->createDefaultFields(); |
||
135 | parent::onAfterWrite(); |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Creates and sets up the default fields |
||
140 | */ |
||
141 | public function createDefaultFields() |
||
142 | { |
||
143 | $fields = Attendee::config()->get('default_fields'); |
||
144 | if (!$this->owner->Fields()->exists()) { |
||
145 | foreach ($fields as $fieldName => $config) { |
||
146 | $field = UserField::createDefaultField($fieldName, $config); |
||
147 | $this->owner->Fields()->add($field); |
||
148 | } |
||
149 | } |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * Extend the page actions with an start check in action |
||
154 | * |
||
155 | * @param FieldList $actions |
||
156 | */ |
||
157 | public function updateCMSActions(FieldList $actions) |
||
158 | { |
||
159 | $checkInButton = new LiteralField('StartCheckIn', |
||
160 | "<a class='action ss-ui-button ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only' |
||
161 | id='Edit_StartCheckIn' |
||
162 | role='button' |
||
163 | href='{$this->owner->Link('checkin')}' |
||
164 | target='_blank'> |
||
165 | Start check in |
||
166 | </a>" |
||
167 | ); |
||
168 | |||
169 | if ($this->owner->Attendees()->exists()) { |
||
170 | $actions->push($checkInButton); |
||
171 | } |
||
172 | } |
||
173 | |||
174 | /** |
||
175 | * Get the guest list status used in the summary fields |
||
176 | */ |
||
177 | public function getGuestListStatus() |
||
0 ignored issues
–
show
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 ![]() |
|||
178 | { |
||
179 | $guests = $this->owner->getGuestList()->count(); |
||
180 | $capacity = $this->owner->Capacity; |
||
181 | return "$guests/$capacity"; |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * Get the leftover capacity |
||
186 | * |
||
187 | * @return int |
||
0 ignored issues
–
show
|
|||
188 | */ |
||
189 | public function getAvailability() |
||
190 | { |
||
191 | return $this->owner->Capacity - $this->owner->getGuestList()->count(); |
||
192 | } |
||
193 | |||
194 | /** |
||
195 | * Check if the tickets are still available |
||
196 | * |
||
197 | * @return bool |
||
198 | */ |
||
199 | public function getTicketsAvailable() |
||
200 | { |
||
201 | return $this->owner->getAvailability() > 0; |
||
202 | } |
||
203 | |||
204 | /** |
||
205 | * Check if the tickets are sold out |
||
206 | * @return bool |
||
207 | */ |
||
208 | public function getTicketsSoldOut() |
||
209 | { |
||
210 | return $this->owner->getAvailability() <= 0; |
||
211 | } |
||
212 | |||
213 | /** |
||
214 | * get The sale start date |
||
215 | * |
||
216 | * @return \SS_DateTime |
||
217 | */ |
||
218 | public function getTicketSaleStartDate() |
||
219 | { |
||
220 | $saleStart = null; |
||
221 | if (($tickets = $this->owner->Tickets())) { |
||
222 | /** @var Ticket $ticket */ |
||
223 | foreach ($tickets as $ticket) { |
||
224 | if (($date = $ticket->getAvailableFrom()) && strtotime($date) < strtotime($saleStart) || $saleStart === null) { |
||
225 | $saleStart = $date; |
||
226 | } |
||
227 | } |
||
228 | } |
||
229 | |||
230 | return $saleStart; |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * Check if the event is expired, either by unavailable tickets or because the date has passed |
||
235 | * |
||
236 | * @return bool |
||
237 | */ |
||
238 | public function getEventExpired() |
||
239 | { |
||
240 | $expired = false; |
||
241 | if (($tickets = $this->owner->Tickets()) && $expired = $tickets->exists()) { |
||
242 | /** @var Ticket $ticket */ |
||
243 | foreach ($tickets as $ticket) { |
||
244 | $expired = (!$ticket->validateDate() && $expired); |
||
245 | } |
||
246 | } |
||
247 | |||
248 | return $expired; |
||
249 | } |
||
250 | |||
251 | /** |
||
252 | * Check if the ticket sale is still pending |
||
253 | * |
||
254 | * @return bool |
||
255 | */ |
||
256 | public function getTicketSalePending() |
||
257 | { |
||
258 | return time() < strtotime($this->owner->getTicketSaleStartDate()); |
||
259 | } |
||
260 | |||
261 | /** |
||
262 | * Get only the attendees who are certain to attend |
||
263 | * Also includes attendees without any reservation, these are manually added |
||
264 | * |
||
265 | * @return \DataList |
||
266 | */ |
||
267 | public function getGuestList() |
||
268 | { |
||
269 | $reservationClass = Reservation::singleton()->getClassName(); |
||
270 | $attendeeClass = Attendee::singleton()->getClassName(); |
||
271 | return Attendee::get() |
||
272 | ->leftJoin($reservationClass, "`$attendeeClass`.`ReservationID` = `$reservationClass`.`ID`") |
||
273 | ->filter(array( |
||
274 | 'EventID' => $this->owner->ID |
||
275 | )) |
||
276 | ->filterAny(array( |
||
277 | 'ReservationID' => 0, |
||
278 | 'Status' => Reservation::STATUS_PAID |
||
279 | )); |
||
280 | } |
||
281 | |||
282 | /** |
||
283 | * Get the checked in count for display in templates |
||
284 | * |
||
285 | * @return string |
||
286 | */ |
||
287 | public function getCheckedInCount() |
||
288 | { |
||
289 | $attendees = $this->getGuestList(); |
||
290 | $checkedIn = $attendees->filter('CheckedIn', true)->count(); |
||
291 | return "($checkedIn/{$attendees->count()})"; |
||
292 | } |
||
293 | |||
294 | /** |
||
295 | * Get the success message |
||
296 | * |
||
297 | * @return mixed|string |
||
298 | */ |
||
299 | View Code Duplication | public function getSuccessContent() |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
300 | { |
||
301 | if (!empty($this->owner->SuccessMessage)) { |
||
302 | return $this->owner->dbObject('SuccessMessage'); |
||
303 | } else { |
||
304 | return SiteConfig::current_site_config()->dbObject('SuccessMessage'); |
||
305 | } |
||
306 | } |
||
307 | |||
308 | /** |
||
309 | * Get the mail message |
||
310 | * |
||
311 | * @return mixed|string |
||
312 | */ |
||
313 | View Code Duplication | public function getMailContent() |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
314 | { |
||
315 | if (!empty($this->owner->SuccessMessageMail)) { |
||
316 | return $this->owner->dbObject('SuccessMessageMail'); |
||
317 | } else { |
||
318 | return SiteConfig::current_site_config()->dbObject('SuccessMessageMail'); |
||
319 | } |
||
320 | } |
||
321 | |||
322 | /** |
||
323 | * Get the Ticket logo |
||
324 | * |
||
325 | * @return \Image |
||
326 | */ |
||
327 | public function getMailLogo() |
||
328 | { |
||
329 | return SiteConfig::current_site_config()->TicketLogo(); |
||
330 | } |
||
331 | |||
332 | /** |
||
333 | * Check if the current event can have tickets |
||
334 | * |
||
335 | * @return bool |
||
336 | */ |
||
337 | public function canCreateTickets() |
||
338 | { |
||
339 | $currentDate = $this->owner->getController()->CurrentDate(); |
||
340 | if ($currentDate && $currentDate->exists()) { |
||
341 | return $currentDate->dbObject('StartDate')->InFuture(); |
||
342 | } |
||
343 | |||
344 | return false; |
||
345 | } |
||
346 | |||
347 | /** |
||
348 | * Get the calendar controller |
||
349 | * |
||
350 | * @return CalendarEvent_Controller |
||
351 | */ |
||
352 | public function getController() |
||
353 | { |
||
354 | return $this->controller |
||
355 | ? $this->controller |
||
356 | : $this->controller = CalendarEvent_Controller::create($this->owner); |
||
357 | } |
||
358 | } |
||
359 |
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: