Completed
Push — master ( 5ac3ed...b5d6ac )
by Brandon
26s
created

Device::isReadyForCommand()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
cc 3
eloc 2
nc 3
nop 0
crap 12
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', 'last_network_update_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 open time of the device converted to the users preferred time and
116
     * converted to a user friendly format of h:i a
117
     *
118
     * @return string
119
     */
120 View Code Duplication
    public function getOpenTimeHumanAttribute()
121
    {
122
        $time = new Carbon($this->attributes['open_time'], 'UTC');
123
        $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...
124
        
125
        return $time->format('h:i a');
126
    }
127
    
128
    /**
129
     * Accessor: Get the close time of the device converted to hours and minutes
130
     * If it is a device accessing the time use UTC
131
     * If it is a user accessing the time use their preferred timezone
132
     *
133
     * @param  string $value
134
     * @return string
135
     */
136 View Code Duplication
    public function getCloseTimeAttribute($value)
137
    {
138
        $time = new Carbon($value, 'UTC');
139
    
140
        //If the user is logged in then use there preferred timezone
141
        if (Auth::check())
142
            $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...
143
        
144
        return $time->format('H:i');
145
    }
146
    
147
    /**
148
     * Accessor: Get the close time of the device converted to the users preferred time and
149
     * converted to a user friendly format of h:i a
150
     *
151
     * @return string
152
     */
153 View Code Duplication
    public function getCloseTimeHumanAttribute()
154
    {
155
        $time = new Carbon($this->attributes['close_time'], 'UTC');
156
        $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...
157
        
158
        return $time->format('h:i a');
159
    }
160
    
161
    /**
162
     * Set the open time to UTC
163
     * If it is a device saving the time use UTC
164
     * If it is a user saving the time use their preferred timezone
165
     *
166
     * @param  string  $value
167
     * @return void
168
     */
169 View Code Duplication
    public function setOpenTimeAttribute($value)
170
    {
171
        //If the user is logged in then use there preferred timezone
172
        if (Auth::check())
173
        {
174
            $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...
175
            $time = $time->setTimezone('UTC');
176
        }
177
        else
178
            $time = new Carbon($value, 'UTC');
179
        
180
        $this->attributes['open_time'] = $time->format('H:i:s');
181
    }
182
    
183
    /**
184
     * Set the close time to UTC
185
     * If it is a device saving the time use UTC
186
     * If it is a user saving the time use their preferred timezone
187
     *
188
     * @param  string  $value
189
     * @return void
190
     */
191 View Code Duplication
    public function setCloseTimeAttribute($value)
192
    {
193
        //If the user is logged in then use there preferred timezone
194
        if (Auth::check())
195
        {
196
            $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...
197
            $time = $time->setTimezone('UTC');
198
        }
199
        else
200
            $time = new Carbon($value, 'UTC');
201
        
202
        $this->attributes['close_time'] = $time->format('H:i:s');
203
    }
204
    
205
    /**
206
     * Accessor: Get the last time the server received and update call from the device converted to a
207
     * user friendly format. The format is Month day 12hour:mins am/pm and will be in the user's preferred timezone
208
     *
209
     * @return string
210
     */
211
    public function getLastNetworkUpdateAtHumanAttribute()
212
    {
213
        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...
214
    }
215
    
216
    /**
217
     * Accessor: Get the last time the server received and update call from the device converted to a
218
     * user friendly detailed format. The format is Month day, year 12hour:mins am/pm and will be in the user's preferred timezone
219
     *
220
     * @return string
221
     */
222
    public function getLastNetworkUpdateAtDetailedAttribute()
