Completed
Pull Request — master (#10)
by Franco
01:51
created

DMSDocumentCartCheckoutPage_Controller::send()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 26
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 21
nc 3
nop 0
1
<?php
2
/**
3
 * @property Text $ThanksMessage
4
 * @property Int  $CartEmailRecipientID
5
 *
6
 * @method Member CartEmailRecipient
7
 */
8
class DMSDocumentCartCheckoutPage extends Page
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
9
{
10
    private static $db = array(
0 ignored issues
show
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...
11
        'ThanksMessage' => 'Text',
12
    );
13
14
    private static $has_one = array(
0 ignored issues
show
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...
15
        'CartEmailRecipient'     => 'Member'
16
    );
17
18
    private static $defaults = array(
0 ignored issues
show
Unused Code introduced by
The property $defaults 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...
19
        'URLSegment'  => 'checkout',
20
        'ShowInMenus' => false,
21
    );
22
23
    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...
24
    {
25
        $fields = parent::getCMSFields();
26
        $members = Member::get('Member');
27
        $recipientDropDown = DropdownField::create(
28
            'CartEmailRecipientID',
29
            _t('DMSDocumentCartCheckoutPage.CART_RECIPIENT', 'Account to receive document print requests'),
30
            $members->Map()->toArray()
31
        )->setEmptyString(_t(
32
            'DMSDocumentCartCheckoutPage.CART_RECIPIENT_EMPTY_STRING',
33
            'Select a member'
34
        ));
35
        $fields->insertBefore('Content', $recipientDropDown);
36
37
        $fields->insertBefore(
38
            'Content',
39
            TextareaField::create(
40
                'ThanksMessage',
41
                _t('DMSDocumentCartCheckoutPage.THANK_YOU_MESSAGE', 'Thank you message')
42
            )
43
        );
44
45
        return $fields;
46
    }
47
    /**
48
     * Automatically create a CheckoutPage if one is not found
49
     * on the site at the time the database is built (dev/build).
50
     */
51
    function requireDefaultRecords()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
52
    {
53
        parent::requireDefaultRecords();
54
55
        if (!SiteTree::get_one($this->class)) {
56
            /** @var DMSDocumentCartCheckoutPage $page */
57
            $page = self::create();
58
            $page->Title = 'Request a printed copy';
59
            $page->MenuTitle = 'Document Cart Checkout';
60
            $page->Content = '';
61
            $page->URLSegment = 'checkout';
62
            $page->ShowInMenus = 0;
63
            $page->ThanksMessage = 'Thanks for your request.';
64
            $page->write();
65
            $page->publish('Stage', 'Live');
66
            $page->flushCache();
67
            DB::alteration_message(
68
                _t(
69
                    'DMSDocumentCartCheckoutPage.ALTERATION_MESSAGE',
70
                    'Document Cart Checkout page \'Request a printed copy\' created'
71
                ),
72
                'created'
73
            );
74
        }
75
    }
76
}
77
78
class DMSDocumentCartCheckoutPage_Controller extends Page_Controller
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
79
{
80
    private static $allowed_actions = array(
0 ignored issues
show
Unused Code introduced by
The property $allowed_actions 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...
81
        'DMSDocumentRequestForm'
82
    );
83
84
    /**
85
     * An array containing the recipients basic information
86
     *
87
     * @var array
88
     */
89
    public static $receiverInfo = array(
90
        'ReceiverName'            => '',
91
        'ReceiverPhone'           => '',
92
        'ReceiverEmail'           => '',
93
        'DeliveryAddressLine1'    => '',
94
        'DeliveryAddressLine2'    => '',
95
        'DeliveryAddressCountry'  => '',
96
        'DeliveryAddressPostCode' => '',
97
    );
98
99
    /**
100
     * Gets and displays an editable list of items within the cart, as well as a contact form with entry
101
     * fields for the recipients information.
102
     *
103
     * To extend use the following from within an Extension subclass:
104
     *
105
     * <code>
106
     * public function updateDMSDocumentRequestForm($form)
107
     * {
108
     *     // Do something here
109
     * }
110
     * </code>
111
     *
112
     * @return DMSDocumentRequestForm
113
     */
114
    public function DMSDocumentRequestForm()
115
    {
116
        $fields = FieldList::create(
117
            TextField::create(
118
                'ReceiverName',
119
                _t('DMSDocumentCartCheckoutPage.RECEIVER_NAME', 'Name')
120
            ),
121
            TextField::create(
122
                'ReceiverPhone',
123
                _t('DMSDocumentCartCheckoutPage.RECEIVER_PHONE', 'Phone')
124
            ),
125
            EmailField::create(
126
                'ReceiverEmail',
127
                _t('DMSDocumentCartCheckoutPage.RECEIVER_EMAIL', 'Email')
128
            ),
129
            TextField::create(
130
                'DeliveryAddressLine1',
131
                _t('DMSDocumentCartCheckoutPage.RECEIVER_ADD_1', 'Delivery Address')
132
            ),
133
            TextField::create('DeliveryAddressLine2', ''),
134
            CountryDropdownField::create(
135
                'DeliveryAddressCountry',
136
                _t('DMSDocumentCartCheckoutPage.RECEIVER_COUNTRY', 'Country')
137
            )->setValue('NZ'),
138
            TextField::create(
139
                'DeliveryAddressPostCode',
140
                _t('DMSDocumentCartCheckoutPage.RECEIVER_POST_CODE', 'Post Code')
141
            )
142
        );
143
        $form = DMSDocumentRequestForm::create($this, 'DMSDocumentRequestForm', $fields, FieldList::create());
144
        if ($receiverInfo = $this->getCart()->getReceiverInfo()) {
145
            $form->loadDataFrom($receiverInfo);
146
        }
147
148
        if ($message = $this->request->getVar('message')) {
0 ignored issues
show
Unused Code introduced by
$message is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
149
            $form->sessionMessage($this->ThanksMessage, 'good');
150
        } else {
151
            $form->clearMessage();
152
        }
153
        $this->extend('updateDMSDocumentRequestForm', $form);
154
155
        return $form;
156
    }
157
158
    /**
159
     * Sends an email to both the configured recipient as well as the requester. The
160
     * configured recipient is bcc'ed to the email in order to fulfill it.
161
     *
162
     * To extend use the following from within an Extension subclass:
163
     *
164
     * <code>
165
     * public function updateSend($email)
166
     * {
167
     *     // Do something here
168
     * }
169
     * </code>
170
     * @return mixed
171
     *
172
     * @throws DMSDocumentCartException
173
     */
174
    public function send()
175
    {
176
        $member = $this->CartEmailRecipient();
177
        if ($member->exists()) {
178
            $cart = $this->getCart();
179
            $from = Config::inst()->get('Email', 'admin_email');
180
            $emailAddress = ($info = $cart->getReceiverInfo()) ? $info['ReceiverEmail'] : $from;
181
            $email = Email::create(
182
                $from,
183
                $emailAddress,
184
                _t('DMSDocumentCartCheckoutPage.EMAIL_SUBJECT', 'Request for Printed Publications')
185
            );
186
            $email->setBcc($member->Email);
187
            $renderedCart = $cart->renderWith('DocumentCart_email');
188
            $body = _t(
189
                'DMSDocumentCartCheckoutPage.EMAIL_BODY',
190
                '<p>A request for printed publications has been submitted with the following details:</p>'
191
            );
192
            $body .= $renderedCart->getValue();
193
            $email->setBody($body)->setReplyTo($emailAddress);
194
            $this->extend('updateSend', $email);
195
            return $email->send();
196
        } else {
197
            throw new DMSDocumentCartException('No recipient has been configured. Please do so from the CMS');
198
        }
199
    }
200
201
    /**
202
     * Handles form submission.
203
     * Totals requested are updated, delivery details added, email sent for fulfillment
204
     * and print request totals updated.
205
     *
206
     * @param array          $data
207
     * @param Form           $form
208
     * @param SS_HTTPRequest $request
209
     *
210
     * @return SS_HTTPResponse
211
     */
212
    public function doRequestSend($data, Form $form, SS_HTTPRequest $request)
213
    {
214
        $this->updateCartItems($data);
215
        $this->updateCartReceiverInfo($data);
216
        $this->send();
217
        $this->trackTimestampedPrintRequest();
218
        $this->getCart()->emptyCart();
219
        return $this->redirect("{$this->Link()}?message=1");
220
    }
221
222
    /**
223
     * Increments the print counts of all documents which were successfully sent.
224
     */
225
    public function trackTimestampedPrintRequest()
226
    {
227
        /** @var DMSRequestItem $item */
228
        foreach ($this->getCart()->getItems() as $item) {
229
            /** @var DMSDocument|DMSDocumentCartExtension $doc */
230
            $doc = $item->getDocument();
231
            $doc->incrementPrintRequest();
0 ignored issues
show
Bug introduced by
The method incrementPrintRequest does only exist in DMSDocumentCartExtension, but not in DMSDocument.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
232
        }
233
    }
234
235
    /**
236
     * Retrieves a {@link DMSDocumentCart} instance
237
     *
238
     * @return DMSDocumentCart
239
     */
240
    public function getCart()
241
    {
242
        return singleton('DMSDocumentCart');
243
    }
244
245
    /**
246
     * Updates the document quantities just before the request is sent.
247
     *
248
     * @param array $data
249
     */
250
    public function updateCartItems($data)
251
    {
252
        if (isset($data['ItemQuantity']) && !empty($data['ItemQuantity'])) {
253
            foreach ($data['ItemQuantity'] as $itemID => $quantity) {
254
                // Only update if quantity has changed
255
                $item = $this->getCart()->getItem($itemID);
256
                if ($item->getQuantity() == $quantity) {
257
                    continue;
258
                }
259
                $this->getCart()->updateItemQuantity($itemID, $quantity - 1);
260
            }
261
        }
262
    }
263
264
    /**
265
     * Updates the cart receiver info just before the request is sent.
266
     *
267
     * @param array          $data
268
     */
269
    public function updateCartReceiverInfo($data)
270
    {
271
        $info = array_merge(self::$receiverInfo, $data);
272
        $this->getCart()->setReceiverInfo($info);
273
    }
274
}
275