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/OrderAttribute.php (35 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
 * @description: base class for OrderItem (item in cart) and OrderModifier (extra - e.g. Tax)
4
 *
5
 * @see OrderModifier
6
 * @see OrderItem
7
 *
8
 *
9
 * @authors: Nicolaas [at] Sunny Side Up .co.nz
10
 * @package: ecommerce
11
 * @sub-package: model
12
 * @inspiration: Silverstripe Ltd, Jeremy
13
 **/
14
class OrderAttribute extends DataObject implements EditableEcommerceObject
15
{
16
    /**
17
     * what variables are accessible through  http://mysite.com/api/ecommerce/v1/ShippingAddress/.
18
     *
19
     * @var array
20
     */
21
    private static $api_access = 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...
22
        'view' => array(
23
            'CalculatedTotal',
24
            'Sort',
25
            'GroupSort',
26
            'TableTitle',
27
            'TableSubTitleNOHTML',
28
            'CartTitle',
29
            'CartSubTitle',
30
            'Order',
31
        ),
32
     );
33
34
    /**
35
     * Standard SS variable.
36
     *
37
     * @var array
38
     */
39
    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...
40
        'CalculatedTotal' => 'Currency',
41
        'Sort' => 'Int',
42
        'GroupSort' => 'Int',
43
    );
44
45
    /**
46
     * Standard SS variable.
47
     *
48
     * @var array
49
     */
50
    private static $has_one = 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...
51
        'Order' => 'Order',
52
    );
53
54
    /**
55
     * Standard SS variable.
56
     *
57
     * @var array
58
     */
59
    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...
60
        'TableTitle' => 'HTMLText',
61
        'TableSubTitle' => 'HTMLText',
62
        'TableSubTitleNOHTML' => 'Text',
63
        'CartTitle' => 'HTMLText',
64
        'CartSubTitle' => 'HTMLText',
65
        'CalculatedTotalAsMoney' => 'Money',
66
    );
67
68
    /**
69
     * Standard SS variable.
70
     *
71
     * @var string
72
     **/
73
    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...
74
        'OrderAttribute.GroupSort' => 'ASC',
75
        'OrderAttribute.Sort' => 'ASC',
76
        'OrderAttribute.ID' => 'ASC'
77
    ];
78
79
    /**
80
     * Standard SS variable.
81
     *
82
     * @var array
83
     */
84
    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...
85
        'GroupSort' => true,
86
        'Sort' => true,
87
        'ID' => true
88
    );
89
90
    /**
91
     * Standard SS variable.
92
     *
93
     * @var string
94
     */
95
    private static $singular_name = 'Order Entry';
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('OrderAttribute.ORDERENTRY', 'Order Entry');
99
    }
100
101
    /**
102
     * Standard SS variable.
103
     *
104
     * @var string
105
     */
106
    private static $plural_name = 'Order Extra Descriptions';
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('OrderAttribute.ORDERENTRIES', 'Order Entries');
110
    }
111
112
    /**
113
     * Standard SS variable.
114
     *
115
     * @var string
116
     */
117
    private static $description = 'Any item that is added to the order - be it before (e.g. product) or after the subtotal (e.g. tax).';
118
119
    /**
120
     * save edit status for speed's sake.
121
     *
122
     * @var bool
123
     */
124
    protected $_canEdit = null;
125
126
    /**
127
     * save view status for speed's sake.
128
     *
129
     * @var bool
130
     */
131
    protected $_canView = null;
132
133
    /**
134
     * we use this variable to make sure that the parent::runUpdate() is called in all child classes
135
     * this is similar to the checks run for parent::init in the controller class.
136
     *
137
     * @var bool
138
     **/
139
    protected $baseInitCalled = false;
140
141
    /**
142
     * extended in OrderModifier and OrderItem
143
     * Starts up the order Atribute
144
     * TODO: introduce system like we have for Controller
145
     * which makes sure that all parent init methods are called.
146
     */
147
    public function init()
148
    {
149
        return true;
150
    }
151
152
    /**
153
     * standard SS method.
154
     *
155
     * @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...
156
     *
157
     * @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...
158
     **/
