Completed
Push — master ( 613b2e...a2195f )
by Nicolaas
03:28
created

EcommerceTaskCheckConfiguration::definedConfigs()   F

Complexity

Conditions 23
Paths > 20000

Size

Total Lines 182
Code Lines 79

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
dl 0
loc 182
rs 2
c 0
b 0
f 0
eloc 79
nc 65603
nop 0

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
 * This class reviews all of the static configurations in e-commerce for review
5
 * (a) which configs are set, but not required
6
 * (b) which configs are required, but not set
7
 * (c) review of set configs.
8
 *
9
 * @TODO: compare to default
10
 *
11
 * shows you the link to remove the current cart
12
 *
13
 * @authors: Nicolaas [at] Sunny Side Up .co.nz
14
 * @package: ecommerce
15
 * @sub-package: tasks
16
 * @inspiration: Silverstripe Ltd, Jeremy
17
 **/
18
class EcommerceTaskCheckConfiguration extends BuildTask
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...
19
{
20
    /**
21
     * Default Location for Configuration File.
22
     *
23
     * @var string
24
     */
25
    protected $defaultLocation = 'ecommerce/_config/ecommerce.yml';
26
27
    /**
28
     * Standard (required) SS variable for BuildTasks.
29
     *
30
     * @var string
31
     */
32
    protected $title = 'Check Configuration';
33
34
    /**
35
     * Standard (required) SS variable for BuildTasks.
36
     *
37
     * @var string
38
     */
39
    protected $description = 'Runs through all static configuration for review.';
40
41
    /**
42
     * Array of definitions - set like this:
43
     * ClassName
44
     * 		VariableName: Description.
45
     *
46
     * @var array
47
     */
48
    protected $definitions = array();
49
50
    /**
51
     * Array of definitions Header - set like this:
52
     * HEADER TITLE
53
     * 		ClassName.
54
     *
55
     * @var array
56
     */
57
    protected $definitionsHeaders = array();
58
59
    /**
60
     * Array of defaults - set like this:
61
     * ClassName
62
     * 		VariableName: Default Variable Value.
63
     *
64
     * @var array
65
     */
66
    protected $defaults = array();
67
68
    /**
69
     * Array of configs - set like this:
70
     * ClassName
71
     * 		VariableName: VariableValue.
72
     *
73
     * @var array
74
     */
75
    protected $configs = array();
76
77
    /**
78
     * which values are derived from DB
79
     * ClassName
80
     * 		VariableName: TRUE | FALSE.
81
     *
82
     * @var array
83
     */
84
    protected $databaseValues = array();
85
86
    /**
87
     * set in default yml, but not customised.
88
     * ClassName
89
     * 		VariableName: TRUE | FALSE.
90
     *
91
     * @var array
92
     */
93
    protected $customisedValues = array();
94
95
    /**
96
     * Other configs
97
     * ClassName
98
     * 		VariableName: TRUE | FLASE.
99
     *
100
     * @var array
101
     */
102
    protected $otherConfigs = array();
103
104
    /**
105
     * Array of classes (partially) missing in configs.
106
     * VariableName: VariableName.
107
     *
108
     *  @var array
109
     */
110
    protected $missingClasses = array();
111
112
    /**
113
     * Standard (required) SS method, runs buildtask.
114
     */
115
    public function run($request)
116
    {
117
        $definitionsObject = EcommerceConfigDefinitions::create();
118
        $this->definitions = $definitionsObject->Definitions();
119
        $this->definitionsHeaders = $definitionsObject->GroupDefinitions();
120
        $configsObject = EcommerceConfig::create();
121
        $this->configs = $configsObject->getCompleteDataSet();
122
        $this->defaults = $this->getDefaultValues();
123
        if ($this->definitions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->definitions of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
124
            if ($this->configs) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->configs of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
125
                if ($this->defaults) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->defaults of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
126
                    $this->checkFiles();
127
                    $this->configsNotSet();
128
                    $this->classesThatDoNotExist();
129
                    $this->definitionsNotSet();
130
                    $this->addEcommerceDBConfigToConfigs();
131
                    $this->addOtherValuesToConfigs();
132
                    $this->addPages();
133
                    $this->orderSteps();
134
                    $this->checkoutAndModifierDetails();
135
                    $this->getAjaxDefinitions();
136
                    $this->definedConfigs();
137
                    $this->checkGEOIP();
138
                } else {
139
                    DB::alteration_message('ERROR: could not find any defaults', 'deleted');
140
                }
141
            } else {
142
                DB::alteration_message('ERROR: could not find any configs', 'deleted');
143
            }
144
        } else {
145
            DB::alteration_message('ERROR: could not find any definitions', 'deleted');
146
        }
