Passed
Pull Request — master (#309)
by Jason
13:47
created

Order::parseOrderDetails()   B

Complexity

Conditions 8
Paths 18

Size

Total Lines 57
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 57
rs 7.2648
c 0
b 0
f 0
cc 8
eloc 28
nc 18
nop 1

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
     * @return array|string
114
     */
115
    public function fieldLabels($includerelations = true)
116
    {
117
        $labels = parent::fieldLabels();
118
119
        $labels['Order_ID'] = _t('Order.Order_ID', 'Order ID#');
120
        $labels['TransactionDate'] = _t('Order.TransactionDate', "Date");
121
        $labels['TransactionDate.NiceUS'] = _t('Order.TransactionDate', "Date");
122
        $labels['Member.Name'] = _t('Order.MemberName', 'Customer');
123
        $labels['Member.ID'] = _t('Order.MemberName', 'Customer');
124
        $labels['ProductTotal.Nice'] = _t('Order.ProductTotal', 'Sub Total');
125
        $labels['TaxTotal.Nice'] = _t('Order.TaxTotal', 'Tax');
126
        $labels['ShippingTotal.Nice'] = _t('Order.ShippingTotal', 'Shipping');
127
        $labels['OrderTotal'] = _t('Order.OrderTotal', 'Total');
128
        $labels['OrderTotal.Nice'] = _t('Order.OrderTotal', 'Total');
129
        $labels['ReceiptLink'] = _t('Order.ReceiptLink', 'Invoice');
130
        $labels['Details.ProductID'] = _t('Order.Details.ProductID', 'Product');
131
132
        return $labels;
133
    }
134
135
    /**
136
     * @return mixed
137
     */
138
    public function ReceiptLink()
139
    {
140
        return $this->getReceiptLink();
141
    }
142
143
    /**
144
     * @return mixed
145
     */
146
    public function getReceiptLink()
147
    {
148
        $obj= DBHTMLVarchar::create();
149
        $obj->setValue('<a href="' . $this->ReceiptURL . '" target="_blank" class="cms-panel-link action external-link">view</a>');
150
        return $obj;
151
    }
152
153
    /**
154
     * @return mixed
155
     */
156
    public function getDecryptedResponse() {
157
        $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...
158
        if (FoxyCart::getStoreKey()) {
159
            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...
160
        }
161
    }
162
163
    /**
164
     * @throws \SilverStripe\ORM\ValidationException
165
     */
166
    public function onBeforeWrite() {
167
168
        $this->parseOrder();
169
        parent::onBeforeWrite();
170
    }
171
172
    /**
173
     * @return bool
174
     * @throws \SilverStripe\ORM\ValidationException
175
     */
176
    public function parseOrder() {
177
178
        if ($this->getDecryptedResponse()) {
179
180
            $response = new \SimpleXMLElement($this->getDecryptedResponse());
181
182
            $this->parseOrderInfo($response);
183
            $this->parseOrderCustomer($response);
184
            $this->parseOrderDetails($response);
185
186
            return true;
187
188
        } else {
189
190
            return false;
191
192
        }
193
    }
194
195
    /**
196
     * @param $response
197
     */
198
    public function parseOrderInfo($response) {
199
200
        foreach ($response->transactions->transaction as $transaction) {
201
202
            // Record transaction data from FoxyCart Datafeed:
203
            $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...
204
            $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...
205
            $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...
206
            $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...
207
            $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...
208
            $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...
209
            $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...
210
            $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...
211
212
            $this->extend('handleOrderInfo', $order, $response);
213
        }
214
    }
215
216
    /**
217
     * @param $response
218
     */
219
    public function parseOrderCustomer($response) {
220
221
        foreach ($response->transactions->transaction as $transaction) {
222
223
            // if not a guest transaction in FoxyCart
224
            if (isset($transaction->customer_email) && $transaction->is_anonymous == 0) {
225
226
                // if Customer is existing member, associate with current order
227
                if(Member::get()->filter('Email', $transaction->customer_email)->First()) {
228
229
                    $customer = Member::get()->filter('Email', $transaction->customer_email)->First();
230
231
                    // if new customer, create account with data from FoxyCart
232
                } else {
233
234
                    // set PasswordEncryption to 'none' so imported, encrypted password is not encrypted again
235
                    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

235
                    Config::inst()->/** @scrutinizer ignore-call */ update('Security', 'password_encryption_algorithm', 'none');
Loading history...
236
237
                    // create new Member, set password info from FoxyCart
238
                    $customer = Member::create();
239
                    $customer->Customer_ID = (int) $transaction->customer_id;
240
                    $customer->FirstName = (string) $transaction->customer_first_name;
241
                    $customer->Surname = (string) $transaction->customer_last_name;
242
                    $customer->Email = (string) $transaction->customer_email;
243
                    $customer->Password = (string) $transaction->customer_password;
244
                    $customer->Salt = (string) $transaction->customer_password_salt;
245
                    $customer->PasswordEncryption = 'none';
246
247
                    // record member record
248
                    $customer->write();
249
                }
250
251
                // set Order MemberID
252
                $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...
253
254
                $this->extend('handleOrderCustomer', $order, $response, $customer);
255
256
            }
257
        }
258
    }
259
260
    /**
261
     * @param $response
262
     * @throws \SilverStripe\ORM\ValidationException
263
     */
264
    public function parseOrderDetails($response) {
265
266
        // remove previous OrderDetails and OrderOptions so we don't end up with duplicates
267
        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

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

330
		return Permission::check('Product_ORDERS', 'any', /** @scrutinizer ignore-type */ $member);
Loading history...
331
	}
332
333
    /**
334
     * @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...
335
     * @return bool
336
     */
337
	public function canEdit($member = null) {
338
        return false;
339
        //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...
340
	}
341
342
    /**
343
     * @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...
344
     * @return bool
345
     */
346
    public function canDelete($member = null)
347
    {
348
        return false;
349
        //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...
350
    }
351
352
    /**
353
     * @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...
354
     * @param array $context
355
     * @return bool
356
     */
357
    public function canCreate($member = null, $context = [])
358
    {
359
        return false;
360
    }
361
362
    /**
363
     * @return array
364
     */
365
    public function providePermissions()
366
    {
367
        return array(
368
            'Product_ORDERS' => 'Allow user to manage Orders and related objects'
369
        );
370
    }
371
}