Issues (2002)

Security Analysis    not enabled

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

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

code/model/money/EcommerceCurrency.php (58 issues)

Upgrade to new PHP Analysis Engine

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

1
<?php
2
3
/**
4
 * Object to manage currencies.
5
 *
6
 * @authors: Nicolaas [at] Sunny Side Up .co.nz
7
 * @package: ecommerce
8
 * @sub-package: money
9
 * Precondition : There should always be at least one currency usable.
10
 **/
11
class EcommerceCurrency extends DataObject implements EditableEcommerceObject
12
{
13
    /**
14
     * standard SS variable.
15
     *
16
     * @var array
17
     */
18
    private static $db = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
19
        'Code' => 'Varchar(3)',
20
        'Name' => 'Varchar(100)',
21
        'InUse' => 'Boolean',
22
    );
23
24
    /**
25
     * standard SS variable.
26
     *
27
     * @var array
28
     */
29
    private static $indexes = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
30
        'Code' => true,
31
        'InUse' => true,
32
        'Name' => true
33
    );
34
35
    /**
36
     * standard SS variable.
37
     *
38
     * @var array
39
     */
40
    private static $casting = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
41
        'IsDefault' => 'Boolean',
42
        'IsDefaultNice' => 'Varchar',
43
        'InUseNice' => 'Varchar',
44
        'ExchangeRate' => 'Double',
45
        'DefaultSymbol' => 'Varchar',
46
        'ShortSymbol' => 'Varchar',
47
        'LongSymbol' => 'Varchar',
48
    );
49
50
    /**
51
     * standard SS variable.
52
     *
53
     * @var array
54
     */
55
    private static $searchable_fields = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
56
        'Code' => 'PartialMatchFilter',
57
        'Name' => 'PartialMatchFilter',
58
    );
59
60
    /**
61
     * standard SS variable.
62
     *
63
     * @var array
64
     */
65
    private static $field_labels = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
66
        'Code' => 'Short Code',
67
        'Name' => 'Name',
68
        'InUse' => 'It is available for use?',
69
        'ExchangeRate' => 'Exchange Rate',
70
        'ExchangeRateExplanation' => 'Exchange Rate explanation',
71
        'IsDefaultNice' => 'Is default currency for site',
72
        'DefaultSymbol' => 'Default symbol',
73
        'ShortSymbol' => 'Short symbol',
74
        'LongSymbol' => 'Long symbol',
75
    );
76
77
    /**
78
     * standard SS variable.
79
     *
80
     * @var array
81
     */
82
    private static $summary_fields = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
83
        'Code' => 'Code',
84
        'Name' => 'Name',
85
        'InUseNice' => 'Available',
86
        'IsDefaultNice' => 'Default Currency',
87
        'ExchangeRate' => 'Exchange Rate',
88
    ); //note no => for relational fields
89
90
    /**
91
     * standard SS variable.
92
     *
93
     * @var string
94
     */
95
    private static $singular_name = 'Currency';
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
96
    public function i18n_singular_name()
97
    {
98
        return _t('EcommerceCurrency.CURRENCY', 'Currency');
99
    }
100
101
    /**
102
     * standard SS variable.
103
     *
104
     * @var string
105
     */
106
    private static $plural_name = 'Currencies';
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
107
    public function i18n_plural_name()
108
    {
109
        return _t('EcommerceCurrency.CURRENCIES', 'Currencies');
110
    }
111
112
    /**
113
     * standard SS variable.
114
     *
115
     * @var string
116
     */
117
    private static $default_sort = [
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
118
        'InUse' => 'DESC',
119
        'Name' => 'ASC',
120
        'Code' => 'ASC',
121
        'ID' => 'DESC'
122
    ];
123
124
    /**
125
     * standard SS variable.
126
     *
127
     * @var array
128
     */
129
    private static $defaults = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
130
        'InUse' => true
131
    );
132
133
    /**
134
     * Standard SS Method.
135
     *
136
     * @param Member $member
0 ignored issues
show
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...
137
     *
138
     * @var bool
139
     */
140
    public function canCreate($member = null)