147
    }
148
149
    /**
150
     * Check what files is being used.
151
     */
152
    protected function checkFiles()
153
    {
154
        $configsObject = EcommerceConfig::create();
155
        DB::alteration_message('<h2>Files Used</h2>');
156
        $files = implode(', ', $configsObject->fileLocations());
157
        global $project;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
158
        $baseFolder = Director::baseFolder();
159
        $projectFolder = $project.'/_config';
160
        $baseAndProjectFolder = $baseFolder.'/'.$projectFolder;
161
        $file = 'ecommerce.yml';
162
        $projectFolderAndFile = $projectFolder.'/'.$file;
163
        $fullFilePath = $baseFolder.'/'.$projectFolderAndFile;
164
        $defaultFileFullPath = Director::baseFolder().'/'.$this->defaultLocation;
165
        DB::alteration_message('
166
			Current files used: <strong style="color: darkRed">'.$files.'</strong>,
167
			unless stated otherwise, all settings can be edited in these file(s).',
168
            'created'
169
        );
170
        if (!file_exists($baseAndProjectFolder)) {
171
            mkdir($baseAndProjectFolder);
172
        }
173
        if (!file_exists($fullFilePath)) {
174
            copy($defaultFileFullPath, $fullFilePath);
175
            DB::alteration_message('We have created a new configuration file for you.', 'created');
176
        }
177
        if ($files == $this->defaultLocation) {
178
            if (file_exists($fullFilePath)) {
179
                DB::alteration_message("A customisable configuration file exists here: $projectFolderAndFile, you should add the following to your config.yml file:
180
<pre>
181
EcommerceConfig:
182
  folder_and_file_locations:
183
    - \"$projectFolderAndFile\"
184
</pre>", 'created');
185
            }
186
        }
187
    }
188
189
    /**
190
     * Work out items set in the configuration but not set in the config file.
191
     */
192
    protected function definitionsNotSet()
193
    {
194
        echo '<h2>Set in configs but not defined</h2>';
195
        $allOK = true;
196
        foreach ($this->configs as $className => $setting) {
197
            if (!isset($this->definitions[$className])) {
198
                $allOK = false;
199
                $this->missingClasses[$className] = $className;
200
                DB::alteration_message("$className", 'deleted');
201
            } else {
202
                $classConfigs = $this->configs[$className];
203
                foreach ($classConfigs as $key => $classConfig) {
204
                    if (!isset($this->definitions[$className][$key])) {
205
                        $allOK = false;
206
                        DB::alteration_message("$className.$key", 'deleted');
207
                    }
208
                }
209
            }
210
        }
211
        if ($allOK) {
212
            DB::alteration_message('Perfect match, nothing to report', 'created');
213
        } else {
214
            DB::alteration_message('Recommended course of action: remove from your config as these are superfluous!', 'edited');
215
        }
216
    }
217
218
    /**
219
     * Work out items set in the configuration but not set in the config file.
220
     */
221
    protected function classesThatDoNotExist()
222
    {
223
        echo '<h2>Classes that do not exist</h2>';
224
        $allOK = true;
225
        foreach ($this->configs as $className => $setting) {
226
            if (!class_exists($className)) {
227
                $allOK = false;
228
                DB::alteration_message("$className", 'deleted');
229
            }
230
        }
231
        if ($allOK) {
232
            DB::alteration_message('Perfect match, nothing to report', 'created');
233
        } else {
234
            DB::alteration_message('Recommended course of action: remove from your config file and review if any other action needs to be taken.', 'edited');
235
        }
236
    }
237
238
    /**
239
     * Work out items set in the definitions but not set in the config file.
240
     */
241
    protected function configsNotSet()
242
    {
243
        echo '<h2>Defined variables not set in configs ...</h2>';
244
        $allOK = true;
245
        //print_r($this->configs["EcommercePayment"]);
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% 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
        foreach ($this->definitions as $className => $setting) {
247
            if (!isset($this->configs[$className])) {
248
                DB::alteration_message("No settings found for $className in /ecommerce/_config/config.yml", 'deleted');
249
            } else {
250
                $classConfigs = $this->definitions[$className];
251
                foreach ($classConfigs as $key => $classConfig) {
252
                    if (!isset($this->configs[$className][$key])) {
253
                        $this->customisedValues[$className][$key] = false;
254
                        //fallback to Configs...
255
                    } else {
256
                        $this->customisedValues[$className][$key] = false;
257
                    }
258
                    if (!isset($this->configs[$className][$key])) {
259
                        DB::alteration_message(" - $className.$key NOT SET in /ecommerce/_config/config.yml", 'deleted');
260
                        $allOK = false;
261
                    } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
262
                        //$this->configs[$className][$key] = EcommerceConfig::get($className, $key);
0 ignored issues
show
Unused Code Comprehensibility introduced by
69% 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...
263
                        //if(!$this->configs[$className][$key]) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
87% 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...
264
                            //DB::alteration_message(" - $className.$key exists, set to FALSE / [EMPTRY STRING]", "edited");
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% 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...
265
                        //}
266
                    }
267
                }
268
            }
269
        }
270
        if ($allOK) {
271
            DB::alteration_message('Perfect match, nothing to report', 'created');
272
        } else {
273
            DB::alteration_message('Recommended course of action: add the above configs to your mysite/_config/ecommerce.yml file if you required them.', 'edited');
274
        }
275
    }
276
277
    /**
278
     * Work out items set in the definitions but not set in the config file.
279
     */
280
    protected function definedConfigs()
281
    {
282
        $htmlHeader = "
283
		<style>
284
			body {margin-left: 300px!important;}
285
			h2 {padding-top: 2em;margin-bottom: 0; padding-bottom: 0;}
286
			th[scope='col'] {text-align: left; border-bottom: 3px solid #ccdef3;padding-top: 40px;}
287
			td {vertical-align: top; border-left: 1px solid #d7d7d7; border-bottom: 1px solid #d7d7d7; padding: 10px; width: 47%;}
288
			/** headings **/
289
			td span.spanTitle {color: #002137; font-weight: 900; display: block; padding-left: 10px; padding-bottom: 5px;}
290
			.ecommerceConfigHeadings th, h2 {
291
				font-size: 1.2em;
292
				padding-bottom: 5px;
293
				color: #002137;
294
			}
295
			td span {color: #000; font-size: 0.8em; display: block; padding-left: 10px; }
296
			.sameConfig {color: #000;}
297
			.newConfig pre:first-of-type{color: #000; background-color: yellow;}
298
			.newConfig pre:first-of-type { }
299
			.newConfig pre:nth-of-type(2) { }
300
			#TOC {
301
				position: fixed;
302
				top: -15px;
303
				bottom: -20px;
304
				color: #fff;
305
				background-color: #000;
306
				width: 270px;
307
				left: 0px;
308
				padding-top: 15px;
309
				z-index: 10000;
310
				overflow: auto;
311
				padding-bottom: 20px;
312
			}
313
			#TOC ul {
314
				list-style-type: none;
315
			}
316
			#TOC li {
317
				line-height: 1.3;
318
				font-size: 80%;
319
				font-weight: 900;
320
				height: auto;
321
				list-style-type: none;
322
			}
323
			#TOC a {
324
				color: #fff;
325
				text-decoration: none;
326
				font-size: 85%;
327
				font-weight: 900;
328
				margin-left: -10px;
329
			}
330
			#TOC a:hover {
331
				color: #7da4be;
332
			}
333
			/* not sure why we needed this ...
334
			#TaskHolder, #EcommerceDatabaseAdmin, .info h1, .info h3, .info a:first-of-type  {
335
				margin-left: 280px !important;
336
			}
337
			*/
338
			.info h1, .info h3, .info a {
339
				padding-left: 30px;
340
			}
341
			a.backToTop {display: block; font-size: 0.7em; float: right;}
342
			td.newConfig {}
343
			table td pre, table td sub {white-space:pre-wrap; font-size: 1em; font-weight: bold;margin: 3px; padding: 3px;}
344
			table td sub {font-weight: normal; font-size: 77%;}
345
346
			li pre {width: auto;}
347
		</style>
348
		";
349
        $htmlTable = '
350
		<table summary="list of configs">
351
		';
352
        $oldClassName = '';
353
        $htmlTOC = '<div id="TOC"><ul>';
354
        $count = 0;
355
        $oldHeaderOfGroup = '';
356
        $newHeader = '';
357
        $completedListOfClasses = array();
358
        foreach ($this->definitionsHeaders as $headerOfGroup => $classesArray) {
359
            if ($headerOfGroup == 'OTHER') {
360
                $classesArray = array_keys(array_diff_key($this->configs, $completedListOfClasses));
361
            }
362
            foreach ($classesArray as $className) {
363
                $completedListOfClasses[$className] = $className;
364
                if (!isset($this->configs[$className])) {
365
                    $this->configs[$className] = array();
366
                }
367
                $settings = $this->configs[$className];
368
                ++$count;
369
                if (in_array($className, $classesArray)) {
370
                    $newHeader = $headerOfGroup;
371
                }
372
                if ($oldHeaderOfGroup != $newHeader) {
373
                    $oldHeaderOfGroup = $headerOfGroup;
374
                    $htmlTOC .= "</ul><li class=\"header\">$headerOfGroup</li><ul>";
375
                }
376
377
                $htmlTOC .= "<li><a href=\"#$className\">$count. $className</a></li>";
378
                if ($className != $oldClassName) {
379
                    $htmlTable .= "<tr  class='ecommerceConfigHeadings' id=\"$className\"><th colspan=\"2\" scope=\"col\">
380
					$count. $className ($newHeader)
381
					<a class=\"backToTop\" href=\"#TaskHolder\">top</a>
382
					</th></tr>";
383
                    $oldClassName = $className;
384
                }
385
                if (is_array($settings)) {
386
                    foreach ($settings as $key => $classConfig) {
387
                        $configError = '';
388
                        $class = '';
389
                        $hasDefaultvalue = false;
0 ignored issues
show
Unused Code introduced by
$hasDefaultvalue is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
390
                        $isDatabaseValues = isset($this->databaseValues[$className][$key]) ? $this->databaseValues[$className][$key] : false;
391
                        $isOtherConfigs = isset($this->otherConfigs[$className][$key]) ? $this->otherConfigs[$className][$key] : false;
392
                        $isCustomisedValues = isset($this->customisedValues[$className][$key]) ? $this->customisedValues[$className][$key] : false;
393
                        if (!isset($this->defaults[$className][$key])) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
394
                            //DB::alteration_message("Could not retrieve default value for: $className $key", "deleted");
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% 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...
395
                        } else {
396
                            $defaultValue = print_r($this->defaults[$className][$key], 1);
397
                            $hasDefaultvalue = true;
0 ignored issues
show
Unused Code introduced by
$hasDefaultvalue is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
398
                        }
399
                        $manuallyAddedValue = print_r($this->configs[$className][$key], 1);
400
                        $actualValueRaw = EcommerceConfig::get($className, $key);
401
                        //if(!$actualValueRaw && $manuallyAddedValue) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
73% 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...
402
                        //	$actualValueRaw = $manuallyAddedValue;
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% 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...
403
                        //}
404
405
                        $actualValue = print_r($actualValueRaw, 1);
406
                        if ($defaultValue === $manuallyAddedValue && $isCustomisedValues) {
0 ignored issues
show
Bug introduced by
The variable $defaultValue does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
407
                            $configError .= 'This is a superfluous entry in your custom config as the default value is the same.';
408
                        }
409
                        $hasDefaultvalue = true;
410
                        if ($defaultValue === $actualValue) {
411
                            $class .= 'sameConfig';
412
                            $defaultValue = '';
413
                            $hasDefaultvalue = false;
414
                        } else {
415
                            $class .= ' newConfig';
416
                        }
417
                        $actualValue = $this->turnValueIntoHumanReadableValue($actualValue);
418
                        if ($hasDefaultvalue) {
419
                            $defaultValue = $this->turnValueIntoHumanReadableValue($defaultValue);
420
                        }
421
422
                        if (!isset($this->definitions[$className][$key])) {
423
                            $description = '<span style="color: red; font-weight: bold">ERROR: no longer required in configs!</span>';
424
                        } else {
425
                            $description = $this->definitions[$className][$key];
426
                            $description .= $this->specialCases($className, $key, $actualValue);
427
                        }
428
                        $defaultValueHTML = '';
429
                        if ($defaultValue && !$isOtherConfigs) {
430
                            $defaultValueHTML = "<sub>default:</sub><pre>$defaultValue</pre>";
431
                        }
432
                        if ($configError) {
433
                            $configError = "<span style=\"color: red; font-size: 10px;\">$configError</span>";
434
                        }
435
                        $sourceNote = '';
436
                        if ($isDatabaseValues) {
437
                            $sourceNote = '<span>Values are set in the database using the CMS.</span>';
438
                        }
439
                        $htmlTable .= "<tr>
440
				<td>
441
					<span class='spanTitle'>$key</span>
442
					<span>$description</span>
443
					$sourceNote
444
				</td>
445
				<td class=\"$class\">
446
					<pre>$actualValue</pre>
447
					$defaultValueHTML
448
					$configError
449
				</td>
450
			</tr>";
451
                    }
452
                }
453
            }
454
        }
455
        $htmlEnd = '
456
		</table>
457
		<h2>--- THE END ---</h2>
458
		';
459
        $htmlTOC .= '</ul></div>';
460
        echo $htmlHeader.$htmlTOC.$htmlTable.$htmlEnd;
461
    }
