Issues (2002)

Security Analysis    not enabled

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.

code/OrderConfirmationPage.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
/**
4
 * @description:
5
 * The Order Confirmation page shows order history.
6
 * It also serves as the end point for the current order...
7
 * once submitted, the Order Confirmation page shows the
8
 * finalised detail of the order.
9
 *
10
 *
11
 * @authors: Nicolaas [at] Sunny Side Up .co.nz
12
 * @package: ecommerce
13
 * @sub-package: Pages
14
 * @inspiration: Silverstripe Ltd, Jeremy
15
 **/
16
class OrderConfirmationPage extends CartPage
17
{
18
    /**
19
     * Standard SS variable.
20
     *
21
     * @var string
22
     */
23
    private static $icon = 'ecommerce/images/icons/OrderConfirmationPage';
24
25
    /**
26
     * Standard SS variable.
27
     *
28
     * @var array
29
     */
30
    private static $db = array(
31
        'StartNewOrderLinkLabel' => 'Varchar(100)',
32
        'CopyOrderLinkLabel' => 'Varchar(100)',
33
        'OrderCancelledHeader' => 'Varchar(255)',
34
        'PaymentSuccessfulHeader' => 'Varchar(255)',
35
        'PaymentNotSuccessfulHeader' => 'Varchar(255)',
36
        'PaymentPendingHeader' => 'Varchar(255)',
37
        'OrderCancelledMessage' => 'HTMLText',
38
        'PaymentSuccessfulMessage' => 'HTMLText',
39
        'PaymentNotSuccessfulMessage' => 'HTMLText',
40
        'PaymentPendingMessage' => 'HTMLText',
41
        'EnableGoogleAnalytics' => 'Boolean',
42
        'IsFeedbackEnabled' => 'Boolean',
43
        'FeedbackFormLinkText' => 'Varchar(255)',
44
        'FeedbackHeader' => 'Varchar(255)',
45
        'FeedbackValuesFieldLabel' => 'Varchar(255)',
46
        'FeedbackValuesOptions' => 'Text',
47
        'FeedbackNotesFieldLabel' => 'Varchar(255)',
48
        'FeedbackFormSubmitLabel' => 'Varchar(255)',
49
        'FeedbackFormThankYou' => 'Varchar(255)'
50
    );
51
52
    /**
53
     * Standard SS variable.
54
     *
55
     * @var array
56
     */
57
    private static $defaults = array(
58
        'ShowInMenus' => false,
59
        'ShowInSearch' => false,
60
        'StartNewOrderLinkLabel' => 'start new order',
61
        'CopyOrderLinkLabel' => 'copy order items into a new order',
62
        'OrderCancelledHeader' => 'Order has been cancelled',
63
        'PaymentSuccessfulHeader' => 'Payment Successful',
64
        'PaymentNotSuccessfulHeader' => 'Payment not Completed',
65
        'PaymentPendingHeader' => 'Payment Pending',
66
        'OrderCancelledMessage' => '<p>This order is no longer valid.</p>',
67
        'PaymentSuccessfulMessage' => '<p>Your order will be processed.</p>',
68
        'PaymentNotSuccessfulMessage' => '<p>Your order will not be processed until your payment has been completed.</p>',
69
        'PaymentPendingMessage' => '<p>Please complete your payment before the order can be processed.</p>',
70
        'FeedbackHeader' => 'Feedback',
71
        'FeedbackValuesFieldLabel' => 'How likely are you to recommend us to your friends?',
72
        'FeedbackValuesOptions' => 'Not At All, Not Likely, Not Sure, Likely, Very Likely',
73
        'FeedbackNotesFieldLabel' => 'What can we do to improve the ordering experience?',
74
        'FeedbackFormSubmitLabel' => 'Submit Your Feedback',
75
        'FeedbackFormThankYou' => 'Thank you for taking the time to submit your feedback, we appreciate it!'
76
    );
77
78
    private static $casting = array(
79
        "PaymentMessage" => "HTMLText"
80
    );
81
82
    /**
83
     * standard SS variable.
84
     *
85
     * @Var String
86
     */
87
    private static $singular_name = 'Order Confirmation Page';
88
    public function i18n_singular_name()
89
    {
90
        return _t('OrderConfirmationpage.SINGULARNAME', 'Order Confirmation Page');
91
    }
92
93
    /**
94
     * standard SS variable.
95
     *
96
     * @Var String
97
     */
98
    private static $plural_name = 'Order Confirmation Pages';
99
    public function i18n_plural_name()
100
    {
101
        return _t('OrderConfirmationpage.PLURALNAME', 'Order Confirmation Pages');
102
    }
103
104
    /**
105
     * Standard SS variable.
106
     *
107
     * @var string
108
     */
109
    private static $description = 'A page where the customer can view her or his submitted order. Every e-commerce site needs an Order Confirmation Page.';
110
111
    /**
112
     * Standard SS function, we only allow for one OrderConfirmation Page to exist
113
     * but we do allow for extensions to exist at the same time.
114
     *
115
     * @param Member $member
116
     *
117
     * @return bool
118
     */
119
    public function canCreate($member = null)
120
    {
121
        return OrderConfirmationPage::get()->filter(array('ClassName' => 'OrderConfirmationPage'))->Count() ? false : $this->canEdit($member);
122
    }
123
124
    /**
125
     * Shop Admins can edit.
126
     *
127
     * @param Member $member
128
     *
129
     * @return bool
130
     */
131
    public function canEdit($member = null)
132
    {
133
        if (Permission::checkMember($member, Config::inst()->get('EcommerceRole', 'admin_permission_code'))) {
134
            return true;
135
        }
136
137
        return parent::canEdit($member);
138
    }
139
140
    /**
141
     * Standard SS method.
142
     *
143
     * @param Member $member
144
     *
145
     * @return bool
146
     */
147
    public function canDelete($member = null)
148
    {
149
        return false;
150
    }
151
152
    /**
153
     * Standard SS method.
154
     *
155
     * @param Member $member
156
     *
157
     * @return bool
158
     */
159
    public function canPublish($member = null)
160
    {
161
        return $this->canEdit($member);
162
    }
163
164
    public function customFieldLabels()
165
    {
166
        $newLabels = array(
167
            'StartNewOrderLinkLabel' => _t('OrderConfirmationPage.STARTNEWORDERLINKLABEL', 'Label for starting new order - e.g. click here to start new order.'),
168
            'CopyOrderLinkLabel' => _t('OrderConfirmationPage.COPYORDERLINKLABEL', 'Label for copying order items into a new one  - e.g. click here start a new order with the current order items.'),
169
            'OrderCancelledHeader' => _t('OrderConfirmationPage.ORDERCANCELLEDHEADER', 'Header showing when order has been cancelled.'),
170
            'PaymentSuccessfulHeader' => _t('OrderConfirmationPage.PAYMENTSUCCESSFULHEADER', 'Header showing when order has been paid in full.'),
171
            'PaymentNotSuccessfulHeader' => _t('OrderConfirmationPage.PAYMENTNOTSUCCESSFULHEADER', 'Header showing when the order has not been paid in full.'),
172
            'PaymentPendingHeader' => _t('OrderConfirmationPage.PAYMENTPENDINGHEADER', 'Header showing when the order has not been paid in full - but the payment is pending.'),
173
            'OrderCancelledMessage' => _t('OrderConfirmationPage.ORDERCANCELLEDMESSAGE', 'Message showing when order has been paid cancelled.'),
174
            'PaymentSuccessfulMessage' => _t('OrderConfirmationPage.PAYMENTSUCCESSFULMESSAGE', 'Message showing when order has been paid in full.'),
175
            'PaymentNotSuccessfulMessage' => _t('OrderConfirmationPage.PAYMENTNOTSUCCESSFULMESSAGE', 'Message showing when the order has not been paid in full.'),
176
            'PaymentPendingMessage' => _t('OrderConfirmationPage.PAYMENTPENDINGMESSAGE', 'Message showing when the order has not been paid in full - but the payment is pending.'),
177
            'EnableGoogleAnalytics' => _t('OrderConfirmationPage.ENABLEGOOGLEANALYTICS', 'Enable E-commerce Google Analytics.  Make sure it is turned on in your Google Analytics account.'),
178
            'IsFeedbackEnabled' => _t('OrderConfirmationPage.ISFEEDBACKENABLED', 'Enable Feedback Form'),
179
            'FeedbackHeader' => _t('OrderConfirmationPage.FEEDBACKHEADER', 'Feedback Form Header'),
180
            'FeedbackValuesFieldLabel' => _t('OrderConfirmationPage.FEEDBACKVALUESFIELDLABEL', 'Feedback Form Options Label'),
181
            'FeedbackValuesOptions' => _t('OrderConfirmationPage.FEEDBACKVALUESOPTIONS', 'Feedback Form Options'),
182
            'FeedbackNotesFieldLabel' => _t('OrderConfirmationPage.FEEDBACKVALUESFIELDLABEL', 'Feedback Form Notes Label'),
183
            'FeedbackFormSubmitLabel' => _t('OrderConfirmationPage.FEEDBACKFORMSUBMITLABEL', 'Feedback Form Submit Button Text'),
184
            'FeedbackFormThankYou' => _t('OrderConfirmationPage.FEEDBACKFORMTHANKYOU', 'Feedback Form Thank you Message')
185
        );
186
187
        return $newLabels;
188
    }
189
190
    /**
191
     * standard SS method for decorators.
192
     *
193
     * @param bool - $includerelations: array of fields to start with
194
     *
195
     * @return array
196
     */
197
    public function fieldLabels($includerelations = true)
198
    {
199
        $defaultLabels = parent::fieldLabels();
200
        $newLabels = $this->customFieldLabels();
201
        $labels = array_merge($defaultLabels, $newLabels);
202
        $extendedArray = $this->extend('updateFieldLabels', $labels);
203
        if ($extendedArray !== null && is_array($extendedArray) && count($extendedArray)) {
204
            foreach ($extendedArray as $extendedResult) {
205
                $labels = array_merge($labels, $extendedResult);
206
            }
207
        }
208
209
        return $labels;
210
    }
211
212
    /**
213
     *@return FieldList
214
     **/
215
    public function getCMSFields()
216
    {
217
        $fields = parent::getCMSFields();
218
        $fields->removeFieldFromTab('Root.Messages.Messages.Actions', 'ProceedToCheckoutLabel');
219
        $fields->removeFieldFromTab('Root.Messages.Messages.Actions', 'ContinueShoppingLabel');
220
        $fields->removeFieldFromTab('Root.Messages.Messages.Actions', 'ContinuePageID');
221
        $fields->removeFieldFromTab('Root.Messages.Messages.Actions', 'SaveOrderLinkLabel');
222
        $fields->removeFieldFromTab('Root.Messages.Messages.Errors', 'NoItemsInOrderMessage');
223
        $fieldLabels = $this->fieldLabels();
224
        $fields->addFieldToTab('Root.Messages.Messages.Actions', TextField::create('StartNewOrderLinkLabel', $fieldLabels['StartNewOrderLinkLabel']));
225
        $fields->addFieldToTab('Root.Messages.Messages.Actions', TextField::create('CopyOrderLinkLabel', $fieldLabels['CopyOrderLinkLabel']));
226
        $fields->addFieldsToTab('Root.Messages.Messages.Payment', array(
227
            HeaderField::create('Successful'),
228
            TextField::create('PaymentSuccessfulHeader', $fieldLabels['PaymentSuccessfulHeader']),
229
            HTMLEditorField::create('PaymentSuccessfulMessage', $fieldLabels['PaymentSuccessfulMessage'])->setRows(3),
230
            HeaderField::create('Unsuccessful'),
231
            TextField::create('PaymentNotSuccessfulHeader', $fieldLabels['PaymentNotSuccessfulHeader']),
232
            HTMLEditorField::create('PaymentNotSuccessfulMessage', $fieldLabels['PaymentNotSuccessfulMessage'])->setRows(3),
233
            HeaderField::create('Pending'),
234
            TextField::create('PaymentPendingHeader', $fieldLabels['PaymentPendingHeader']),
235
            HTMLEditorField::create('PaymentPendingMessage', $fieldLabels['PaymentPendingMessage'])->setRows(3),
236
            HeaderField::create('Cancelled'),
237
            TextField::create('OrderCancelledHeader', $fieldLabels['OrderCancelledHeader']),
238
            HTMLEditorField::create('OrderCancelledMessage', $fieldLabels['OrderCancelledMessage'])->setRows(3),
239
        ));
240
        $fields->addFieldToTab('Root.Analytics', CheckboxField::create('EnableGoogleAnalytics', $fieldLabels['EnableGoogleAnalytics']));
241
        if ($this->IsFeedbackEnabled) {
242
            $fields->addFieldsToTab(
243
                'Root.FeedbackForm',
244
                array(
245
                    CheckboxField::create('IsFeedbackEnabled', $fieldLabels['IsFeedbackEnabled'])
246
                        ->setDescription(_t('OrderConfirmationPage.IsFeedbackEnabled_RIGHT', 'Enabling this option will display a feedback form on the order confirmation page and include links to the form in all order emails')),
247
                    TextField::create('FeedbackHeader', $fieldLabels['FeedbackHeader'])
248
                        ->setRightTitle(_t('OrderConfirmationPage.FeedbackHeader_RIGHT', 'e.g. Please let us know what you think')),
249
                    TextField::create('FeedbackValuesFieldLabel', $fieldLabels['FeedbackValuesFieldLabel'])
250
                        ->setRightTitle(_t('OrderConfirmationPage.FeedbackValuesFieldLabel_RIGHT', 'e.g. Please rate our service')),
251
                    TextField::create('FeedbackValuesOptions', $fieldLabels['FeedbackValuesOptions'])
252
                        ->setRightTitle(_t('OrderConfirmationPage.FeedbackValuesOptions_RIGHT', 'Comma separated list of feedback rating options (eg Good, Neutral, Bad)')),
253
                    TextField::create('FeedbackNotesFieldLabel', $fieldLabels['FeedbackNotesFieldLabel'])
254
                        ->setRightTitle(_t('OrderConfirmationPage.FeedbackNotesFieldLabel_RIGHT', 'e.g. Please add any comments')),
255
                    TextField::create('FeedbackFormSubmitLabel', $fieldLabels['FeedbackFormSubmitLabel'])
256
                        ->setRightTitle(_t('OrderConfirmationPage.FeedbackFormSubmitLabel_RIGHT', 'e.g. Submit Feedback Now')),
257
                    TextField::create('FeedbackFormThankYou', $fieldLabels['FeedbackFormThankYou'])
258
                        ->setRightTitle(_t('OrderConfirmationPage.FeedbackFormThankYou_RIGHT', 'Thank you message displayed to user after submitting the feedback form'))
259
                )
260
            );
261
        } else {
262
            $fields->addFieldsToTab(
263
                'Root.FeedbackForm',
264
                array(
265
                    CheckboxField::create('IsFeedbackEnabled', $fieldLabels['IsFeedbackEnabled'])
266
                        ->setDescription('Enabling this option will display a feedback form on the order confirmation page and include links to the form in all order emails')
267
                )
268
            );
269
        }
270
        return $fields;
271
    }
272
273
    /**
274
     * Returns the link or the Link to the OrderConfirmationPage page on this site.
275
     * @param string $action [optional]
276
     * @return string (URLSegment)
277
     */
278
    public static function find_link($action = null)
279
    {
280
        if ($page = DataObject::get_one('OrderConfirmationPage', array('ClassName' => 'OrderConfirmationPage'))) {
281
            return $page->Link($action);
282
        } elseif ($page = DataObject::get_one('OrderConfirmationPage')) {
283
            return $page->Link($action);
284
        }
285
286
        return CartPage::find_link();
287
    }
288
289
    /**
290
     * Return a link to view the order on this page.
291
     *
292
     * @param int|string $orderID ID of the order
293
     *
294
     * @return string (URLSegment)
295
     */
296
    public static function get_order_link($orderID)
297
    {
298
        return OrderConfirmationPage::find_link().'showorder/'.$orderID.'/';
299
    }
300
301
    /**
302
     * Return a link to view the order on this page.
303
     *
304
     * @param int|string $orderID                ID of the order
305
     * @param string     $type                   - the type of email you want to send.
306
     * @param bool       $actuallySendEmail      - do we actually send the email
307
     * @param int        $alternativeOrderStepID - OrderStep to use
308
     *
309
     * @return string (URLSegment)
310
     */
311
    public static function get_email_link($orderID, $emailClassName = 'Order_StatusEmail', $actuallySendEmail = false, $alternativeOrderStepID = 0)
312
    {
313
        $link = OrderConfirmationPage::find_link().'sendemail/'.$orderID.'/'.$emailClassName;
314
        $getParams = array();
315
        if ($actuallySendEmail) {
316
            $getParams['send'] = 1;
317
        }
318
        if ($alternativeOrderStepID) {
319
            $getParams['test'] = $alternativeOrderStepID;
320
        }
321
        $getParams = http_build_query($getParams);
322
        $link .= '?'.$getParams;
323
324
        return $link;
325
    }
326
327
    /**
328
     * Return a link to view the order on this page.
329
     *
330
     * @param int|string $orderID ID of the order
331
     *
332
     * @return string (URLSegment)
333
     */
334
    public function getOrderLink($orderID)
335
    {
336
        return OrderConfirmationPage::get_order_link($orderID);
337
    }
338
339
    /**
340
     * returns the Checkout_StepDescription assocatiated with the final step: the order confirmation.
341
     *
342
     * @param bool $isCurrentStep
343
     *
344
     * @return Checkout_StepDescription
345
     */
346
    public function CurrentCheckoutStep($isCurrentStep = false)
347
    {
348
        $do = new CheckoutPage_StepDescription();
349
        $do->Link = $this->Link;
350
        $do->Heading = $this->MenuTitle;
351
        $do->Code = $this->URLSegment;
352
        $do->LinkingMode = 'notCompleted';
353
        if ($isCurrentStep) {
354
            $do->LinkingMode .= ' current';
355
        }
356
        $do->Completed = 0;
357
        $do->ID = 99;
358
359
        return $do;
360
    }
361
362
    /**
363
     * standard SS method for use in templates
364
     * we are overriding the code from the Cart Page here.
365
     *
366
     * @return string
367
     */
368
    public function LinkingMode()
369
    {
370
        return parent::LinkingMode();
371
    }
372
373
    /**
374
     * standard SS method for use in templates
375
     * we are overriding the code from the Cart Page here.
376
     *
377
     * @return string
378
     */
379
    public function LinkOrSection()
380
    {
381
        return parent::LinkOrSection();
382
    }
383
384
    /**
385
     * standard SS method for use in templates
386
     * we are overriding the code from the Cart Page here.
387
     *
388
     * @return string
389
     */
390
    public function LinkOrCurrent()
391
    {
392
        return parent::LinkOrCurrent();
393
    }
394
395
    public function requireDefaultRecords()
396
    {
397
        parent::requireDefaultRecords();
398
        $checkoutPage = DataObject::get_one('CheckoutPage');
399
        if ($checkoutPage) {
400
            $orderConfirmationPage = DataObject::get_one('OrderConfirmationPage');
401
            if (!$orderConfirmationPage) {
402
                $orderConfirmationPage = OrderConfirmationPage::create();
403
                $orderConfirmationPage->Title = 'Order Confirmation';
404
                $orderConfirmationPage->MenuTitle = 'Order Confirmation';
405
                $orderConfirmationPage->URLSegment = 'order-confirmation';
406
                $orderConfirmationPage->writeToStage('Stage');
407
                $orderConfirmationPage->publish('Stage', 'Live');
408
            }
409
        }
410
    }
411
}
412
413
class OrderConfirmationPage_Controller extends CartPage_Controller
414
{
415
    /**
416
     * @static array
417
     * standard SS variable
418
     * it is important that we list all the options here
419
     */
420
    private static $allowed_actions = array(
421
        'saveorder',
422
        'CreateAccountForm',
423
        'retrieveorder',
424
        'loadorder',
425
        'startneworder',
426
        'showorder',
427
        'copyorder',
428
        'sendemail',
429
        'CancelForm',
430
        'FeedbackForm',
431
        'PaymentForm',
432
    );
433
434
    /**
435
     * standard controller function.
436
     **/
437
    public function init()
438
    {
439
        //we retrieve the order in the parent page
440
        //the parent page also takes care of the security
441
        if ($sessionOrderID = Session::get('CheckoutPageCurrentOrderID')) {
442
            $this->currentOrder = Order::get()->byID($sessionOrderID);
443
            if ($this->currentOrder) {
444
                $this->overrideCanView = true;
445
                //more than an hour has passed...
446
                $validUntil = intval(Session::get('CheckoutPageCurrentRetrievalTime')) - 0;
447
                if ($validUntil < time()) {
448
                    $this->clearRetrievalOrderID();
449
                    $this->overrideCanView = false;
450
                    $this->currentOrder = null;
451
                }
452
            }
453
        }
454
        parent::init();
455
        Requirements::themedCSS('Order', 'ecommerce');
456
        Requirements::themedCSS('Order_Print', 'ecommerce', 'print');
457
        Requirements::themedCSS('CheckoutPage', 'ecommerce');
458
        Requirements::javascript('ecommerce/javascript/EcomPayment.js');
459
        Requirements::javascript('ecommerce/javascript/EcomPrintAndMail.js');
460
        $this->includeGoogleAnalyticsCode();
461
    }
462
463
    /**
464
     * This method exists just so that template
465
     * sets CurrentOrder variable.
466
     *
467
     * @param HTTPRequest
468
     *
469
     * @return array
470
     **/
471
    public function showorder(SS_HTTPRequest $request)
472
    {
473
        isset($project) ? $themeBaseFolder = $project : $themeBaseFolder = 'mysite';
474
        if (isset($_REQUEST['print'])) {
475
            Requirements::clear();
476
            Requirements::themedCSS('typography', $themeBaseFolder); // LEAVE HERE - NOT EASY TO INCLUDE VIA TEMPLATE
477
            Requirements::themedCSS('OrderReport', 'ecommerce'); // LEAVE HERE - NOT EASY TO INCLUDE VIA TEMPLATE
478
            Requirements::themedCSS('Order_Invoice', 'ecommerce'); // LEAVE HERE - NOT EASY TO INCLUDE VIA TEMPLATE
479
            Requirements::themedCSS('Order_Invoice_Print_Only', 'ecommerce', 'print'); // LEAVE HERE - NOT EASY TO INCLUDE VIA TEMPLATE
480
            Config::nest();
481
            Config::inst()->update('SSViewer', 'theme_enabled', true);
482
            $html = $this->renderWith('Invoice');
483
            Config::unnest();
484
485
            return $html;
486
        } elseif (isset($_REQUEST['packingslip'])) {
487
            Requirements::clear();
488
            Requirements::themedCSS('typography', $themeBaseFolder); // LEAVE HERE - NOT EASY TO INCLUDE VIA TEMPLATE
489
            Requirements::themedCSS('OrderReport', 'ecommerce'); // LEAVE HERE - NOT EASY TO INCLUDE VIA TEMPLATE
490
            Requirements::themedCSS('Order_PackingSlip', 'ecommerce'); // LEAVE HERE - NOT EASY TO INCLUDE VIA TEMPLATE
491
            Config::nest();
492
            Config::inst()->update('SSViewer', 'theme_enabled', true);
493
            $html = $this->renderWith('PackingSlip');
494
            Config::unnest();
495
496
            return $html;
497
        }
498
499
        return array();
500
    }
501
502
    /**
503
     * This is an additional way to look at an order.
504
     * The order is already retrieved from the init function.
505
     *
506
     * @return array
507
     **/
508
    public function retrieveorder(SS_HTTPRequest $request)
509
    {
510
        return array();
511
    }
512
513
    /**
514
     * copies either the current order into the shopping cart.
515
     *
516
     * TO DO: untested
517
     * TO DO: what to do with old order
518
     *
519
     * @param SS_HTTPRequest
520
     *
521
     * @return array
522
     */
523
    public function copyorder(SS_HTTPRequest $request)
524
    {
525
        self::set_message(_t('CartPage.ORDERLOADED', 'Order has been loaded.'));
526
        ShoppingCart::singleton()->copyOrder($this->currentOrder->ID);
527
528
        return $this->redirect(CheckoutPage::find_link());
529
    }
530
531
    /**
532
     * Returns a dataobject set of the checkout steps if
533
     * the OrderConfirmationPage is shown as part of the checkout process
534
     * We repeat these here so that you can show the user that (s)he has reached the last step.
535
     *
536
     * @param int $number - if set, it returns that one step.
537
     */
538
    public function CheckoutSteps($number = 0)
539
    {
540
        $where = '';
541
        if ($number) {
542
            $where = "\"CheckoutPage_StepDescription\".\"ID\" = $number";
543
        }
544
        if (EcommerceConfig::get('OrderConfirmationPage_Controller', 'include_as_checkout_step')) {
545
            if ($this->currentOrder->IsInSession()) {
546
                $dos = CheckoutPage_StepDescription::get()->where($where)->sort('ID', 'ASC');
547
                if ($number) {
548
                    if ($dos && $dos->count()) {
549
                        return $dos->First();
550
                    }
551
                }
552
                $arrayList = new ArrayList(array());
553
                foreach ($dos as $do) {
554
                    $do->LinkingMode = 'link completed';
555
                    $do->Completed = 1;
556
                    $do->Link = '';
557
                    $arrayList->push($do);
558
                }
559
                $do = $this->CurrentCheckoutStep(true);
560
                if ($do) {
561
                    $arrayList->push($do);
562
                }
563
564
                return $arrayList;
565
            }
566
        }
567
    }
568
569
    /**
570
     * returns the percentage of checkout steps done (0 - 100).
571
     *
572
     * @return int
573
     */
574
    public function PercentageDone()
575
    {
576
        return 100;
577
    }
578
579
    /**
580
     * @return string
581
     */
582
    public function PaymentHeader()
583
    {
584
        if ($order = $this->Order()) {
585
            if ($this->OrderIsCancelled()) {
586
                return $this->OrderCancelledHeader;
587
            } elseif ($this->PaymentIsPending()) {
588
                return $this->PaymentPendingHeader;
589
            } elseif ($this->IsPaid()) {
590
                return $this->PaymentSuccessfulHeader;
591
            } else {
592
                return $this->PaymentNotSuccessfulHeader;
593
            }
594
        }
595
    }
596
597
    /**
598
     * @return string | null
599
     */
600
    public function PaymentMessage()
601
    {
602
        if ($order = $this->Order()) {
603
            if ($this->OrderIsCancelled()) {
604
                return $this->OrderCancelledMessage;
605
            } elseif ($this->PaymentIsPending()) {
606
                return $this->PaymentPendingMessage;
607
            } elseif ($this->IsPaid()) {
608
                return $this->PaymentSuccessfulMessage;
609
            } else {
610
                return $this->PaymentNotSuccessfulMessage;
611
            }
612
        }
613
    }
614
615
    /**
616
     * @return string | null
617
     */
618
    public function PaymentMessageType()
619
    {
620
        if ($order = $this->Order()) {
621
            if ($this->OrderIsCancelled()) {
622
                return "bad";
623
            } elseif ($this->PaymentIsPending()) {
624
                return "warning";
625
            } elseif ($this->IsPaid()) {
626
                return "good";
627
            } else {
628
                return "bad";
629
            }
630
        }
631
    }
632
633
    /**
634
     * @return bool
635
     */
636
    public function OrderIsCancelled()
637
    {
638
        if ($order = $this->Order()) {
639
            return $order->getIsCancelled();
640
        }
641
    }
642
643
    /**
644
     * Is the Order paid?
645
     * This can be useful for choosing what header to show.
646
     *
647
     * @return bool
648
     */
649
    public function IsPaid()
650
    {
651
        if ($order = $this->Order()) {
652
            return $order->IsPaid();
653
        }
654
    }
655
656
    /**
657
     * Are there any order Payments Pending
658
     * This can be useful for choosing what header to show.
659
     *
660
     * @return bool
661
     */
662
    public function PaymentIsPending()
663
    {
664
        if ($order = $this->Order()) {
665
            return $order->PaymentIsPending();
666
        }
667
    }
668
669
    /**
670
     * Returns the form to cancel the current order,
671
     * checking to see if they can cancel their order
672
     * first of all.
673
     *
674
     * @return OrderForm_Cancel
675
     */
676
    public function CancelForm()
677
    {
678
        if ($this->Order()) {
679
            if ($this->currentOrder->canCancel()) {
680
                return OrderForm_Cancel::create($this, 'CancelForm', $this->currentOrder);
681
            }
682
        }
683
        //once cancelled, you will be redirected to main page - hence we need this...
684
        if ($this->orderID) {
685
            return array();
686
        }
687
    }
688
689
    /**
690
     * Returns the form for providing feedback about current order,
691
     * checking to see if IsFeedbackEnabled is true
692
     * first of all.
693
     *
694
     * @return OrderForm_Feedback
0 ignored issues
show
Should the return type not be OrderConfirmationPage_Controller|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...
695
     */
696
    public function FeedbackForm()
697
    {
698
        if ($this->Order()) {
699
            if ($this->IsFeedbackEnabled) {
700
                return OrderForm_Feedback::create($this, 'FeedbackForm', $this->currentOrder);
701
            }
702
        }
703
    }
704
705
    /**
706
     * show the payment form.
707
     *
708
     * @return Form (OrderForm_Payment) or Null
709
     **/
710
    public function PaymentForm()
711
    {
712
        if ($this->currentOrder) {
713
            if ($this->currentOrder->canPay()) {
714
                Requirements::javascript('ecommerce/javascript/EcomPayment.js');
715
716
                return OrderForm_Payment::create($this, 'PaymentForm', $this->currentOrder);
717
            }
718
        }
719
720
        return array();
721
    }
722
723
    /**
724
     * Can this page only show Submitted Orders (e.g. OrderConfirmationPage) ?
725
     *
726
     * @return bool
727
     */
728
    protected function onlyShowSubmittedOrders()
729
    {
730
        return true;
731
    }
732
733
    /**
734
     * Can this page only show Unsubmitted Orders (e.g. CartPage) ?
735
     *
736
     * @return bool
737
     */
738
    protected function onlyShowUnsubmittedOrders()
739
    {
740
        return false;
741
    }
742
743
    /**
744
     * sends an order email, which can be specified in the URL
745
     * and displays a sample email
746
     * typically this link is opened in a new window.
747
     *
748
     * @param SS_HTTPRequest $request
749
     *
750
     * @return HTML
751
     **/
752
    public function sendemail(SS_HTTPRequest $request)
753
    {
754
        if ($this->currentOrder) {
755
            $subject = '';
756
            $message = '';
757
            $emailClassName = 'Order_ReceiptEmail';
758
            if (class_exists($request->param('OtherID'))) {
759
                if (is_a(singleton($request->param('OtherID')), Object::getCustomClass('Order_Email'))) {
760
                    $emailClassName = $request->param('OtherID');
761
                }
762
            }
763
            if ($statusID = intval($request->getVar('test'))) {
764
                $step = OrderStep::get()->byID($statusID);
765
                $subject = $step->CalculatedEmailSubject($this->currentOrder);
766
                $message = $step->CalculatedCustomerMessage($this->currentOrder);
767
                if ($step) {
768
                    $emailClassName = $step->getEmailClassName();
769
                }
770
                if ($request->getVar('send')) {
771
                    $email = filter_var($request->getVar('send'), FILTER_SANITIZE_EMAIL);
772
                    if (! $email) {
773
                        $email = true;
774
                    }
775
                    $this->currentOrder->sendEmail(
776
                        $emailClassName,
777
                        _t('Account.TEST_ONLY', '--- TEST ONLY ---') . ' ' . $subject,
778
                        $message,
779
                        $resend = true,
780
                        $adminOnlyOrToEmail = $email
781
                    );
782
                }
783
            } elseif ($request->getVar('send')) {
784
                if ($email = $this->currentOrder->getOrderEmail()) {
785
                    $step = OrderStep::get()->byID($this->currentOrder->StatusID);
786
                    $ecomConfig = $this->EcomConfig();
787
                    $subject = $ecomConfig->InvoiceTitle ? $ecomConfig->InvoiceTitle : _t('OrderConfirmationPage.INVOICE', 'Invoice');
788
                    $message = $ecomConfig->InvoiceMessage ? $ecomConfig->InvoiceMessage : _t('OrderConfirmationPage.MESSAGE', '<p>Thank you for your order.</p>');
789
                    $emailClassName = 'Order_InvoiceEmail';
790
                    if (
791
                        $this->currentOrder->sendEmail(
792
                            $emailClassName,
793
                            $subject,
794
                            $message,
795
                            $resend = true,
796
                            $adminOnlyOrToEmail = false
797
                        )
798
                    ) {
799
                        $message = _t('OrderConfirmationPage.RECEIPTSENT', 'An email has been sent to: ').$email.'.';
800
                    } else {
801
                        $message = _t('OrderConfirmationPage.RECEIPT_NOT_SENT', 'Email could NOT be sent to: ').$email;
802
                    }
803
                } else {
804
                    $message = _t('OrderConfirmationPage.RECEIPTNOTSENTNOEMAIL', 'No customer details found.  EMAIL NOT SENT.');
805
                }
806
            }
807
            //display same data...
808
            Requirements::clear();
809
            return $this->currentOrder->renderOrderInEmailFormat(
810
                $emailClassName,
811
                $subject,
812
                $message
813
            );
814
        } else {
815
            return _t('OrderConfirmationPage.RECEIPTNOTSENTNOORDER', 'Order could not be found.');
816
        }
817
    }
818
819
    protected function includeGoogleAnalyticsCode()
820
    {
821
        if ($this->EnableGoogleAnalytics && $this->currentOrder && (Director::isLive() || isset($_GET['testanalytics']))) {
822
            $var = EcommerceConfig::get('OrderConfirmationPage_Controller', 'google_analytics_variable');
823
            if ($var) {
824
                $currencyUsedObject = $this->currentOrder->CurrencyUsed();
825
                if ($currencyUsedObject) {
826
                    $currencyUsedString = $currencyUsedObject->Code;
827
                }
828
                if (empty($currencyUsedString)) {
829
                    $currencyUsedString = EcommerceCurrency::default_currency_code();
830
                }
831
                $js = '
832
                jQuery(document).ready(
833
                    function(){
834
                        '.$var.'(\'require\', \'ecommerce\');
835
                        '.$var.'(
836
                            \'ecommerce:addTransaction\',
837
                            {
838
                                \'id\': \''.$this->currentOrder->ID.'\',
839
                                \'revenue\': \''.$this->currentOrder->getSubTotal().'\',
840
                                \'currency\': \''.$currencyUsedString.'\'
841
                            }
842
                        );
843
                        '.$var.'(\'ecommerce:send\');
844
                    }
845
                );
846
    ';
847
                Requirements::customScript($js, 'GoogleAnalyticsEcommerce');
848
            }
849
        }
850
    }
851
}
852