Completed
Pull Request — master (#27)
by Brandon
02:01
created

ApiController::update()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 64
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 64
ccs 0
cts 25
cp 0
rs 9.3956
cc 3
eloc 40
nc 3
nop 1
crap 12

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace App\Http\Controllers;
4
5
use Validator;
6
use Illuminate\Http\Request;
7
use App\Device;
8
9
class ApiController extends Controller
10
{
11
    /**
12
     * Creates a json response for all the devices.
13
     *
14
     * @return Response
15
     */    
16
    public function index()
17
    {
18
        $devices = Device::all();
19
        return response()->json($devices, 200);
0 ignored issues
show
Bug introduced by
It seems like $devices defined by \App\Device::all() on line 18 can also be of type object<Illuminate\Database\Eloquent\Collection>; however, Illuminate\Contracts\Rou...ResponseFactory::json() does only seem to accept string|array, 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...
20
    }
21
22
    /**
23
     * Creates a json response for a specifc device.
24
     *
25
     * @param  Device  $device
26
     * @return Response
27
     */    
28
    public function show(Device $device)
29
    {
30
        return response()->json($device, 200);
31
    }
32
33
    /**
34
     * Updates the status of a device.
35
     *
36
     * @param  Request  $request
37
     * @return Response
38
     */
39
    public function update(Request $request)
40
    {
41
        // Validate the request
42
        $validator = Validator::make($request->all(), [
43
            'uuid'          => 'required|string|max:255|exists:devices,uuid',
44
            'token'         => 'required|string|max:60',
45
            'version'       => 'nullable|string|max:32',
46
            'hostname'      => 'nullable|string|alpha_num|max:255',
47
            'ip'            => 'nullable|ip',
48
            'mac_address'   => 'nullable|string|min:16|max:16',
49
            'time'          => 'nullable|date',
50
            'cover_status'  => 'nullable|string|max:32',
51
            'error_msg'     => 'nullable|string',
52
            'limitsw_open'   => 'nullable|boolean',
53
            'limitsw_closed' => 'nullable|boolean',
54
            'light_in'      => 'nullable|numeric',
55
            'light_out'     => 'nullable|numeric',
56
            'cpu_temp'      => 'nullable|numeric',
57
            'temperature'   => 'nullable|numeric',
58
            'humidity'      => 'nullable|numeric',
59
        ]);
60
        
61
        // If validation fails, send the validation error back with status 400
62
        if ($validator->fails()) {
63
            return response()->json(['data' => $validator->toArray()], 400);
64
        }
65
        
66
        // Get the device record
67
        $device = Device::where('uuid', $request->input('uuid'))->first();
68
        
69
        // If token doesnt match then send 401 unauthorized.
70
        if ($request->input('token') != $device->token) {
71
            return response()->json(['data' => 'Bad token.'], 401);
72
        }
73
        
74
        // Update the device
75
        $device->version = $request->input('version');
76
        $device->hostname = $request->input('hostname');
77
        $device->ip = $request->input('ip');
78
        $device->mac_address = $request->input('mac_address');
79
        $device->time = $request->input('time');
80
        $device->cover_status = $request->input('cover_status');
81
        $device->error_msg = $request->input('error_msg');
82
        $device->limitsw_open = $request->input('limitsw_open');
83
        $device->limitsw_closed = $request->input('limitsw_closed');
84
        $device->light_in = $request->input('light_in');
85
        $device->light_out = $request->input('light_out');
86
        $device->cpu_temp = $request->input('cpu_temp');
87
        $device->temperature = $request->input('temperature');
88
        $device->humidity = $request->input('humidity');
89
        
90
        $device->save();
91
        
92
        // Create an api token for the new device.
93
        $device->generateToken();
94
        
95
        // A 'Registered' event is created and will trigger any relevant
96
        // observers, such as sending a confirmation email or any 
97
        // code that needs to be run as soon as the device is created.
98
        //event(new Registered(true));
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% 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...
99
        
100
        // Return the new device info including the token.
101
        return response()->json(['data' => $device->toArray()], 201);
102
    }
103
    
104
    /**
105
     * Registers a new device.
106
     *
107
     * @param  Request  $request
108
     * @return Response
109
     */
110
    public function register(Request $request)
111
    {
112
        // Validate the request
113
        $validator = Validator::make($request->all(), [
114
            'uuid' => 'required|string|max:255',
115
            'challenge' => 'required|string|min:6',
116
        ]);
117
        
118
        // If validation fails, send the validation error back with status 400
119
        if ($validator->fails()) {
120
            return response()->json(['data' => $validator->toArray()], 400);
121
        }
122
        
123
        // If challenge string doesnt match then send 401 unauthorized.
124
        if ($request->input('challenge') != 'temppass') {
125
            return response()->json(['data' => 'Bad challenge.'], 401);
126
        }
127
        
128
        // If the uuid already exists then just send them the record.
129
        if ($device = Device::where('uuid', $request->input('uuid'))->first()) {
130
            return response()->json([ 'data' => [ 
131
                'name' => $device->name,
132
                'uuid' => $device->uuid,
133
                'id' => $device->id,
134
                'token' => $device->token,
135
            ]], 200);
136
        }
137
        
138
        // Create the new device
139
        $device = new Device;
140
        $device->name = 'New Device';
0 ignored issues
show
Documentation introduced by
The property name does not exist on object<App\Device>. 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...
141
        $device->uuid = $request->input('uuid');
0 ignored issues
show
Documentation introduced by
The property uuid does not exist on object<App\Device>. 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...
142
        $device->save();
143
        
144
        // Create an api token for the new device.
145
        $device->generateToken();
146
        
147
        // A 'Registered' event is created and will trigger any relevant
148
        // observers, such as sending a confirmation email or any 
149
        // code that needs to be run as soon as the device is created.
150
        //event(new Registered(true));
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% 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...
151
        
152
        // Return the new device info including the token.
153
        return response()->json([ 'data' => [ 
154
            'name' => $device->name,
0 ignored issues
show
Documentation introduced by
The property name does not exist on object<App\Device>. 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...
155
            'uuid' => $device->uuid,
0 ignored issues
show
Documentation introduced by
The property uuid does not exist on object<App\Device>. 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...
156
            'id' => $device->id,
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<App\Device>. 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...
157
            'token' => $device->token,
0 ignored issues
show
Documentation introduced by
The property token does not exist on object<App\Device>. 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...
158
        ]], 201);
159
    }
160
}
161
162
// HTTP STATUS CODES:
163
// 200: OK. The standard success code and default option.
164
// 201: Object created. Useful for the store actions.
165
// 204: No content. When an action was executed successfully, but there is no content to return.
166
// 206: Partial content. Useful when you have to return a paginated list of resources.
167
// 400: Bad request. The standard option for requests that fail to pass validation.
168
// 401: Unauthorized. The user needs to be authenticated.
169
// 403: Forbidden. The user is authenticated, but does not have the permissions to perform an action.
170
// 404: Not found. This will be returned automatically by Laravel when the resource is not found.
171
// 500: Internal server error. Ideally you're not going to be explicitly returning this, but if something unexpected breaks, this is what your user is going to receive.
172
// 503: Service unavailable. Pretty self explanatory, but also another code that is not going to be returned explicitly by the application.