Completed
Push — master ( 563a7d...907f98 )
by
unknown
27s
created

Device   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 345
Duplicated Lines 13.33 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 0%

Importance

Changes 5
Bugs 0 Features 0
Metric Value
wmc 32
c 5
b 0
f 0
lcom 1
cbo 6
dl 46
loc 345
ccs 0
cts 85
cp 0
rs 9.6

18 Methods

Rating   Name   Duplication   Size   Complexity  
A getOpenTimeAttribute() 10 10 2
A getCloseTimeAttribute() 10 10 2
A location() 0 4 1
A getSiteAttribute() 0 4 1
A setOpenTimeAttribute() 13 13 2
A setCloseTimeAttribute() 13 13 2
A getLastNetworkUpdateAtHumanAttribute() 0 4 1
A scopeByLocation() 0 4 1
A scopePublicDashData() 0 17 1
A generateToken() 0 7 1
A getDeviceByUUID() 0 4 1
A image() 0 4 1
A sensors() 0 4 1
A data() 0 4 1
A isReadyForCommand() 0 4 3
A isDuringScheduleOpen() 0 14 3
C actualCoverStatus() 0 32 7
A dashPageNum() 0 9 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace App;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Database\Eloquent\SoftDeletes;
7
use Carbon\Carbon;
8
use Illuminate\Support\Facades\Auth;
9
use Spatie\Activitylog\Traits\LogsActivity;
10
11
class Device extends Model
12
{
13
    use SoftDeletes;
14
    use LogsActivity;
15
    //use CausesActivity;
16
    
17
    /**
18
     * The attributes that should be mutated to dates.
19
     *
20
     * @var array
21
     */
22
    protected $dates = [
23
        'deleted_at',
24
        'last_network_update_at'
25
    ];
26
    
27
    /**
28
     * The attributes that should be hidden for arrays.
29
     *
30
     * @var array
31
     */
32
    protected $hidden = ['token'];
33
    
34
    /**
35
     * The attributes that are mass assignable.
36
     *
37
     * @var array
38
     */
39
    protected $fillable = [
40
        'name', 'location_id', 'uuid', 'version', 'hostname', 'ip', 'mac_address', 
41
        'time', 'cover_command', 'cover_status', 'error_msg', 'limitsw_open', 'limitsw_closed',
42
        'light_in', 'light_out', 'update_rate', 'image_rate', 'sensor_rate', 
43
        'open_time', 'close_time', 'last_network_update_at',
44
    ];
45
    
46
    /**
47
     * The attributes to ignore in the Activity Log
48
     *
49
     * @var array
50
     */
51
    protected static $ignoreChangedAttributes = ['updated_at'];
52
    
53
    /**
54
     * The attributes to log in the Activity Log
55
     *
56
     * @var array
57
     */
58
    protected static $logAttributes = [
59
        'name', 'location_id', 'uuid', 'version', 'hostname', 'ip', 'mac_address', 
60
        'time', 'cover_status', 'error_msg', 'limitsw_open', 'limitsw_closed', 
61
        'light_in', 'light_out', 'update_rate', 'image_rate', 'sensor_rate', 
62
        'open_time', 'close_time'
63
    ];
64
    
65
    /**
66
     * Only log those that have actually changed after the update.
67
     *
68
     * @var array
69
     */
70
    protected static $logOnlyDirty = true;
71
    
72
    /**
73
     * Update the updated_at and created_at timestamps?
74
     *
75
     * @var array
76
     */
77
    public $timestamps = true;
78
    
79
    /**
80
     * Get the location for the device
81
     */
82
    public function location()
83
    {
84
        return $this->belongsTo('App\Location', 'location_id');
85
    }
86
    
87
    /**
88
     * Get the site for the device using model accessor
89
     */
90
    public function getSiteAttribute()
91
    {
92
        return $this->location->site ?? (object)[];
93
    }
94
    
95
    /**
96
     * Accessor: Get the open time of the device converted to hours and minutes
97
     * If it is a device accessing the time use UTC
98
     * If it is a user accessing the time use their preferred timezone
99
     *
100
     * @param  string $value
101
     * @return string
102
     */
103 View Code Duplication
    public function getOpenTimeAttribute($value)
104
    {
105
        $time = new Carbon($value, 'UTC');
106
        
107
        //If the user is logged in then use there preferred timezone
108
        if (Auth::check())
109
            $time = $time->setTimezone(Auth::user()->timezone);
0 ignored issues
show
Bug introduced by
Accessing timezone on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
110
111
        return $time->format('H:i');
112
    }
113
    
114
    /**
115
     * Accessor: Get the close time of the device converted to hours and minutes
116
     * If it is a device accessing the time use UTC
117
     * If it is a user accessing the time use their preferred timezone
118
     *
119
     * @param  string $value
120
     * @return string
121
     */
122 View Code Duplication
    public function getCloseTimeAttribute($value)
123
    {
124
        $time = new Carbon($value, 'UTC');
125
    
126
        //If the user is logged in then use there preferred timezone
127
        if (Auth::check())
128
            $time = $time->setTimezone(Auth::user()->timezone);
0 ignored issues
show
Bug introduced by
Accessing timezone on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
129
        
130
        return $time->format('H:i');
131
    }
132
    
133
    /**
134
     * Set the open time to UTC
135
     * If it is a device saving the time use UTC
136
     * If it is a user saving the time use their preferred timezone
137
     *
138
     * @param  string  $value
139
     * @return void
140
     */
141 View Code Duplication
    public function setOpenTimeAttribute($value)
142
    {
143
        //If the user is logged in then use there preferred timezone
144
        if (Auth::check())
145
        {
146
            $time = new Carbon($value, Auth::user()->timezone);
0 ignored issues
show
Bug introduced by
Accessing timezone on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
147
            $time = $time->setTimezone('UTC');
148
        }
149
        else
150
            $time = new Carbon($value, 'UTC');
151
        
152
        $this->attributes['open_time'] = $time->format('H:i:s');
153
    }
154
    
155
    /**
156
     * Set the close time to UTC
157
     * If it is a device saving the time use UTC
158
     * If it is a user saving the time use their preferred timezone
159
     *
160
     * @param  string  $value
161
     * @return void
162
     */
163 View Code Duplication
    public function setCloseTimeAttribute($value)
164
    {
165
        //If the user is logged in then use there preferred timezone
166
        if (Auth::check())
167
        {
168
            $time = new Carbon($value, Auth::user()->timezone);
0 ignored issues
show
Bug introduced by
Accessing timezone on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
169
            $time = $time->setTimezone('UTC');
170
        }
171
        else
172
            $time = new Carbon($value, 'UTC');
173
        
174
        $this->attributes['close_time'] = $time->format('H:i:s');
175
    }
176
    
177
    /**
178
     * Accessor: Get the last time the server received and update call from the device converted to a
179
     * user friendly format. The format is Month day 12hour:mins am/pm and will be in the user's preferred timezone
180
     *
181
     * @return string
182
     */
183
    public function getLastNetworkUpdateAtHumanAttribute()
184
    {
185
        return $this->last_network_update_at->setTimezone(Auth::user()->timezone)->format('M j g:i a');
0 ignored issues
show
Bug introduced by
Accessing timezone on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
186
    }
187
    
188
    /**
189
     * Scope a query to only include devices belonging to a given location
190
     *
191
     * @param \Illuminate\Database\Eloquent\Builder $query
192
     * @param int $location_id
193
     * @return \Illuminate\Database\Eloquent\Builder
194
     */
195
    public function scopeByLocation($query, $location_id)
196
    {
197
        return $query->where('location_id', $location_id);
198
    }
199
    
200
    /**
201
     * Scope a query to limit the included columns to only include what is publicly needed to be displayed on the
202
     * dashboard
203
     *
204
     * @param \Illuminate\Database\Eloquent\Builder $query
205
     * @return \Illuminate\Database\Eloquent\Builder
206
     */
207
    public function scopePublicDashData($query)
208
    {
209
        return $query->select([
0 ignored issues
show
Bug introduced by
The method select() does not exist on Illuminate\Database\Eloquent\Builder. Did you maybe mean createSelectWithConstraint()?

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

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

Loading history...
210
            'devices.id',
211
            'name',
212
            'location_id',
213
            'cover_command',
214
            'cover_status',
215
            'open_time',
216
            'close_time',
217
            'update_rate',
218
            'image_rate',
219
            'sensor_rate',
220
            'last_network_update_at',
221
            'image.updated_at as image_updated_at',
222
        ]);
223
    }
224
    
225
    /**
226
     * Create a new API token for the device.
227
     */
228
    public function generateToken()
229
    {
230
        $this->token = str_random(60);
231
        $this->save();
232
        
233
        return $this->token;
234
    }
235
    
236
    /**
237
     * Get a device by uuid
238
     *
239
     * @param string $uuid
240
     * @return Device|Illuminate\Database\Eloquent\Model
241
     */
242
    public static function getDeviceByUUID($uuid)
243
    {
244
        return self::where('uuid', $uuid)->first();
245
    }
246
    
247
    /**
248
     * Get the deviceimage record associated with the device.
249
     */
250
    public function image()
251
    {
252
        return $this->hasOne('App\Deviceimage');
253
    }
254
    
255
256
    /**
257
     * Get the sensors associated with the device.
258
     */
259
    public function sensors()
260
    {
261
        return $this->hasMany('App\Sensor');
262
    }
263
    
264
    /**
265
     * Get the sensor data associated with the device.
266
     */
267
    public function data()
268
    {
269
        return $this->hasManyThrough('App\SensorData', 'App\Sensor');
270
    }
271
    
272
    /**
273
     * Check if the device is ready for a cover command
274
     *
275
     * @return boolean
276
     */
277
    public function isReadyForCommand()
278
    {
279
        return ($this->cover_status == 'open' || $this->cover_status == 'closed' || $this->cover_status == 'locked');
280
    }
281
    
282
    /**
283
     * Check if the current time is during the devices scheduled time to be open
284
     *
285
     * @return boolean
286
     */
287
    public function isDuringScheduleOpen()
288
    {
289
        $timezone = Auth::user()->timezone;
0 ignored issues
show
Bug introduced by
Accessing timezone on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
290
        //Get the open, close, and current time in the users timezone
291
        $open_time = new Carbon($this->open_time, $timezone);
292
        $close_time = new Carbon($this->close_time, $timezone);
293
        $time_now = Carbon::now($timezone);
294
    
295
        //Check if the current time is during the open schedule or not
296
        if ($time_now->gt($open_time) && $time_now->lt($close_time))
297
            return true;
298
        else
299
            return false;
300
    }
301
    
302
    /**
303
     * Get the covers actual status based on the current command and the devices status
304
     *
305
     * @return string
306
     */
307
    public function actualCoverStatus()
308
    {
309
        $status = '';
0 ignored issues
show
Unused Code introduced by
$status 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...
310
        $isOpen = $this->cover_status === 'open';
311
        $isClosed = $this->cover_status === 'closed';
312
            
313
        switch ($this['cover_command'])
314
        {
315
            case 'open':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
316
                if ($isOpen)
317
                    $status = 'open';
318
                else
319
                    $status = 'opening';
320
                break;
321
            case 'close':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
322
                if ($isClosed)
323
                    $status = 'closed';
324
                else
325
                    $status = 'closing';
326
                break;
327
            case 'lock':
328
                $status = 'locked';
329
                break;
330
            default:
331
                $status = 'error';
332
        }
333
    
334
        if ($this->cover_status === 'error')
335
            $status = 'error';
336
        
337
        return $status;
338
    }
339
    
340
    /**
341
     * Get the page number of the device for the dashboard device table pagination
342
     *
343
     * @param int $limit
344
     * @return int
345
     */
346
    public function dashPageNum($limit)
347
    {
348
        $pos = Device::where('location_id', '=', $this->location_id)
349
            ->where('name', '<=', $this->name)
350
            ->orderBy('name', 'ASC')
351
            ->count();
352
        
353
        return ceil($pos / $limit);
354
    }
355
}
356