Completed
Push — master ( 181911...c15eac )
by Nicolaas
03:23
created

OrderAttribute::canEdit()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 11
nc 10
nop 1
dl 0
loc 18
rs 8.8571
c 0
b 0
f 0
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
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
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
Unused Code introduced by
The property $api_access is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
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
Unused Code introduced by
The property $db is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
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
Unused Code introduced by
The property $has_one is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
51
        'Order' => 'Order',
52
    );
53
54
    /**
55
     * Standard SS variable.
56
     *
57
     * @var array
58
     */
59
    private static $casting = array(
0 ignored issues
show
Unused Code introduced by
The property $casting is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
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...
Unused Code introduced by
The property $default_sort is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
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...
Unused Code introduced by
The property $indexes is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
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...
Unused Code introduced by
The property $singular_name is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
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...
Unused Code introduced by
The property $plural_name is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
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).';
0 ignored issues
show
Unused Code introduced by
The property $description is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
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
Documentation introduced by
Should the type for parameter $member not be Member|null?

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

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

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

Loading history...
156
     *
157
     * @return bool
0 ignored issues
show
Documentation introduced by
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
Documentation introduced by
$member is of type object<DataObject>|null, but the function expects a object<Member>|integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
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
Bug introduced by
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
Documentation introduced by
Should the type for parameter $member not be Member|null?

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

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

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

Loading history...
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
Documentation introduced by
$member is of type object<DataObject>|null, but the function expects a object<Member>|integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
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
Documentation introduced by
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
Bug introduced by
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
Documentation introduced by
Should the type for parameter $member not be Member|null?

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

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

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

Loading history...
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
Documentation introduced by
$member is of type object<DataObject>|null, but the function expects a object<Member>|integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
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
Documentation introduced by
Should the type for parameter $member not be Member|null?

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

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

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

Loading history...
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
Documentation introduced by
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
Documentation introduced by
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
Documentation introduced by
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
Documentation introduced by
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
Documentation introduced by
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
Documentation introduced by
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
Documentation introduced by
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
Bug introduced by
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
Documentation introduced by
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 Boolean
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
Documentation introduced by
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
Documentation introduced by
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
Documentation introduced by
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
Documentation introduced by
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
Documentation introduced by
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