Passed
Push — master ( fd14ef...e3fcf4 )
by
unknown
02:45
created

CountryPrice_OrderDOD::localise_order()   F

Complexity

Conditions 23
Paths 762

Size

Total Lines 79
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 79
rs 2.5316
c 0
b 0
f 0
cc 23
eloc 50
nc 762
nop 3

How to fix   Long Method    Complexity   

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
4
5
/**
6
 * Adds functionality to Order
7
 */
8
class CountryPrice_OrderDOD extends DataExtension
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
        'IP' => 'Varchar(45)',
12
        'CurrencyCountry' => 'Varchar(3)',
13
        'OriginatingCountryCode' => 'Varchar(3)'
14
    );
15
16
    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...
17
        'Distributor' => 'Distributor'
18
    );
19
20
    private static $searchable_fields = array(
0 ignored issues
show
Unused Code introduced by
The property $searchable_fields 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...
21
        'DistributorID' => array(
22
            'title' => 'Distributor'
23
        ),
24
        'OriginatingCountryCode' => array(
25
            'field' => 'TextField',
26
            'filter' => 'PartialMatchFilter',
27
            'title' => 'Country Code (e.g. NZ)'
28
        )
29
    );
30
31
    private static $field_labels = array(
0 ignored issues
show
Unused Code introduced by
The property $field_labels 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...
32
        'CurrencyCountry' => 'Currency Country',
33
        'OriginatingCountryCode' => 'Country'
34
    );
35
36
    private static $summary_fields = array(
0 ignored issues
show
Unused Code introduced by
The property $summary_fields 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...
37
        'Distributor.Title' => 'Distributor',
38
        'OriginatingCountryCode' => 'OriginatingCountryCode',
39
        'CurrencyUsed.Title' => 'Currency'
40
    );
41
42
    private static $_number_of_times_we_have_run_localise_order = 0;
43
44
    private static $only_allow_within_country_sales = false;
0 ignored issues
show
Unused Code introduced by
The property $only_allow_within_country_sales 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...
45
46
    /**
47
     * this method basically makes sure that the Order
48
     * has all the localised stuff attached to it, specifically
49
     * the right currency
50
     */
51
    public static function localise_order($countryCode = null, $force = false, $runAgain = false)
52
    {
53
        if($runAgain) {
54
            self::$_number_of_times_we_have_run_localise_order = 0;
55
        }
56
        if (self::$_number_of_times_we_have_run_localise_order > 2) {
57
            return;
58
        }
59
        self::$_number_of_times_we_have_run_localise_order++;
60
        $order = ShoppingCart::current_order();
61
        if ($order && $order->exists()) {
62
            if ($order->IsSubmitted()) {
63
                return true;
64
            }
65
            if (! $countryCode) {
66
                $countryCode = $order->getCountry();
67
            }
68
            $currencyObject = CountryPrice_EcommerceCurrency::get_currency_for_country($countryCode);
69
            if (Config::inst()->get('CountryPrice_OrderDOD', 'only_allow_within_country_sales')) {
70
                $distributor = $order->getDistributor($countryCode);
71
                $countryOptions = $distributor->Countries();
72
                if ($countryOptions && $countryOptions->count()) {
73
                    EcommerceCountry::set_for_current_order_only_show_countries($countryOptions->column('Code'));
74
                }
75
            }
76
            //check if the billing and shipping address have a country so that they will not be overridden by previous Orders
77
            //we do this to make sure that the previous address can not change the region and thereby destroy the order in the cart
78
            if ($billingAddress = $order->CreateOrReturnExistingAddress('BillingAddress')) {
79
                if (! $billingAddress->Country || $force) {
80
                    $billingAddress->Country = $countryCode;
81
                    $billingAddress->write();
82
                }
83
            }
84
            if ($shippingAddress = $order->CreateOrReturnExistingAddress('ShippingAddress')) {
85
                if (! $shippingAddress->ShippingCountry || $force) {
86
                    $shippingAddress->ShippingCountry = $countryCode;
87
                    $shippingAddress->write();
88
                }
89
            }
90
91
            //if a country code and currency has been set then all is good
92
            //from there we keep it this way
93
            if (
94
                $order->OriginatingCountryCode ==  $countryCode &&
95
                $order->CurrencyUsedID == $currencyObject->ID
96
            ) {
97
                return true;
98
            }
99
            $order->resetLocale = true;
100
            $order->write();
101
            $order = Order::get()->byID($order->ID);
102
            $orderHasBeenChanged = false;
103
104
             //check currency ...
105
            if ($order->CurrencyUsedID != $currencyObject->ID) {
106
                $order->SetCurrency($currencyObject);
107
                $orderHasBeenChanged = true;
108
            }
109
            if ($orderHasBeenChanged) {
110
                ShoppingCart::reset_order_reference();
0 ignored issues
show
Bug introduced by
The method reset_order_reference() does not seem to exist on object<ShoppingCart>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
111
                $order->write();
112
                $items = $order->OrderItems();
113
                if ($items) {
114
                    foreach ($items as $item) {
115
                        $buyable = $item->Buyable(true);
116
                        if (! $buyable->canPurchase()) {
117
                            $item->delete();
118
                        }
119
                    }
120
                }
121
                // Called after because some modifiers use the country field to calculate the values
122
                $order->calculateOrderAttributes(true);
123
            }
124
            self::localise_order($countryCode);
125
        } else {
126
            Session::set('temporary_country_order_store', $countryCode);
127
        }
128
129
    }
