OrderEmailRecord::canView()   A
last analyzed

Complexity

Conditions 6
Paths 8

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
dl 0
loc 19
rs 9.0111
c 0
b 0
f 0
nc 8
nop 1
1
<?php
2
3
/**
4
 * @Description: DataObject recording all order emails sent.
5
 *
6
 *
7
 * @authors: Silverstripe, Jeremy, Nicolaas
8
 *
9
 *
10
 * @authors: Nicolaas [at] Sunny Side Up .co.nz
11
 * @package: ecommerce
12
 * @sub-package: model
13
 * @inspiration: Silverstripe Ltd, Jeremy
14
 **/
15
class OrderEmailRecord extends DataObject implements EditableEcommerceObject
16
{
17
    /**
18
     * standard SS variable.
19
     *
20
     * @var array
21
     */
22
    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...
23
        'From' => 'Varchar(255)',
24
        'To' => 'Varchar(255)',
25
        'Subject' => 'Varchar(255)',
26
        'Content' => 'HTMLText',
27
        'Result' => 'Boolean',
28
    );
29
30
    /**
31
     * standard SS variable.
32
     *
33
     * @var array
34
     */
35
    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...
36
        'Order' => 'Order',
37
        'OrderStep' => 'OrderStep',
38
    );
39
40
    /**
41
     * standard SS variable.
42
     *
43
     * @var array
44
     */
45
    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...
46
        'Title' => 'Varchar',
47
        'OrderStepNice' => 'Varchar',
48
        'ResultNice' => 'Varchar',
49
    );
50
51
    /**
52
     * standard SS variable.
53
     *
54
     * @var array
55
     */
56
    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...
57
        'Created' => 'Send',
58
        'OrderStepNice' => 'Order Step',
59
        'From' => 'From',
60
        'To' => 'To',
61
        'Subject' => 'Subject',
62
        'ResultNice' => 'Sent Succesfully',
63
    );
64
65
    /**
66
     * standard SS variable.
67
     *
68
     * @var array
69
     */
70
    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...
71
        'Created' => 'Send',
72
        'OrderStepNice' => 'Order Step',
73
        'From' => 'From',
74
        'To' => 'To',
75
        'Subject' => 'Subject',
76
        'ResultNice' => 'Sent Succesfully',
77
    );
78
79
    /**
80
     * standard SS variable.
81
     *
82
     * @var array
83
     */
84
    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...
85
        'OrderID' => array(
86
            'field' => 'NumericField',
87
            'title' => 'Order Number',
88
        ),
89
        'From' => 'PartialMatchFilter',
90
        'To' => 'PartialMatchFilter',
91
        'Subject' => 'PartialMatchFilter',
92
        //make sure to keep the item below, otherwise they do not show in form
93
        'OrderStepID' => array(
94
            'filter' => 'OrderEmailRecordFilters_MultiOptionsetStatusIDFilter',
95
        ),
96
        'Result' => true,
97
    );
98
99
    /**
100
     * casted Variable.
101
     *
102
     * @var string
103
     */
104
    public function ResultNice()
105
    {
106
        return $this->getResultNice();
107
    }
108
    public function getResultNice()
109
    {
110
        if ($this->Result) {
0 ignored issues
show
Documentation introduced by
The property Result does not exist on object<OrderEmailRecord>. 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...
111
            return _t('OrderEmailRecord.YES', 'Yes');
112
        }
113
114
        return _t('OrderEmailRecord.NO', 'No');
115
    }
116
117
    /**
118
     * standard SS variable.
119
     *
120
     * @var string
121
     */
122
    private static $singular_name = 'Customer Email';
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...
123
    public function i18n_singular_name()
124
    {
125
        return _t('OrderEmailRecord.CUSTOMEREMAIL', 'Customer Email');
126
    }
127
128
    /**
129
     * standard SS variable.
130
     *
131
     * @var string
132
     */
133
    private static $plural_name = 'Customer Emails';
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...
134
    public function i18n_plural_name()
135
    {
136
        return _t('OrderEmailRecord.CUSTOMEREMAILS', 'Customer Emails');
137
    }
