These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * @package comments |
||
5 | */ |
||
6 | |||
7 | class CommentingController extends Controller { |
||
8 | |||
9 | private static $allowed_actions = array( |
||
10 | 'delete', |
||
11 | 'spam', |
||
12 | 'ham', |
||
13 | 'approve', |
||
14 | 'rss', |
||
15 | 'CommentsForm', |
||
16 | 'reply', |
||
17 | 'doPostComment', |
||
18 | 'doPreviewComment' |
||
19 | ); |
||
20 | |||
21 | private static $url_handlers = array( |
||
22 | 'reply/$ParentCommentID//$ID/$OtherID' => 'reply', |
||
23 | ); |
||
24 | |||
25 | /** |
||
26 | * Fields required for this form |
||
27 | * |
||
28 | * @var array |
||
29 | * @config |
||
30 | */ |
||
31 | private static $required_fields = array( |
||
32 | 'Name', |
||
33 | 'Email', |
||
34 | 'Comment' |
||
35 | ); |
||
36 | |||
37 | /** |
||
38 | * Base class this commenting form is for |
||
39 | * |
||
40 | * @var string |
||
41 | */ |
||
42 | private $baseClass = ""; |
||
43 | |||
44 | /** |
||
45 | * The record this commenting form is for |
||
46 | * |
||
47 | * @var DataObject |
||
48 | */ |
||
49 | private $ownerRecord = null; |
||
50 | |||
51 | /** |
||
52 | * Parent controller record |
||
53 | * |
||
54 | * @var Controller |
||
55 | */ |
||
56 | private $ownerController = null; |
||
57 | |||
58 | /** |
||
59 | * Backup url to return to |
||
60 | * |
||
61 | * @var string |
||
62 | */ |
||
63 | protected $fallbackReturnURL = null; |
||
64 | |||
65 | /** |
||
66 | * Set the base class to use |
||
67 | * |
||
68 | * @param string $class |
||
69 | */ |
||
70 | public function setBaseClass($class) { |
||
71 | $this->baseClass = $class; |
||
72 | } |
||
73 | |||
74 | /** |
||
75 | * Get the base class used |
||
76 | * |
||
77 | * @return string |
||
78 | */ |
||
79 | public function getBaseClass() { |
||
80 | return $this->baseClass; |
||
81 | } |
||
82 | |||
83 | /** |
||
84 | * Set the record this controller is working on |
||
85 | * |
||
86 | * @param DataObject $record |
||
87 | */ |
||
88 | public function setOwnerRecord($record) { |
||
89 | $this->ownerRecord = $record; |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * Get the record |
||
94 | * |
||
95 | * @return DataObject |
||
96 | */ |
||
97 | public function getOwnerRecord() { |
||
98 | return $this->ownerRecord; |
||
99 | } |
||
100 | |||
101 | /** |
||
102 | * Set the parent controller |
||
103 | * |
||
104 | * @param Controller $controller |
||
105 | */ |
||
106 | public function setOwnerController($controller) { |
||
107 | $this->ownerController = $controller; |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * Get the parent controller |
||
112 | * |
||
113 | * @return Controller |
||
114 | */ |
||
115 | public function getOwnerController() { |
||
116 | return $this->ownerController; |
||
117 | } |
||
118 | |||
119 | /** |
||
120 | * Get the commenting option for the current state |
||
121 | * |
||
122 | * @param string $key |
||
123 | * @return mixed Result if the setting is available, or null otherwise |
||
124 | */ |
||
125 | public function getOption($key) { |
||
126 | // If possible use the current record |
||
127 | if($record = $this->getOwnerRecord()) { |
||
128 | return $record->getCommentsOption($key); |
||
129 | } |
||
130 | |||
131 | // Otherwise a singleton of that record |
||
132 | if($class = $this->getBaseClass()) { |
||
133 | return singleton($class)->getCommentsOption($key); |
||
134 | } |
||
135 | |||
136 | // Otherwise just use the default options |
||
137 | return singleton('CommentsExtension')->getCommentsOption($key); |
||
138 | } |
||
139 | |||
140 | /** |
||
141 | * Workaround for generating the link to this controller |
||
142 | * |
||
143 | * @return string |
||
144 | */ |
||
145 | public function Link($action = '', $id = '', $other = '') { |
||
146 | return Controller::join_links(Director::baseURL(), __CLASS__ , $action, $id, $other); |
||
147 | } |
||
148 | |||
149 | /** |
||
150 | * Outputs the RSS feed of comments |
||
151 | * |
||
152 | * @return HTMLText |
||
153 | */ |
||
154 | public function rss() { |
||
155 | return $this->getFeed($this->request)->outputToBrowser(); |
||
156 | } |
||
157 | |||
158 | /** |
||
159 | * Return an RSSFeed of comments for a given set of comments or all |
||
160 | * comments on the website. |
||
161 | * |
||
162 | * To maintain backwards compatibility with 2.4 this supports mapping |
||
163 | * of PageComment/rss?pageid= as well as the new RSS format for comments |
||
164 | * of CommentingController/rss/{classname}/{id} |
||
165 | * |
||
166 | * @param SS_HTTPRequest |
||
167 | * |
||
168 | * @return RSSFeed |
||
169 | */ |
||
170 | public function getFeed(SS_HTTPRequest $request) { |
||
171 | $link = $this->Link('rss'); |
||
172 | $class = $request->param('ID'); |
||
173 | $id = $request->param('OtherID'); |
||
174 | |||
175 | // Support old pageid param |
||
176 | if(!$id && !$class && ($id = $request->getVar('pageid'))) { |
||
177 | $class = 'SiteTree'; |
||
178 | } |
||
179 | |||
180 | $comments = Comment::get()->filter(array( |
||
181 | 'Moderated' => 1, |
||
182 | 'IsSpam' => 0, |
||
183 | )); |
||
184 | |||
185 | // Check if class filter |
||
186 | if($class) { |
||
187 | if(!is_subclass_of($class, 'DataObject') || !$class::has_extension('CommentsExtension')) { |
||
188 | return $this->httpError(404); |
||
189 | } |
||
190 | $this->setBaseClass($class); |
||
191 | $comments = $comments->filter('BaseClass', $class); |
||
192 | $link = Controller::join_links($link, $class); |
||
193 | |||
194 | // Check if id filter |
||
195 | if($id) { |
||
196 | $comments = $comments->filter('ParentID', $id); |
||
197 | $link = Controller::join_links($link, $id); |
||
198 | $this->setOwnerRecord(DataObject::get_by_id($class, $id)); |
||
199 | } |
||
200 | } |
||
201 | |||
202 | $title = _t('CommentingController.RSSTITLE', "Comments RSS Feed"); |
||
203 | |||
204 | $comments = new PaginatedList($comments, $request); |
||
205 | $comments->setPageLength($this->getOption('comments_per_page')); |
||
206 | |||
207 | return new RSSFeed( |
||
208 | $comments, |
||
209 | $link, |
||
210 | $title, |
||
211 | $link, |
||
212 | 'Title', 'EscapedComment', 'AuthorName' |
||
213 | ); |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * Deletes a given {@link Comment} via the URL. |
||
218 | */ |
||
219 | View Code Duplication | public function delete() { |
|
220 | $comment = $this->getComment(); |
||
221 | if(!$comment) return $this->httpError(404); |
||
222 | if(!$comment->canDelete()) { |
||
223 | return Security::permissionFailure($this, 'You do not have permission to delete this comment'); |
||
224 | } |
||
225 | if(!$comment->getSecurityToken()->checkRequest($this->request)) return $this->httpError(400); |
||
226 | |||
227 | $comment->delete(); |
||
228 | |||
229 | return $this->request->isAjax() |
||
230 | ? true |
||
231 | : $this->redirectBack(); |
||
232 | } |
||
233 | |||
234 | /** |
||
235 | * Marks a given {@link Comment} as spam. Removes the comment from display |
||
236 | */ |
||
237 | View Code Duplication | public function spam() { |
|
238 | $comment = $this->getComment(); |
||
239 | if(!$comment) return $this->httpError(404); |
||
240 | if(!$comment->canEdit()) { |
||
241 | return Security::permissionFailure($this, 'You do not have permission to edit this comment'); |
||
242 | } |
||
243 | if(!$comment->getSecurityToken()->checkRequest($this->request)) return $this->httpError(400); |
||
244 | |||
245 | $comment->markSpam(); |
||
246 | return $this->renderChangedCommentState($comment); |
||
247 | } |
||
248 | |||
249 | /** |
||
250 | * Marks a given {@link Comment} as ham (not spam). |
||
251 | */ |
||
252 | View Code Duplication | public function ham() { |
|
253 | $comment = $this->getComment(); |
||
254 | if(!$comment) return $this->httpError(404); |
||
255 | if(!$comment->canEdit()) { |
||
256 | return Security::permissionFailure($this, 'You do not have permission to edit this comment'); |
||
257 | } |
||
258 | if(!$comment->getSecurityToken()->checkRequest($this->request)) return $this->httpError(400); |
||
259 | |||
260 | $comment->markApproved(); |
||
261 | return $this->renderChangedCommentState($comment); |
||
262 | } |
||
263 | |||
264 | /** |
||
265 | * Marks a given {@link Comment} as approved. |
||
266 | */ |
||
267 | View Code Duplication | public function approve() { |
|
268 | $comment = $this->getComment(); |
||
269 | if(!$comment) return $this->httpError(404); |
||
270 | if(!$comment->canEdit()) { |
||
271 | return Security::permissionFailure($this, 'You do not have permission to approve this comment'); |
||
272 | } |
||
273 | if(!$comment->getSecurityToken()->checkRequest($this->request)) return $this->httpError(400); |
||
274 | |||
275 | $comment->markApproved(); |
||
276 | return $this->renderChangedCommentState($comment); |
||
277 | } |
||
278 | |||
279 | /** |
||
280 | * Redirect back to referer if available, ensuring that only site URLs |
||
281 | * are allowed to avoid phishing. If it's an AJAX request render the |
||
282 | * comment in it's new state |
||
283 | */ |
||
284 | private function renderChangedCommentState($comment) { |
||
285 | $referer = $this->request->getHeader('Referer'); |
||
286 | |||
287 | // Render comment using AJAX |
||
288 | if ($this->request->isAjax()) { |
||
289 | return $comment->renderWith('CommentsInterface_singlecomment'); |
||
290 | } else { |
||
291 | // Redirect to either the comment or start of the page |
||
292 | if (empty($referer)) { |
||
293 | return $this->redirectBack(); |
||
294 | } else { |
||
295 | // Redirect to the comment, but check for phishing |
||
296 | $url = $referer . '#comment-' . $comment->ID; |
||
297 | // absolute redirection URLs not located on this site may cause phishing |
||
298 | if(Director::is_site_url($url)) { |
||
299 | return $this->redirect($url); |
||
300 | } else { |
||
301 | return false; |
||
302 | } |
||
303 | } |
||
304 | } |
||
305 | } |
||
306 | |||
307 | /** |
||
308 | * Returns the comment referenced in the URL (by ID). Permission checking |
||
309 | * should be done in the callee. |
||
310 | * |
||
311 | * @return Comment|false |
||
312 | */ |
||
313 | public function getComment() { |
||
314 | $id = isset($this->urlParams['ID']) ? $this->urlParams['ID'] : false; |
||
315 | |||
316 | if($id) { |
||
317 | $comment = DataObject::get_by_id('Comment', $id); |
||
318 | |||
319 | if($comment) { |
||
320 | $this->fallbackReturnURL = $comment->Link(); |
||
321 | return $comment; |
||
322 | } |
||
323 | } |
||
324 | |||
325 | return false; |
||
326 | } |
||
327 | |||
328 | /** |
||
329 | * Create a reply form for a specified comment |
||
330 | * |
||
331 | * @param Comment $comment |
||
332 | */ |
||
333 | public function ReplyForm($comment) { |
||
334 | // Enables multiple forms with different names to use the same handler |
||
335 | $form = $this->CommentsForm(); |
||
336 | $form->setName('ReplyForm_'.$comment->ID); |
||
337 | $form->addExtraClass('reply-form'); |
||
338 | |||
339 | // Load parent into reply form |
||
340 | $form->loadDataFrom(array( |
||
341 | 'ParentCommentID' => $comment->ID |
||
342 | )); |
||
343 | |||
344 | // Customise action |
||
345 | $form->setFormAction($this->Link('reply', $comment->ID)); |
||
346 | |||
347 | $this->extend('updateReplyForm', $form); |
||
348 | return $form; |
||
349 | } |
||
350 | |||
351 | |||
352 | /** |
||
353 | * Request handler for reply form. |
||
354 | * This method will disambiguate multiple reply forms in the same method |
||
355 | * |
||
356 | * @param SS_HTTPRequest $request |
||
357 | */ |
||
358 | public function reply(SS_HTTPRequest $request) { |
||
359 | // Extract parent comment from reply and build this way |
||
360 | if($parentID = $request->param('ParentCommentID')) { |
||
361 | $comment = DataObject::get_by_id('Comment', $parentID, true); |
||
362 | if($comment) { |
||
363 | return $this->ReplyForm($comment); |
||
364 | } |
||
365 | } |
||
366 | return $this->httpError(404); |
||
367 | } |
||
368 | |||
369 | /** |
||
370 | * Post a comment form |
||
371 | * |
||
372 | * @return Form |
||
373 | */ |
||
374 | public function CommentsForm() { |
||
375 | $usePreview = $this->getOption('use_preview'); |
||
376 | |||
377 | $nameRequired = _t('CommentInterface.YOURNAME_MESSAGE_REQUIRED', 'Please enter your name'); |
||
378 | $emailRequired = _t('CommentInterface.EMAILADDRESS_MESSAGE_REQUIRED', 'Please enter your email address'); |
||
379 | $emailInvalid = _t('CommentInterface.EMAILADDRESS_MESSAGE_EMAIL', 'Please enter a valid email address'); |
||
380 | $urlInvalid = _t('CommentInterface.COMMENT_MESSAGE_URL', 'Please enter a valid URL'); |
||
381 | $commentRequired = _t('CommentInterface.COMMENT_MESSAGE_REQUIRED', 'Please enter your comment'); |
||
382 | |||
383 | $fields = new FieldList( |
||
384 | $dataFields = new CompositeField( |
||
385 | // Name |
||
386 | TextField::create("Name", _t('CommentInterface.YOURNAME', 'Your name')) |
||
387 | ->setCustomValidationMessage($nameRequired) |
||
388 | ->setAttribute('data-msg-required', $nameRequired), |
||
389 | |||
390 | |||
391 | EmailField::create( |
||
392 | "Email", |
||
393 | _t('CommentingController.EMAILADDRESS', "Your email address (will not be published)") |
||
394 | ) |
||
395 | ->setCustomValidationMessage($emailRequired) |
||
396 | ->setAttribute('data-msg-required', $emailRequired) |
||
397 | ->setAttribute('data-msg-email', $emailInvalid) |
||
398 | ->setAttribute('data-rule-email', true), |
||
399 | |||
400 | // Url |
||
401 | TextField::create("URL", _t('CommentingController.WEBSITEURL', "Your website URL")) |
||
402 | ->setAttribute('data-msg-url', $urlInvalid) |
||
403 | ->setAttribute('data-rule-url', true), |
||
404 | |||
405 | // Comment |
||
406 | TextareaField::create("Comment", _t('CommentingController.COMMENTS', "Comments")) |
||
407 | ->setCustomValidationMessage($commentRequired) |
||
408 | ->setAttribute('data-msg-required', $commentRequired) |
||
409 | ), |
||
410 | HiddenField::create("ParentID"), |
||
411 | HiddenField::create("ReturnURL"), |
||
412 | HiddenField::create("ParentCommentID"), |
||
413 | HiddenField::create("BaseClass") |
||
414 | ); |
||
415 | |||
416 | // Preview formatted comment. Makes most sense when shortcodes or |
||
417 | // limited HTML is allowed. Populated by JS/Ajax. |
||
418 | if($usePreview) { |
||
419 | $fields->insertAfter( |
||
420 | ReadonlyField::create('PreviewComment', _t('CommentInterface.PREVIEWLABEL', 'Preview')) |
||
421 | ->setAttribute('style', 'display: none'), // enable through JS |
||
422 | 'Comment' |
||
423 | ); |
||
424 | } |
||
425 | |||
426 | $dataFields->addExtraClass('data-fields'); |
||
427 | |||
428 | // save actions |
||
429 | $actions = new FieldList( |
||
430 | new FormAction("doPostComment", _t('CommentInterface.POST', 'Post')) |
||
431 | ); |
||
432 | if($usePreview) { |
||
433 | $actions->push( |
||
434 | FormAction::create('doPreviewComment', _t('CommentInterface.PREVIEW', 'Preview')) |
||
435 | ->addExtraClass('action-minor') |
||
436 | ->setAttribute('style', 'display: none') // enable through JS |
||
437 | ); |
||
438 | } |
||
439 | |||
440 | // required fields for server side |
||
441 | $required = new RequiredFields($this->config()->required_fields); |
||
442 | |||
443 | // create the comment form |
||
444 | $form = new Form($this, 'CommentsForm', $fields, $actions, $required); |
||
445 | |||
446 | // if the record exists load the extra required data |
||
447 | if($record = $this->getOwnerRecord()) { |
||
448 | |||
449 | // Load member data |
||
450 | $member = Member::currentUser(); |
||
451 | if(($record->CommentsRequireLogin || $record->PostingRequiredPermission) && $member) { |
||
452 | $fields = $form->Fields(); |
||
453 | |||
454 | $fields->removeByName('Name'); |
||
455 | $fields->removeByName('Email'); |
||
456 | $fields->insertBefore(new ReadonlyField("NameView", _t('CommentInterface.YOURNAME', 'Your name'), $member->getName()), 'URL'); |
||
457 | $fields->push(new HiddenField("Name", "", $member->getName())); |
||
458 | $fields->push(new HiddenField("Email", "", $member->Email)); |
||
459 | } |
||
460 | |||
461 | // we do not want to read a new URL when the form has already been submitted |
||
462 | // which in here, it hasn't been. |
||
463 | $form->loadDataFrom(array( |
||
464 | 'ParentID' => $record->ID, |
||
465 | 'ReturnURL' => $this->request->getURL(), |
||
466 | 'BaseClass' => $this->getBaseClass() |
||
467 | )); |
||
468 | } |
||
469 | |||
470 | // Set it so the user gets redirected back down to the form upon form fail |
||
471 | $form->setRedirectToFormOnValidationError(true); |
||
472 | |||
473 | // load any data from the cookies |
||
474 | if($data = Cookie::get('CommentsForm_UserData')) { |
||
475 | $data = Convert::json2array($data); |
||
476 | |||
477 | $form->loadDataFrom(array( |
||
478 | "Name" => isset($data['Name']) ? $data['Name'] : '', |
||
479 | "URL" => isset($data['URL']) ? $data['URL'] : '', |
||
480 | "Email" => isset($data['Email']) ? $data['Email'] : '' |
||
481 | )); |
||
482 | // allow previous value to fill if comment not stored in cookie (i.e. validation error) |
||
483 | $prevComment = Cookie::get('CommentsForm_Comment'); |
||
484 | if($prevComment && $prevComment != ''){ |
||
0 ignored issues
–
show
|
|||
485 | $form->loadDataFrom(array("Comment" => $prevComment)); |
||
486 | } |
||
487 | } |
||
488 | |||
489 | if(!empty($member)) { |
||
490 | $form->loadDataFrom($member); |
||
491 | } |
||
492 | |||
493 | // hook to allow further extensions to alter the comments form |
||
494 | $this->extend('alterCommentForm', $form); |
||
495 | |||
496 | return $form; |
||
497 | } |
||
498 | |||
499 | /** |
||
500 | * Process which creates a {@link Comment} once a user submits a comment from this form. |
||
501 | * |
||
502 | * @param array $data |
||
503 | * @param Form $form |
||
504 | */ |
||
505 | public function doPostComment($data, $form) { |
||
506 | // Load class and parent from data |
||
507 | if(isset($data['BaseClass'])) { |
||
508 | $this->setBaseClass($data['BaseClass']); |
||
509 | } |
||
510 | if(isset($data['ParentID']) && ($class = $this->getBaseClass())) { |
||
511 | $this->setOwnerRecord($class::get()->byID($data['ParentID'])); |
||
512 | } |
||
513 | if(!$this->getOwnerRecord()) return $this->httpError(404); |
||
514 | |||
515 | // cache users data |
||
516 | Cookie::set("CommentsForm_UserData", Convert::raw2json($data)); |
||
517 | Cookie::set("CommentsForm_Comment", $data['Comment']); |
||
518 | |||
519 | // extend hook to allow extensions. Also see onAfterPostComment |
||
520 | $this->extend('onBeforePostComment', $form); |
||
521 | |||
522 | // If commenting can only be done by logged in users, make sure the user is logged in |
||
523 | if(!$this->getOwnerRecord()->canPostComment()) { |
||
524 | return Security::permissionFailure( |
||
525 | $this, |
||
526 | _t( |
||
527 | 'CommentingController.PERMISSIONFAILURE', |
||
528 | "You're not able to post comments to this page. Please ensure you are logged in and have an " |
||
529 | . "appropriate permission level." |
||
530 | ) |
||
531 | ); |
||
532 | } |
||
533 | |||
534 | if($member = Member::currentUser()) { |
||
535 | $form->Fields()->push(new HiddenField("AuthorID", "Author ID", $member->ID)); |
||
536 | } |
||
537 | |||
538 | // What kind of moderation is required? |
||
539 | switch($this->getOwnerRecord()->ModerationRequired) { |
||
540 | case 'Required': |
||
541 | $requireModeration = true; |
||
542 | break; |
||
543 | case 'NonMembersOnly': |
||
544 | $requireModeration = empty($member); |
||
545 | break; |
||
546 | case 'None': |
||
547 | default: |
||
548 | $requireModeration = false; |
||
549 | break; |
||
550 | } |
||
551 | |||
552 | $comment = new Comment(); |
||
553 | $form->saveInto($comment); |
||
554 | |||
555 | $comment->AllowHtml = $this->getOption('html_allowed'); |
||
556 | $comment->Moderated = !$requireModeration; |
||
557 | |||
558 | // Save into DB, or call pre-save hooks to give accurate preview |
||
559 | $usePreview = $this->getOption('use_preview'); |
||
560 | $isPreview = $usePreview && !empty($data['IsPreview']); |
||
561 | if($isPreview) { |
||
562 | $comment->extend('onBeforeWrite'); |
||
563 | } else { |
||
564 | $comment->write(); |
||
565 | |||
566 | // extend hook to allow extensions. Also see onBeforePostComment |
||
567 | $this->extend('onAfterPostComment', $comment); |
||
568 | } |
||
569 | |||
570 | // we want to show a notification if comments are moderated |
||
571 | if ($requireModeration && !$comment->IsSpam) { |
||
572 | Session::set('CommentsModerated', 1); |
||
573 | } |
||
574 | |||
575 | // clear the users comment since it passed validation |
||
576 | Cookie::set('CommentsForm_Comment', false); |
||
577 | |||
578 | // Find parent link |
||
579 | if(!empty($data['ReturnURL'])) { |
||
580 | $url = $data['ReturnURL']; |
||
581 | } elseif($parent = $comment->getParent()) { |
||
582 | $url = $parent->Link(); |
||
583 | } else { |
||
584 | return $this->redirectBack(); |
||
585 | } |
||
586 | |||
587 | // Given a redirect page exists, attempt to link to the correct anchor |
||
588 | if($comment->IsSpam) { |
||
589 | // Link to the form with the error message contained |
||
590 | $hash = $form->FormName(); |
||
591 | } else if(!$comment->Moderated) { |
||
592 | // Display the "awaiting moderation" text |
||
593 | $holder = $this->getOption('comments_holder_id'); |
||
594 | $hash = "{$holder}_PostCommentForm_error"; |
||
595 | } else { |
||
596 | // Link to the moderated, non-spam comment |
||
597 | $hash = $comment->Permalink(); |
||
598 | } |
||
599 | |||
600 | return $this->redirect(Controller::join_links($url, "#{$hash}")); |
||
601 | } |
||
602 | |||
603 | public function doPreviewComment($data, $form) { |
||
604 | $data['IsPreview'] = 1; |
||
605 | |||
606 | return $this->doPostComment($data, $form); |
||
607 | } |
||
608 | |||
609 | public function redirectBack() { |
||
610 | // Don't cache the redirect back ever |
||
611 | HTTP::set_cache_age(0); |
||
612 | |||
613 | $url = null; |
||
614 | |||
615 | // In edge-cases, this will be called outside of a handleRequest() context; in that case, |
||
616 | // redirect to the homepage - don't break into the global state at this stage because we'll |
||
617 | // be calling from a test context or something else where the global state is inappropraite |
||
618 | if($this->request) { |
||
619 | if($this->request->requestVar('BackURL')) { |
||
620 | $url = $this->request->requestVar('BackURL'); |
||
621 | } else if($this->request->isAjax() && $this->request->getHeader('X-Backurl')) { |
||
622 | $url = $this->request->getHeader('X-Backurl'); |
||
623 | } else if($this->request->getHeader('Referer')) { |
||
624 | $url = $this->request->getHeader('Referer'); |
||
625 | } |
||
626 | } |
||
627 | |||
628 | if(!$url) $url = $this->fallbackReturnURL; |
||
629 | if(!$url) $url = Director::baseURL(); |
||
630 | |||
631 | // absolute redirection URLs not located on this site may cause phishing |
||
632 | if(Director::is_site_url($url)) { |
||
633 | return $this->redirect($url); |
||
634 | } else { |
||
635 | return false; |
||
636 | } |
||
637 | |||
638 | } |
||
639 | } |
||
640 |
In PHP, under loose comparison (like
==
, or!=
, orswitch
conditions), values of different types might be equal.For
string
values, the empty string''
is a special case, in particular the following results might be unexpected: