Passed
Pull Request — master (#373)
by Nic
05:55
created

Order::getTransaction()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Dynamic\FoxyStripe\Model;
4
5
use Dynamic\FoxyStripe\Foxy\Transaction;
6
use Dynamic\FoxyStripe\Page\ProductPage;
7
use SilverStripe\Core\Config\Config;
8
use SilverStripe\Forms\DateField;
9
use SilverStripe\ORM\DataObject;
10
use SilverStripe\ORM\FieldType\DBHTMLVarchar;
11
use SilverStripe\Security\Member;
12
use SilverStripe\Security\Permission;
13
use SilverStripe\Security\PermissionProvider;
14
use SilverStripe\Security\Security;
15
16
/**
17
 * Class Order
18
 * @package Dynamic\FoxyStripe\Model
19
 *
20
 * @property \SilverStripe\ORM\FieldType\DBInt Order_ID
21
 * @property \SilverStripe\ORM\FieldType\DBDatetime TransactionDate
22
 * @property \SilverStripe\ORM\FieldType\DBCurrency ProductTotal
23
 * @property \SilverStripe\ORM\FieldType\DBCurrency TaxTotal
24
 * @property \SilverStripe\ORM\FieldType\DBCurrency ShippingTotal
25
 * @property \SilverStripe\ORM\FieldType\DBCurrency OrderTotal
26
 * @property \SilverStripe\ORM\FieldType\DBVarchar ReceiptURL
27
 * @property \SilverStripe\ORM\FieldType\DBVarchar OrderStatus
28
 * @property \SilverStripe\ORM\FieldType\DBVarchar Response
29
 *
30
 * @property int MemberID
31
 * @method Member Member
32
 *
33
 * @method \SilverStripe\ORM\HasManyList Details
34
 */
35
class Order extends DataObject implements PermissionProvider
36
{
37
    /**
38
     * @var array
39
     */
40
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
41
        'Order_ID' => 'Int',
42
        'TransactionDate' => 'DBDatetime',
43
        'ProductTotal' => 'Currency',
44
        'TaxTotal' => 'Currency',
45
        'ShippingTotal' => 'Currency',
46
        'OrderTotal' => 'Currency',
47
        'ReceiptURL' => 'Varchar(255)',
48
        'OrderStatus' => 'Varchar(255)',
49
        'Response' => 'Text',
50
    ];
51
52
    /**
53
     * @var array
54
     */
55
    private static $has_one = [
0 ignored issues
show
introduced by
The private property $has_one is not used, and could be removed.
Loading history...
56
        'Member' => Member::class,
57
    ];
58
59
    /**
60
     * @var array
61
     */
62
    private static $has_many = [
0 ignored issues
show
introduced by
The private property $has_many is not used, and could be removed.
Loading history...
63
        'Details' => OrderDetail::class,
64
    ];
65
66
    /**
67
     * @var string
68
     */
69
    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...
70
71
    /**
72
     * @var string
73
     */
74
    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...
75
76
    /**
77
     * @var string
78
     */
79
    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...
80
81
    /**
82
     * @var string
83
     */
84
    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...
85
86
    /**
87
     * @var array
88
     */
89
    private static $summary_fields = [
0 ignored issues
show
introduced by
The private property $summary_fields is not used, and could be removed.
Loading history...
90
        'Order_ID',
91
        'TransactionDate.Nice',
92
        'Member.Name',
93
        'ProductTotal.Nice',
94
        'ShippingTotal.Nice',
95
        'TaxTotal.Nice',
96
        'OrderTotal.Nice',
97
        'ReceiptLink',
98
    ];
99
100
    /**
101
     * @var array
102
     */
103
    private static $searchable_fields = [
0 ignored issues
show
introduced by
The private property $searchable_fields is not used, and could be removed.
Loading history...
104
        'Order_ID',
105
        'TransactionDate' => [
106
            'field' => DateField::class,
107
            'filter' => 'PartialMatchFilter',
108
        ],
109
        'Member.ID',
110
        'OrderTotal',
111
        'Details.ProductID',
112
    ];
113
114
    /**
115
     * @var array
116
     */
117
    private static $casting = [
0 ignored issues
show
introduced by
The private property $casting is not used, and could be removed.
Loading history...
118
        'ReceiptLink' => 'HTMLVarchar',
119
    ];
120
121
    /**
122
     * @var array
123
     */
124
    private static $indexes = [
0 ignored issues
show
introduced by
The private property $indexes is not used, and could be removed.
Loading history...
125
        'Order_ID' => true, // make unique
126
    ];
127
128
    /**
129
     * @var string
130
     */
131
    private static $table_name = 'Order';
0 ignored issues
show
introduced by
The private property $table_name is not used, and could be removed.
Loading history...
132
133
    /**
134
     * @var Transaction
135
     */
136
    private $transaction;
137
138
    /**
139
     * @param bool $includerelations
140
     *
141
     * @return array|string
142
     */
143 1
    public function fieldLabels($includerelations = true)
144
    {
145 1
        $labels = parent::fieldLabels();
146
147 1
        $labels['Order_ID'] = _t('Order.Order_ID', 'Order ID#');
148 1
        $labels['TransactionDate'] = _t('Order.TransactionDate', 'Date');
149 1
        $labels['TransactionDate.NiceUS'] = _t('Order.TransactionDate', 'Date');
150 1
        $labels['Member.Name'] = _t('Order.MemberName', 'Customer');
151 1
        $labels['Member.ID'] = _t('Order.MemberName', 'Customer');
152 1
        $labels['ProductTotal.Nice'] = _t('Order.ProductTotal', 'Sub Total');
153 1
        $labels['TaxTotal.Nice'] = _t('Order.TaxTotal', 'Tax');
154 1
        $labels['ShippingTotal.Nice'] = _t('Order.ShippingTotal', 'Shipping');
155 1
        $labels['OrderTotal'] = _t('Order.OrderTotal', 'Total');
156 1
        $labels['OrderTotal.Nice'] = _t('Order.OrderTotal', 'Total');
157 1
        $labels['ReceiptLink'] = _t('Order.ReceiptLink', 'Invoice');
158 1
        $labels['Details.ProductID'] = _t('Order.Details.ProductID', 'Product');
159
160 1
        return $labels;
161
    }
162
163
    /**
164
     * @return mixed
165
     */
166 1
    public function ReceiptLink()
167
    {
168 1
        return $this->getReceiptLink();
169
    }
170
171
    /**
172
     * @return mixed
173
     */
174 1
    public function getReceiptLink()
175
    {
176 1
        $obj = DBHTMLVarchar::create();
177 1
        $obj->setValue(
178 1
            '<a href="' . $this->ReceiptURL . '" target="_blank" class="cms-panel-link action external-link">view</a>'
179
        );
180
181 1
        return $obj;
182
    }
183
184
    /**
185
     * @throws \SilverStripe\ORM\ValidationException
186
     */
187 9
    protected function onBeforeWrite()
188
    {
189 9
        parent::onBeforeWrite();
190
191 9
        $this->parseOrder();
192
    }
193
194
    /**
195
     * @return mixed
196
     */
197 9
    protected function getTransaction()
198
    {
199 9
        if (!$this->transaction) {
200 9
            $this->setTransaction();
201
        }
202
203 9
        return $this->transaction;
204
    }
205
206
    /**
207
     * @return $this
208
     */
209 9
    protected function setTransaction()
210
    {
211 9
        if ($this->Response) {
212
            $this->transaction = Transaction::create($this->Order_ID, urldecode($this->Response));
213
        } else {
214 9
            $this->transaction = false;
0 ignored issues
show
Documentation Bug introduced by
It seems like false of type false is incompatible with the declared type Dynamic\FoxyStripe\Foxy\Transaction of property $transaction.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
215
        }
216
217 9
        return $this;
218
    }
219
220
    /**
221
     * @return bool
222
     *
223
     * @throws \SilverStripe\ORM\ValidationException
224
     */
225 9
    public function parseOrder()
226
    {
227 9
        if ($this->getTransaction() && $this->getTransaction()->exists()) {
228
            $this->parseOrderInfo();
229
            $this->parseOrderCustomer();
230
            $this->parseOrderDetails();
231
        }
232
    }
233
234
    /**
235
     * @return bool|string
236
     */
237
    private function getDecryptedResponse()
0 ignored issues
show
Unused Code introduced by
The method getDecryptedResponse() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
238
    {
239
        if (FoxyCart::getStoreKey() && $this->Response) {
240
            return \rc4crypt::decrypt(FoxyCart::getStoreKey(), urldecode($this->Response));
0 ignored issues
show
Bug introduced by
It seems like Dynamic\FoxyStripe\Model\FoxyCart::getStoreKey() can also be of type false; however, parameter $pwd of rc4crypt::decrypt() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

240
            return \rc4crypt::decrypt(/** @scrutinizer ignore-type */ FoxyCart::getStoreKey(), urldecode($this->Response));
Loading history...
241
        }
242
243
        return false;
244
    }
245
246
    /**
247
     * @param $response
248
     */
249
    public function parseOrderInfo()
250
    {
251
        $transaction = $this->getTransaction()->getTransaction();
252
253
        // Record transaction data from FoxyCart Datafeed:
254
        $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...
255
        $this->TransactionDate = (string)$transaction->transaction_date;
0 ignored issues
show
Documentation Bug introduced by
It seems like (string)$transaction->transaction_date of type string is incompatible with the declared type SilverStripe\ORM\FieldType\DBDatetime of property $TransactionDate.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
256
        $this->ProductTotal = (float)$transaction->product_total;
0 ignored issues
show
Documentation Bug introduced by
It seems like (double)$transaction->product_total of type double is incompatible with the declared type SilverStripe\ORM\FieldType\DBCurrency of property $ProductTotal.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
257
        $this->TaxTotal = (float)$transaction->tax_total;
0 ignored issues
show
Documentation Bug introduced by
It seems like (double)$transaction->tax_total of type double is incompatible with the declared type SilverStripe\ORM\FieldType\DBCurrency of property $TaxTotal.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
258
        $this->ShippingTotal = (float)$transaction->shipping_total;
0 ignored issues
show
Documentation Bug introduced by
It seems like (double)$transaction->shipping_total of type double is incompatible with the declared type SilverStripe\ORM\FieldType\DBCurrency of property $ShippingTotal.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
259
        $this->OrderTotal = (float)$transaction->order_total;
0 ignored issues
show
Documentation Bug introduced by
It seems like (double)$transaction->order_total of type double is incompatible with the declared type SilverStripe\ORM\FieldType\DBCurrency of property $OrderTotal.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
260
        $this->ReceiptURL = (string)$transaction->receipt_url;
0 ignored issues
show
Documentation Bug introduced by
It seems like (string)$transaction->receipt_url of type string is incompatible with the declared type SilverStripe\ORM\FieldType\DBVarchar of property $ReceiptURL.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
261
        $this->OrderStatus = (string)$transaction->status;
0 ignored issues
show
Documentation Bug introduced by
It seems like (string)$transaction->status of type string is incompatible with the declared type SilverStripe\ORM\FieldType\DBVarchar of property $OrderStatus.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
262
263
        $this->extend('handleOrderInfo', $order, $response);
264
    }
265
266
    /**
267
     * @param $response
268
     * @throws \SilverStripe\ORM\ValidationException
269
     */
270
    public function parseOrderCustomer()
271
    {
272
        $transaction = $this->getTransaction()->getTransaction();
273
274
        // if not a guest transaction in FoxyCart
275
        if (isset($transaction->customer_email) && $transaction->is_anonymous == 0) {
276
            if (!$customer = Member::get()->filter('Email', $transaction->customer_email)->first()) {
277
                $customer = Member::create();
278
            }
279
280
            $customer->FromDataFeed = true;
281
282
            $customer = $customer->setDataFromTransaction($transaction);
283
284
            $customer->write();
285
            $customer = Member::get()->byID($customer->ID);
286
287
            // set Order MemberID
288
            $this->MemberID = $customer->ID;
289
290
            $this->extend('handleOrderCustomer', $order, $response, $customer);
291
        }
292
    }
293
294
    /**
295
     * @param $response
296
     *
297
     * @throws \SilverStripe\ORM\ValidationException
298
     */
299
    public function parseOrderDetails()
300
    {
301
        // remove previous OrderDetails and OrderOptions so we don't end up with duplicates
302
        foreach ($this->Details() as $detail) {
303
            /** @var OrderOption $orderOption */
304
            foreach ($detail->OrderOptions() as $orderOption) {
305
                $orderOption->delete();
306
            }
307
            $detail->delete();
308
        }
309
310
        $transaction = $this->getTransaction()->getTransaction();
311
312
        // Associate ProductPages, Options, Quantity with Order
313
        foreach ($transaction->transaction_details->transaction_detail as $detail) {
314
            $OrderDetail = OrderDetail::create();
315
316
            $OrderDetail->Quantity = (int)$detail->product_quantity;
317
            $OrderDetail->ProductName = (string)$detail->product_name;
318
            $OrderDetail->ProductCode = (string)$detail->product_code;
319
            $OrderDetail->ProductImage = (string)$detail->image;
320
            $OrderDetail->ProductCategory = (string)$detail->category_code;
321
            $priceModifier = 0;
322
323
            // parse OrderOptions
324
            foreach ($detail->transaction_detail_options->transaction_detail_option as $option) {
325
                // Find product via product_id custom variable
326
                if ($option->product_option_name == 'product_id') {
327
                    // if product is found, set relation to OrderDetail
328
                    $OrderProduct = ProductPage::get()->byID((int)$option->product_option_value);
329
                    if ($OrderProduct) {
330
                        $OrderDetail->ProductID = $OrderProduct->ID;
331
                    }
332
                } else {
333
                    $OrderOption = OrderOption::create();
334
                    $OrderOption->Name = (string)$option->product_option_name;
335
                    $OrderOption->Value = (string)$option->product_option_value;
336
                    $OrderOption->write();
337
                    $OrderDetail->OrderOptions()->add($OrderOption);
338
339
                    $priceModifier += $option->price_mod;
340
                }
341
            }
342
343
            $OrderDetail->Price = (float)$detail->product_price + (float)$priceModifier;
344
345
            // extend OrderDetail parsing, allowing for recording custom fields from FoxyCart
346
            $this->extend('handleOrderItem', $order, $response, $OrderDetail);
347
348
            // write
349
            $OrderDetail->write();
350
351
            // associate with this order
352
            $this->Details()->add($OrderDetail);
353
        }
354
    }
355
356
    /**
357
     * @param bool $member
358
     *
359
     * @return bool|int
360
     */
361 10
    public function canView($member = null)
362
    {
363 10
        return Permission::check('Product_ORDERS', 'any', $member);
0 ignored issues
show
Bug introduced by
It seems like $member can also be of type boolean; however, parameter $member of SilverStripe\Security\Permission::check() does only seem to accept SilverStripe\Security\Member|integer, maybe add an additional type check? ( Ignorable by Annotation )

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

363
        return Permission::check('Product_ORDERS', 'any', /** @scrutinizer ignore-type */ $member);
Loading history...
364
    }
365
366
    /**
367
     * @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...
368
     *
369
     * @return bool
370
     */
371 1
    public function canEdit($member = null)
372
    {
373 1
        return false;
374
        //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...
375
    }
376
377
    /**
378
     * @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...
379
     *
380
     * @return bool
381
     */
382 1
    public function canDelete($member = null)
383
    {
384 1
        return false;
385
        //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...
386
    }
387
388
    /**
389
     * @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...
390
     * @param array $context
391
     *
392
     * @return bool
393
     */
394 1
    public function canCreate($member = null, $context = [])
395
    {
396 1
        return false;
397
    }
398
399
    /**
400
     * @return array
401
     */
402 1
    public function providePermissions()
403
    {
404
        return [
405 1
            'Product_ORDERS' => 'Allow user to manage Orders and related objects',
406
        ];
407
    }
408
}
409