Completed
Pull Request — master (#116)
by
unknown
02:19
created

Device::getLastNetworkUpdateAtDetailedAttribute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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