130
131
132
    public function onInit()
133
    {
134
        $this->setCountryDetailsForOrder();
135
    }
136
137
    public function onCalculateOrder()
138
    {
139
        $this->setCountryDetailsForOrder();
140
    }
141
142
    public function updateCMSFields(FieldList $fields)
143
    {
144
        foreach (array('IP', 'OriginatingCountryCode', 'CurrencyCountry') as $fieldName) {
145
            $field = $fields->dataFieldByName($fieldName);
146
            $field = $field->performReadonlyTransformation();
147
            $fields->addFieldToTab("Root.Country", $field);
148
            $fields->addFieldToTab(
149
                'Root.Country',
150
                DropdownField::create(
151
                    'DistributorID',
152
                     _t('Distributor.SINGULAR_NAME', 'Distributor'),
153
                    array(''=> '--- Please select ---') + Distributor::get()->map()->toArray()
154
                )
155
            );
156
        }
157
    }
158
159
    /**
160
     * Event handler called after writing to the database.
161
     */
162
    public function onAfterWrite()
163
    {
164
        if(! $this->owner->DistributorID) {
165
            if($defaultDistributor = Distributor::get_default_distributor()) {
166
                if($defaultDistributor->exists()) {
167
                    if($defaultDistributor->ID) {
168
                        $this->owner->DistributorID = $defaultDistributor->ID;
169
                        $this->owner->write();
170
                    }
171
                }
172
            }
173
        }
174
    }
175
176
    public function canView($member = null)
177
    {
178
        return $this->canEdit($member);
179
    }
180
181
    public function canEdit($member = null)
182
    {
183
        if (! $member) {
184
            $member = Member::currentUser();
185
        }
186 View Code Duplication
        if ($member) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
187
            if ($distributor = $this->owner->Distributor()) {
188
                foreach ($distributor->Members() as $distributorMember) {
189
                    if ($member->ID == $distributorMember->ID) {
190
                        return true;
191
                    }
192
                }
193
            }
194
        }
195
    }
196
197
    /**
198
     * it is safer to only allow creation on the front-end...
199
     *
200
     */
201
    public function canCreate($member = null)
202
    {
203
        return false;
204
    }
205
206
    /**
207
     *
208
     * @param string (optional) $countryCode
209
     * @return Distributor | null
0 ignored issues
show
Documentation introduced by
Should the return type not be Distributor|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...
210
     */