159
    public function canCreate($member = null)
160
    {
161
        if (! $member) {
162
            $member = Member::currentUser();
163
        }
164
        $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...
165
        if ($extended !== null) {
166
            return $extended;
167
        }
168
        if (Permission::checkMember($member, Config::inst()->get('EcommerceRole', 'admin_permission_code'))) {
169
            return true;
170
        }
171
172
        return parent::canEdit($member);
0 ignored issues
show
It seems like $member defined by \Member::currentUser() on line 162 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...
173
    }
174
175
    /**
176
     * Standard SS method
177
     * This is an important method.
178
     *
179
     * @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...
180
     *
181
     * @return bool
182
     **/
183
    public function canView($member = null)
184
    {
185
        if (! $member) {
186
            $member = Member::currentUser();
187
        }
188
        $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...
189
        if ($extended !== null) {
190
            return $extended;
191
        }
192
        if (!$this->exists()) {
193
            return true;
194
        }
195
        if ($this->_canView === null) {
196
            $this->_canView = false;
197
            if ($this->OrderID) {
0 ignored issues
show
The property OrderID does not exist on object<OrderAttribute>. 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...
198
                if ($o = $this->Order()) {
199
                    if ($o->exists()) {
200
                        if ($o->canView($member)) {
0 ignored issues
show
It seems like $member defined by \Member::currentUser() on line 186 can also be of type object<DataObject>; however, Order::canView() 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...
201
                            $this->_canView = true;
202
                        }
203
                    }
204
                }
205
            }
206
        }
207
208
        return $this->_canView;
209
    }
210
211
    /**
212
     * Standard SS method
213
     * This is an important method.
214
     *
215
     * @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...
216
     *
217
     * @return bool
218
     **/
219
    public function canEdit($member = null)
220
    {
221
        if (! $member) {
222
            $member = Member::currentUser();
223
        }
224
        $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...
225
        if ($extended !== null) {
226
            return $extended;
227
        }
228
        if (!$this->exists()) {
229
            return true;
230
        }
231
        if ($this->_canEdit === null) {
232
            $this->_canEdit = $this->priceHasBeenFixed() ? false : true;
233
        }
234
235
        return $this->_canEdit;
236
    }
237
238
    /**
239
     * Standard SS method.
240
     *
241
     * @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...
242
     *
243
     * @return bool
244
     **/
245
    public function canDelete($member = null)
246
    {
247
        return false;
248
    }
249
250
    /**
251
     * link to edit the record.
252
     *
253
     * @param string | Null $action - e.g. edit
254
     *
255
     * @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...
256
     */
257
    public function CMSEditLink($action = null)
258
    {
259
        return CMSEditLinkAPI::find_edit_link_for_object($this, $action);
260
    }
261
262
263
    /**
264
     * Helps in speeding up code.
265
     * This can be a static variable as it is the same for all OrderItems for an Order.
266
     *
267
     * @var array
268
     */
269
    private static $_price_has_been_fixed = array();
270
271
272
    /**
273
     * @param int $orderID
274
     * @param bool $value
275
     */
276
    public static function set_price_has_been_fixed($orderID = 0, $value = false)
277
    {
278
        $orderID = ShoppingCart::current_order_id($orderID);
279
        self::$_price_has_been_fixed[$orderID] = $value;
280
    }
281
282
    /**
283
     * @param int $orderID
284
     * @return bool|null
285
     */
286
    public static function get_price_has_been_fixed($orderID = 0)
287
    {
288
        $orderID = ShoppingCart::current_order_id($orderID);
289
290
        return isset(self::$_price_has_been_fixed[$orderID]) ? self::$_price_has_been_fixed[$orderID] : null;
291
    }
292
293
    /**
294
     * @description - tells you if an order item price has been "fixed"
295
     * meaning that is has been saved in the CalculatedTotal field so that
296
     * it can not be altered.
297
     *
298
     * Default returns false; this is good for uncompleted orders
299
     * but not so good for completed ones.
300
     *
301
     * We use direct calls to self::$_price_has_been_fixed to make the code simpler and faster.
302
     *
303
     * @return bool
304
     **/
