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

EcommerceDBConfig::CMSEditLink()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
eloc 5
nc 1
nop 1
1
<?php
2
3
/**
4
 * Database Settings for E-commerce
5
 * Similar to SiteConfig but then for E-commerce
6
 * To access a singleton here, use: EcommerceDBConfig::current_ecommerce_db_config().
7
 *
8
 * @authors: Nicolaas [at] Sunny Side Up .co.nz
9
 * @package: ecommerce
10
 * @sub-package: tasks
11
 * @inspiration: Silverstripe Ltd, Jeremy
12
 **/
13
class EcommerceDBConfig extends DataObject implements EditableEcommerceObject
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...
14
{
15
    /**
16
     * Standard SS Variable.
17
     *
18
     * @var array
19
     */
20
    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...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
21
        'Title' => 'Varchar(30)',
22
        'UseThisOne' => 'Boolean',
23
        'ShopClosed' => 'Boolean',
24
        'ShopPricesAreTaxExclusive' => 'Boolean',
25
        'InvoiceTitle' => 'Varchar(200)',
26
        'PackingSlipTitle' => 'Varchar(200)',
27
        'PackingSlipNote' => 'HTMLText',
28
        'ShopPhysicalAddress' => 'HTMLText',
29
        'ReceiptEmail' => 'Varchar(255)',
30
        'PostalCodeURL' => 'Varchar(255)',
31
        'PostalCodeLabel' => 'Varchar(255)',
32
        'NumberOfProductsPerPage' => 'Int',
33
        'ProductsAlsoInOtherGroups' => 'Boolean',
34
        'OnlyShowProductsThatCanBePurchased' => 'Boolean',
35
        'NotForSaleMessage' => 'HTMLText',
36
        'ProductsHaveWeight' => 'Boolean',
37
        'ProductsHaveModelNames' => 'Boolean',
38
        'ProductsHaveQuantifiers' => 'Boolean',
39
        //"ProductsHaveVariations" => "Boolean",
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
40
        'CurrenciesExplanation' => 'HTMLText',
41
        'AllowFreeProductPurchase' => 'Boolean',
42
    );
43
44
    /**
45
     * Standard SS Variable.
46
     *
47
     * @var array
48
     */
49
    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...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
50
        'EmailLogo' => 'Image',
51
        'DefaultProductImage' => 'Product_Image',
52
    );
53
54
    /**
55
     * Standard SS Variable.
56
     *
57
     * @var array
58
     */
59
    private static $indexes = array(
0 ignored issues
show
Unused Code introduced by
The property $indexes 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...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
60
        'UseThisOne' => true,
61
        'ShopClosed' => true,
62
        'ShopPricesAreTaxExclusive' => true,
63
        'NumberOfProductsPerPage' => true,
64
        'OnlyShowProductsThatCanBePurchased' => true,
65
    );
66
67
    /**
68
     * Standard SS Variable.
69
     *
70
     * @var array
71
     */
72
    private static $casting = array(
0 ignored issues
show
Unused Code introduced by
The property $casting 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...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
73
        'UseThisOneNice' => 'Varchar',
74
    ); //adds computed fields that can also have a type (e.g.
75
76
    /**
77
     * Standard SS Variable.
78
     *
79
     * @var array
80
     */
81
    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...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
82
        'Title' => 'PartialMatchFilter',
83
    );
84
85
    /**
86
     * Standard SS Variable.
87
     *
88
     * @var array
89
     */
90
    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...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
91
92
    /**
93
     * Standard SS Variable.
94
     *
95
     * @var array
96
     */
97
    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...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
98
        'Title' => 'Title',
99
        'UseThisOneNice' => 'Use this configuration set',
100
    ); //note no => for relational fields
101
102
    /**
103
     * Standard SS Method.
104
     *
105
     * @param Member $member
0 ignored issues
show
Documentation introduced by
Should the type for parameter $member not be Member|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
106
     *
107
     * @var bool
108
     */
109
    public function canCreate($member = null)