211
    public function getDistributor($countryCode = null)
212
    {
213
        if ($this->owner->DistributorID) {
214
            return Distributor::get()->byID($this->owner->DistributorID);
215
        } else {
216
            if (!$countryCode) {
217
                $countryCode = $this->owner->getCountry();
218
            }
219
            return Distributor::get_one_for_country($countryCode);
220
        }
221
    }
222
223
    /**
224
     * this needs to run as part of the order live update
225
     *
226
     */
227
    protected function setCountryDetailsForOrder()
228
    {
229
        if ($this->owner->IsSubmitted()) {
230
            return;
231
        }
232
233
        //set IP
234
        $this->owner->IP = EcommerceCountry::get_ip();
235
236
        //here we need to get the REAL ORIGINAL COUNTRY
237
        $countryCode = EcommerceCountry::get_country();
238
        if (Config::inst()->get('CountryPrice_OrderDOD', 'only_allow_within_country_sales')) {
239
            $this->owner->CurrencyCountry = $countryCode;
240
            EcommerceCountry::set_for_current_order_only_show_countries(array($countryCode));
241
            $this->owner->SetCountryFields($countryCode, $billingAddress = true, $shippingAddress = true);
242
        }
243
        $this->owner->OriginatingCountryCode = $countryCode;
244
245
        // set currency
246
        $currencyObject = CountryPrice_EcommerceCurrency::get_currency_for_country($countryCode);
0 ignored issues
show
Documentation introduced by
$countryCode is of type string, but the function expects a object<strin>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
247
        if ($currencyObject) {
248
            $this->owner->CurrencyUsedID = $currencyObject->ID;
249
        }
250
        //the line below causes a loop!!!
251
        //$this->owner->SetCurrency($currencyObject);
0 ignored issues
show
Unused Code Comprehensibility introduced by
78% 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...
252
253
        $distributor = Distributor::get_one_for_country($countryCode);
254
        if ($distributor) {
255
            $this->owner->DistributorID = $distributor->ID;
256
        }
257
    }
258
259
260
    /**
261
     *
262
     * 1. adds distribut emails to order step emails ... if $step->SendEmailToDistributor === true
263
     *
264
     * 2. adds country specific data into arrayData that is used for search
265
     * and replace in email ...
266
     *
267
     * @param ArrayData $arrayData
268
     */
269
    public function updateReplacementArrayForEmail(ArrayData $arrayData)
270
    {
271
        $step = $this->owner->MyStep();
272
        $countryCode = $this->owner->getCountry();
273
        $countryMessageObject = null;
274
        if ($step && $countryCode) {
275
            $countryMessageObject = EcommerceOrderStepCountryData::get()
276
                ->filter(
277
                    array(
278
                        "OrderStepID" => $step->ID,
279
                        "EcommerceCountryID" => CountryPrice_EcommerceCountry::get_real_country($countryCode)->ID
280
                    )
281
                )
282
                ->first();
283
        }
284
        if ($countryMessageObject) {
285
            $arrayData->setField(
286
                "Subject",
287
                $countryMessageObject->CountrySpecificEmailSubject
288
            );
289
            $arrayData->setField(
290
                "OrderStepMessage",
291
                $countryMessageObject->CountrySpecificEmailMessage
292
            );
293
        }
294
        if($step->SendEmailToDistributor) {
295
            if ($distributor = $this->owner->Distributor()) {
296
                $distributorEmail = $distributor->Email;
297
                if ($distributorEmail) {
298
                    $bccArray = array($distributorEmail => $distributorEmail);
299
                    foreach ($distributor->Members() as $member) {
300
                        if ($member && $member->Email) {
301
                            $bccArray[$member->Email] = $member->Email;
302
                        }
303
                    }
304
                    $arrayData->setField('BCC', implode(', ', $bccArray));
305
                }
306
            }
307
        }
308
    }
309
}
310