305
    protected function priceHasBeenFixed($recalculate = false)
306
    {
307
        if (self::get_price_has_been_fixed($this->OrderID) === null || $recalculate) {
0 ignored issues
show
The property OrderID does not exist on object<OrderAttribute>. 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...
308
            self::$_price_has_been_fixed[$this->OrderID] = false;
0 ignored issues
show
The property OrderID does not exist on object<OrderAttribute>. 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...
309
            if ($order = $this->Order()) {
310
                if ($order->IsSubmitted()) {
311
                    self::$_price_has_been_fixed[$this->OrderID] = true;
0 ignored issues
show
The property OrderID does not exist on object<OrderAttribute>. 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...
312
                    if ($recalculate) {
313
                        user_error('You are trying to recalculate an order that is already submitted.', E_USER_NOTICE);
314
                    }
315
                }
316
            }
317
        }
318
319
        return self::$_price_has_been_fixed[$this->OrderID];
0 ignored issues
show
The property OrderID does not exist on object<OrderAttribute>. 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...
320
    }
321
322
    ######################
323
    ## TEMPLATE METHODS ##
324
    ######################
325
326
    /**
327
     * This is a key function that returns the type of the
328
     * object.  In principle anything can be returned
329
     * but the intention is to only return a few options
330
     * e.g. OrderItem, Tax, Delivery, etc... so that
331
     * computations can be carried out based on the type of
332
     * OrderAttribute we are looking at.
333
     * It also allows to get a group of Order Attributes that
334
     * contains both modifiers and orderItems.
335
     *
336
     * @return string
337
     */
338
    public function OrderAttributeType()
339
    {
340
        return $this->ClassName;
341
    }
342
343
    /**
344
     * returns the order - for some unknown reason it seems we need this.
345
     *
346
     * @return Order | null
0 ignored issues
show
Should the return type not be Order|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...
347
     */
348
    public function Order()
349
    {
350
        return Order::get()->byID($this->OrderID);
0 ignored issues
show
The property OrderID does not exist on object<OrderAttribute>. 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...
351
    }
352
353
    /**
354
     * Return a string of class names, in order
355
     * of hierarchy from OrderAttribute for the
356
     * current attribute.
357
     *
358
     * e.g.: "product_orderitem orderitem
359
     * orderattribute".
360
     *
361
     * Used by the templates and for ajax updating functionality.
362
     *
363
     * @return string
364
     */
365
    public function Classes()
366
    {
367
        $class = get_class($this);
368
        $classes = array();
369
        $classes[] = strtolower($class);
370
        while (get_parent_class($class) != 'DataObject' && $class = get_parent_class($class)) {
371
            $classes[] = strtolower($class);
372
        }
373
        if (is_a($this, Object::getCustomClass('OrderItem'))) {
374
            $classes[] = strtolower($this->BuyableClassName);
0 ignored issues
show
The property BuyableClassName does not seem to exist. Did you mean ClassName?

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

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

Loading history...
375
        }
376
377
        return implode(' ', $classes);
378
    }
379
380
    /**
381
     * returns the instance of EcommerceConfigAjax for use in templates.
382
     * In templates, it is used like this:
383
     * $EcommerceConfigAjax.TableID.
384
     *
385
     * @return EcommerceConfigAjax
0 ignored issues
show
Should the return type not be EcommerceConfigAjaxDefinitions?

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...
386
     **/
387
    public function AJAXDefinitions()
388
    {
389
        return EcommerceConfigAjax::get_one($this);
390
    }
391
392
    /**
393
     * returns the instance of EcommerceDBConfig.
394
     *
395
     * @return EcommerceDBConfig
396
     **/
397
    public function EcomConfig()
398
    {
399
        return EcommerceDBConfig::current_ecommerce_db_config();
400
    }
401
402
    /*
403
     * Should this item be shown on check out page table?
404
     * @return bool
405
     **/
406
    public function ShowInTable()
407
    {
408
        return true;
409
    }
410
411
    /**
412
     *Should this item be shown on in the cart (which is on other pages than the checkout page).
413
     *
414
     *@return bool
415
     **/
