Passed
Push — clockify ( 14a036...ab4086 )
by Guillaume
35:36
created

Clockify::workspaces()   A

Complexity

Conditions 2
Paths 4

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 6
nc 4
nop 0
dl 0
loc 9
ccs 6
cts 6
cp 1
crap 2
rs 10
c 1
b 0
f 1
1
<?php
2
3
namespace Godbout\Alfred\Time\Services;
4
5
use Carbon\Carbon;
6
use Godbout\Alfred\Time\Workflow;
7
use GuzzleHttp\Client;
8
9
class Clockify extends TimerService
10
{
11
    private $client;
12
13
    private $data = null;
0 ignored issues
show
introduced by
The private property $data is not used, and could be removed.
Loading history...
14
15 78
16
    public function __construct($apiToken)
17 78
    {
18 78
        $this->client = new Client([
19
            'base_uri' => 'https://api.clockify.me/api/v1/',
20 78
            'headers' => [
21 78
                'content-type' => 'application/json',
22
                'X-Api-Key' => $apiToken
23
            ]
24 78
        ]);
25
    }
26 12
27
    public function projects()
28
    {
29 12
        try {
30 6
            $user = json_decode(
31
                $this->client->get("user")->getBody()->getContents()
32 6
            );
33 6
34 6
            Workflow::getConfig()->write('clockify.active_workspace_id', $user->activeWorkspace);
35
36
            $response = $this->client->get("workspaces/{$user->activeWorkspace}/projects");
37
38 18
            $projects = json_decode($response->getBody()->getContents());
39
40
            return array_column($projects, 'name', 'id');
41 18
        } catch (\Exception $e) {
42 18
            return [];
43
        }
44
    }
45 12
46
    public function tags()
47 12
    {
48
        try {
49 12
            $workspaceId = Workflow::getConfig()->read('clockify.active_workspace_id');
50 6
51 6
            $response = $this->client->get("workspaces/$workspaceId/tags");
52
            $tags = json_decode($response->getBody()->getContents());
53
54
            return array_column($tags, 'name', 'id');
55 18
        } catch (\Exception $e) {
56
            return [];
57
        }
58 18
    }
59
60 18
    public function startTimer()
61 12
    {
62
        try {
63 12
            $workspaceId = Workflow::getConfig()->read('clockify.active_workspace_id');
64 6
65 6
            $response = $this->client->post("workspaces/$workspaceId/time-entries", [
66
                'json' => [
67
                    'start' => (new \DateTime())->format('Y-m-d\TH:i:s\Z'),
68
                    'description' => getenv('timer_description'),
69 30
                    'projectId' => getenv('timer_project_id'),
70
                    'tagIds' => getenv('timer_tag_id') ? [getenv('timer_tag_id')] : [''],
71
                ]
72 30
            ]);
73
74 30
            $timer = json_decode($response->getBody()->getContents());
75 10
76 30
            if (! isset($timer->id)) {
77 30
                return false;
78 30
            }
79 30
        } catch (Exception $e) {
0 ignored issues
show
Bug introduced by
The type Godbout\Alfred\Time\Services\Exception was not found. Did you mean Exception? If so, make sure to prefix the type with \.
Loading history...
80
            return false;
81
        }
82
83 30
        return $timer->id;
84
    }
85 30
86 30
    public function stopCurrentTimer()
87
    {
88
        $user = json_decode(
89
            $this->client->get("user")->getBody()->getContents()
90
        );
91
92 30
        if ($timerId = $this->runningTimer()) {
0 ignored issues
show
Unused Code introduced by
The assignment to $timerId is dead and can be removed.
Loading history...
93
            $response = $this->client->patch("workspaces/{$user->activeWorkspace}/user/{$user->id}/time-entries", [
94
                'json' => [
95 30
                    'end' => (new \DateTime())->format('Y-m-d\TH:i:s\Z'),
96
                ]
97 30
            ]) ;
98 30
99
            $timer = json_decode($response->getBody()->getContents());
100 30
101 30
            if (! isset($timer->timeInterval->end)) {
102
                throw new Exception("Can't stop current running timer.", 1);
103 30
104
                return false;
0 ignored issues
show
Unused Code introduced by
return false is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
105
            }
106
107 30
            return true;
108
        }
109 30
110
        return false;
111
    }
112
113
    public function runningTimer()
114
    {
115 30
        try {
116
            $user = json_decode(
117
                $this->client->get("user")->getBody()->getContents()
118 6
            );
119
120
            $response = $this->client->get(
121 78
                "workspaces/{$user->activeWorkspace}/user/{$user->id}/time-entries?in-progress=true"
122
            );
123
124 78
            $timer = json_decode($response->getBody()->getContents());
125 78
126
            return $timer[0]->id ?? false;
127 78
        } catch (\Exception $e) {
128
            return false;
129 78
        }
130
131 78
        return true;
0 ignored issues
show
Unused Code introduced by
return true is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
132
    }
133
134
    public function pastTimers()
135
    {
136
        try {
137
            $pastTimers = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $pastTimers is dead and can be removed.
Loading history...
138
139 6
            $user = json_decode(
140
                $this->client->get("user")->getBody()->getContents()
141
            );
142 6
143
            $response = $this->client->get("workspaces/{$user->activeWorkspace}/user/{$user->id}/time-entries", [
144 6
                'start' => Carbon::today(),
145 6
                'end' => Carbon::today()->subDays(30),
146
            ]);
147 6
            $clockifyTimers = json_decode($response->getBody()->getContents());
148 6
149 6
            return $this->convertToPastTimers($clockifyTimers);
150
        } catch (Exception $e) {
151 6
            return [];
152
        }
153 6
    }
154
155
    public function continueTimer($timerId = null)
156
    {
157
        /**
158
         * Timer attributes are stored in env variables
159 6
         * gathered in startTimer.
160
         */
161
        return $this->startTimer();
162
    }
163
164
    public function deleteTimer($timerId)
165 6
    {
166
        return false;
167
    }
168 6
169
    protected function convertToPastTimers($clockifyTimers)
170 6
    {
171
        $projects = $this->projects();
172
        $tags = $this->tags();
173 6
174
        return array_map(function ($clockifyTimer) use ($projects, $tags) {
175 6
            return $this->buildPastTimerObject($clockifyTimer, $projects, $tags);
176 6
        }, $clockifyTimers);
177
    }
178
179 6
    protected function buildPastTimerObject($clockifyTimer, $projects, $tags)
180 6
    {
181
        $pastTimer['id'] = $clockifyTimer->id;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$pastTimer was never initialized. Although not strictly required by PHP, it is generally a good practice to add $pastTimer = array(); before regardless.
Loading history...
182
        $pastTimer['description'] = $clockifyTimer->description;
183 6
184
        if (isset($clockifyTimer->projectId)) {
185 6
            $pastTimer['project_id'] = $clockifyTimer->projectId;
186 6
            $pastTimer['project_name'] = $projects[$clockifyTimer->projectId];
187
        }
188 6
189 6
        if (isset($clockifyTimer->tagIds[0])) {
190 6
            $pastTimer['tag_id'] = $clockifyTimer->tagIds[0];
191
            $pastTimer['tags'] = $tags[$clockifyTimer->tagIds[0]];
192
        }
193 6
194 6
        $pastTimer['duration'] = $clockifyTimer->timeInterval->duration;
195 6
196
        return (object) $pastTimer;
197
    }
198
}
199