462
463
    protected function getDefaultValues()
464
    {
465
        require_once 'thirdparty/spyc/spyc.php';
466
        $fixtureFolderAndFile = Director::baseFolder().'/'.$this->defaultLocation;
467
        $parser = new Spyc();
468
469
        return $parser->loadFile($fixtureFolderAndFile);
470
    }
471
472
    /**
473
     * Adding EcommerceDBConfig values.
474
     */
475
    protected function addEcommerceDBConfigToConfigs()
476
    {
477
        $ecommerceDBConfig = EcommerceDBConfig::current_ecommerce_db_config();
478
        $fields = $ecommerceDBConfig->fieldLabels();
479
        if ($fields) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $fields of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
480
            foreach ($fields as $field => $description) {
481
                if ($field != 'Title' && $field != 'UseThisOne') {
482
                    $defaultsDefaults = $ecommerceDBConfig->stat('defaults');
483
                    $this->definitions['EcommerceDBConfig'][$field] = "$description. <br />see: <a href=\"/admin/shop/EcommerceDBConfig/EditForm/field/EcommerceDBConfig/item/".$ecommerceDBConfig->ID.'/edit">Ecommerce Configuration</a>';
484
                    $this->configs['EcommerceDBConfig'][$field] = $ecommerceDBConfig->$field;
485
                    $this->databaseValues['EcommerceDBConfig'][$field] = true;
486
                    $this->defaults['EcommerceDBConfig'][$field] = isset($defaultsDefaults[$field]) ? $defaultsDefaults[$field] : 'no default set';
487
                    $imageField = $field.'ID';
488
                    if (isset($ecommerceDBConfig->$imageField)) {
489
                        if ($image = $ecommerceDBConfig->$field()) {
490
                            if ($image->exists() && is_a($image, Object::getCustomClass('Image'))) {
491
                                $this->configs['EcommerceDBConfig'][$field] = '[Image]  --- <img src="'.$image->Link().'" />';
492
                                $this->databaseValues['EcommerceDBConfig'][$field] = true;
493
                            }
494
                        }
495
                    }
496
                }
497
            }
498
        }