141
    {
142
        if (! $member) {
143
            $member = Member::currentUser();
144
        }
145
        $extended = $this->extendedCan(__FUNCTION__, $member);
0 ignored issues
show
$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...
146
        if ($extended !== null) {
147
            return $extended;
148
        }
149
        if (Permission::checkMember($member, Config::inst()->get('EcommerceRole', 'admin_permission_code'))) {
150
            return true;
151
        }
152
153
        return parent::canEdit($member);
0 ignored issues
show
It seems like $member defined by \Member::currentUser() on line 143 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 canCreate()). 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...
154
    }
155
156
    /**
157
     * Standard SS Method.
158
     *
159
     * @param Member $member
0 ignored issues
show
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...
160
     *
161
     * @var bool
162
     */
163
    public function canView($member = null)
164
    {
165
        if (! $member) {
166
            $member = Member::currentUser();
167
        }
168
        $extended = $this->extendedCan(__FUNCTION__, $member);
0 ignored issues
show
$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...
169
        if ($extended !== null) {
170
            return $extended;
171
        }
172
        if (Permission::checkMember($member, Config::inst()->get('EcommerceRole', 'admin_permission_code'))) {
173
            return true;
174
        }
175
176
        return parent::canEdit($member);
0 ignored issues
show
It seems like $member defined by \Member::currentUser() on line 166 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 canView()). 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...
177
    }
178
179
    /**
180
     * Standard SS Method.
181
     *
182
     * @param Member $member
0 ignored issues
show
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...
183
     *
184
     * @var bool
185
     */
186
    public function canEdit($member = null)
187
    {
188
        if (! $member) {
189
            $member = Member::currentUser();
190
        }
191
        $extended = $this->extendedCan(__FUNCTION__, $member);
0 ignored issues
show
$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...
192
        if ($extended !== null) {
193
            return $extended;
194
        }
195
        if (Permission::checkMember($member, Config::inst()->get('EcommerceRole', 'admin_permission_code'))) {
196
            return true;
197
        }
198
199
        return parent::canEdit($member);
0 ignored issues
show
It seems like $member defined by \Member::currentUser() on line 189 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...
200
    }
201
202
    /**
203
     * Standard SS method.
204
     *
205
     * @param Member $member
0 ignored issues
show
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...
206
     *
207
     * @return bool
0 ignored issues
show
Should the return type not be boolean|string|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...
208
     */
209
    public function canDelete($member = null)
210
    {
211
        if (!$this->InUse && EcommerceCurrency::get()->Count() > 1) {
0 ignored issues
show
The property InUse does not exist on object<EcommerceCurrency>. 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...
212
            if (! $member) {
213
                $member = Member::currentUser();
214
            }
215
            $extended = $this->extendedCan(__FUNCTION__, $member);
0 ignored issues
show
$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...
216
            if ($extended !== null) {
217
                return $extended;
218
            }
219
            if (Permission::checkMember($member, Config::inst()->get('EcommerceRole', 'admin_permission_code'))) {
220
                return true;
221
            }
222
223
            return parent::canEdit($member);
0 ignored issues
show
It seems like $member defined by \Member::currentUser() on line 213 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...
224
        }
225
226
        return false;
227
    }
228
229
    /**
230
     * NOTE: when there is only one currency we return an empty DataList
231
     * as one currency is meaningless.
232
     *
233
     * @return DataList | null
0 ignored issues
show
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...
234
     */
235
    public static function ecommerce_currency_list()
236
    {
237
        $dos = EcommerceCurrency::get()
238
            ->Filter(array('InUse' => 1))
239
            ->Sort(
240
                array(
241
                    "IF(\"Code\" = '".strtoupper(EcommerceConfig::get('EcommerceCurrency', 'default_currency'))."', 0, 1)" => 'ASC',
242
                    'Name' => 'ASC',
243
                    'Code' => 'ASC',
244
                )
245
            );
246
        if ($dos->count() < 2) {
247
            return;
248
        }
249
250
        return $dos;
251
    }
252
253
    public static function get_list()
