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
Loading history...
|
|||||
152 | 1 | $pastTimer['description'] = $togglTimer->description ?? ''; |
|||
153 | 1 | $pastTimer['duration'] = CarbonInterval::seconds($togglTimer->duration)->cascade()->format('%H:%I:%S'); |
|||
0 ignored issues
–
show
The method
Carbon\CarbonInterval::seconds() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
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 |