416
    public function ShowInCart()
417
    {
418
        return $this->ShowInTable();
419
    }
420
421
    /**
422
     * Return a name of what this attribute is
423
     * called e.g. "Product 21" or "Discount".
424
     *
425
     * @return string
426
     */
427
    public function TableTitle()
428
    {
429
        return $this->getTableTitle();
430
    }
431
    public function getTableTitle()
432
    {
433
        return $this->i18n_singular_name();
434
    }
435
436
    /**
437
     * Return a name of what this attribute is
438
     * called e.g. "Product 21" or "Discount"
439
     * Cart is a short version of table.
440
     *
441
     * @return string
442
     */
443
    public function CartTitle()
444
    {
445
        return $this->getCartTitle();
446
    }
447
    public function getCartTitle()
448
    {
449
        return $this->TableTitle();
450
    }
451
452
    /**
453
     * the sub title for the order item or order modifier.
454
     *
455
     * @return string
456
     **/
457
    public function TableSubTitle()
458
    {
459
        return $this->getTableSubTitle();
460
    }
461
    public function getTableSubTitle()
462
    {
463
        return '';
464
    }
465
466
    /**
467
     * the sub title for the order item or order modifier.
468
     *
469
     * @return string
470
     **/
471
    public function TableSubTitleNOHTML()
472
    {
473
        return $this->getTableSubTitleNOHTML();
474
    }
475
    public function getTableSubTitleNOHTML()
476
    {
477
        return str_replace("\n", '', strip_tags($this->getTableSubTitle()));
478
    }
479
480
    /**
481
     * the sub title for the order item or order modifier.
482
     * Cart is a short version of table.
483
     *
484
     * @return string
485
     **/
486
    public function CartSubTitle()
487
    {
488
        return $this->getCartSubTitle();
489
    }
490
    public function getCartSubTitle()
491
    {
492
        return $this->TableSubTitle();
493
    }
494
495
    /**
496
     * Returns the Money object of the CalculatedTotal.
497
     *
498
     * @return Money
499
     **/
500
    public function CalculatedTotalAsMoney()
501
    {
502
        return $this->getCalculatedTotalAsMoney();
503
    }
504
    public function getCalculatedTotalAsMoney()
505
    {
506
        return EcommerceCurrency::get_money_object_from_order_currency($this->CalculatedTotal, $this->Order());
0 ignored issues
show
The property CalculatedTotal does not exist on object<OrderAttribute>. 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...
507
    }
508
509
    public function runUpdate($force = false)
510
    {
511
        $this->baseRunUpdateCalled = true;
0 ignored issues
show
The property baseRunUpdateCalled does not exist on object<OrderAttribute>. 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...
512
    }
513
514
    /**
515
     * Standard SS method
516
     * We add the Sort value from the OrderAttribute_Group to the OrderAttribute.
517
     */
518
    public function onBeforeWrite()
519
    {
520
        parent::onBeforeWrite();
521
        if ($this->OrderAttribute_GroupID) {
0 ignored issues
show
The property OrderAttribute_GroupID does not exist on object<OrderAttribute>. 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...
522
            if ($group = $this->OrderAttribute_Group()) {
0 ignored issues
show
Documentation Bug introduced by
The method OrderAttribute_Group does not exist on object<OrderAttribute>? 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...
523
                $this->GroupSort = $group->Sort;
0 ignored issues
show
The property GroupSort does not exist on object<OrderAttribute>. 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...
524
            }
525
        }
526
    }
527
528
    /**
529
     * Standard SS method.
530
     */
531
    public function onAfterWrite()
532
    {
533
        parent::onAfterWrite();
534
        //crucial!
535
        Order::set_needs_recalculating(true, $this->OrderID);
0 ignored issues
show
The property OrderID does not exist on object<OrderAttribute>. 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...
536
    }
537
538
    /**
539
     * Debug helper method.
540
     * Access through : /shoppingcart/debug/.
541
     */
542
    public function debug()
543
    {
544
        $html = EcommerceTaskDebugCart::debug_object($this);
545
546
        return $html;
547
    }
548
}
549