254
    {
255
        return EcommerceCurrency::get()
256
            ->filter(array('InUse' => 1))
257
            ->sort(
258
                array(
259
                    "IF(\"Code\" = '".EcommerceConfig::get('EcommerceCurrency', 'default_currency')."', 0, 1)" => 'ASC',
260
                    'Name' => 'ASC',
261
                    'Code' => 'ASC',
262
                )
263
            );
264
    }
265
266
    /**
267
     * @param float | Currency $price
268
     * @param Order $order
0 ignored issues
show
Should the type for parameter $order not be null|Order?

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...
269
     *
270
     * @return Money
271
     */
272
    public static function get_money_object_from_order_currency($price, Order $order = null)
273
    {
274
        if ($price instanceof Currency) {
275
            $price = $price->getValue();
276
        }
277
        if (!$order) {
278
            $order = ShoppingCart::current_order();
279
        }
280
        $currency = $order->CurrencyUsed();
0 ignored issues
show
Documentation Bug introduced by
The method CurrencyUsed does not exist on object<Order>? 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...
281
        $currencyCode = $currency->Code;
282
        if ($order) {
283
            if ($order->HasAlternativeCurrency()) {
284
                $exchangeRate = $order->ExchangeRate;
0 ignored issues
show
The property ExchangeRate does not exist on object<Order>. 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...
285
                if ($exchangeRate && $exchangeRate != 1) {
286
                    $price = $exchangeRate * $price;
287
                }
288
            }
289
        }
290
291
        $updatedCurrencyCode = Injector::inst()->get('EcommerceCurrency')->extend('updateCurrencyCodeForMoneyObect', $currencyCode);
292
        if ($updatedCurrencyCode !== null && is_array($updatedCurrencyCode) && count($updatedCurrencyCode)) {
293
            $currencyCode = $updatedCurrencyCode[0];
294
        }
295
296
        return DBField::create_field(
297
            'Money',
298
            array(
299
                'Amount' => $price,
300
                'Currency' => $currencyCode
301
            )
302
        );
303
    }
304
305
    /**
306
     * returns the default currency.
307
     */
308
    public static function default_currency()
309
    {
310
        return DataObject::get_one(
311
            'EcommerceCurrency',
312
            array(
313
                'Code' => trim(strtolower(EcommerceConfig::get('EcommerceCurrency', 'default_currency'))),
314
                'InUse' => 1,
315
            )
316
        );
317
    }
318
319
    /**
320
     * returns the default currency as Code.
321
     *
322
     * @return string - e.g. NZD
323
     */
324
    public static function default_currency_code()
325
    {
326
        $obj = self::default_currency();
327
        if ($obj) {
328
            $code = $obj->Code;
329
        }
330
        if (!$code) {
0 ignored issues
show
The variable $code 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...
331
            $code = EcommerceConfig::get('EcommerceCurrency', 'default_currency');
332
        }
333
        if (!$code) {
334
            $code = 'NZD';
335
        }
336
337
        return strtoupper($code);
338
    }
339
340
    /**
341
     * @return int
342
     */
343
    public static function default_currency_id()
344
    {
345
        $currency = self::default_currency();
346
347
        return $currency ? $currency->ID : 0;
348
    }
349
350
    /**
351
     * Only returns a currency when it is a valid currency.
352
     *
353
     * @param string $currencyCode - the code of the currency, e.g. nzd
354
     *
355
     * @return EcommerceCurrency | Null
356
     */
357
    public static function get_one_from_code($currencyCode)
358
    {
359
        return DataObject::get_one(
360
            'EcommerceCurrency',
361
            array(
362
                'Code' => trim(strtoupper($currencyCode)),
363
                'InUse' => 1,
364
            )
365
        );
366
    }
367
368
    /**
369
     * STANDARD SILVERSTRIPE STUFF.
370
     **/
371
    public function getCMSFields()
