Issues (171)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

code/model/PickUpOrDeliveryModifierOptions.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * @author nicolaas [at] sunnysideup.co.nz
5
 * Precondition : There can only be 1 default option
6
 */
7
class PickUpOrDeliveryModifierOptions extends DataObject
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...
8
{
9
    private static $db = array(
10
        "IsDefault" => "Boolean",
11
        "Code" => "Varchar(25)",
12
        "Name" => "Varchar(175)",
13
        "Percentage" => "Double",
14
        "FixedCost" => "Currency",
15
        "WeightMultiplier" => "Double",
16
        "WeightUnit" => "Double",
17
        "MinimumDeliveryCharge" => "Currency",
18
        "MaximumDeliveryCharge" => "Currency",
19
        "MinimumOrderAmountForZeroRate" => "Currency",
20
        "FreeShippingUpToThisOrderAmount" => "Currency",
21
        "Sort" => "Int"
22
    );
23
24
    private static $has_one = array(
25
        "ExplanationPage" => "SiteTree"
26
    );
27
28
    private static $many_many = array(
29
        "AvailableInCountries" => "EcommerceCountry",
30
        "AvailableInRegions" => "EcommerceRegion",
31
        "WeightBrackets" => "PickUpOrDeliveryModifierOptions_WeightBracket",
32
        "SubtotalBrackets" => "PickUpOrDeliveryModifierOptions_SubTotalBracket",
33
        "ExcludedProducts" => 'Product'
34
    );
35
36
    private static $belongs_many_many = array(
37
        "ExcludeFromCountries" => "EcommerceCountry",
38
    );
39
40
    private static $indexes = array(
41
        "IsDefault" => true,
42
        "Code" => true
43
    );
44
45
    private static $searchable_fields = array(
46
        "Code",
47
        "Name" => "PartialMatchFilter"
48
    );
49
50
    private static $field_labels = array(
51
        "IsDefaultNice" => "Default option",
52
        "IsDefault" => "Default delivery option?",
53
        "Code" => "Code",
54
        "Name" => "Long Name",
55
        "Percentage" => "Percentage",
56
        "FixedCost" =>  "Fixed cost",
57
        "WeightMultiplier" => "Cost per kilogram",
58
        "WeightUnit" => "Weight unit in kilograms",
59
        "MinimumDeliveryCharge" => "Minimum delivery charge",
60
        "MaximumDeliveryCharge" => "Maximum delivery charge",
61
        "MinimumOrderAmountForZeroRate" => "Minimum for 0 rate",
62
        "FreeShippingUpToThisOrderAmount" => "Free shipping up to",
63
        "Sort" =>  "Sort Index",
64
        "ListOfCountries" =>  "Applicable Countries"
65
    );
66
67
    private static $field_labels_right = array(
68
        "Percentage" => "number between 0 = 0% and 1 = 100% (e.g. 0.05 would add 5 cents to every dollar ordered).",
69
        "FixedCost" =>  "e.g. entering 10 will add a fixed 10 dollars (or whatever currency is being used) delivery fee.",
70
        "WeightMultiplier" => "it multiplies the total weight of the total order with this number to work out charge for delivery. NOTE: you can also setup weight brackets (e.g. from 0 - 1kg = $123, from 1kg - 2kg = $456).",
71
        "WeightUnit" => "if you enter 0.1 here, the price will go up with every 100 grams of total order weight.",
72
        "MinimumDeliveryCharge" => "minimum delivery charge.",
73
        "MaximumDeliveryCharge" => "maximum delivery charge.",
74
        "MinimumOrderAmountForZeroRate" => "if this option is selected and the total order is over the amounted entered above then delivery is free.",
75
        "FreeShippingUpToThisOrderAmount" => "if this option is selected and the total order is less than the amount entered above then delivery is free. This is for situations where a small order would have a large delivery cost.",
76
        "Sort" =>  "lower numbers show first."
77
    );
78
79
    private static $defaults = array(
80
        "Code" => "homedelivery",
81
        "Name" => "Home Delivery",
82
        "Percentage" => 0,
83
        "FixedCost" => 0,
84
        "WeightMultiplier" => 0,
85
        "WeightUnit" => 1,
86
        "MinimumDeliveryCharge" => 0,
87
        "MaximumDeliveryCharge" => 0,
88
        "MinimumOrderAmountForZeroRate" => 0,
89
        "Sort" => 0
90
    );
91
92
    private static $summary_fields = array(
93
        "IsDefaultNice",
94
        "Code",
95
        "Name",
96
        'ListOfCountries'
97
    );
98
99
    private static $casting = array(
100
        "IsDefaultNice" => "Varchar",
101
        "ListOfCountries" => "Varchar"
102
    );
103
104
    private static $singular_name = "Delivery / Pick-up Option";
105
    public function i18n_singular_name()
106
    {
107
        return _t("PickUpOrDeliveryModifierOptions.DELIVERYOPTION", "Delivery / Pick-up Option");
108
    }
109
110
    private static $plural_name = "Delivery / Pick-up Options";
111
    public function i18n_plural_name()
112
    {
113
        return _t("PickUpOrDeliveryModifierOptions.DELIVERYOPTION", "Delivery / Pick-up Options");
114
    }
115
116
    private static $default_sort = "\"IsDefault\" DESC, \"Sort\" ASC, \"Name\" ASC";
117
118
    /**
119
     * returns the default PickUpOrDeliveryModifierOptions object
120
     * if none exists, it creates one.
121
     * @return PickUpOrDeliveryModifierOptions
122
     */
123
    public static function default_object()
124
    {
125
        if ($obj = PickUpOrDeliveryModifierOptions::get()->filter(array("IsDefault" => "1"))->First()) {
126
            //do nothing
127
        } else {
128
            $obj = new PickUpOrDeliveryModifierOptions();
129
            $obj->IsDefault = 1;
130
            $obj->write();
131
        }
132
        return $obj;
133
    }
134
135
    /**
136
     * returns an array of countries available for all options combined.
137
     * like this
138
     * array(
139
     *	"NZ" => "NZ"
140
     * );
141
     * @return Array
142
     */
143
    public static function get_all_as_country_array()
144
    {
145
        $array = array();
146
        $options = PickUpOrDeliveryModifierOptions::get();
147
        if ($options->count()) {
148
            foreach ($options as $option) {
149
                if ($countries = $option->AvailableInCountries()) {
150
                    if ($countries->count()) {
151
                        foreach ($countries as $country) {
152
                            $array[$option->Code][] = $country->Code;
153
                        }
154
                    }
155
                }
156
            }
157
        }
158
        return $array;
159
    }
160
161
    /**
162
     * @return String
163
     */
164
    public function IsDefaultNice()
165
    {
166
        return $this->getIsDefaultNice();
167
    }
168
    public function getIsDefaultNice()
169
    {
170
        return $this->IsDefault ? "yes"  : "no";
171
    }
172
173
174
    /**
175
     * standard SS method
176
     * @param Member | NULL
177
     * @return Boolean
178
     */
179 View Code Duplication
    public function canCreate($member = null)
180
    {
181
        if (Permission::checkMember($member, Config::inst()->get("EcommerceRole", "admin_permission_code"))) {
182
            return true;
183
        }
184
        return parent::canCreate($member);
185
    }
186
187
    /**
188
     * standard SS method
189
     * @param Member | NULL
190
     * @return Boolean
191
     */
192 View Code Duplication
    public function canView($member = null)
193
    {
194
        if (Permission::checkMember($member, Config::inst()->get("EcommerceRole", "admin_permission_code"))) {
195
            return true;
196
        }
197
        return parent::canCreate($member);
198
    }
199
200
    /**
201
     * standard SS method
202
     * @param Member | NULL
203
     * @return Boolean
204
     */
205 View Code Duplication
    public function canEdit($member = null)
206
    {
207
        if (Permission::checkMember($member, Config::inst()->get("EcommerceRole", "admin_permission_code"))) {
208
            return true;
209
        }
210
        return parent::canEdit($member);
211
    }
212
213
    /**
214
     * standard SS method
215
     * @param Member | NULL
216
     * @return Boolean
217
     */
218 View Code Duplication
    public function canDelete($member = null)
219
    {
220
        if (Permission::checkMember($member, Config::inst()->get("EcommerceRole", "admin_permission_code"))) {
221
            return true;
222
        }
223
        return parent::canDelete($member);
224
    }
225
226
    /**
227
     * standard SS method
228
     */
229
    public function getCMSFields()
230
    {
231
        $fields = parent::getCMSFields();
232
        $availableInCountriesField = $this->createGridField("EcommerceCountry", "AvailableInCountries", "Available in");
233
        if ($availableInCountriesField) {
234
            $fields->replaceField("AvailableInCountries", $availableInCountriesField);
235
        }
236
        $excludeFromCountriesField = $this->createGridField("EcommerceCountry", "ExcludeFromCountries", "Excluded from");
237
        if ($excludeFromCountriesField) {
238
            $fields->replaceField("ExcludeFromCountries", $excludeFromCountriesField);
239
        }
240
        $regionField = $this->createGridField("EcommerceRegion", "AvailableInRegions", "Regions");
241
        if ($regionField) {
242
            $fields->replaceField("AvailableInRegions", $regionField);
243
        }
244
        if (class_exists("DataObjectSorterController") && $this->hasExtension("DataObjectSorterController")) {
245
            $fields->addFieldToTab("Root.Sort", new LiteralField("InvitationToSort", $this->dataObjectSorterPopupLink()));
246
        }
247
        $fields->replaceField("ExplanationPageID", new OptionalTreeDropdownField($name = "ExplanationPageID", $title = "Page", "SiteTree"));
248
249
        //add headings
250
        $fields->addFieldToTab(
251
            "Root.Main",
252
            new HeaderField(
253
                "Charges",
254
                _t("PickUpOrDeliveryModifierOptions.CHARGES", "Charges (enter zero (0) to ignore)")
255
            ),
256
            "Percentage"
257
        );
258
        $fields->addFieldToTab(
259
            "Root.Main",
260
            new HeaderField(
261
                "MinimumAndMaximum",
262
                _t("PickUpOrDeliveryModifierOptions.MIN_AND_MAX", "Minimum and Maximum (enter zero (0) to ignore)")
263
            ),
264
            "MinimumDeliveryCharge"
265
        );
266
        $fields->addFieldToTab(
267
            "Root.Main",
268
            new HeaderField(
269
                "ExplanationHeader",
270
                _t("PickUpOrDeliveryModifierOptions.EXPLANATION_HEADER", "More information about delivery option")
271
            ),
272
            "ExplanationPageID"
273
        );
274
        $fields->replaceField(
275
            'ExcludedProducts',
276
            $excludedProdsField = GridField::create(
277
                'ExcludedProducts',
278
                'Excluded Products',
279
                $this->ExcludedProducts(),
280
                $config = GridFieldBasicPageRelationConfig::create()
281
            )
282
        );
283
        $excludedProdsField->setDescription("Products added here will not be charged delivery costs. If a customer's order contains more than one item (and not all items are listed here), then delivery costs will still be calculated.");
284
        if (EcommerceDBConfig::current_ecommerce_db_config()->ProductsHaveWeight) {
285
            $weightBrackets = $this->WeightBrackets();
286
            if ($weightBrackets && $weightBrackets->count()) {
287
                $fields->removeByName("WeightMultiplier");
288
                $fields->removeByName("WeightUnit");
289
            } else {
290
                $fields->addFieldToTab("Root.Main", new HeaderField("WeightOptions", "Weight Options (also see Weight Brackets tab)"), "WeightMultiplier");
291
            }
292
        } else {
293
            $fields->removeByName("WeightBrackets");
294
            $fields->removeByName("WeightMultiplier");
295
            $fields->removeByName("WeightUnit");
296
        }
297
        $fields->addFieldToTab("Root.Main", new HeaderField("MoreInformation", "Other Settings"), "Sort");
298
        foreach ($this->Config()->get("field_labels_right") as $fieldName => $fieldDescription) {
299
            $field = $fields->dataFieldByName($fieldName);
300
            if ($field) {
301
                $field->setRightTitle($fieldDescription);
302
            }
303
        }
304
        return $fields;
305
    }
306
307
    private function createGridField($dataObjectName = "EcommerceCountry", $fieldName = "AvailableInCountries", $title)
308
    {
309
        $field = null;
310
        $dos = $dataObjectName::get();
311
        if ($dos->count()) {
312
            if (class_exists("MultiSelectField")) {
313
                $array = $dos->map('ID', 'Title')->toArray();
314
                //$name, $title = "", $source = array(), $value = "", $form = null
315
                $field = new MultiSelectField(
316
                    $fieldName,
317
                    'This option is available in... ',
318
                    $array
319
                );
320
            } else {
321
                // $controller,  $name,  $sourceClass, [ $fieldList = null], [ $detailFormFields = null], [ $sourceFilter = ""], [ $sourceSort = ""], [ $sourceJoin = ""]
322
                /**
323
                * @todo: Auto completer may not be functioning correctly: ExactMatchFilter does not accept EcommerceCountryFilters_AllowSales as modifiers
324
                *
325
                */
326
327
                $gridFieldConfig = GridFieldConfig::create();
328
                $gridFieldConfig->addComponent(new GridFieldButtonRow('before'));
329
                $gridFieldConfig->addComponent(new GridFieldAddExistingAutocompleter('buttons-before-left'));
330
                $gridFieldConfig->addComponent(new GridFieldToolbarHeader());
331
                $gridFieldConfig->addComponent($sort = new GridFieldSortableHeader());
332
                $gridFieldConfig->addComponent($filter = new GridFieldFilterHeader());
333
                $gridFieldConfig->addComponent(new GridFieldDataColumns());
334
                $gridFieldConfig->addComponent(new GridFieldEditButton());
335
                $gridFieldConfig->addComponent(new GridFieldDeleteAction(true));
336
                $gridFieldConfig->addComponent(new GridFieldPageCount('toolbar-header-right'));
337
                $gridFieldConfig->addComponent($pagination = new GridFieldPaginator());
338
                $gridFieldConfig->addComponent(new GridFieldDetailForm());
339
340
                $source = $this->$fieldName();
341
                return new GridField($fieldName, _t("PickUpOrDeliverModifierOptions.AVAILABLEINCOUNTRIES", "".$title), $source, $gridFieldConfig);
342
            }
343
        }
344
        if ($field) {
345
            return $field;
346
        } else {
347
            return new HiddenField($fieldName);
348
        }
349
    }
350
351
    /**
352
     * make sure there is only exactly one default
353
     */
354
    public function onAfterWrite()
355
    {
356
        parent::onAfterWrite();
357
        // no other record but current one is not default
358
        if ((!$this->IsDefault) && (PickUpOrDeliveryModifierOptions::get()->exclude(array("ID" => intval($this->ID)))->count() == 0)) {
359
            DB::query("
360
                UPDATE \"PickUpOrDeliveryModifierOptions\"
361
                SET \"IsDefault\" = 1
362
                WHERE \"ID\" <> ".$this->ID.";");
363
        }
364
        //current default -> reset others
365
        elseif ($this->IsDefault) {
366
            DB::query("
367
                UPDATE \"PickUpOrDeliveryModifierOptions\"
368
                SET \"IsDefault\" = 0
369
                WHERE \"ID\" <> ".intval($this->ID).";");
370
        }
371
    }
372
373
    /**
374
     * make sure all are unique codes
375
     */
376
    public function onBeforeWrite()
377
    {
378
        parent::onBeforeWrite();
379
        $this->Code = trim(preg_replace("/[^a-zA-Z0-9]+/", "", $this->Code));
380
        $i = 0;
381
        if (!$this->Code) {
382
            $defaults = $this->Config()->get("Code");
383
            $this->Code = empty($defaults["Code"]) ? "CODE" : $defaults["Code"];
384
        }
385
        $baseCode = $this->Code;
386
        while (PickUpOrDeliveryModifierOptions::get()->filter(array("Code" => $this->Code))->exclude(array("ID" => $this->ID))->count() && $i < 100) {
387
            $i++;
388
            $this->Code = $baseCode.'_'.$i;
389
        }
390
        if ($this->MinimumDeliveryCharge && $this->MaximumDeliveryCharge) {
391
            if ($this->MinimumDeliveryCharge > $this->MaximumDeliveryCharge) {
392
                $this->MinimumDeliveryCharge = $this->MaximumDeliveryCharge;
393
            }
394
        }
395
    }
396
397
    public function getListOfCountries()
398
    {
399
        $in = '';
400
        $out = '';
401
        if ($this->AvailableInCountries()->count()) {
402
            $in = "".implode(', ', $this->AvailableInCountries()->column("Code"));
403
        }
404
        if ($this->ExcludeFromCountries()->count()) {
405
            $out = " // OUT: ".implode(', ', $this->ExcludeFromCountries()->column("Code"));
406
        }
407
        return $in.$out;
408
    }
409
}
410