138
139
    /**
140
     * Standard SS variable.
141
     *
142
     * @var string
143
     */
144
    private static $description = 'A record of any email that has been sent in relation to an order.';
145
146
    /**
147
     * standard SS method.
148
     *
149
     * @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...
150
     *
151
     * @return bool
152
     */
153
    public function canCreate($member = null)
154
    {
155
        return false;
156
    }
157
158
    /**
159
     * standard SS method.
160
     *
161
     * @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...
162
     *
163
     * @return bool
164
     */
165
    public function canView($member = null)
166
    {
167
        if (! $member) {
168
            $member = Member::currentUser();
169
        }
170
        $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...
171
        if ($extended !== null) {
172
            return $extended;
173
        }
174
        $order = $this->Order();
0 ignored issues
show
Documentation Bug introduced by
The method Order does not exist on object<OrderEmailRecord>? 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...
175
        if ($order && $order->exists()) {
176
            return $order->canView();
177
        }
178
        if (Permission::checkMember($member, Config::inst()->get('EcommerceRole', 'admin_permission_code'))) {
179
            return true;
180
        }
181
182
        return parent::canEdit($member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by \Member::currentUser() on line 168 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...
183
    }
184
185
    /**
186
     * standard SS method.
187
     *
188
     * @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...
189
     *
190
     * @return bool
191
     */
192
    public function canEdit($member = null)
193
    {
194
        return false;
195
    }
196
197
    /**
198
     * standard SS method.
199
     *
200
     * @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...
201
     *
202
     * @return bool
203
     */
204
    public function canDelete($member = null)
205
    {
206
        return false;
207
    }
208
209
    //defaults
210
211
    /**
212
     * standard SS variable.
213
     *
214
     * @return string
215
     */
216
    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...
217
        'ID' => 'ASC'
218
    ];
219
220
    private static $indexes = [
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...
221
        'From' => true,
222
        'To' => true,
223
        'Result' => true
224
    ];
225
226
    /**
227
     * standard SS method.
228
     *
229
     * @return FieldList
230
     */
231
    public function getCMSFields()
232
    {
233
        $fields = parent::getCMSFields();
234
        $fields->addFieldsToTab(
235
            'Root.Details',
236
            array(
237
                $fields->dataFieldByName("To"),
238
                $fields->dataFieldByName("Subject"),
239
                $fields->dataFieldByName("From"),
240
                $fields->dataFieldByName("Result"),
241
                $fields->dataFieldByName("OrderID"),
242
                $fields->dataFieldByName("OrderStepID")
243
            )
244
        );
245
        $emailLink = OrderEmailRecord_Review::review_link($this);
246
        $fields->replaceField('Content', new LiteralField('Content', "<iframe src=\"$emailLink\" width=\"100%\" height=\"700\"  style=\"border: 5px solid #2e7ead; border-radius: 2px;\"></iframe>"));
247
        $fields->replaceField('OrderID', $fields->dataFieldByName('OrderID')->performReadonlyTransformation());
248
        $fields->replaceField('OrderStepID', new ReadonlyField('OrderStepNice', 'Order Step', $this->OrderStepNice()));
249
250
        return $fields;
251
    }
252
253
    /**
254
     * link to edit the record.
255
     *
256
     * @param string | Null $action - e.g. edit
257
     *
258
     * @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...
259
     */
260
    public function CMSEditLink($action = null)
261
    {
262
        return CMSEditLinkAPI::find_edit_link_for_object($this, $action);
263
    }
264
265
    /**
266
     * Determine which properties on the DataObject are
267
     * searchable, and map them to their default {@link FormField}
268
     * representations. Used for scaffolding a searchform for {@link ModelAdmin}.
269
     *
270
     * Some additional logic is included for switching field labels, based on
271
     * how generic or specific the field type is.
272
     *
273
     * Used by {@link SearchContext}.
274
     *
275
     * @param array $_params
0 ignored issues
show
Documentation introduced by
Should the type for parameter $_params not be array|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...
276
     *                       'fieldClasses': Associative array of field names as keys and FormField classes as values
277
     *                       'restrictFields': Numeric array of a field name whitelist
278
     *
279
     * @return FieldList
280
     */
