Completed
Push — master ( 3b0b6a...263c36 )
by Guillaume
02:53
created

src/Services/Toggl.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
    public function __construct($apiToken)
18
    {
19
        $this->client = new TogglApi($apiToken);
20
    }
21
22
    public function projects()
23
    {
24
        return $this->extractFromData('projects');
25
    }
26
27
    public function tags()
28
    {
29
        return $this->extractFromData('tags');
30
    }
31
32
    public function pastTimers()
33
    {
34
        try {
35
            $pastTimers = [];
36
37
            $togglTimers = $this->client->getTimeEntriesInRange(Carbon::today(), Carbon::today()->subDays(30));
0 ignored issues
show
\Carbon\Carbon::today() is of type object, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
38
39
            return $this->convertToPastTimers($togglTimers);
40
        } catch (Exception $e) {
41
            return [];
42
        }
43
    }
44
45
    public function startTimer()
46
    {
47
        try {
48
            $timer = $this->client->startTimeEntry([
49
                'description' => getenv('timer_description'),
50
                'pid' => getenv('timer_project_id'),
51
                'tags' => getenv('timer_tag') ? [getenv('timer_tag')] : '',
52
                'created_with' => 'Alfred Time'
53
            ]);
54
55
            if (! isset($timer->id)) {
56
                return false;
57
            }
58
        } catch (Exception $e) {
59
            return false;
60
        }
61
62
        return $timer->id;
63
    }
64
65 View Code Duplication
    public function stopCurrentTimer()
66
    {
67
        if ($timerId = $this->runningTimer()) {
68
            $response = $this->client->stopTimeEntry($timerId);
69
70
            if (! isset($response->id)) {
71
                throw new Exception("Can't stop current running timer.", 1);
72
73
                return false;
74
            }
75
76
            return true;
77
        }
78
79
        return false;
80
    }
81
82
    public function runningTimer()
83
    {
84
        $timer = $this->client->getRunningTimeEntry();
85
86
        return $timer->id ?? false;
87
    }
88
89
    public function continueTimer($timerId)
90
    {
91
        /**
92
         * Timer attributes are stored in env variables
93
         * gathered in startTimer.
94
         */
95
        return $this->startTimer();
96
    }
97
98
    public function deleteTimer($timerId)
99
    {
100
        try {
101
            $this->client->deleteTimeEntry($timerId);
102
        } catch (Exception $e) {
103
            return false;
104
        }
105
106
        return true;
107
    }
108
109
    private function extractFromData($needle)
110
    {
111
        $data = $this->getData();
112
113
        if (! isset($data->$needle)) {
114
            return [];
115
        }
116
117
        $nonDeletedData = $this->filterOutServerwiseDeletedItemsFromData($data->$needle);
118
119
        return array_column($nonDeletedData, 'name', 'id');
120
    }
121
122
    private function getData()
123
    {
124
        if (is_null($this->data)) {
125
            return $this->client->getMe(true);
126
        }
127
128
        return $this->data;
129
    }
130
131
    private function filterOutServerwiseDeletedItemsFromData($items = [])
132
    {
133
        return array_filter($items, function ($item) {
134
            return ! isset($item->server_deleted_at);
135
        });
136
    }
137
138
    protected function convertToPastTimers($togglTimers)
139
    {
140
        $projects = $this->projects();
141
142
        return array_reverse(
143
            array_map(function ($togglTimer) use ($projects) {
144
                return $this->buildPastTimerObject($togglTimer, $projects);
145
            }, $togglTimers)
146
        );
147
    }
148
149
    protected function buildPastTimerObject($togglTimer, $projects)
150
    {
151
        $pastTimer['id'] = $togglTimer->id;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$pastTimer was never initialized. Although not strictly required by PHP, it is generally a good practice to add $pastTimer = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
152
        $pastTimer['description'] = $togglTimer->description ?? null;
153
        $pastTimer['duration'] = CarbonInterval::seconds($togglTimer->duration)->cascade()->format('%H:%I:%S');
154
155
        if (isset($togglTimer->pid)) {
156
            $pastTimer['project_id'] = $togglTimer->pid;
157
            $pastTimer['project_name'] = $projects[$togglTimer->pid];
158
        }
159
160
        if (isset($togglTimer->tags)) {
161
            $pastTimer['tags'] = implode(', ', (array) $togglTimer->tags);
162
        }
163
164
        return (object) $pastTimer;
165
    }
166
}
167