499
    }
500
501
    protected function addOtherValuesToConfigs()
502
    {
503
        $this->definitions['Email']['admin_email_address'] = 'Default administrator email. <br />SET USING Email::$admin_email = "[email protected]" in the _config.php FILES';
504
        $this->configs['Email']['admin_email_address'] = Config::inst()->get('Email', 'admin_email');
505
        $this->defaults['Email']['admin_email_address'] = '[no default set]';
506
        $this->otherConfigs['Email']['admin_email_address'] = true;
507
508
        $siteConfig = SiteConfig::current_site_config();
509
        $this->definitions['SiteConfig']['website_title'] = 'The name of the website. <br />see: <a href="/admin/settings/">site configuration</a>.';
510
        $this->configs['SiteConfig']['website_title'] = $siteConfig->Title;
511
        $this->defaults['SiteConfig']['website_title'] = '[no default set]';
512
        $this->otherConfigs['SiteConfig']['website_title'] = true;
513
514
        $this->definitions['SiteConfig']['website_tagline'] = 'The subtitle or tagline of the website. <br />see: <a href="/admin/settings/">site configuration</a>.';
515
        $this->configs['SiteConfig']['website_tagline'] = $siteConfig->Tagline;
516
        $this->defaults['SiteConfig']['website_tagline'] = '[no default set]';
517
        $this->otherConfigs['SiteConfig']['website_tagline'] = true;
518
    }
519
520
    protected function addPages()