110
    {
111
        if (! $member) {
112
            $member = Member::currentUser();
113
        }
114
        $extended = $this->extendedCan(__FUNCTION__, $member);
0 ignored issues
show
Documentation introduced by
$member is of type object<DataObject>|null, but the function expects a object<Member>|integer.

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...
115
        if ($extended !== null) {
116
            return $extended;
117
        }
118
119
        return $this->canEdit($member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by \Member::currentUser() on line 112 can also be of type object<DataObject>; however, EcommerceDBConfig::canEdit() does only seem to accept object<Member>|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
120
    }
121
122
    /**
123
     * Standard SS Method.
124
     *
125
     * @param Member $member
0 ignored issues
show
Documentation introduced by
Should the type for parameter $member not be Member|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
126
     *
127
     * @var bool
128
     */
129
    public function canView($member = null)
130
    {
131
        if (! $member) {
132
            $member = Member::currentUser();
133
        }
134
        $extended = $this->extendedCan(__FUNCTION__, $member);
0 ignored issues
show
Documentation introduced by
$member is of type object<DataObject>|null, but the function expects a object<Member>|integer.

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...
135
        if ($extended !== null) {
136
            return $extended;
137
        }
138
139
        return $this->canEdit($member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by \Member::currentUser() on line 132 can also be of type object<DataObject>; however, EcommerceDBConfig::canEdit() does only seem to accept object<Member>|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
140
    }
141
142
    /**
143
     * Standard SS Method.
144
     *
145
     * @param Member $member
0 ignored issues
show
Documentation introduced by
Should the type for parameter $member not be Member|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
146
     *
147
     * @var bool
148
     */
149
    public function canEdit($member = null)
150
    {
151
        if (! $member) {
152
            $member = Member::currentUser();
153
        }
154
        $extended = $this->extendedCan(__FUNCTION__, $member);
0 ignored issues
show
Documentation introduced by
$member is of type object<DataObject>|null, but the function expects a object<Member>|integer.

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...
155
        if ($extended !== null) {
156
            return $extended;
157
        }
158
        if (Permission::checkMember($member, Config::inst()->get('EcommerceRole', 'admin_permission_code'))) {
159
            return true;
160
        }
161
162
        return parent::canEdit($member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by \Member::currentUser() on line 152 can also be of type object<DataObject>; however, DataObject::canEdit() does only seem to accept object<Member>|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
163
    }
164
165
    /**
166
     * Standard SS Method.
167
     *
168
     * @param Member $member
0 ignored issues
show
Documentation introduced by
Should the type for parameter $member not be Member|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
169
     *
170
     * @var bool
171
     */
172
    public function canDelete($member = null)
173
    {
174
        if ($this->UseThisOne) {
0 ignored issues
show
Documentation introduced by
The property UseThisOne does not exist on object<EcommerceDBConfig>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
175
            return false;
176
        } else {
177
            if (! $member) {
178
                $member = Member::currentUser();
179
            }
180
            $extended = $this->extendedCan(__FUNCTION__, $member);
0 ignored issues
show
Documentation introduced by
$member is of type object<DataObject>|null, but the function expects a object<Member>|integer.

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...
181
            if ($extended !== null) {
182
                return $extended;
183
            }
184
            if (Permission::checkMember($member, Config::inst()->get('EcommerceRole', 'admin_permission_code'))) {
185
                return true;
186
            }
187
188
            return parent::canEdit($member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by \Member::currentUser() on line 178 can also be of type object<DataObject>; however, DataObject::canEdit() does only seem to accept object<Member>|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Comprehensibility Bug introduced by
It seems like you call parent on a different method (canEdit() instead of canDelete()). Are you sure this is correct? If so, you might want to change this to $this->canEdit().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
189
        }
190
    }
191
192
    /**
193
     * Standard SS variable.
194
     *
195
     * @var string
196
     */
197
    private static $default_sort = '"UseThisOne" DESC, "Created" ASC';
0 ignored issues
show
Unused Code introduced by
The property $default_sort 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...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
198
199
    /**
200
     * Standard SS variable.
201
     *
202
     * @var array
203
     */
204
    private static $defaults = array(
0 ignored issues
show
Unused Code introduced by
The property $defaults 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...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
205
        'Title' => 'Ecommerce Site Config',
206
        'UseThisOne' => true,
207
        'ShopClosed' => false,
208
        'ShopPricesAreTaxExclusive' => false,
209
        'InvoiceTitle' => 'Invoice',
210
        'PackingSlipTitle' => 'Package Contents',
211
        'PackingSlipNote' => 'Please make sure that all items are contained in this package.',
212
        'ShopPhysicalAddress' => '<p>Enter your shop address here.</p>',
213
        //"ReceiptEmail" => "Varchar(255)", - see populate defaults
214
        'PostalCodeURL' => '',
215
        'PostalCodeLabel' => '',
216
        'NumberOfProductsPerPage' => 12,
217
        'ProductsAlsoInOtherGroups' => false,
218
        'OnlyShowProductsThatCanBePurchased' => false,
219
        'NotForSaleMessage' => '<p>Not for sale, please contact us for more information.</p>',
220
        'ProductsHaveWeight' => false,
221
        'ProductsHaveModelNames' => false,
222
        'ProductsHaveQuantifiers' => false,
223
        //"ProductsHaveVariations" => false,
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
224
        'CurrenciesExplanation' => '<p>Apart from our main currency, you can view prices in a number of other currencies. The exchange rate is indicative only.</p>',
225
        'AllowFreeProductPurchase' => true,
226
    );
227
228
    /**
229
     * Standard SS Method.
230
     *
231
     * @var array
232
     */
233
    public function populateDefaults()
234
    {
235
        parent::populateDefaults();
236
        $this->ReceiptEmail = Email::config()->admin_email;
0 ignored issues
show
Documentation introduced by
The property ReceiptEmail does not exist on object<EcommerceDBConfig>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
237
    }
238
239
    /**
240
     * Standard SS variable.
241
     *
242
     * @var string
243
     */
244
    private static $singular_name = 'Main E-commerce Configuration';
0 ignored issues
show
Unused Code introduced by
The property $singular_name 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...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
245
    public function i18n_singular_name()
246
    {
247
        return _t('EcommerceDBConfig.ECOMMERCECONFIGURATION', 'Main E-commerce Configuration');
248
    }
249
250
    /**
251
     * Standard SS variable.
252
     *
253
     * @var string
254
     */
255
    private static $plural_name = 'Main E-commerce Configurations';
0 ignored issues
show
Unused Code introduced by
The property $plural_name 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...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
256
    public function i18n_plural_name()
257
    {
258
        return _t('EcommerceDBConfig.ECOMMERCECONFIGURATIONS', 'Main E-commerce Configurations');
259
    }
260
261
    /**
262
     * Standard SS variable.
263
     *
264
     * @var string
265
     */
266
    private static $description = 'A set of configurations for the shop. Each shop needs to have one or more of these settings.';
0 ignored issues
show
Unused Code introduced by
The property $description 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...
267
268
    /**
269
     * static holder for its own (or other EcommerceDBConfig) class.
270
     *
271
     * @var string | NULL
272
     */
273
    private static $_my_current_one = null;
274
    public static function reset_my_current_one()
275
    {
276
        self::$_my_current_one = null;
277
    }
278
279
    /**
280
     * implements singleton pattern.
281
     * Gets the current USE THIS ONE e-commerce option.
282
     *
283
     * @return EcommerceDBConfig | Object
284
     */
285
    public static function current_ecommerce_db_config()
286
    {
287
        if (!self::$_my_current_one) {
288
            $className = EcommerceConfig::get('EcommerceDBConfig', 'ecommerce_db_config_class_name');
289
            if (!class_exists('EcommerceDBConfig')) {
290
                $class = 'EcommerceDBConfig';
0 ignored issues
show
Unused Code introduced by
$class 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...
291
            }
292
            if (self::$_my_current_one = $className::get()->filter(array('UseThisOne' => 1))->first()) {
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...
293
                //do nothing
294
            } else {
295
                self::$_my_current_one = $className::create();
296
            }
297
        }
298
299
        return self::$_my_current_one;
300
    }
301
302
    /**
303
     * standard SS method for decorators.
304
     *
305
     * @param bool $includerelations
306
     *
307
     * @return array
308
     */
309
    public function fieldLabels($includerelations = true)
310
    {
311
        $defaultLabels = parent::fieldLabels();
312
        $newLabels = $this->customFieldLabels();
313
        $labels = array_merge($defaultLabels, $newLabels);
314
        $extendedLabels = $this->extend('updateFieldLabels', $labels);
315
        if ($extendedLabels !== null && is_array($extendedLabels) && count($extendedLabels)) {
316
            foreach ($extendedLabels as $extendedLabelsUpdate) {
317
                $labels = array_merge($labels, $extendedLabelsUpdate);
318
            }
319
        }
320
321
        return $labels;
322
    }
323
324
    /**
325
     * definition of field lables
326
     * TODO: is this a common SS method?
327
     *
328
     * @return array
329
     */
330
    public function customFieldLabels()
331
    {
332
        $newLabels = array(
333
            'Title' => _t('EcommerceDBConfig.TITLE', 'Name of settings'),
334
            'UseThisOne' => _t('EcommerceDBConfig.USETHISONE', 'Use these configuration settings'),
335
            'ShopClosed' => _t('EcommerceDBConfig.SHOPCLOSED', 'Shop Closed'),
336
            'ShopPricesAreTaxExclusive' => _t('EcommerceDBConfig.SHOPPRICESARETAXEXCLUSIVE', 'Shop prices are tax exclusive'),
337
            'InvoiceTitle' => _t('EcommerceDBConfig.INVOICETITLE', 'Default Email title'),
338
            'PackingSlipTitle' => _t('EcommerceDBConfig.PACKING_SLIP_TITLE', 'Packing slip title'),
339
            'PackingSlipNote' => _t('EcommerceDBConfig.PACKING_SLIP_NOTE', 'Packing slip notes'),
340
            'ShopPhysicalAddress' => _t('EcommerceDBConfig.SHOPPHYSICALADDRESS', 'Shop physical address'),
341
            'ReceiptEmail' => _t('EcommerceDBConfig.RECEIPTEMAIL', 'Shop Email Address'),
342
            'PostalCodeURL' => _t('EcommerceDBConfig.POSTALCODEURL', 'Postal code link'),
343
            'PostalCodeLabel' => _t('EcommerceDBConfig.POSTALCODELABEL', 'Postal code link label'),
344
            'NumberOfProductsPerPage' => _t('EcommerceDBConfig.NUMBEROFPRODUCTSPERPAGE', 'Number of products per page'),
345
            'OnlyShowProductsThatCanBePurchased' => _t('EcommerceDBConfig.ONLYSHOWPRODUCTSTHATCANBEPURCHASED', 'Only show products that can be purchased.'),
346
            'NotForSaleMessage' => _t('EcommerceDBConfig.NOTFORSALEMESSAGE', 'Not for sale message'),
347
            'ProductsHaveWeight' => _t('EcommerceDBConfig.PRODUCTSHAVEWEIGHT', 'Products have weight (e.g. 1.2kg)'),
348
            'ProductsHaveModelNames' => _t('EcommerceDBConfig.PRODUCTSHAVEMODELNAMES', 'Products have model names / numbers / codes'),
349
            'ProductsHaveQuantifiers' => _t('EcommerceDBConfig.PRODUCTSHAVEQUANTIFIERS', 'Products have quantifiers (e.g. per year, each, per dozen, etc...)'),
350
            'ProductsAlsoInOtherGroups' => _t('EcommerceDBConfig.PRODUCTSALSOINOTHERGROUPS', 'Allow products to show in multiple product groups'),
351
            //"ProductsHaveVariations" => _t("EcommerceDBConfig.PRODUCTSHAVEVARIATIONS", "Products have variations (e.g. size, colour, etc...)."),
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
352
            'CurrenciesExplanation' => _t('EcommerceDBConfig.CURRENCIESEXPLANATION', 'Currency explanation'),
353
            'EmailLogo' => _t('EcommerceDBConfig.EMAILLOGO', 'Email Logo'),
354
            'DefaultProductImage' => _t('EcommerceDBConfig.DEFAULTPRODUCTIMAGE', 'Default Product Image'),
355
            'DefaultThumbnailImageSize' => _t('EcommerceDBConfig.DEFAULTTHUMBNAILIMAGESIZE', 'Product Thumbnail Optimised Size'),
356
            'DefaultSmallImageSize' => _t('EcommerceDBConfig.DEFAULTSMALLIMAGESIZE', 'Product Small Image Optimised Size'),
357
            'DefaultContentImageSize' => _t('EcommerceDBConfig.DEFAULTCONTENTIMAGESIZE', 'Product Content Image Optimised Size'),
358
            'DefaultLargeImageSize' => _t('EcommerceDBConfig.DEFAULTLARGEIMAGESIZE', 'Product Large Image Optimised Size'),
359
            'AllowFreeProductPurchase' => _t('EcommerceDBConfig.ALLOWFREEPRODUCTPURCHASE', 'Allow free products to be purchased? '),
360
        );
361
362
        return $newLabels;
363
    }
364
365
    /**
366
     * definition of field lables
367
     * TODO: is this a common SS method?
368
     *
369
     * @return array
370
     */
371
    public function customDescriptionsForFields()
372
    {
373
        $newLabels = array(
374
            'Title' => _t('EcommerceDBConfig.TITLE_DESCRIPTION', 'For internal use only.'),
375
            'UseThisOne' => _t('EcommerceDBConfig.USETHISONE_DESCRIPTION', 'You can create several setting records so that you can switch between configurations.'),
376
            'ShopPricesAreTaxExclusive' => _t('EcommerceDBConfig.SHOPPRICESARETAXEXCLUSIVE_DESCRIPTION', 'If this option is NOT ticked, it is assumed that prices are tax inclusive.'),
377
            'ReceiptEmail' => _t('EcommerceDBConfig.RECEIPTEMAIL_DESCRIPTION_DESCRIPTION', 'e.g. [email protected], you can also use something like: "Our Shop Name Goes Here" &lt;[email protected]&gt;'),
378
            'AllowFreeProductPurchase' => _t('EcommerceDBConfig.ALLOWFREEPRODUCTPURCHASE_DESCRIPTION', 'This is basically a protection to disallow sales of products that do not have a price entered yet. '),
379
            'CurrenciesExplanation' => _t('EcommerceDBConfig.CURRENCIESEXPLANATION_DESCRIPTION', 'Explain how the user can switch between currencies and how the exchange rates are worked out.'),
380
            'PackingSlipTitle' => _t('EcommerceDBConfig.PACKINGSLIPTITLE', 'e.g. Package Contents'),
381
            'PackingSlipNote' => _t('EcommerceDBConfig.PACKING_SLIP_NOTE', 'e.g. a disclaimer'),
382
            'InvoiceTitle' => _t('EcommerceDBConfig.INVOICETITLE', 'e.g. Tax Invoice or Update for your recent order on www.yoursite.co.nz'),
383
        );
384
385
        return $newLabels;
386
    }
387
388
    /**
389
     * standard SS method.
390
     *
391
     * @return FieldList
392
     */
393
    public function getCMSFields()
394
    {
395
        $fields = parent::getCMSFields();
0 ignored issues
show
Unused Code introduced by
$fields 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...
396
397
        $self = $this;
398
        $self->beforeUpdateCMSFields(
399
            function ($fields) use ($self) {
400
                foreach ($self->customFieldLabels() as $name => $label) {
401
                    $fields->removeByName($name);
402
                }
403
                //new section
404
                $fieldDescriptions = $self->customDescriptionsForFields();
405
                $fieldLabels = $self->fieldLabels();
406
                $productImage = new Product_Image();
407
                $versionInfo = EcommerceConfigDefinitions::create();
0 ignored issues
show
Unused Code introduced by
$versionInfo 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...
408
                $fields->addFieldToTab('Root.Main', new TextField('Title', $fieldLabels['Title']));
409
                $fields->addFieldsToTab('Root', array(
410
                    Tab::create(
411
                        'Pricing',
412
                        _t('EcommerceDBConfig.PRICING', 'Pricing'),
413
                        new CheckboxField('ShopPricesAreTaxExclusive', $fieldLabels['ShopPricesAreTaxExclusive']),
414
                        new CheckboxField('AllowFreeProductPurchase', $fieldLabels['AllowFreeProductPurchase']),
415
                        $htmlEditorField1 = new HTMLEditorField('CurrenciesExplanation', $fieldLabels['CurrenciesExplanation'])
416
                    ),
417
                    Tab::create(
418
                        'Products',
419
                        _t('EcommerceDBConfig.PRODUCTS', 'Products'),
420
                        new NumericField('NumberOfProductsPerPage', $fieldLabels['NumberOfProductsPerPage']),
421
                        new CheckboxField('ProductsAlsoInOtherGroups', $fieldLabels['ProductsAlsoInOtherGroups']),
422
                        new CheckboxField('OnlyShowProductsThatCanBePurchased', $fieldLabels['OnlyShowProductsThatCanBePurchased']),
423
                        $htmlEditorField2 = new HTMLEditorField('NotForSaleMessage', $fieldLabels['NotForSaleMessage']),
424
                        new CheckboxField('ProductsHaveWeight', $fieldLabels['ProductsHaveWeight']),
425
                        new CheckboxField('ProductsHaveModelNames', $fieldLabels['ProductsHaveModelNames']),
426
                        new CheckboxField('ProductsHaveQuantifiers', $fieldLabels['ProductsHaveQuantifiers'])
427
                        //new CheckboxField("ProductsHaveVariations", $fieldLabels["ProductsHaveVariations"])
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% 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...
428
                    ),
429
                    Tab::create(
430
                        'ProductImages',
431
                        _t('EcommerceDBConfig.PRODUCT_IMAGES', 'Product Images'),
432
                        //new Product_ProductImageUploadField("DefaultProductImage", $fieldLabels["DefaultProductImage"], null, null, null, "default-product-image"),
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% 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...
433
                        new ReadonlyField('DefaultThumbnailImageSize', $fieldLabels['DefaultThumbnailImageSize'], $productImage->ThumbWidth().'px x '.$productImage->ThumbHeight().'px '),
434
                        new ReadonlyField('DefaultSmallImageSize', $fieldLabels['DefaultSmallImageSize'], $productImage->SmallWidth().'px x '.$productImage->SmallHeight().'px '),
435
                        new ReadonlyField('DefaultContentImageSize', $fieldLabels['DefaultContentImageSize'], $productImage->ContentWidth().'px wide'),
436
                        new ReadonlyField('DefaultLargeImageSize', $fieldLabels['DefaultLargeImageSize'], $productImage->LargeWidth().'px wide')
437
                    ),
438
                    Tab::create(
439
                        'AddressAndDelivery',
440
                        _t('EcommerceDBConfig.ADDRESS_AND_DELIVERY', 'Address and Delivery'),
441
                        new TextField('PostalCodeURL', $fieldLabels['PostalCodeURL']),
442
                        new TextField('PostalCodeLabel', $fieldLabels['PostalCodeLabel']),
443
                        $htmlEditorField3 = new HTMLEditorField('ShopPhysicalAddress', $fieldLabels['ShopPhysicalAddress']),
444
                        new TextField('PackingSlipTitle', $fieldLabels['PackingSlipTitle']),
445
                        $htmlEditorField4 = new HTMLEditorField('PackingSlipNote', $fieldLabels['PackingSlipNote'])
446
                    ),
447
                    Tab::create(
448
                        'Emails',
449
                        _t('EcommerceDBConfig.EMAILS', 'Emails'),
450
                        new TextField('ReceiptEmail', $fieldLabels['ReceiptEmail']),
451
                        new UploadField('EmailLogo', $fieldLabels['EmailLogo'],  null, null, null, 'logos'),
0 ignored issues
show
Unused Code introduced by
The call to UploadField::__construct() has too many arguments starting with null.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
452
                        new TextField('InvoiceTitle', $fieldLabels['InvoiceTitle'])
453
                    ),
454
                    Tab::create(
455
                        'Process',
456
                        _t('EcommerceDBConfig.PROCESS', 'Process'),
457
                        $self->getOrderStepsField()
458
                    ),
459
                    Tab::create(
460
                        'Advanced',
461
                        _t('EcommerceDBConfig.ADVANCED', 'Advanced'),
462
                        new LiteralField(
463
                            'ReviewHardcodedSettings',
464
                            '<p>
465
                                Your developer has pre-set some configurations for you.
466
                                You can
467
                                <a href="/dev/ecommerce/ecommercetaskcheckconfiguration" data-popup="true">review these settings</a>
468
                                but you will need to ask your developer to change them if they are not right.
469
                                The reason they can not be set is that changing them can break your application.
470
                            </p>'
471
                        )
472
                    )
473
                ));
474
                $mappingArray = Config::inst()->get('BillingAddress', 'fields_to_google_geocode_conversion');
475
                if (is_array($mappingArray) && count($mappingArray)) {
476
                    $mappingArray = Config::inst()->get('ShippingAddress', 'fields_to_google_geocode_conversion');
477
                    if (is_array($mappingArray) && count($mappingArray)) {
478
                        $fields->removeByName('PostalCodeURL');
479
                        $fields->removeByName('PostalCodeLabel');
480
                    }
481
                }
482
                $htmlEditorField1->setRows(3);
483
                $htmlEditorField2->setRows(3);
484
                $htmlEditorField3->setRows(3);
485
                $htmlEditorField4->setRows(3);
486
                $fields->addFieldsToTab(
487
                    'Root.Main',
488
                    array(
489
                        new CheckboxField('UseThisOne', $fieldLabels['UseThisOne']),
490
                        new CheckboxField('ShopClosed', $fieldLabels['ShopClosed']),
491
                    )
492
                );
493
                //set cols
494
                if ($f = $fields->dataFieldByName('CurrenciesExplanation')) {
495
                    $f->setRows(2);
496
                }
497
                if ($f = $fields->dataFieldByName('NotForSaleMessage')) {
498
                    $f->setRows(2);
499
                }
500
                if ($f = $fields->dataFieldByName('ShopPhysicalAddress')) {
501
                    $f->setRows(2);
502
                }
503
                foreach ($fields->dataFields() as $field) {
504
                    if (isset($fieldDescriptions[$field->getName()])) {
505
                        if ($field instanceof CheckboxField) {
506
                            $field->setDescription($fieldDescriptions[$field->Name]);
507
                        } else {
508
                            $field->setRightTitle($fieldDescriptions[$field->Name]);
509
                        }
510
                    }
511
                }
512
                Requirements::block('ecommerce/javascript/EcomPrintAndMail.js');
513
                if (strnatcmp(phpversion(), '5.5.1') >= 0) {
514
                    $fields->addFieldToTab('Root.ProductImages', new Product_ProductImageUploadField('DefaultProductImage', $fieldLabels['DefaultProductImage'], null, null, null, 'default-product-image'));
0 ignored issues
show
Unused Code introduced by
The call to Product_ProductImageUploadField::__construct() has too many arguments starting with null.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
515
                }
516
            }
517
        );
518
519
        return parent::getCMSFields();
520
    }
521
522
    /**
523
     * link to edit the record.
524
     *
525
     * @param string | Null $action - e.g. edit
526
     *
527
     * @return string
528
     */
529
    public function CMSEditLink($action = null)
530
    {
531
        return Controller::join_links(
532
            Director::baseURL(),
533
            '/admin/shop/'.$this->ClassName.'/EditForm/field/'.$this->ClassName.'/item/'.$this->ID.'/',
534
            $action
535
        );
536
    }
537
538
    public function getOrderStepsField()
539
    {
540
        $gridFieldConfig = GridFieldConfig::create()->addComponents(
541
            new GridFieldToolbarHeader(),
542
            new GridFieldSortableHeader(),
543
            new GridFieldDataColumns(10),
0 ignored issues
show
Unused Code introduced by
The call to GridFieldDataColumns::__construct() has too many arguments starting with 10.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
544
            new GridFieldPaginator(10),
545
            new GridFieldEditButton(),
546
            new GridFieldDeleteAction(),
547
            new GridFieldDetailForm()
548
        );
549
550
        return new GridField('OrderSteps', _t('OrderStep.PLURALNAME', 'Order Steps'), OrderStep::get(), $gridFieldConfig);
551
    }
552
553
    /**
554
     * tells us if a Class Name is a buyable.
555
     *
556
     * @todo: consider using Ecomerce Configuration instead?
557
     * In EcomConfig we only list base classes.
558
     *
559
     * @param string $className - name of the class to be tested
560
     *
561
     * @return bool
562
     */
563
    public static function is_buyable($className)
564
    {
565
        $implementorsArray = class_implements($className);
566
        if (is_array($implementorsArray) && in_array('BuyableModel', $implementorsArray)) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return is_array($impleme...', $implementorsArray);.
Loading history...
567
            return true;
568
        }
569
570
        return false;
571
    }
572
573
    /**
574
     * Returns the Current Member.
575
     */
576
    public function Customer()
577
    {
578
        return Member::currentUser();
579
    }
580
581
    /**
582
     * Returns the Current Member.
583
     */
584
    public function CustomerForOrder()
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...
585
    {
586
        $order = ShoppingCart::current_order();
587
588
        return $order->Member();
0 ignored issues
show
Bug introduced by
The method Member() does not exist on Order. Did you maybe mean CreateOrReturnExistingMember()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
589
    }
590
591
    /**
592
     * Return the currency being used on the site e.g. "NZD" or "USD".
593
     *
594
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be array|integer|double|string|boolean?

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...
595
     */
596
    public function Currency()
597
    {
598
        return EcommerceConfig::get('EcommerceCurrency', 'default_currency');
599
    }
600
601
    /**
602
     * return null if there is less than two currencies in use
603
     * on the site.
604
     *
605
     * @return DataList | Null
0 ignored issues
show
Documentation introduced by
Should the return type not be DataList|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...
606
     */
607
    public function Currencies()
608
    {
609
        $list = EcommerceCurrency::get_list();
610
        if ($list && $list->count() > 1) {
611
            return $list;
612
        }
613
    }
614
615
    /**
616
     * @return string (URLSegment)
617
     **/
618
    public function AccountPageLink()
619
    {
620
        return AccountPage::find_link();
621
    }
622
623
    /**
624
     * @return string (URLSegment)
625
     **/
626
    public function CheckoutLink()
627
    {
628
        return CheckoutPage::find_link();
629
    }
630
631
    /**
632
     *@return string (URLSegment)
633
     **/
634
    public function CartPageLink()
635
    {
636
        return CartPage::find_link();
637
    }
638
639
    /**
640
     *@return string (URLSegment)
641
     **/
642
    public function OrderConfirmationPageLink()
643
    {
644
        return OrderConfirmationPage::find_link();
645
    }
646
647
    /**
648
     * Returns a link to a default image.
649
     * If a default image is set in the site config then this link is returned
650
     * Otherwise, a standard link is returned.
651
     *
652
     * @return string
653
     */
654
    public function DefaultImageLink()
655
    {
656
        if ($this->DefaultProductImageID) {
0 ignored issues
show
Documentation introduced by
The property DefaultProductImageID does not exist on object<EcommerceDBConfig>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
657
            $defaultImage = $this->DefaultProductImage();
0 ignored issues
show
Documentation Bug introduced by
The method DefaultProductImage does not exist on object<EcommerceDBConfig>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
658
            if ($defaultImage && $defaultImage->exists()) {
659
                return $defaultImage->Link();
660
            }
661
        }
662
663
        return 'ecommerce/images/productPlaceHolderThumbnail.gif';
664
    }
665
666
    /**
667
     * Returns the default image or a dummy one if it does not exists.
668
     *
669
     * @return string
670
     */
671
    public function DefaultImage()
672
    {
673
        if ($this->DefaultProductImageID) {
0 ignored issues
show
Documentation introduced by
The property DefaultProductImageID does not exist on object<EcommerceDBConfig>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
674
            if ($defaultImage = $this->DefaultProductImage()) {
0 ignored issues
show
Documentation Bug introduced by
The method DefaultProductImage does not exist on object<EcommerceDBConfig>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
675
                if ($defaultImage->exists()) {
676
                    return $defaultImage;
677
                }
678
            }
679
        }
680
        $obj = Product_Image::create();
681
        $obj->Link = $this->DefaultImageLink();
0 ignored issues
show
Documentation introduced by
The property Link does not exist on object<Product_Image>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
682
        $obj->URL = $this->DefaultImageLink();
0 ignored issues
show
Documentation introduced by
The property URL does not exist on object<Product_Image>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
683
684
        return $obj;
685
    }
686
687
    /**
688
     * standard SS method.
689
     */
690
    public function onAfterWrite()
691
    {
692
        if ($this->UseThisOne) {
0 ignored issues
show
Documentation introduced by
The property UseThisOne does not exist on object<EcommerceDBConfig>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
693
            $configs = EcommerceDBConfig::get()
694
                ->Filter(array('UseThisOne' => 1))
695
                ->Exclude(array('ID' => $this->ID));
696
            if ($configs->count()) {
697
                foreach ($configs as $config) {
698
                    $config->UseThisOne = 0;
699
                    $config->write();
700
                }
701
            }
702
        }
703
        $configs = EcommerceDBConfig::get()
704
            ->Filter(array('Title' => $this->Title))
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<EcommerceDBConfig>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
705
            ->Exclude(array('ID' => $this->ID));
706
        if ($configs->count()) {
707
            foreach ($configs as $key => $config) {
708
                $config->Title = $config->Title.'_'.$config->ID;
709
                $config->write();
710
            }
711
        }
712
    }
713
714
    /**
715
     * standard SS Method.
716
     */
717
    public function requireDefaultRecords()
718
    {
719
        parent::requireDefaultRecords();
720
        if (!self::current_ecommerce_db_config()) {
721
            $obj = self::create();
722
            $obj->write();
723
        }
724
        DB::alteration_message('
725
            <hr /><hr /><hr /><hr /><hr />
726
            <h1 style="color: darkRed">Please make sure to review your <a href="/dev/ecommerce/">e-commerce settings</a>.</h1>
727
            <hr /><hr /><hr /><hr /><hr />',
728
            'edited'
729
        );
730
    }
731
732
    /**
733
     * returns site config.
734
     *
735
     * @return SiteConfig
736
     */
737
    public function SiteConfig()
738
    {
739
        return SiteConfig::current_site_config();
740
    }
741
742
    /**
743
     * Casted Variable.
744
     *
745
     * @return string
746
     */
747
    public function UseThisOneNice()
748
    {
749
        return $this->UseThisOne ? 'YES' : 'NO';
0 ignored issues
show
Documentation introduced by
The property UseThisOne does not exist on object<EcommerceDBConfig>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
750
    }
751
}
752