Completed
Push — master ( 44db84...1717c1 )
by
unknown
02:20
created

CountryPrice_OrderDOD::setCountryDetailsForOrder()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 31
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 31
rs 8.439
c 0
b 0
f 0
cc 5
eloc 16
nc 9
nop 0
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)
52
    {
53
        if (self::$_number_of_times_we_have_run_localise_order > 2) {
54
            return;
55
        }
56
        self::$_number_of_times_we_have_run_localise_order++;
57
        $order = ShoppingCart::current_order();
58
        if (!$order) {
59
            return true;
60
        }
61
        if ($order->IsSubmitted()) {
62
            return true;
63
        }
64
        if (! $countryCode) {
65
            $countryCode = $order->getCountry();
66
        }
67
        $currencyObject = CountryPrice_EcommerceCurrency::get_currency_for_country($countryCode);
68
        if (Config::inst()->get('CountryPrice_OrderDOD', 'only_allow_within_country_sales')) {
69
            $distributor = $order->getDistributor($countryCode);
70
            $countryOptions = $distributor->Countries();
71
            if ($countryOptions && $countryOptions->count()) {
72
                EcommerceCountry::set_for_current_order_only_show_countries($countryOptions->column('Code'));
73
            }
74
        }
75
        //check if the billing and shipping address have a country so that they will not be overridden by previous Orders
76
        //we do this to make sure that the previous address can not change the region and thereby destroy the order in the cart
77
        if ($billingAddress = $order->CreateOrReturnExistingAddress('BillingAddress')) {
78
            if (! $billingAddress->Country || $force) {
79
                $billingAddress->Country = $countryCode;
80
                $billingAddress->write();
81
            }
82
        }
83
        if ($shippingAddress = $order->CreateOrReturnExistingAddress('ShippingAddress')) {
84
            if (! $shippingAddress->ShippingCountry || $force) {
85
                $shippingAddress->ShippingCountry = $countryCode;
86
                $shippingAddress->write();
87
            }
88
        }
89
90
        //if a country code and currency has been set then all is good
91
        //from there we keep it this way
92
        if (
93
            $order->OriginatingCountryCode ==  $countryCode &&
94
            $order->CurrencyUsedID == $currencyObject->ID
95
        ) {
96
            return true;
97
        }
98
        $order->resetLocale = true;
99
        $order->write();
100
        $order = Order::get()->byID($order->ID);
101
        $orderHasBeenChanged = false;
102
103
         //check currency ...
104
        if ($order->CurrencyUsedID != $currencyObject->ID) {
105
            $order->SetCurrency($currencyObject);
106
            $orderHasBeenChanged = true;
107
        }
108
        if ($orderHasBeenChanged) {
109
            $order->write();
110
            $items = $order->OrderItems();
111
            if ($items) {
112
                foreach ($items as $item) {
113
                    $buyable = $item->Buyable(true);
114
                    if (! $buyable->canPurchase()) {
115
                        $item->delete();
116
                    }
117
                }
118
            }
119
            // Called after because some modifiers use the country field to calculate the values
120
            $order->calculateOrderAttributes(true);
121
        }
122
        self::localise_order($countryCode);
123
    }
124
125
126
    public function onInit()
127
    {
128
        $this->setCountryDetailsForOrder();
129
    }
130
131
    public function onCalculateOrder()
132
    {
133
        $this->setCountryDetailsForOrder();
134
    }
135
136
    public function updateCMSFields(FieldList $fields)
137
    {
138
        foreach (array('IP', 'OriginatingCountryCode', 'CurrencyCountry') as $fieldName) {
139
            $field = $fields->dataFieldByName($fieldName);
140
            $field = $field->performReadonlyTransformation();
141
            $fields->addFieldToTab("Root.Country", $field);
142
            $fields->addFieldToTab(
143
                'Root.Country',
144
                DropdownField::create(
145
                    'DistributorID',
146
                     _t('Distributor.SINGULAR_NAME', 'Distributor'),
147
                    array(''=> '--- Please select ---') + Distributor::get()->map()->toArray()
148
                )
149
            );
150
        }
151
    }
152
153
    /**
154
     * Event handler called after writing to the database.
155
     */
156
    public function onAfterWrite()
157
    {
158
        if(! $this->owner->DistributorID) {
159
            if($defaultDistributor = Distributor::get_default_distributor()) {
160
                if($defaultDistributor->exists()) {
161
                    if($defaultDistributor->ID) {
162
                        $this->owner->DistributorID = $defaultDistributor->ID;
163
                        $this->owner->write();
164
                    }
165
                }
166
            }
167
        }
168
    }