521
    {
522
        if ($checkoutPage = CheckoutPage::get()->First()) {
523
            $this->getPageDefinitions($checkoutPage);
524
            $this->definitions['Pages']['CheckoutPage'] = 'Page where customers finalise (checkout) their order. This page is required.<br />'.($checkoutPage ? '<a href="/admin/pages/edit/show/'.$checkoutPage->ID.'/">edit</a>' : 'Create one in the <a href="/admin/pages/add/">CMS</a>');
525
            $this->configs['Pages']['CheckoutPage'] = $checkoutPage ? 'view: <a href="'.$checkoutPage->Link().'">'.$checkoutPage->Title.'</a><br />'.$checkoutPage->configArray : ' NOT CREATED!';
526
            $this->defaults['Pages']['CheckoutPage'] = $checkoutPage ? $checkoutPage->defaultsArray : '[add page first to see defaults]';
527
            $this->databaseValues['Pages']['CheckoutPage'] = true;
528
        }
529
530
        if ($orderConfirmationPage = OrderConfirmationPage::get()->First()) {
531
            $this->getPageDefinitions($orderConfirmationPage);
532
            $this->definitions['Pages']['OrderConfirmationPage'] = 'Page where customers review their order after it has been placed. This page is required.<br />'.($orderConfirmationPage ? '<a href="/admin/pages/edit/show/'.$orderConfirmationPage->ID.'/">edit</a>' : 'Create one in the <a href="/admin/pages/add/">CMS</a>');
533
            $this->configs['Pages']['OrderConfirmationPage'] = $orderConfirmationPage ? 'view: <a href="'.$orderConfirmationPage->Link().'">'.$orderConfirmationPage->Title.'</a><br />'.$orderConfirmationPage->configArray : ' NOT CREATED!';
534
            $this->defaults['Pages']['OrderConfirmationPage'] = $orderConfirmationPage ? $orderConfirmationPage->defaultsArray : '[add page first to see defaults]';
535
            $this->databaseValues['Pages']['OrderConfirmationPage'] = true;
536
        }
537
538
        if ($accountPage = AccountPage::get()->First()) {
539
            $this->getPageDefinitions($accountPage);
540
            $this->definitions['Pages']['AccountPage'] = 'Page where customers can review their account. This page is required.<br />'.($accountPage ? '<a href="/admin/pages/edit/show/'.$accountPage->ID.'/">edit</a>' : 'Create one in the <a href="/admin/pages/add/">CMS</a>');
541
            $this->configs['Pages']['AccountPage'] = $accountPage ? 'view: <a href="'.$accountPage->Link().'">'.$accountPage->Title.'</a><br />'.$accountPage->configArray : ' NOT CREATED!';
542
            $this->defaults['Pages']['AccountPage'] = $accountPage ? $accountPage->defaultsArray : '[add page first to see defaults]';
543
            $this->databaseValues['Pages']['AccountPage'] = true;
544
        }
545
546
        if (
547
            $cartPage = CartPage::get()
548
                ->Filter(array('ClassName' => 'CartPage'))
549
                ->First()
550
        ) {
551
            $this->getPageDefinitions($cartPage);
552
            $this->definitions['Pages']['CartPage'] = 'Page where customers review their cart while shopping. This page is optional.<br />'.($cartPage ? '<a href="/admin/pages/edit/show/'.$cartPage->ID.'/">edit</a>' : 'Create one in the <a href="/admin/pages/add/">CMS</a>');
553
            $this->configs['Pages']['CartPage'] = $cartPage ? 'view: <a href="'.$cartPage->Link().'">'.$cartPage->Title.'</a>, <a href="/admin/pages/edit/show/'.$cartPage->ID.'/">edit</a><br />'.$cartPage->configArray : ' NOT CREATED!';
554
            $this->defaults['Pages']['CartPage'] = $cartPage ? $cartPage->defaultsArray : '[add page first to see defaults]';
555
            $this->defaults['Pages']['CartPage'] = $cartPage ? $cartPage->defaultsArray : '[add page first to see defaults]';
556
            $this->databaseValues['Pages']['CartPage'] = true;
557
        }
558
    }
559
560
    private function getPageDefinitions(SiteTree $page)
561
    {
562
        if ($page) {
563
            $fields = Config::inst()->get($page->ClassName, 'db');
564
            $defaultsArray = $page->stat('defaults', true);
565
            $configArray = array();
566
            if ($fields) {
567
                foreach ($fields as $fieldKey => $fieldType) {
0 ignored issues
show
Bug introduced by
The expression $fields of type array|integer|double|string|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
568
                    $configArray[$fieldKey] = $page->$fieldKey;
569
                    if (!isset($defaultsArray[$fieldKey])) {
570
                        $defaultsArray[$fieldKey] = '[default not set]';
571
                    }
572
                }
573
            }
574
            $page->defaultsArray = $defaultsArray;
0 ignored issues
show
Bug introduced by
The property defaultsArray does not seem to exist. Did you mean defaults?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
575
            $page->configArray = print_r($configArray, 1);
576
        }
577
    }
578
579
    public function orderSteps()
