Completed
Pull Request — master (#309)
by Jason
05:20
created

Order::parseOrderDetails()   B

Complexity

Conditions 8
Paths 18

Size

Total Lines 53
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 53
ccs 0
cts 29
cp 0
rs 7.1199
cc 8
eloc 29
nc 18
nop 1
crap 72

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Dynamic\FoxyStripe\Model;
4
5
use Dynamic\FoxyStripe\Page\ProductPage;
6
use SilverStripe\Core\Config\Config;
7
use SilverStripe\ORM\DataObject;
8
use SilverStripe\ORM\FieldType\DBHTMLVarchar;
9
use SilverStripe\Security\Member;
10
use SilverStripe\Security\Permission;
11
use SilverStripe\Security\PermissionProvider;
12
13
class Order extends DataObject implements PermissionProvider
14
{
15
    /**
16
     * @var array
17
     */
18
    private static $db = array(
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
19
        'Order_ID' => 'Int',
20
        'TransactionDate' => 'Datetime',
21
        'ProductTotal' => 'Currency',
22
        'TaxTotal' => 'Currency',
23
        'ShippingTotal' => 'Currency',
24
        'OrderTotal' => 'Currency',
25
        'ReceiptURL' => 'Varchar(255)',
26
        'OrderStatus' => 'Varchar(255)',
27
        'Response' => 'Text',
28
    );
29
30
    /**
31
     * @var array
32
     */
33
    private static $has_one = array(
0 ignored issues
show
introduced by
The private property $has_one is not used, and could be removed.
Loading history...
34
        'Member' => 'Member',
35
    );
36
37
    /**
38
     * @var array
39
     */
40
    private static $has_many = array(
0 ignored issues
show
introduced by
The private property $has_many is not used, and could be removed.
Loading history...
41
        'Details' => 'OrderDetail',
42
    );
43
44
    /**
45
     * @var string
46
     */
47
    private static $singular_name = 'Order';
0 ignored issues
show
introduced by
The private property $singular_name is not used, and could be removed.
Loading history...
48
49
    /**
50
     * @var string
51
     */
52
    private static $plural_name = 'Orders';
0 ignored issues
show
introduced by
The private property $plural_name is not used, and could be removed.
Loading history...
53
54
    /**
55
     * @var string
56
     */
57
    private static $description = 'Orders from FoxyCart Datafeed';
0 ignored issues
show
introduced by
The private property $description is not used, and could be removed.
Loading history...
58
59
    /**
60
     * @var string
61
     */
62
    private static $default_sort = 'TransactionDate DESC, ID DESC';
0 ignored issues
show
introduced by
The private property $default_sort is not used, and could be removed.
Loading history...
63
64
    /**
65
     * @var array
66
     */
67
    private static $summary_fields = array(
0 ignored issues
show
introduced by
The private property $summary_fields is not used, and could be removed.
Loading history...
68
        'Order_ID',
69
        'TransactionDate.NiceUS',
70
        'Member.Name',
71
        'ProductTotal.Nice',
72
        'ShippingTotal.Nice',
73
        'TaxTotal.Nice',
74
        'OrderTotal.Nice',
75
        'ReceiptLink',
76
    );
77
78
    /**
79
     * @var array
80
     */
81
    private static $searchable_fields = array(
0 ignored issues
show
introduced by
The private property $searchable_fields is not used, and could be removed.
Loading history...
82
        'Order_ID',
83
        'TransactionDate' => array(
84
            'field' => 'DateField',
85
            'filter' => 'PartialMatchFilter',
86
        ),
87
        'Member.ID',
88
        'OrderTotal',
89
        'Details.ProductID',
90
    );
91
92
    /**
93
     * @var array
94
     */
95
    private static $casting = array(
0 ignored issues
show
introduced by
The private property $casting is not used, and could be removed.
Loading history...
96
        'ReceiptLink' => 'HTMLVarchar',
97
    );
98
99
    /**
100
     * @var array
101
     */
102
    private static $indexes = array(
0 ignored issues
show
introduced by
The private property $indexes is not used, and could be removed.
Loading history...
103
        'Order_ID' => true, // make unique
104
    );
105
106
    /**
107
     * @var string
108
     */
109
    private static $table_name = 'FS_Order';
0 ignored issues
show
introduced by
The private property $table_name is not used, and could be removed.
Loading history...
110
111
    /**
112
     * @param bool $includerelations
113
     *
114
     * @return array|string
115
     */
116 1
    public function fieldLabels($includerelations = true)
117
    {
118 1
        $labels = parent::fieldLabels();
119
120 1
        $labels['Order_ID'] = _t('Order.Order_ID', 'Order ID#');
121 1
        $labels['TransactionDate'] = _t('Order.TransactionDate', 'Date');
122 1
        $labels['TransactionDate.NiceUS'] = _t('Order.TransactionDate', 'Date');
123 1
        $labels['Member.Name'] = _t('Order.MemberName', 'Customer');
124 1
        $labels['Member.ID'] = _t('Order.MemberName', 'Customer');
125 1
        $labels['ProductTotal.Nice'] = _t('Order.ProductTotal', 'Sub Total');
126 1
        $labels['TaxTotal.Nice'] = _t('Order.TaxTotal', 'Tax');
127 1
        $labels['ShippingTotal.Nice'] = _t('Order.ShippingTotal', 'Shipping');
128 1
        $labels['OrderTotal'] = _t('Order.OrderTotal', 'Total');
129 1
        $labels['OrderTotal.Nice'] = _t('Order.OrderTotal', 'Total');
130 1
        $labels['ReceiptLink'] = _t('Order.ReceiptLink', 'Invoice');
131 1
        $labels['Details.ProductID'] = _t('Order.Details.ProductID', 'Product');
132
133 1
        return $labels;
134
    }
135
136
    /**
137
     * @return mixed
138
     */
139 1
    public function ReceiptLink()
140
    {
141 1
        return $this->getReceiptLink();
142
    }
143
144
    /**
145
     * @return mixed
146
     */
147 1
    public function getReceiptLink()
148
    {
149 1
        $obj = DBHTMLVarchar::create();
150 1
        $obj->setValue(
151 1
            '<a href="'.$this->ReceiptURL.'" target="_blank" class="cms-panel-link action external-link">view</a>'
152
        );
153
154 1
        return $obj;
155
    }
156
157
    /**
158
     * @return mixed
159
     */
160 49
    public function getDecryptedResponse()
161
    {
162 49
        $decrypted = urldecode($this->Response);
0 ignored issues
show
Bug Best Practice introduced by
The property Response does not exist on Dynamic\FoxyStripe\Model\Order. Since you implemented __get, consider adding a @property annotation.
Loading history...
163 49
        if (FoxyCart::getStoreKey()) {
164
            return \rc4crypt::decrypt(FoxyCart::getStoreKey(), $decrypted);
0 ignored issues
show
Bug introduced by
The type rc4crypt was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
165
        }
166
    }
167
168
    /**
169
     * @throws \SilverStripe\ORM\ValidationException
170
     */
171 49
    public function onBeforeWrite()
172
    {
173 49
        $this->parseOrder();
174 49
        parent::onBeforeWrite();
175
    }
176
177
    /**
178
     * @return bool
179
     *
180
     * @throws \SilverStripe\ORM\ValidationException
181
     */
182 49
    public function parseOrder()
183
    {
184 49
        if ($this->getDecryptedResponse()) {
185
            $response = new \SimpleXMLElement($this->getDecryptedResponse());
186
187
            $this->parseOrderInfo($response);
188
            $this->parseOrderCustomer($response);
189
            $this->parseOrderDetails($response);
190
191
            return true;
192
        } else {
193 49
            return false;
194
        }
195
    }
196
197
    /**
198
     * @param $response
199
     */
200
    public function parseOrderInfo($response)
201
    {
202
        foreach ($response->transactions->transaction as $transaction) {
203
            // Record transaction data from FoxyCart Datafeed:
204
            $this->Store_ID = (int) $transaction->store_id;
0 ignored issues
show
Bug Best Practice introduced by
The property Store_ID does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
205
            $this->TransactionDate = (string) $transaction->transaction_date;
0 ignored issues
show
Bug Best Practice introduced by
The property TransactionDate does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
206
            $this->ProductTotal = (float) $transaction->product_total;
0 ignored issues
show
Bug Best Practice introduced by
The property ProductTotal does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
207
            $this->TaxTotal = (float) $transaction->tax_total;
0 ignored issues
show
Bug Best Practice introduced by
The property TaxTotal does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
208
            $this->ShippingTotal = (float) $transaction->shipping_total;
0 ignored issues
show
Bug Best Practice introduced by
The property ShippingTotal does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
209
            $this->OrderTotal = (float) $transaction->order_total;
0 ignored issues
show
Bug Best Practice introduced by
The property OrderTotal does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
210
            $this->ReceiptURL = (string) $transaction->receipt_url;
0 ignored issues
show
Bug Best Practice introduced by
The property ReceiptURL does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
211
            $this->OrderStatus = (string) $transaction->status;
0 ignored issues
show
Bug Best Practice introduced by
The property OrderStatus does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
212
213
            $this->extend('handleOrderInfo', $order, $response);
214
        }
215
    }
216
217
    /**
218
     * @param $response
219
     * @throws \SilverStripe\ORM\ValidationException
220
     */
221
    public function parseOrderCustomer($response)
222
    {
223
        foreach ($response->transactions->transaction as $transaction) {
224
            // if not a guest transaction in FoxyCart
225
            if (isset($transaction->customer_email) && $transaction->is_anonymous == 0) {
226
                // if Customer is existing member, associate with current order
227
                if (Member::get()->filter('Email', $transaction->customer_email)->First()) {
228
                    $customer = Member::get()->filter('Email', $transaction->customer_email)->First();
229
                    // if new customer, create account with data from FoxyCart
230
                } else {
231
                    // set PasswordEncryption to 'none' so imported, encrypted password is not encrypted again
232
                    Config::inst()->update('Security', 'password_encryption_algorithm', 'none');
0 ignored issues
show
Bug introduced by
The method update() does not exist on SilverStripe\Config\Coll...nfigCollectionInterface. It seems like you code against a sub-type of SilverStripe\Config\Coll...nfigCollectionInterface such as SilverStripe\Config\Coll...\MemoryConfigCollection. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

232
                    Config::inst()->/** @scrutinizer ignore-call */ update('Security', 'password_encryption_algorithm', 'none');
Loading history...
233
234
                    // create new Member, set password info from FoxyCart
235
                    $customer = Member::create();
236
                    $customer->Customer_ID = (int) $transaction->customer_id;
237
                    $customer->FirstName = (string) $transaction->customer_first_name;
238
                    $customer->Surname = (string) $transaction->customer_last_name;
239
                    $customer->Email = (string) $transaction->customer_email;
240
                    $customer->Password = (string) $transaction->customer_password;
241
                    $customer->Salt = (string) $transaction->customer_password_salt;
242
                    $customer->PasswordEncryption = 'none';
243
244
                    // record member record
245
                    $customer->write();
246
                }
247
248
                // set Order MemberID
249
                $this->MemberID = $customer->ID;
0 ignored issues
show
Bug Best Practice introduced by
The property MemberID does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
250
251
                $this->extend('handleOrderCustomer', $order, $response, $customer);
252
            }
253
        }
254
    }
255
256
    /**
257
     * @param $response
258
     *
259
     * @throws \SilverStripe\ORM\ValidationException
260
     */
261
    public function parseOrderDetails($response)
262
    {
263
264
        // remove previous OrderDetails and OrderOptions so we don't end up with duplicates
265
        foreach ($this->Details() as $detail) {
0 ignored issues
show
Bug introduced by
The method Details() does not exist on Dynamic\FoxyStripe\Model\Order. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

265
        foreach ($this->/** @scrutinizer ignore-call */ Details() as $detail) {
Loading history...
266
            foreach ($detail->OrderOptions() as $orderOption) {
267
                $orderOption->delete();
268
            }
269
            $detail->delete();
270
        }
271
272
        foreach ($response->transactions->transaction as $transaction) {
273
            // Associate ProductPages, Options, Quantity with Order
274
            foreach ($transaction->transaction_details->transaction_detail as $detail) {
275
                $OrderDetail = OrderDetail::create();
276
277
                $OrderDetail->Quantity = (int) $detail->product_quantity;
278
                $OrderDetail->ProductName = (string) $detail->product_name;
279
                $OrderDetail->ProductCode = (string) $detail->product_code;
280
                $OrderDetail->ProductImage = (string) $detail->image;
281
                $OrderDetail->ProductCategory = (string) $detail->category_code;
282
                $priceModifier = 0;
283
284
                // parse OrderOptions
285
                foreach ($detail->transaction_detail_options->transaction_detail_option as $option) {
286
                    // Find product via product_id custom variable
287
                    if ($option->product_option_name == 'product_id') {
288
                        // if product is found, set relation to OrderDetail
289
                        $OrderProduct = ProductPage::get()->byID((int) $option->product_option_value);
290
                        if ($OrderProduct) {
291
                            $OrderDetail->ProductID = $OrderProduct->ID;
292
                        }
293
                    } else {
294
                        $OrderOption = OrderOption::create();
295
                        $OrderOption->Name = (string) $option->product_option_name;
296
                        $OrderOption->Value = (string) $option->product_option_value;
297
                        $OrderOption->write();
298
                        $OrderDetail->OrderOptions()->add($OrderOption);
299
300
                        $priceModifier += $option->price_mod;
301
                    }
302
                }
303
304
                $OrderDetail->Price = (float) $detail->product_price + (float) $priceModifier;
305
306
                // extend OrderDetail parsing, allowing for recording custom fields from FoxyCart
307
                $this->extend('handleOrderItem', $order, $response, $OrderDetail);
308
309
                // write
310
                $OrderDetail->write();
311
312
                // associate with this order
313
                $this->Details()->add($OrderDetail);
314
            }
315
        }
316
    }
317
318
    /**
319
     * @param bool $member
320
     *
321
     * @return bool|int
322
     */
323 49
    public function canView($member = false)
324
    {
325 49
        return Permission::check('Product_ORDERS', 'any', $member);
0 ignored issues
show
Bug introduced by
$member of type boolean is incompatible with the type SilverStripe\Security\Member|integer expected by parameter $member of SilverStripe\Security\Permission::check(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

325
        return Permission::check('Product_ORDERS', 'any', /** @scrutinizer ignore-type */ $member);
Loading history...
326
    }
327
328
    /**
329
     * @param null $member
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $member is correct as it would always require null to be passed?
Loading history...
330
     *
331
     * @return bool
332
     */
333 1
    public function canEdit($member = null)
334
    {
335 1
        return false;
336
        //return Permission::check('Product_ORDERS', 'any', $member);
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% 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...
337
    }
338
339
    /**
340
     * @param null $member
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $member is correct as it would always require null to be passed?
Loading history...
341
     *
342
     * @return bool
343
     */
344 1
    public function canDelete($member = null)
345
    {
346 1
        return false;
347
        //return Permission::check('Product_ORDERS', 'any', $member);
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% 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...
348
    }
349
350
    /**
351
     * @param null  $member
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $member is correct as it would always require null to be passed?
Loading history...
352
     * @param array $context
353
     *
354
     * @return bool
355
     */
356 1
    public function canCreate($member = null, $context = [])
357
    {
358 1
        return false;
359
    }
360
361
    /**
362
     * @return array
363
     */
364 1
    public function providePermissions()
365
    {
366
        return array(
367 1
            'Product_ORDERS' => 'Allow user to manage Orders and related objects',
368
        );
369
    }
370
}
371