1 | <?php |
||
2 | |||
3 | namespace Godbout\Alfred\Time\Services; |
||
4 | |||
5 | use Exception; |
||
6 | use Carbon\Carbon; |
||
7 | use Carbon\CarbonInterval; |
||
8 | use MorningTrain\TogglApi\TogglApi; |
||
9 | |||
10 | class Toggl extends TimerService |
||
11 | { |
||
12 | private $client; |
||
13 | |||
14 | private $data = null; |
||
15 | |||
16 | |||
17 | 28 | public function __construct($apiToken) |
|
18 | { |
||
19 | 28 | $this->client = new TogglApi($apiToken); |
|
20 | 28 | } |
|
21 | |||
22 | 6 | public function projects() |
|
23 | { |
||
24 | 6 | return $this->extractFromData('projects'); |
|
25 | } |
||
26 | |||
27 | 4 | public function tags() |
|
28 | { |
||
29 | 4 | return $this->extractFromData('tags'); |
|
30 | } |
||
31 | |||
32 | 1 | public function pastTimers() |
|
33 | { |
||
34 | try { |
||
35 | 1 | $pastTimers = []; |
|
36 | |||
37 | 1 | $togglTimers = $this->client->getTimeEntriesInRange(Carbon::today(), Carbon::today()->subDays(30)); |
|
38 | |||
39 | 1 | return $this->convertToPastTimers($togglTimers); |
|
40 | } catch (Exception $e) { |
||
41 | return []; |
||
42 | } |
||
43 | } |
||
44 | |||
45 | 11 | public function startTimer() |
|
46 | { |
||
47 | try { |
||
48 | 11 | $timer = $this->client->startTimeEntry([ |
|
49 | 11 | 'description' => getenv('timer_description'), |
|
50 | 11 | 'pid' => getenv('timer_project_id'), |
|
51 | 11 | 'tags' => getenv('timer_tag') ? [getenv('timer_tag')] : '', |
|
52 | 11 | 'created_with' => 'Alfred Time' |
|
53 | ]); |
||
54 | |||
55 | 11 | if (! isset($timer->id)) { |
|
56 | 11 | return false; |
|
57 | } |
||
58 | } catch (Exception $e) { |
||
59 | return false; |
||
60 | } |
||
61 | |||
62 | 11 | return $timer->id; |
|
63 | } |
||
64 | |||
65 | 9 | public function stopCurrentTimer() |
|
66 | { |
||
67 | 9 | if ($timerId = $this->runningTimer()) { |
|
68 | 9 | $response = $this->client->stopTimeEntry($timerId); |
|
69 | |||
70 | 9 | if (! isset($response->id)) { |
|
71 | throw new Exception("Can't stop current running timer.", 1); |
||
72 | |||
73 | return false; |
||
74 | } |
||
75 | |||
76 | 9 | return true; |
|
77 | } |
||
78 | |||
79 | 1 | return false; |
|
80 | } |
||
81 | |||
82 | 22 | public function runningTimer() |
|
83 | { |
||
84 | 22 | $timer = $this->client->getRunningTimeEntry(); |
|
85 | |||
86 | 22 | return $timer->id ?? false; |
|
87 | } |
||
88 | |||
89 | 2 | public function continueTimer($timerId) |
|
90 | { |
||
91 | /** |
||
92 | * Timer attributes are stored in env variables |
||
93 | * gathered in startTimer. |
||
94 | */ |
||
95 | 2 | return $this->startTimer(); |
|
96 | } |
||
97 | |||
98 | 11 | public function deleteTimer($timerId) |
|
99 | { |
||
100 | try { |
||
101 | 11 | $this->client->deleteTimeEntry($timerId); |
|
102 | } catch (Exception $e) { |
||
103 | return false; |
||
104 | } |
||
105 | |||
106 | 11 | return true; |
|
107 | } |
||
108 | |||
109 | 10 | private function extractFromData($needle) |
|
110 | { |
||
111 | 10 | $data = $this->getData(); |
|
112 | |||
113 | 10 | if (! isset($data->$needle)) { |
|
114 | 6 | return []; |
|
115 | } |
||
116 | |||
117 | 4 | $nonDeletedData = $this->filterOutServerwiseDeletedItemsFromData($data->$needle); |
|
118 | |||
119 | 4 | return array_column($nonDeletedData, 'name', 'id'); |
|
120 | } |
||
121 | |||
122 | 10 | private function getData() |
|
123 | { |
||
124 | 10 | if (is_null($this->data)) { |
|
125 | 10 | return $this->client->getMe(true); |
|
126 | } |
||
127 | |||
128 | return $this->data; |
||
129 | } |
||
130 | |||
131 | 4 | private function filterOutServerwiseDeletedItemsFromData($items = []) |
|
132 | { |
||
133 | return array_filter($items, function ($item) { |
||
134 | 4 | return ! isset($item->server_deleted_at); |
|
135 | 4 | }); |
|
136 | } |
||
137 | |||
138 | 1 | protected function convertToPastTimers($togglTimers) |
|
139 | { |
||
140 | 1 | $projects = $this->projects(); |
|
141 | |||
142 | 1 | return array_reverse( |
|
143 | array_map(function ($togglTimer) use ($projects) { |
||
144 | 1 | return $this->buildPastTimerObject($togglTimer, $projects); |
|
145 | 1 | }, $togglTimers) |
|
146 | ); |
||
147 | } |
||
148 | |||
149 | 1 | protected function buildPastTimerObject($togglTimer, $projects) |
|
150 | { |
||
151 | 1 | $pastTimer['id'] = $togglTimer->id; |
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
![]() |
|||
152 | 1 | $pastTimer['description'] = $togglTimer->description ?? ''; |
|
153 | 1 | $pastTimer['duration'] = CarbonInterval::seconds($togglTimer->duration)->cascade()->format('%H:%I:%S'); |
|
154 | |||
155 | 1 | if (isset($togglTimer->pid)) { |
|
156 | 1 | $pastTimer['project_id'] = $togglTimer->pid; |
|
157 | 1 | $pastTimer['project_name'] = $projects[$togglTimer->pid]; |
|
158 | } |
||
159 | |||
160 | 1 | if (isset($togglTimer->tags)) { |
|
161 | 1 | $pastTimer['tags'] = implode(', ', (array) $togglTimer->tags); |
|
162 | } |
||
163 | |||
164 | 1 | return (object) $pastTimer; |
|
165 | } |
||
166 | } |
||
167 |