580
    {
581
        $steps = OrderStep::get();
582
        if ($steps->count()) {
583
            foreach ($steps as $step) {
584
                $fields = Config::inst()->get($step->ClassName, 'db');
585
                $defaultsArray = $step->stat('defaults', true);
586
                $configArray = array();
587
                foreach ($fields as $fieldKey => $fieldType) {
0 ignored issues
show
Bug introduced by
The expression $fields of type array|integer|double|string|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
588
                    if ($fields) {
589
                        $configArray[$fieldKey] = $step->$fieldKey;
590
                        if (!isset($defaultsArray[$fieldKey])) {
591
                            $defaultsArray[$fieldKey] = '[default not set]';
592
                        }
593
                    }
594
                }
595
                $ecommerceDBConfig = EcommerceDBConfig::current_ecommerce_db_config();
0 ignored issues
show
Unused Code introduced by
$ecommerceDBConfig is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
596
                $this->definitions['OrderStep'][$step->Code] = $step->Description.'<br />see: <a href="/admin/shop/OrderStep/EditForm/field/OrderStep/item/'.$step->ID.'/edit">Ecommerce Configuration</a>.';
597
                $this->configs['OrderStep'][$step->Code] = $configArray;
598
                $this->defaults['OrderStep'][$step->Code] = $defaultsArray;
599
                $this->databaseValues['OrderStep'][$step->Code] = true;
600
            }
601
        }
602
    }
603
604
    public function checkoutAndModifierDetails()
605
    {
606
        $checkoutPage = CheckoutPage::get()->First();
607
        if (!$checkoutPage) {
608
            $task = new EcommerceTaskDefaultRecords();
609
            $task->run(null);
610
            $checkoutPage = CheckoutPage::get()->First();
611
            if (!$checkoutPage) {
612
                user_error('There is no checkout page available and it seems impossible to create one.');
613
            }
614
        }
615
        $steps = CheckoutPage_StepDescription::get();
616
        if ($steps->count()) {
617
            foreach ($steps as $key => $step) {
618
                $stepNumber = $key + 1;
619
                $fields = Config::inst()->get($step->ClassName, 'db');
620
                $defaultsArray = $step->stat('defaults', true);
621
                $configArray = array();
622
                foreach ($fields as $fieldKey => $fieldType) {
0 ignored issues
show
Bug introduced by
The expression $fields of type array|integer|double|string|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
623
                    if ($fields) {
624
                        $configArray[$fieldKey] = $step->$fieldKey;
625
                        if (!isset($defaultsArray[$fieldKey])) {
626
                            $defaultsArray[$fieldKey] = '[default not set]';
627
                        }
628
                    }
629
                }
630
                $this->definitions['CheckoutPage_Controller']["STEP_$stepNumber".'_'.$step->getCode()] = $step->Description.'<br />see: <a href="/admin/pages/edit/show/'.$checkoutPage->ID.'/">checkout page</a>.';
631
                $this->configs['CheckoutPage_Controller']["STEP_$stepNumber".'_'.$step->getCode()] = $configArray;
632
                $this->defaults['CheckoutPage_Controller']["STEP_$stepNumber".'_'.$step->getCode()] = $defaultsArray;
633
                $this->databaseValues['CheckoutPage_Controller']["STEP_$stepNumber".'_'.$step->getCode()] = true;
634
            }
635
        }
636
        $steps = OrderModifier_Descriptor::get();
637
        if ($steps->count()) {
638
            foreach ($steps as $step) {
639
                $fields = Config::inst()->get($step->ClassName, 'db');
640
                $defaultsArray = $step->stat('defaults', true);
641
                $configArray = array();
642
                foreach ($fields as $fieldKey => $fieldType) {
0 ignored issues
show
Bug introduced by
The expression $fields of type array|integer|double|string|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
643
                    if ($fields) {
644
                        $configArray[$fieldKey] = $step->$fieldKey;
645
                        if (!isset($defaultsArray[$fieldKey])) {
646
                            $defaultsArray[$fieldKey] = '[default not set]';
647
                        }
648
                    }
649
                }
650
                $this->definitions['CheckoutPage_Controller']['OrderModifier_Descriptor_'.$step->ModifierClassName] = $step->Description.'<br />see: <a href="/admin/pages/edit/show/'.$checkoutPage->ID.'/">checkout page</a>.';
651
                $this->configs['CheckoutPage_Controller']['OrderModifier_Descriptor_'.$step->ModifierClassName] = $configArray;
652
                $this->defaults['CheckoutPage_Controller']['OrderModifier_Descriptor_'.$step->ModifierClassName] = $defaultsArray;
653
                $this->databaseValues['CheckoutPage_Controller']['OrderModifier_Descriptor_'.$step->ModifierClassName] = true;
654
            }
655
        }
656
    }
657
658
    private function getAjaxDefinitions()
