1 | <?php |
||
2 | |||
3 | namespace Godbout\Alfred\Time\Services; |
||
4 | |||
5 | use Carbon\Carbon; |
||
6 | use Carbon\CarbonInterval; |
||
7 | use Required\Harvest\Client; |
||
8 | use Required\Harvest\Exception\NotFoundException; |
||
9 | use Required\Harvest\Exception\AuthenticationException; |
||
10 | use Required\Harvest\Exception\ValidationFailedException; |
||
11 | |||
12 | class Harvest extends TimerService |
||
13 | { |
||
14 | public $allowsEmptyProject = false; |
||
15 | |||
16 | public $allowsEmptyTag = false; |
||
17 | |||
18 | private $client; |
||
19 | |||
20 | |||
21 | 15 | public function __construct($accountId, $apiToken) |
|
22 | { |
||
23 | 15 | $this->client = new Client(); |
|
24 | |||
25 | 15 | $this->client->authenticate($accountId, $apiToken); |
|
26 | 15 | } |
|
27 | |||
28 | 3 | public function projects() |
|
29 | { |
||
30 | try { |
||
31 | 3 | return array_column($this->client->projects()->all(['']), 'name', 'id'); |
|
32 | 2 | } catch (AuthenticationException $e) { |
|
33 | 2 | return []; |
|
34 | } |
||
35 | } |
||
36 | |||
37 | 4 | public function tags() |
|
38 | { |
||
39 | try { |
||
40 | 4 | $taskAssignments = $this->client->projects()->taskAssignments()->all( |
|
41 | 4 | (int) getenv('timer_project_id'), |
|
42 | 4 | ['is_active' => true] |
|
43 | ); |
||
44 | |||
45 | array_walk($taskAssignments, function ($taskAssignment) use (&$tags) { |
||
46 | 2 | $tags[$taskAssignment['task']['id']] = $taskAssignment['task']['name']; |
|
47 | 2 | }); |
|
48 | |||
49 | 2 | return $tags; |
|
50 | 2 | } catch (AuthenticationException $e) { |
|
51 | 2 | return []; |
|
52 | } |
||
53 | } |
||
54 | |||
55 | 1 | public function pastTimers() |
|
56 | { |
||
57 | try { |
||
58 | 1 | $harvestTimers = $this->client->timeEntries()->all([ |
|
59 | 1 | 'from' => Carbon::today()->subDays(30), |
|
60 | 1 | 'to' => Carbon::today() |
|
61 | ]); |
||
62 | |||
63 | 1 | return $this->convertToPastTimers($harvestTimers); |
|
64 | } catch (AuthenticationException $e) { |
||
65 | return []; |
||
66 | } |
||
67 | } |
||
68 | |||
69 | 6 | public function startTimer() |
|
70 | { |
||
71 | try { |
||
72 | 6 | $timer = $this->client->timeEntries()->create([ |
|
73 | 6 | 'notes' => getenv('timer_description'), |
|
74 | 6 | 'project_id' => (int) getenv('timer_project_id'), |
|
75 | 6 | 'task_id' => (int) getenv('timer_tag_id'), |
|
76 | 6 | 'spent_date' => date('Y-m-d') |
|
77 | ]); |
||
78 | |||
79 | 6 | if (! isset($timer['id'])) { |
|
80 | 6 | return false; |
|
81 | } |
||
82 | } catch (ValidationFailedException $e) { |
||
83 | return false; |
||
84 | } |
||
85 | |||
86 | 6 | return $timer['id']; |
|
87 | } |
||
88 | |||
89 | 5 | public function stopCurrentTimer() |
|
90 | { |
||
91 | 5 | if ($timerId = $this->runningTimer()) { |
|
92 | 5 | $timer = $this->client->timeEntries()->stop($timerId); |
|
93 | |||
94 | 5 | if (! isset($timer['id'])) { |
|
95 | throw new \Exception("Can't stop current running timer.", 1); |
||
96 | |||
97 | return false; |
||
0 ignored issues
–
show
|
|||
98 | } |
||
99 | |||
100 | 5 | return true; |
|
101 | } |
||
102 | |||
103 | 1 | return false; |
|
104 | } |
||
105 | |||
106 | 13 | public function runningTimer() |
|
107 | { |
||
108 | try { |
||
109 | 13 | $timer = $this->client->timeEntries()->all(['is_running' => true]); |
|
110 | |||
111 | 13 | return $timer[0]['id'] ?? false; |
|
112 | } catch (\Exception $e) { |
||
113 | return false; |
||
114 | } |
||
115 | } |
||
116 | |||
117 | 1 | public function continueTimer($timerId) |
|
118 | { |
||
119 | 1 | $timer = $this->client->timeEntries()->restart($timerId); |
|
120 | |||
121 | 1 | return $timer['id'] ?? false; |
|
122 | } |
||
123 | |||
124 | 6 | public function deleteTimer($timerId) |
|
125 | { |
||
126 | try { |
||
127 | 6 | $this->client->timeEntries()->remove($timerId); |
|
128 | } catch (NotFoundException $e) { |
||
129 | return false; |
||
130 | } |
||
131 | |||
132 | 6 | return true; |
|
133 | } |
||
134 | |||
135 | 1 | protected function convertToPastTimers($harvestTimers) |
|
136 | { |
||
137 | return array_map(function ($harvestTimer) { |
||
138 | 1 | return $this->buildPastTimerObject($harvestTimer); |
|
139 | 1 | }, $harvestTimers); |
|
140 | } |
||
141 | |||
142 | 1 | protected function buildPastTimerObject($harvestTimer) |
|
143 | { |
||
144 | 1 | $pastTimer['id'] = $harvestTimer['id']; |
|
145 | 1 | $pastTimer['description'] = $harvestTimer['notes']; |
|
146 | 1 | $pastTimer['project_id'] = $harvestTimer['project']['id']; |
|
147 | 1 | $pastTimer['project_name'] = $harvestTimer['project']['name']; |
|
148 | 1 | $pastTimer['tag_id'] = $harvestTimer['task']['id']; |
|
149 | 1 | $pastTimer['tags'] = $harvestTimer['task']['name']; |
|
150 | 1 | $pastTimer['duration'] = CarbonInterval::seconds( |
|
151 | 1 | floor($harvestTimer['hours'] * 3600) |
|
152 | 1 | )->cascade()->format('%H:%I:%S'); |
|
153 | |||
154 | 1 | return (object) $pastTimer; |
|
155 | } |
||
156 | } |
||
157 |
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
orexit
statements that have been added for debug purposes.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.