Passed
Pull Request — master (#30)
by Guillaume
05:29 queued 03:46
created

Clockify::buildPastTimerObject()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 11
c 0
b 0
f 0
nc 4
nop 3
dl 0
loc 20
rs 9.9
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
14
    public function __construct($apiToken)
15
    {
16
        $this->client = new Client([
17
            'base_uri' => 'https://api.clockify.me/api/v1/',
18
            'headers' => [
19
                'content-type' => 'application/json',
20
                'X-Api-Key' => $apiToken
21
            ]
22
        ]);
23
    }
24
25
    public function projects()
26
    {
27
        try {
28
            $user = json_decode(
29
                $this->client->get("user")->getBody()->getContents()
30
            );
31
32
            Workflow::getConfig()->write('clockify.active_workspace_id', $user->activeWorkspace);
33
34
            $response = $this->client->get("workspaces/{$user->activeWorkspace}/projects");
35
36
            $projects = json_decode($response->getBody()->getContents());
37
38
            return array_column($projects, 'name', 'id');
39
        } catch (\Exception $e) {
40
            return [];
41
        }
42
    }
43
44
    public function tags()
45
    {
46
        try {
47
            $workspaceId = Workflow::getConfig()->read('clockify.active_workspace_id');
48
49
            $response = $this->client->get("workspaces/$workspaceId/tags");
50
            $tags = json_decode($response->getBody()->getContents());
51
52
            return array_column($tags, 'name', 'id');
53
        } catch (\Exception $e) {
54
            return [];
55
        }
56
    }
57
58
    public function startTimer()
59
    {
60
        try {
61
            $workspaceId = Workflow::getConfig()->read('clockify.active_workspace_id');
62
63
            $response = $this->client->post("workspaces/$workspaceId/time-entries", [
64
                'json' => [
65
                    'start' => (new \DateTime())->format('Y-m-d\TH:i:s\Z'),
66
                    'description' => getenv('timer_description'),
67
                    'projectId' => getenv('timer_project_id'),
68
                    'tagIds' => getenv('timer_tag_id') ? [getenv('timer_tag_id')] : [''],
69
                ]
70
            ]);
71
72
            $timer = json_decode($response->getBody()->getContents());
73
74
            if (! isset($timer->id)) {
75
                return false;
76
            }
77
        } 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...
78
            return false;
79
        }
80
81
        return $timer->id;
82
    }
83
84
    public function stopCurrentTimer()
85
    {
86
        $user = json_decode(
87
            $this->client->get("user")->getBody()->getContents()
88
        );
89
90
        if ($this->runningTimer()) {
91
            $response = $this->client->patch("workspaces/{$user->activeWorkspace}/user/{$user->id}/time-entries", [
92
                'json' => [
93
                    'end' => (new \DateTime())->format('Y-m-d\TH:i:s\Z'),
94
                ]
95
            ]) ;
96
97
            $timer = json_decode($response->getBody()->getContents());
98
99
            if (! isset($timer->timeInterval->end)) {
100
                throw new Exception("Can't stop current running timer.", 1);
101
            }
102
103
            return true;
104
        }
105
106
        return false;
107
    }
108
109
    public function runningTimer()
110
    {
111
        try {
112
            $user = json_decode(
113
                $this->client->get("user")->getBody()->getContents()
114
            );
115
116
            $response = $this->client->get(
117
                "workspaces/{$user->activeWorkspace}/user/{$user->id}/time-entries?in-progress=true"
118
            );
119
120
            $timer = json_decode($response->getBody()->getContents());
121
122
            return $timer[0]->id ?? false;
123
        } catch (\Exception $e) {
124
            return false;
125
        }
126
127
        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...
128
    }
129
130
    public function pastTimers()
131
    {
132
        try {
133
            $user = json_decode(
134
                $this->client->get("user")->getBody()->getContents()
135
            );
136
137
            $response = $this->client->get("workspaces/{$user->activeWorkspace}/user/{$user->id}/time-entries", [
138
                'start' => Carbon::today(),
139
                'end' => Carbon::today()->subDays(30),
140
            ]);
141
            $clockifyTimers = json_decode($response->getBody()->getContents());
142
143
            return $this->convertToPastTimers($clockifyTimers);
144
        } catch (Exception $e) {
145
            return [];
146
        }
147
    }
148
149
    public function continueTimer($timerId = null)
150
    {
151
        /**
152
         * Timer attributes are stored in env variables
153
         * gathered in startTimer.
154
         */
155
        return $this->startTimer();
156
    }
157
158
    protected function convertToPastTimers($clockifyTimers)
159
    {
160
        $projects = $this->projects();
161
        $tags = $this->tags();
162
163
        return array_map(function ($clockifyTimer) use ($projects, $tags) {
164
            return $this->buildPastTimerObject($clockifyTimer, $projects, $tags);
165
        }, $clockifyTimers);
166
    }
167
168
    protected function buildPastTimerObject($clockifyTimer, $projects, $tags)
169
    {
170
        $pastTimer = [];
171
172
        $pastTimer['id'] = $clockifyTimer->id;
173
        $pastTimer['description'] = $clockifyTimer->description;
174
175
        if (isset($clockifyTimer->projectId)) {
176
            $pastTimer['project_id'] = $clockifyTimer->projectId;
177
            $pastTimer['project_name'] = $projects[$clockifyTimer->projectId];
178
        }
179
180
        if (isset($clockifyTimer->tagIds[0])) {
181
            $pastTimer['tag_id'] = $clockifyTimer->tagIds[0];
182
            $pastTimer['tags'] = $tags[$clockifyTimer->tagIds[0]];
183
        }
184
185
        $pastTimer['duration'] = $clockifyTimer->timeInterval->duration;
186
187
        return (object) $pastTimer;
188
    }
189
}
190