Passed
Push — master ( 16e453...952352 )
by Guillaume
03:11
created

src/Services/Toggl.php (4 issues)

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 = [];
0 ignored issues
show
The assignment to $pastTimers is dead and can be removed.
Loading history...
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;
0 ignored issues
show
return false 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...
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
$pastTimer was never initialized. Although not strictly required by PHP, it is generally a good practice to add $pastTimer = array(); before regardless.
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
Bug Best Practice introduced by
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 ignore-call  annotation

153
        $pastTimer['duration'] = CarbonInterval::/** @scrutinizer ignore-call */ seconds($togglTimer->duration)->cascade()->format('%H:%I:%S');
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