169
170
    public function canView($member = null)
171
    {
172
        return $this->canEdit($member);
173
    }
174
175
    public function canEdit($member = null)
176
    {
177
        if (! $member) {
178
            $member = Member::currentUser();
179
        }
180 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...
181
            if ($distributor = $this->owner->Distributor()) {
182
                foreach ($distributor->Members() as $distributorMember) {
183
                    if ($member->ID == $distributorMember->ID) {
184
                        return true;
185
                    }
186
                }
187
            }
188
        }
189
    }
190
191
    /**
192
     * it is safer to only allow creation on the front-end...
193
     *
194
     */
195
    public function canCreate($member = null)
196
    {
197
        return false;
198
    }
199
200
    /**
201
     *
202
     * @param string (optional) $countryCode
203
     * @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...
204
     */
205
    public function getDistributor($countryCode = null)
206
    {
207
        if ($this->owner->DistributorID) {
208
            return Distributor::get()->byID($this->owner->DistributorID);
209
        } else {
210
            if (!$countryCode) {
211
                $countryCode = $this->owner->getCountry();
212
            }
213
            return Distributor::get_one_for_country($countryCode);
214
        }
215
    }
216
217
    /**
218
     * this needs to run as part of the order live update
219
     *
220
     */
221
    protected function setCountryDetailsForOrder()
222
    {
223
        if ($this->owner->IsSubmitted()) {
224
            return;
225
        }
226
227
        //set IP
228
        $this->owner->IP = EcommerceCountry::get_ip();
229
230
        //here we need to get the REAL ORIGINAL COUNTRY
231
        $countryCode = EcommerceCountry::get_country();
232
        if (Config::inst()->get('CountryPrice_OrderDOD', 'only_allow_within_country_sales')) {
233
            $this->owner->CurrencyCountry = $countryCode;
234
            EcommerceCountry::set_for_current_order_only_show_countries(array($countryCode));
235
            $this->owner->SetCountryFields($countryCode, $billingAddress = true, $shippingAddress = true);
236
        }
237
        $this->owner->OriginatingCountryCode = $countryCode;
238
239
        // set currency
240
        $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...
241
        if ($currencyObject) {
242
            $this->owner->CurrencyUsedID = $currencyObject->ID;
243
        }
244
        //the line below causes a loop!!!
245
        //$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...
246
247
        $distributor = Distributor::get_one_for_country($countryCode);
248
        if ($distributor) {
249
            $this->owner->DistributorID = $distributor->ID;
250
        }
251
    }
252
253
254
    /**
255
     *
256
     * 1. adds distribut emails to order step emails ... if $step->SendEmailToDistributor === true
257
     *
258
     * 2. adds country specific data into arrayData that is used for search
259
     * and replace in email ...
260
     *
261
     * @param ArrayData $arrayData
262
     */
263
    public function updateReplacementArrayForEmail(ArrayData $arrayData)
264
    {
265
        $step = $this->owner->MyStep();
266
        $countryCode = $this->owner->getCountry();
267
        $countryMessageObject = null;
268
        if ($step && $countryCode) {
269
            $countryMessageObject = EcommerceOrderStepCountryData::get()
270
                ->filter(
271
                    array(
272
                        "OrderStepID" => $step->ID,
273
                        "EcommerceCountryID" => CountryPrice_EcommerceCountry::get_real_country($countryCode)->ID
274
                    )
275
                )
276
                ->first();
277
        }
278
        if ($countryMessageObject) {
279
            $arrayData->setField(
280
                "Subject",
281
                $countryMessageObject->CountrySpecificEmailSubject
282
            );
283
            $arrayData->setField(
284
                "OrderStepMessage",
285
                $countryMessageObject->CountrySpecificEmailMessage
286
            );
287
        }
288
        if($step->SendEmailToDistributor) {
289
            if ($distributor = $this->owner->Distributor()) {
290
                $distributorEmail = $distributor->Email;
291
                if ($distributorEmail) {
292
                    $bccArray = array($distributorEmail => $distributorEmail);
293
                    foreach ($distributor->Members() as $member) {
294
                        if ($member && $member->Email) {
295
                            $bccArray[$member->Email] = $member->Email;
296
                        }
297
                    }
298
                    $arrayData->setField('BCC', implode(', ', $bccArray));
299
                }
300
            }
301
        }
302
    }
303
}
304