Completed
Pull Request — master (#96)
by Brandon
02:26
created

DeviceController::locations()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 9
ccs 0
cts 5
cp 0
rs 9.6666
cc 2
eloc 5
nc 2
nop 1
crap 6
1
<?php
2
3
namespace App\Http\Controllers;
4
5
use App\Http\Requests\EditDevice;
6
use Validator;
7
use Illuminate\Http\Request;
8
use App\DataTables\DevicesDataTable;
9
use Illuminate\Support\Facades\Route;
10
use App\Device;
11
use App\Site;
12
use App\Location;
13
14
class DeviceController extends Controller
15
{
16
    /**
17
     * Create a new controller instance.
18
     *
19
     */
20
    public function __construct()
21
    {
22
        $this->middleware('auth');
23
    }
24
25
    /**
26
     * Display index page and process dataTable ajax request.
27
     *
28
     * @param \App\DataTables\DevicesDataTable $dataTable
29
     * @return \Illuminate\Http\JsonResponse|\Illuminate\View\View
30
     */
31
    public function index(DevicesDataTable $dataTable)
32
    {
33
        $trashed = Device::onlyTrashed()->get();
34
        return $dataTable->render('device.index', compact('trashed'));
35
    }
36
37
    /**
38
     * Show create device page.
39
     *
40
     * @return \BladeView|bool|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
41
     */
42
    public function create()
43
    {
44
        return view('device.index');
45
    }
46
47
    /**
48
     * Show the given device.
49
     *
50
     * @param  string  $id
51
     * @return \BladeView|bool|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
52
     */
53
    public function show($id)
54
    {
55
        $device = Device::findOrFail($id);
56
        return view('device.show', [ 'device' => $device ]);
57
    }
58
59
    /**
60
     * View the edit device page
61
     *
62
     * @param  string  $id
63
     * @return \BladeView|bool|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
64
     */
65
    public function edit($id)
66
    {
67
        //Get the device with the given id
68
        $device = Device::publicDashData()->findOrFail($id);
69
        //Get the devices location
70
        $location = $device->location()->select('id', 'name', 'site_id')->first();
71
    
72
        //Get the site id and location id if they exist and if not assign 0
73
        $site_id = $location->site_id ?? 0;
74
        $location_id = $location->id ?? 0;
75
    
76
        //Get all sites with the current site first
77
        $sites = Site::select('id', 'name')->orderByRaw("id = ? DESC", $site_id)
78
            ->orderBy('name', 'ASC')->get();
79
        //Get all locations for the selected site with the selected location first
80
        $locations = Location::select('id', 'name')->where('site_id', '=', $sites[0]->id ?? 0)
81
            ->orderByRaw("id = ? DESC", $location_id)->orderBy('name', 'ASC')->get();
82
        
83
        return view('device.edit', [ 'device' => $device, 'locations' => $locations, 'sites' => $sites ]);
84
    }
85
86
    /**
87
     * Update the given device.
88
     *
89
     * @param  EditDevice  $request
90
     * @param  string  $id
91
     * @return \Illuminate\Http\RedirectResponse
92
     */
93
    public function update(EditDevice $request, $id)
94
    {
95
        $device = Device::findOrFail($id);
96
        
97
        //Get the site id of the old or newly created site
98
        if (!empty($request->input('new_site_name')))
99
        {
100
            //Create a new site
101
            $site = Site::create(['name' => $request->input('new_site_name')]);
102
            $site_id = $site->id;
103
        }
104
        else
105
            $site_id = $request->input('site_id');
106
        
107
        //Get the location id of the old or newly created location
108
        if (!empty($request->input('new_location_name')))
109
        {
110
            //Create a new location
111
            $location = Location::create(['name' => $request->input('new_location_name'), 'site_id' => $site_id]);
112
            $location_id = $location->id;
113
        }
114
        else
115
            $location_id = $request->input('location_id');
116
        
117
        //Update the device
118
        $device->location_id = $location_id;
119
        $device->name = $request->input('name');
120
        $device->open_time = $request->input('open_time');
121
        $device->close_time = $request->input('close_time');
122
        $device->update_rate = $request->input('update_rate');
123
        $device->image_rate = $request->input('image_rate');
124
        $device->sensor_rate = $request->input('sensor_rate');
125
        //Check if the cover_command needs to be updated
126
        if ($request->input('command') != null)
127
        {
128
            //If device is currently opening, closing or in an error state don't update command
129
            if (!$device->isReadyForCommand())
130
                return response()->json("Device is currently in use.", 403);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return response()->json(...rrently in use.', 403); (Illuminate\Http\JsonResponse) is incompatible with the return type documented by App\Http\Controllers\DeviceController::update of type Illuminate\Http\RedirectResponse.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
131
    
132
            $command = $request->input('command');
133
            
134
            //If command is to unlock the device then check if the device should be open or closed based on the schedule
135
            if ($request->command === 'unlock')
0 ignored issues
show
Documentation introduced by
The property command does not exist on object<App\Http\Requests\EditDevice>. 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...
136
            {
137
                if ($device->isDuringScheduleOpen())
138
                    $command =  'open';
139
                else
140
                    $command =  'close';
141
            }
142
            $device->cover_command = $command;
143
        }
144
        
145
        $device->save();
146
    
147
        if (\Request::ajax())
148
            return response()->json(['success' => 'Device updated successfully']);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return response()->json(...pdated successfully')); (Illuminate\Http\JsonResponse) is incompatible with the return type documented by App\Http\Controllers\DeviceController::update of type Illuminate\Http\RedirectResponse.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
149
        else
150
            return redirect()->route('device.show', $id)
1 ignored issue
show
Documentation introduced by
$id is of type string, but the function expects a array.

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...
151
                ->with('success', 'Device updated successfully');
152
    }
153
154
    /**
155
     * Deletes a device.
156
     *
157
     * @param  string  $id
158
     * @return \Illuminate\Http\RedirectResponse
159
     */
160 View Code Duplication
    public function destroy($id)
161
    {
162
        $device = Device::withTrashed()->findOrFail($id);
163
164
        if ($device->trashed())
165
        {
166
            //If the device was already deleted then permanently delete it
167
            $device->forceDelete($device->id);
168
        }
169
        else
170
        {
171
            //Remove the location from the device
172
            $device->location_id = null;
173
            $device->save();
174
            
175
            //Soft delete the device the first time
176
            $device->delete();
177
        }
178
179
        return redirect()->route('device.index')
180
            ->with('success','Device deleted successfully');
181
    }
182
    
183
    /**
184
     * Restores a device.
185
     *
186
     * @param  string  $id
187
     * @return \Illuminate\Http\RedirectResponse
188
     */
189 View Code Duplication
    public function restore($id)
190
    {
191
        $device = Device::onlyTrashed()->findOrFail($id);
192
193
        $device->restore();
194
        
195
        return redirect()->route('device.show', $device->id)
196
            ->with('success','Device restored successfully');
197
    }
198
}
199