372
    {
373
        $fields = parent::getCMSFields();
374
        $fieldLabels = $this->fieldLabels();
375
        $codeField = $fields->dataFieldByName('Code');
376
        $codeField->setRightTitle('e.g. NZD, use uppercase codes');
377
        $titleField = $fields->dataFieldByName('Name');
378
        $titleField->setRightTitle('e.g. New Zealand Dollar');
379
        $fields->addFieldToTab('Root.Main', new ReadonlyField('IsDefaulNice', $fieldLabels['IsDefaultNice'], $this->getIsDefaultNice()));
380
        if (!$this->isDefault()) {
381
            $fields->addFieldToTab('Root.Main', new ReadonlyField('ExchangeRate', $fieldLabels['ExchangeRate'], $this->ExchangeRate()));
382
            $fields->addFieldToTab('Root.Main', new ReadonlyField('ExchangeRateExplanation', $fieldLabels['ExchangeRateExplanation'], $this->ExchangeRateExplanation()));
383
        }
384
        $fields->addFieldsToTab('Root.Main', array(
385
            new HeaderField('Symbols'),
386
            new ReadonlyField('DefaultSymbol', 'Default'),
387
            new ReadonlyField('ShortSymbol', 'Short'),
388
            new ReadonlyField('LongSymbol', 'Long'),
389
        ));
390
391
        return $fields;
392
    }
393
394
    /**
395
     * link to edit the record.
396
     *
397
     * @param string | Null $action - e.g. edit
398
     *
399
     * @return string
0 ignored issues
show
Should the return type not be null|string?

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...
400
     */
401
    public function CMSEditLink($action = null)
402
    {
403
        return CMSEditLinkAPI::find_edit_link_for_object($this, $action);
404
    }
405
406
    public function DefaultSymbol()
407
    {
408
        return $this->getDefaultSymbol();
409
    }
410
    public function getDefaultSymbol()
411
    {
412
        return EcommerceMoney::get_default_symbol($this->Code);
0 ignored issues
show
The property Code does not exist on object<EcommerceCurrency>. 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...
413
    }
414
415
    public function ShortSymbol()
416
    {
417
        return $this->getShortSymbol();
418
    }
419
    public function getShortSymbol()
420
    {
421
        return EcommerceMoney::get_short_symbol($this->Code);
0 ignored issues
show
The property Code does not exist on object<EcommerceCurrency>. 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...
422
    }
423
424
    public function LongSymbol()
425
    {
426
        return $this->getLongSymbol();
427
    }
428
    public function getLongSymbol()
429
    {
430
        return EcommerceMoney::get_long_symbol($this->Code);
0 ignored issues
show
The property Code does not exist on object<EcommerceCurrency>. 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...
431
    }
432
433
    /**
434
     * casted variable method.
435
     *
436
     * @return bool
437
     */
438
    public function IsDefault()
439
    {
440
        return $this->getIsDefault();
441
    }
442
    public function getIsDefault()
443
    {
444
        $outcome = false;
0 ignored issues
show
$outcome 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...
445
        if ($this->exists()) {
446
            if (!$this->Code) {
0 ignored issues
show
The property Code does not exist on object<EcommerceCurrency>. 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...
447
                user_error('This currency (ID = '.$this->ID.') does not have a code ');
448
            }
449
        }
450
451
        return strtoupper($this->Code) ==  strtoupper(EcommerceConfig::get('EcommerceCurrency', 'default_currency'));
0 ignored issues
show
The property Code does not exist on object<EcommerceCurrency>. 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...
452
    }
453
454
    /**
455
     * casted variable method.
456
     *
457
     * @return string
458
     */
459
    public function IsDefaultNice()
460
    {
461
        return $this->getIsDefaultNice();
462
    }
463
    public function getIsDefaultNice()
464
    {
465
        if ($this->getIsDefault()) {
466
            return _t('EcommerceCurrency.YES', 'Yes');
467
        } else {
468
            return _t('EcommerceCurrency.NO', 'No');
469
        }
470
    }
471
472
    /**
473
     * casted variable method.
474
     *
475
     * @return string
476
     */
477
    public function InUseNice()
478
    {
479
        return $this->getInUseNice();
480
    }
481
    public function getInUseNice()
482
    {
483
        if ($this->InUse) {
0 ignored issues
show
The property InUse does not exist on object<EcommerceCurrency>. 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...
484
            return _t('EcommerceCurrency.YES', 'Yes');
485
        } else {
486
            return _t('EcommerceCurrency.NO', 'No');
487
        }
488
    }
