Completed
Push — master ( 9f0c7a...06d573 )
by Arthur
02:58
created

ACSController   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 191
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 7
dl 0
loc 191
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A get() 0 4 1
A __construct() 0 9 1
C store() 0 50 7
A handleDoor() 0 17 2
A handleDevice() 0 18 3
B handleSystemCheckIn() 0 31 5
A sendResponse() 0 7 1
A returnMemberStatus() 0 13 2
1
<?php namespace BB\Http\Controllers;
2
3
use BB\Entities\DetectedDevice;
4
use BB\Repo\ACSNodeRepository;
5
use BB\Validators\ACSValidator;
6
7
class ACSController extends Controller
8
{
9
10
    /**
11
     * @var ACSNodeRepository
12
     */
13
    private $deviceRepository;
0 ignored issues
show
Unused Code introduced by
The property $deviceRepository is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
14
    /**
15
     * @var ACSValidator
16
     */
17
    private $ACSValidator;
18
    /**
19
     * @var \BB\Services\KeyFobAccess
20
     */
21
    private $keyFobAccess;
22
23
    function __construct(
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
24
        ACSNodeRepository $acsNodeRepository,
25
        ACSValidator $ACSValidator,
26
        \BB\Services\KeyFobAccess $keyFobAccess
27
    ) {
28
        $this->acsNodeRepository = $acsNodeRepository;
0 ignored issues
show
Bug introduced by
The property acsNodeRepository does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
29
        $this->ACSValidator     = $ACSValidator;
30
        $this->keyFobAccess     = $keyFobAccess;
31
    }
32
33
    public function get()
34
    {
35
36
    }
37
38
    public function store()
39
    {
40
        $data = \Request::only('device', 'service', 'message', 'tag', 'time', 'payload', 'signature', 'nonce');
41
42
        //device = the device id from the devices table - unique to each piece of hardware
43
        //service = what the request is for, entry, usage, consumable
44
        //message = system message, heartbeat, boot
45
        //tag = the keyfob id
46
        //time = the time of the action
47
        //payload = any extra data relavent to the request
48
        //signature = an encoded value generated using a secret key - oauth style
49
        //nonce = a unique value suitable to stop replay attacks
50
51
        $this->ACSValidator->validate($data);
52
53
54
        //System messages
55
        if (in_array($data['message'], ['boot', 'heartbeat'])) {
56
            return $this->handleSystemCheckIn($data['message'], $data['device'], $data['service']);
57
        }
58
59
60
        switch ($data['service']) {
61
            case 'entry':
62
                return $this->handleDoor($data);
63
            case 'usage':
64
                return $this->handleDevice($data);
65
            case 'consumable':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
66
67
                break;
68
            case 'shop':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
69
70
                break;
71
            case 'status':
72
                return $this->returnMemberStatus($data);
73
74
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
75
            default:
76
                \Log::debug(json_encode($data));
77
        }
78
79
        $responseArray = [
80
            'time'      => time(),
81
            'command'   => null,      //stored command for the device to process
82
            'valid'     => true,      //member request
83
            'available' => true,      //device status - remote shutdown,
84
            'member'    => null,      //member name
85
        ];
86
87
    }
88
89
    private function handleDoor($data)
90
    {
91
        //Door entry is quite simple - this will just deal with lookups
92
93
        try {
94
            $this->keyFobAccess->verifyForEntry($data['tag'], 'main-door', $data['time']);
95
96
            $this->keyFobAccess->logSuccess();
97
        } catch (\Exception $e) {
98
            return $this->sendResponse(404, ['valid' => '0', 'cmd' => null]);
99
        }
100
101
        $cmd = $this->acsNodeRepository->popCommand($data['device']);
102
103
        $responseData = ['member' => $this->keyFobAccess->getMemberName(), 'valid' => '1', 'cmd' => $cmd];
104
        return $this->sendResponse(200, $responseData);
105
    }
106
107
    private function handleDevice($data)
108
    {
109
        $device = $this->acsNodeRepository->getByName($data['device']);
110
111
        if ($data['message'] == 'boot') {
112
            $this->acsNodeRepository->logBoot($data['device']);
113
        } elseif ($data['message'] == 'heartbeat') {
114
            $this->acsNodeRepository->logHeartbeat($data['device']);
115
        }
116
117
        //$member = $this->keyFobAccess->verifyForDevice($data['tag'], 'laser');
0 ignored issues
show
Unused Code Comprehensibility introduced by
69% 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...
118
119
        $deviceStatus = 'ok';
120
121
        $responseData = ['deviceStatus' => $deviceStatus];
122
123
        return $this->sendResponse(200, $responseData);
124
    }
125
126
127
    /**
128
     * System checkins are common across all devices
129
     * Record the time and return pending status messages
130
     *
131
     * @param $message
132
     * @param $device
133
     * @return Response
134
     */
135
    private function handleSystemCheckIn($message, $device, $service)
136
    {
137
        switch ($message) {
138
            case 'boot':
139
                $this->acsNodeRepository->logBoot($device);
140
                break;
141
            case 'heartbeat':
142
                $this->acsNodeRepository->logHeartbeat($device);
143
                break;
144
        }
145
146
        //The command comes from the database and will instruct the door entry system to clear its memory if set
147
        $cmd = $this->acsNodeRepository->popCommand($device);
148
149
        switch ($service) {
150
            case 'entry':
151
                //we don't have a system for this at the moment but could have a global shutdown option
152
                $deviceStatus = '1';
153
                break;
154
            case 'usage':
155
                //lookup the piece of equipment from the device id and get the status
156
                $deviceStatus = '1';
157
                break;
158
            default:
159
                $deviceStatus = '1';
160
        }
161
162
        $responseData = ['cmd' => $cmd, 'deviceStatus' => $deviceStatus];
163
164
        return $this->sendResponse(200, $responseData);
165
    }
166
167
    /**
168
     * Json encode the response data and return
169
     *
170
     * @param int   $statusCode
171
     * @param array $responseData
172
     *
173
     * @return \Response
174
     */
175
    private function sendResponse($statusCode = 200, array $responseData)
176
    {
177
        $responseData['time'] = time();
178
        $response = response()->json($responseData, $statusCode);
179
        $response->headers->set('Content-Length', strlen($response->getContent()));
180
        return $response;
181
    }
182
183
    private function returnMemberStatus($data)
184
    {
185
        try {
186
            $user = $this->keyFobAccess->verifyForEntry($data['tag'], 'main-door', $data['time']);
187
        } catch (\Exception $e) {
188
            $responseData = ['valid' => '0', 'cmd' => ''];
189
            return $this->sendResponse(404, $responseData);
190
        }
191
192
        $responseData = ['member' => $this->keyFobAccess->getMemberName(), 'valid' => '1', 'cmd' => ''];
193
194
        return $this->sendResponse(200, $responseData);
195
    }
196
197
} 
198