659
    {
660
        $definitionsObject = EcommerceConfigDefinitions::create();
661
        $methodArray = $definitionsObject->getAjaxMethods();
662
        $requestor = new ArrayData(
663
            array(
664
                'ID' => '[ID]',
665
                'ClassName' => '[CLASSNAME]',
666
            )
667
        );
668
        $obj = EcommerceConfigAjax::get_one($requestor);
0 ignored issues
show
Documentation introduced by
$requestor is of type object<ArrayData>, but the function expects a object<DataObject>.

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...
669
        foreach ($methodArray as $method => $description) {
670
            if ($method != 'setRequestor') {
671
                if (strpos($method, 'lassName')) {
672
                    $selector = 'classname';
673
                } else {
674
                    $selector = 'id';
675
                }
676
                $note = "
677
					This variable can be used like this: <pre>&lt;div $selector=\"\$AJAXDefinitions.".$method.'"&gt;&lt;/div&gt;</pre>
678
					<a href="/shoppingcart/ajaxtest/?ajax=1">AJAX</a> will then use this selector to put the following content: ';
679
                $this->definitions['Templates']["AJAXDefinitions_$method"] = $note.'<br />'.$description;
680
                $this->configs['Templates']["AJAXDefinitions_$method"] = $obj->$method();
681
                $this->defaults['Templates']["AJAXDefinitions_$method"] = '';
682
                $this->otherConfigs['Templates']["AJAXDefinitions_$method"] = true;
683
            }
684
        }
685
    }
686
687
    /**
688
     * check for any additional settings.
689
     */
690
    private function specialCases($className, $key, $actualValue)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
691
    {
692
        switch ($className.'.'.$key) {
693
            case 'Order_Email.css_file_location':
694
                if (!file_exists(Director::baseFolder()."/$actualValue")) {
695
                    return '<span style="color: red">ADDITIONAL CHECK: this file '.Director::baseFolder().'/'.$actualValue.' does not exist! For proper functioning of e-commerce, please make sure to create this file.</span>';
696
                } else {
697
                    return '<span style="color: #7da4be">ADDITIONAL CHECK: file exists.</span>';
698
                }
699
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
700
            case 'Order.modifiers':
701
                $classes = ClassInfo::subclassesFor('OrderModifier');
702
                unset($classes['OrderModifier']);
703
                $classesAsString = implode(', <br />', $classes);
704
705
                return "<br /><h4>Available Modifiers</h4>$classesAsString";
706
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
707
            case 'OrderStatusLog.available_log_classes_array':
708
                $classes = ClassInfo::subclassesFor('OrderStatusLog');
709
                unset($classes['OrderStatusLog']);
710
                $classesAsString = implode(', <br />', $classes);
711
712
                return "<br /><h4>Available Modifiers</h4>$classesAsString";
713
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
714
            case 'OrderStep.order_steps_to_include':
715
                $classes = ClassInfo::subclassesFor('OrderStep');
716
                unset($classes['OrderStep']);
717
                $classesAsString = implode('<br /> - ', $classes);
718
719
                return "<br /><h4>Available Order Steps</h4> - $classesAsString";
720
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
721
        }
722
    }
723
724
    private function turnValueIntoHumanReadableValue($actualValue)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
725
    {
726
        if ($actualValue === '') {
727
            $actualValue = '[FALSE] / [EMPTY STRING] ';
728
        }
729
        if ($actualValue === null) {
730
            $actualValue = '[NULL]';
731
        }
732
        if ($actualValue === '1' || $actualValue === 1) {
733
            $actualValue = '[TRUE] / 1';
734
        }
735
        if ($actualValue === '0' || $actualValue === false) {
736
            $actualValue = '[FALSE] / 0';
737
        }
738
739
        return $actualValue;
740
    }
741
742
    protected function checkGEOIP()
743
    {
744
        if (Config::inst()->get('EcommerceCountry', 'visitor_country_provider') == 'EcommerceCountry_VisitorCountryProvider' && !class_exists('Geoip')) {
745
            user_error("
746
				You need to install Geoip module that has a method Geoip::visitor_country, returning the country code associated with the user's IP address.
747
				Alternatively you can set the following config EcommerceCountry.visitor_country_provider to something like MyGEOipProvider.
748
				You then create a class MyGEOipProvider with a method getCountry().",
749
                E_USER_NOTICE
750
            );
751
        } elseif (Director::isLive() && !EcommerceCountry::get_country_from_ip()) {
752
            user_error("
753
				Please make sure that '".$this->Config()->get('visitor_country_provider')."' (visitor_country_provider) is working on your server (see the GEOIP module for details).",
754
                E_USER_NOTICE
755
            );
756
        }
757
    }
758
}
759