489
490
    /**
491
     * casted variable.
492
     * @alias for getExchangeRate
493
     *
494
     * @return float
495
     */
496
    public function ExchangeRate()
497
    {
498
        return $this->getExchangeRate();
499
    }
500
501
    /**
502
     *
503
     * @return float
504
     */
505
    public function getExchangeRate()
506
    {
507
        $exchangeRateProviderClassName = EcommerceConfig::get('EcommerceCurrency', 'exchange_provider_class');
508
        $exchangeRateProvider = new $exchangeRateProviderClassName();
509
510
        return $exchangeRateProvider->ExchangeRate(EcommerceConfig::get('EcommerceCurrency', 'default_currency'), $this->Code);
0 ignored issues
show
The property Code does not exist on object<EcommerceCurrency>. 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...
511
    }
512
513
    /**
514
     * casted variable.
515
     *
516
     * @return string
0 ignored issues
show
Should the return type not be string|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...
517
     */
518
    public function ExchangeRateExplanation()
519
    {
520
        return $this->getExchangeRateExplanation();
521
    }
522
523
    /**
524
     *
525
     *
526
     * @return string
0 ignored issues
show
Should the return type not be string|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...
527
     */
528
    public function getExchangeRateExplanation()
529
    {
530
        $string = '1 '.EcommerceConfig::get('EcommerceCurrency', 'default_currency').' = '.round($this->getExchangeRate(), 3).' '.$this->Code;
0 ignored issues
show
The property Code does not exist on object<EcommerceCurrency>. 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...
531
        $exchangeRate = $this->getExchangeRate();
532
        $exchangeRateError = '';
533
        if (!$exchangeRate) {
534
            $exchangeRate = 1;
535
            $exchangeRateError = _t('EcommerceCurrency.EXCHANGE_RATE_ERROR', 'Error in exchange rate. ');
536
        }
537
        $string .= ', 1 '.$this->Code.' = '.round(1 / $exchangeRate, 3).' '.EcommerceConfig::get('EcommerceCurrency', 'default_currency').'. '.$exchangeRateError;
0 ignored issues
show
The property Code does not exist on object<EcommerceCurrency>. 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...
538
    }
539
540
    /**
541
     * @return bool
542
     */
543
    public function IsCurrent()
544
    {
545
        $order = ShoppingCart::current_order();
546
547
        return $order ? $order->CurrencyUsedID == $this->ID : false;
0 ignored issues
show
The property CurrencyUsedID does not exist on object<Order>. 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...
548
    }
549
550
    /**
551
     * Returns the link that can be used in the shopping cart to
552
     * set the preferred currency to this one.
553
     * For example: /shoppingcart/setcurrency/nzd/
554
     * Dont be fooled by the set_ part in the set_currency_link....
555
     *
556
     * @return string
557
     */
558
    public function Link()
559
    {
560
        return ShoppingCart_Controller::set_currency_link($this->Code);
0 ignored issues
show
The property Code does not exist on object<EcommerceCurrency>. 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...
561
    }
562
563
    /**
564
     * returns the link type.
565
     *
566
     * @return string (link | default | current)
567
     */
568
    public function LinkingMode()
569
    {
570
        $linkingMode = '';
571
        if ($this->IsDefault()) {
572
            $linkingMode .= ' default';
573
        }
574
        if ($this->IsCurrent()) {
575
            $linkingMode .= ' current';
576
        } else {
577
            $linkingMode .= ' link';
578
        }
579
580
        return $linkingMode;
581
    }
582
583
    public function validate()