281
    public function scaffoldSearchFields($_params = null)
282
    {
283
        $fieldList = parent::scaffoldSearchFields($_params);
284
        $fieldList->replaceField('OrderID', new NumericField('OrderID', 'Order Number'));
285
        $statusOptions = OrderStep::get();
286
        if ($statusOptions && $statusOptions->count()) {
287
            $createdOrderStatusID = 0;
0 ignored issues
show
Unused Code introduced by
$createdOrderStatusID 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...
288
            $preSelected = array();
289
            $createdOrderStatus = $statusOptions->First();
290
            if ($createdOrderStatus) {
291
                $createdOrderStatusID = $createdOrderStatus->ID;
0 ignored issues
show
Unused Code introduced by
$createdOrderStatusID 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...
292
            }
293
            $arrayOfStatusOptions = clone $statusOptions->map('ID', 'Title');
294
            $arrayOfStatusOptionsFinal = array();
295
            if (count($arrayOfStatusOptions)) {
296
                foreach ($arrayOfStatusOptions as $key => $value) {
297
                    if (isset($_GET['q']['OrderStepID'][$key])) {
298
                        $preSelected[$key] = $key;
299
                    }
300
                    $count = OrderEmailRecord::get()
301
                        ->Filter(array('OrderStepID' => intval($key)))
302
                        ->count();
303
                    if ($count < 1) {
304
                        //do nothing
305
                    } else {
306
                        $arrayOfStatusOptionsFinal[$key] = $value." ($count)";
307
                    }
308
                }
309
            }
310
            $statusField = new CheckboxSetField(
311
                'OrderStepID',
312
                Injector::inst()->get('OrderStep')->i18n_singular_name(),
313
                $arrayOfStatusOptionsFinal,
314
                $preSelected
0 ignored issues
show
Documentation introduced by
$preSelected is of type array, but the function expects a string.

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...
315
            );
316
            $fieldList->push($statusField);
317
        }
318
319
        return $fieldList;
320
    }
321
322
    /**
323
     * casted variable.
324
     *
325
     *@ return String
326
     **/
327
    public function Title()
328
    {
329
        return $this->getTitle();
330
    }
331
    public function getTitle()
332
    {
333
        $str = 'TO: '.$this->To;
0 ignored issues
show
Documentation introduced by
The property To does not exist on object<OrderEmailRecord>. 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...
334
        if ($order = $this->Order()) {
0 ignored issues
show
Documentation Bug introduced by
The method Order does not exist on object<OrderEmailRecord>? 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...
Unused Code introduced by
$order 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...
335
            $str .= ' - '.$this->Order()->getTitle();
0 ignored issues
show
Documentation Bug introduced by
The method Order does not exist on object<OrderEmailRecord>? 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...
336
            $str .= ' - '.$this->OrderStepNice();
337
        }
338
339
        return $str;
340
    }
341
342
    /**
343
     * casted variable.
344
     *
345
     *@ return String
346
     **/
347
    public function OrderStepNice()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

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

Loading history...
348
    {
349
        return $this->getOrderStepNice();
350
    }
351
    public function getOrderStepNice()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

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

Loading history...
352
    {
353
        if ($this->OrderStepID) {
0 ignored issues
show
Documentation introduced by
The property OrderStepID does not exist on object<OrderEmailRecord>. 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...
354
            $orderStep = OrderStep::get()->byID($this->OrderStepID);
0 ignored issues
show
Documentation introduced by
The property OrderStepID does not exist on object<OrderEmailRecord>. 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...
355
            if ($orderStep) {
356
                return $orderStep->Name;
357
            }
358
        }
359
    }
360
361
    /**
362
     * Debug helper method.
363
     * Can be called from /shoppingcart/debug/.
364
     *
365
     * @return string
366
     */
367
    public function debug()
368
    {
369
        return EcommerceTaskDebugCart::debug_object($this);
370
    }
371
}
372