Completed
Pull Request — master (#63)
by Brandon
02:14
created

DeviceController::editDetails()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 31
Code Lines 12

Duplication

Lines 31
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 31
loc 31
ccs 0
cts 11
cp 0
rs 8.8571
cc 2
eloc 12
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
        // TODO: Setup logging
24
        // $this->middleware('log')->only('index');
0 ignored issues
show
Unused Code Comprehensibility introduced by
77% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
25
    }
26
27
    /**
28
     * Display index page and process dataTable ajax request.
29
     *
30
     * @param \App\DataTables\DevicesDataTable $dataTable
31
     * @return \Illuminate\Http\JsonResponse|\Illuminate\View\View
32
     */
33
    public function index(DevicesDataTable $dataTable)
34
    {
35
        return $dataTable->render('device.index');
36
    }
37
38
    /**
39
     * Show create device page.
40
     *
41
     * @return \BladeView|bool|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
42
     */
43
    public function create()
44
    {
45
        return view('device.create');
46
    }
47
48
    /**
49
     * Show the given device.
50
     *
51
     * @param  string  $id
52
     * @return \BladeView|bool|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
53
     */
54
    public function show($id)
55
    {
56
        $device = Device::publicDashData()->findOrFail($id);
0 ignored issues
show
Bug introduced by
The method publicDashData() does not exist on App\Device. Did you maybe mean scopePublicDashData()?

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...
57
58
        return view('device.show', [ 'device' => $device ]);
59
    }
60
61
    /**
62
     * View the edit device page or the edit device modal
63
     *
64
     * @param  string  $id
65
     * @return \BladeView|bool|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
66
     */
67
    public function edit($id)
68
    {
69
        //Get the device with the given id
70
        $device = Device::publicDashData()->findOrFail($id);
0 ignored issues
show
Bug introduced by
The method publicDashData() does not exist on App\Device. Did you maybe mean scopePublicDashData()?

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...
71
        
72
        //Get the devices location
73
        $location = $device->location()->select('id', 'name', 'site_id')->firstOrFail();
74
        
75
        //Check if the selected device has a location
76
        if ($location)
77
        {
78
            //Get all the sites except for the current site ordered by name
79
            $sites = Site::select('id', 'name')->orderBy('name', 'ASC')->get()->except($location->site->id);
80
            //Get all the locations except for the current location for the given site ordered by name
81
            $locations = $location->site->locations()->select('id', 'name', 'site_id')->orderBy('name', 'ASC')->get()->except($location->id);
82
            
83
            //Add the current site to the front of the collection of sites
84
            $sites->prepend($location->site);
85
            //Add the current location to the front of the collection of locations
86
            $locations->prepend($location);
87
        }
88
        else
89
        {
90
            //Set locations to null since there is no site or location attached to the selected device
91
            $locations = null;
92
            //Get all of the sites
93
            $sites = Site::all();
94
        }
95
        
96
        if (\Request::ajax())
97
            return response()->json([ 'device' => $device, 'locations' => $locations, 'sites' => $sites ]);
98
        else
99
            return view('device.edit', [ 'device' => $device, 'locations' => $locations, 'sites' => $sites ]);
100
    }
101
    
102
    /**
103
     * Get the locations with the given site id
104
     *
105
     * @param  int $site_id
106
     * @return Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
107
     */
108
    public function locations($site_id)
109
    {
110
        $locations = Location::bySite($site_id)->select('id', 'name', 'site_id')->get();
0 ignored issues
show
Bug introduced by
The method bySite() does not exist on App\Location. Did you maybe mean scopeBySite()?

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...
111
    
112
        return response()->json($locations);
113
    }
114
    
115
    /**
116
     * Get the devices details
117
     *
118
     * @param  int  $id
119
     * @return Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
120
     */
121
    public function details($id)
122
    {
123
        $device = Device::publicDashData()->findOrFail($id);
0 ignored issues
show
Bug introduced by
The method publicDashData() does not exist on App\Device. Did you maybe mean scopePublicDashData()?

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...
124
        
125
        return response()->json($device);
126
    }