584
    {
585
        $result = parent::validate();
586
        $errors = array();
587
        if (!$this->Code || mb_strlen($this->Code) != 3) {
0 ignored issues
show
The property Code does not exist on object<EcommerceCurrency>. 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...
588
            $errors[] = 'The code must be 3 characters long.';
589
        }
590
        if (!$this->Name) {
0 ignored issues
show
The property Name does not exist on object<EcommerceCurrency>. 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...
591
            $errors[] = 'The name is required.';
592
        }
593
        if (!count($errors)) {
594
            $this->Code = strtoupper($this->Code);
0 ignored issues
show
The property Code does not exist on object<EcommerceCurrency>. 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...
The property Code does not exist on object<EcommerceCurrency>. 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...
595
            // Check that there are no 2 same code currencies in use
596
            if ($this->isChanged('Code')) {
597
                if (EcommerceCurrency::get()->where("UPPER(\"Code\") = '".$this->Code."'")->exclude('ID', intval($this->ID) - 0)->count()) {
0 ignored issues
show
The property Code does not exist on object<EcommerceCurrency>. 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...
598
                    $errors[] = "There is alreay another currency in use which code is '$this->Code'.";
0 ignored issues
show
The property Code does not exist on object<EcommerceCurrency>. 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...
599
                }
600
            }
601
        }
602
        foreach ($errors as $error) {
603
            $result->error($error);
604
        }
605
606
        return $result;
607
    }
608
609
    /**
610
     * Standard SS Method
611
     * Adds the default currency.
612
     */
613
    public function populateDefaults()
614
    {
615
        parent::populateDefaults();
616
        $this->InUse = true;
0 ignored issues
show
The property InUse does not exist on object<EcommerceCurrency>. 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...
617
    }
618
619
    public function onBeforeWrite()
620
    {
621
        parent::onBeforeWrite();
622
        // Check that there is always at least one currency in use
623
        $this->Code = strtoupper($this->Code);
0 ignored issues
show
The property Code does not exist on object<EcommerceCurrency>. 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...
The property Code does not exist on object<EcommerceCurrency>. 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...
624
        if (!$this->InUse) {
0 ignored issues
show
The property InUse does not exist on object<EcommerceCurrency>. 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...
625
            $list = self::get_list();
626
            if ($list->count() == 0 || ($list->Count() == 1 && $list->First()->ID == $this->ID)) {
627
                $this->InUse = true;
0 ignored issues
show
The property InUse does not exist on object<EcommerceCurrency>. 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...
628
            }
629
        }
630
    }
631
632
    /**
633
     * Standard SS Method
634
     * Adds the default currency.
635
     */
636
    public function requireDefaultRecords()
637
    {
638
        parent::requireDefaultRecords();
639
        if (! self::default_currency()) {
640
            self::create_new(EcommerceConfig::get('EcommerceCurrency', 'default_currency'));
641
        }
642
    }
643
644
    /**
645
     * checks if a currency exists, creates it and returns it.
646
     *
647
     * @param string $code
648
     * @param string $name OPTIONAL
649
     */
650
    public static function create_new($code, $name = '')
651
    {
652
        $code = trim(strtoupper($code));
653
        if (!$name) {
654
            $currencies = Config::inst()->get('EcommerceCurrency', 'currencies');
655
            if (isset($currencies[$code])) {
656
                $name = $currencies[$code];
657
            } else {
658
                $name = $code;
659
            }
660
        }
661
        $name = ucwords($name);
662
        $currency = DataObject::get_one(
663
            'EcommerceCurrency',
664
            array('Code' => $code),
665
            $cacheDataObjectGetOne = false
666
        );
667
        if ($currency) {
668
            $currency->Name = $name;
669
            $currency->InUse = true;
670
        } else {
671
            $currency = EcommerceCurrency::create(
672
                array(
673
                'Code' => $code,
674
                'Name' => $name,
675
                'InUse' => true,
676
                )
677
            );
678
        }
679
        $valid = $currency->write();
680
        if ($valid) {
681
            return $currency;
682
        }
683
    }
684
685
    /**
686
     * Debug helper method.
687
     * Can be called from /shoppingcart/debug/.
688
     *
689
     * @return string
690
     */
691
    public function debug()
692
    {
693
        return EcommerceTaskDebugCart::debug_object($this);
694
    }