223
    {
224
        return $this->last_network_update_at->setTimezone(Auth::user()->timezone)->format('M j, Y 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...
225
    }
226
    
227
    /**
228
     * Accessor: Get the devices last update time converted to a
229
     * user friendly format. The format is Month day, year 12hour:mins am/pm and will be in the user's preferred timezone
230
     *
231
     * @return string
232
     */
233
    public function getUpdatedAtHumanAttribute()
234
    {
235
        return $this->updated_at->setTimezone(Auth::user()->timezone)->format('M j, Y 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...
236
    }
237
    
238
    /**
239
     * Accessor: Get the devices created at time converted to a
240
     * user friendly format. The format is Month day, year 12hour:mins am/pm and will be in the user's preferred timezone
241
     *
242
     * @return string
243
     */
244
    public function getCreatedAtHumanAttribute()
245
    {
246
        return $this->updated_at->setTimezone(Auth::user()->timezone)->format('M j, Y 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...
247
    }
248
    
249
    /**
250
     * Scope a query to only include devices belonging to a given location
251
     *
252
     * @param \Illuminate\Database\Eloquent\Builder $query
253
     * @param int $location_id
254
     * @return \Illuminate\Database\Eloquent\Builder
255
     */
256
    public function scopeByLocation($query, $location_id)
257
    {
258
        return $query->where('location_id', $location_id);
259
    }
260
    
261
    /**
262
     * Scope a query to limit the included columns to only include what is publicly needed to be displayed on the
263
     * dashboard
264
     *
265
     * @param \Illuminate\Database\Eloquent\Builder $query
266
     * @return \Illuminate\Database\Eloquent\Builder
267
     */
268
    public function scopePublicDashData($query)
269
    {
270
        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...
271
            'devices.id',
272
            'name',
273
            'location_id',
274
            'cover_command',
275
            'cover_status',
276
            'open_time',
277
            'close_time',
278
            'update_rate',
279
            'image_rate',
280
            'sensor_rate',
281
            'last_network_update_at',
282
            'image.updated_at as image_updated_at',
283
        ]);
284
    }
285
    
286
    /**
287
     * Create a new API token for the device.
288
     */
289
    public function generateToken()
290
    {
291
        $this->token = str_random(60);
292
        $this->save();
293
        
294
        return $this->token;
295
    }
296
    
297
    /**
298
     * Get a device by uuid
299
     *
300
     * @param string $uuid
301
     * @return Device|Illuminate\Database\Eloquent\Model
302
     */
303
    public static function getDeviceByUUID($uuid)
304
    {
305
        return self::where('uuid', $uuid)->first();
306
    }
307
    
308
    /**
309
     * Get the deviceimage record associated with the device.
310
     */
311
    public function image()
312
    {
313
        return $this->hasOne('App\Deviceimage');
314
    }
315
    
316
317
    /**
318
     * Get the sensors associated with the device.
319
     */
320
    public function sensors()
321
    {
322
        return $this->hasMany('App\Sensor');
323
    }
324
    
325
    /**
326
     * Get the sensor data associated with the device.
327
     */
328
    public function data()
329
    {
330
        return $this->hasManyThrough('App\SensorData', 'App\Sensor');
331
    }
332
    
333
    /**
334
     * Check if the device is ready for a cover command
335
     *
336
     * @return boolean
337
     */
338
    public function isReadyForCommand()
339
    {
340
        return ($this->cover_status == 'open' || $this->cover_status == 'closed' || $this->cover_status == 'locked');
341
    }
342
    
343
    /**
344
     * Check if the current time is during the devices scheduled time to be open
345
     *
346
     * @return boolean
347
     */
348
    public function isDuringScheduleOpen()
349
    {
350
        $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...
351
        //Get the open, close, and current time in the users timezone
352
        $open_time = new Carbon($this->open_time, $timezone);
353
        $close_time = new Carbon($this->close_time, $timezone);
354
        $time_now = Carbon::now($timezone);
355
    
356
        //Check if the current time is during the open schedule or not
357
        if ($time_now->gt($open_time) && $time_now->lt($close_time))
358
            return true;
359
        else
360
            return false;
361
    }
362
    
363
    /**
364
     * Get the covers actual status based on the current command and the devices status
365
     *
366
     * @return string
367
     */
368
    public function actualCoverStatus()
369
    {
370
        $isOpen = $this->cover_status === 'open';
371
        $isClosed = $this->cover_status === 'closed';
372
        $isLocked = $this->cover_status === 'locked';
373
            
374
        switch ($this['cover_command'])
375
        {
376
            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...
377
                if ($isOpen)
378
                    $status = 'open';
379
                else if ($isLocked)
380
                    $status = 'unlocking';
381
                else
382
                    $status = 'opening';
383
                break;
384
            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...
385
                if ($isClosed)
386
                    $status = 'closed';
387
                else if ($isLocked)
388
                    $status = 'unlocking';
389
                else
390
                    $status = 'closing';
391
                break;
392
            case 'lock':
393
                $status = 'locked';
394
                break;
395
            default:
396
                $status = 'error';
397
        }
398
    
399
        if ($this->cover_status === 'error')
400
            $status = 'error';
401
        
402
        return $status;
403
    }
404
    
405
    /**
406
     * Get the page number of the device for the dashboard device table pagination
407
     *
408
     * @param int $limit
409
     * @return int
410
     */
411
    public function dashPageNum($limit)
412
    {
413
        $pos = Device::where('location_id', '=', $this->location_id)
414
            ->where('name', '<=', $this->name)
415
            ->orderBy('name', 'ASC')
416
            ->count();
417
        
418
        return ceil($pos / $limit);
419
    }
420
}
421