127
128
    /**
129
     * Update the given device.
130
     *
131
     * @param  EditDevice  $request
132
     * @param  string  $id
133
     * @return \Illuminate\Http\RedirectResponse
134
     */
135
    public function update(EditDevice $request, $id)
136
    {
137
        $device = Device::findOrFail($id);
138
        $location = null;
0 ignored issues
show
Unused Code introduced by
$location 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...
139
        $site = null;
0 ignored issues
show
Unused Code introduced by
$site 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...
140
141
        // TODO figure out way for unique location names for each specific site
142
        
143
        //Get the site id of the old or newly created site
144
        if (!empty($request->input('new_site_name')))
145
        {
146
            //Create a new site
147
            $siteName = $request->input('new_site_name');
148
            $site_id = Site::createSite($siteName)->id;
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<App\Site>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write 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.");
        }
    }

}

Since the property has write access only, you can use the @property-write 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...
Bug introduced by
It seems like $siteName defined by $request->input('new_site_name') on line 147 can also be of type array; however, App\Site::createSite() does only seem to accept string, 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...
149
        }
150
        else
151
        {
152
            $site_id = $request->input('site');
153
        }
154
        
155
        //Get the location id of the old or newly created location
156
        if (!empty($request->input('new_location_name')))
157
        {
158
            //Create a new location
159
            $locationName = $request->input('new_location_name');
160
            $location_id = Location::createLocation($locationName, $site_id)->id;
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<App\Location>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write 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.");
        }
    }

}

Since the property has write access only, you can use the @property-write 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...
Bug introduced by
It seems like $locationName defined by $request->input('new_location_name') on line 159 can also be of type array; however, App\Location::createLocation() does only seem to accept string, 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...
161
        }
162
        else
163
        {
164
            $location_id = $request->input('location');
165
        }
166
        
167
        //Update the devices name and location_id
168
        $device->location_id = $location_id;
169
        $device->name = $request->input('name');
170
        $device->open_time = $request->input('open_time');
171
        $device->close_time = $request->input('close_time');
172
        $device->update_rate = $request->input('update_rate');
173
        $device->image_rate = $request->input('image_rate');
174
        $device->sensor_rate = $request->input('sensor_rate');
175
        $device->save();
176
177
        //Remove any unused sites or locations
178
        $this->RemoveUnusedSiteLoc();
179
    
180
        if (\Request::ajax())
181
            return response()->json("Success");
0 ignored issues
show
Bug Best Practice introduced by
The return type of return response()->json('Success'); (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...
182
        else
183
            return redirect('device');
184
    }
185
186
    /**
187
     * Deletes a device.
188
     *
189
     * @param  string  $id
190
     * @return \Illuminate\Http\RedirectResponse
191
     */
192
    public function destroy($id)
193
    {
194
        $device = Device::findOrFail($id);
195
196
        if ($device->trashed())
197
        {
198
            //If the device was already deleted then permanently delete it
199
            Device::destroy($id);
200
        }
201
        else
202
        {
203
            //Remove the location from the device
204
            $device->location_id = null;
205
            
206
            //Remove any unused sites or locations
207
            $this->RemoveUnusedSiteLoc();
208
            
209
            //Soft delete the user the first time
210
            $device->delete();
211
        }
212
213
        return redirect('device');
214
    }
215
    
216
    /**
217
     * Confirms deletion of a device.
218
     *
219
     * @param  string  $id
220
     * @return Response
221
     */
222
    public function remove($id)
223
    {
224
        $device = Device::findOrFail($id);
225
        
226
        return view('device.remove', [ 'device' => $device ]);
227
    }
228
    
229
    /**
230
     * Delete all unused sites and locations
231
     */
232
    private function RemoveUnusedSiteLoc()
233
    {
234
        //Delete all sites that don't have any devices
235
        //Locations connected to these sites will automatically be deleted by the database
236
        Site::doesntHave('devices')->delete();
237
    
238
        //Delete all locations that don't have any devices
239
        Location::doesntHave('devices')->delete();
240
    }
241
}
242