695
696
    private static $currencies = array(
697
        'AFA' => 'afghanistan afghanis',
698
        'ALL' => 'albania leke',
699
        'DZD' => 'algeria dinars',
700
        'ARS' => 'argentina pesos',
701
        'AUD' => 'australia dollars',
702
        'ATS' => 'austria schillings*',
703
        'BSD' => 'bahamas dollars',
704
        'BHD' => 'bahrain dinars',
705
        'BDT' => 'bangladesh taka',
706
        'BBD' => 'barbados dollars',
707
        'BEF' => 'belgium francs*',
708
        'BMD' => 'bermuda dollars',
709
        'BRL' => 'brazil reais',
710
        'BGN' => 'bulgaria leva',
711
        'CAD' => 'canada dollars',
712
        'XOF' => 'cfa bceao francs',
713
        'XAF' => 'cfa beac francs',
714
        'CLP' => 'chile pesos',
715
        'CNY' => 'china yuan renminbi',
716
        'COP' => 'colombia pesos',
717
        'CRC' => 'costa rica colones',
718
        'HRK' => 'croatia kuna',
719
        'CYP' => 'cyprus pounds',
720
        'CZK' => 'czech republic koruny',
721
        'DKK' => 'denmark kroner',
722
        'DOP' => 'dominican republic pesos',
723
        'XCD' => 'eastern caribbean dollars',
724
        'EGP' => 'egypt pounds',
725
        'EEK' => 'estonia krooni',
726
        'EUR' => 'euro',
727
        'FJD' => 'fiji dollars',
728
        'DEM' => 'germany deutsche marks*',
729
        'XAU' => 'gold ounces',
730
        'NLG' => 'holland (netherlands) guilders*',
731
        'HKD' => 'hong kong dollars',
732
        'HUF' => 'hungary forint',
733
        'ISK' => 'iceland kronur',
734
        'XDR' => 'imf special drawing right',
735
        'INR' => 'india rupees',
736
        'IDR' => 'indonesia rupiahs',
737
        'IRR' => 'iran rials',
738
        'IQD' => 'iraq dinars',
739
        'ILS' => 'israel new shekels',
740
        'JMD' => 'jamaica dollars',
741
        'JPY' => 'japan yen',
742
        'JOD' => 'jordan dinars',
743
        'KES' => 'kenya shillings',
744
        'KRW' => 'korea (south) won',
745
        'KWD' => 'kuwait dinars',
746
        'LBP' => 'lebanon pounds',
747
        'MYR' => 'malaysia ringgits',
748
        'MTL' => 'malta liri',
749
        'MUR' => 'mauritius rupees',
750
        'MXN' => 'mexico pesos',
751
        'MAD' => 'morocco dirhams',
752
        'NZD' => 'new zealand dollars',
753
        'NOK' => 'norway kroner',
754
        'OMR' => 'oman rials',
755
        'PKR' => 'pakistan rupees',
756
        'XPD' => 'palladium ounces',
757
        'PEN' => 'peru nuevos soles',
758
        'PHP' => 'philippines pesos',
759
        'PLN' => 'poland zlotych',
760
        'QAR' => 'qatar riyals',
761
        'ROL' => 'romania lei',
762
        'RUB' => 'russia rubles',
763
        'SAR' => 'saudi arabia riyals',
764
        'XAG' => 'silver ounces',
765
        'SGD' => 'singapore dollars',
766
        'SKK' => 'slovakia koruny',
767
        'SIT' => 'slovenia tolars',
768
        'ZAR' => 'south africa rand',
769
        'KRW' => 'south korea won',
770
        'LKR' => 'sri lanka rupees',
771
        'SDD' => 'sudan dinars',
772
        'SEK' => 'sweden kronor',
773
        'CHF' => 'switzerland francs',
774
        'TWD' => 'taiwan new dollars',
775
        'THB' => 'thailand baht',
776
        'TTD' => 'trinidad and tobago dollars',
777
        'TND' => 'tunisia dinars',
778
        'TRY' => 'turkey new lira',
779
        'AED' => 'united arab emirates dirhams',
780
        'gbp' => 'united kingdom pounds',
781
        'USD' => 'united states dollars',
782
        'VEB' => 'venezuela bolivares',
783
        'VND' => 'vietnam dong',
784
        'ZMK' => 'zambia kwacha',
785
    );
786
}
787