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