Passed
Branch master (51117f)
by Guillaume
02:50
created

Harvest::convertToPastTimers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Godbout\Alfred\Time\Services;
4
5
use Carbon\Carbon;
6
use Carbon\CarbonInterval;
7
use Required\Harvest\Client;
8
use Required\Harvest\Exception\NotFoundException;
9
use Required\Harvest\Exception\AuthenticationException;
10
use Required\Harvest\Exception\ValidationFailedException;
11
12
class Harvest extends TimerService
13
{
14
    public $allowsEmptyProject = false;
15
16
    public $allowsEmptyTag = false;
17
18
    private $client;
19
20
21 16
    public function __construct($accountId, $apiToken)
22
    {
23 16
        $this->client = new Client();
24
25 16
        $this->client->authenticate($accountId, $apiToken);
26 16
    }
27
28 3
    public function projects()
29
    {
30
        try {
31 3
            return array_column($this->client->projects()->all(['']), 'name', 'id');
32 2
        } catch (AuthenticationException $e) {
33 2
            return [];
34
        }
35
    }
36
37 4
    public function tags()
38
    {
39
        try {
40 4
            $taskAssignments = $this->client->projects()->taskAssignments()->all(
41 4
                (int) getenv('timer_project_id'),
42 4
                ['is_active' => true]
43
            );
44
45
            array_walk($taskAssignments, function ($taskAssignment) use (&$tags) {
0 ignored issues
show
Bug introduced by
It seems like $taskAssignments can also be of type string; however, parameter $array of array_walk() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

45
            array_walk(/** @scrutinizer ignore-type */ $taskAssignments, function ($taskAssignment) use (&$tags) {
Loading history...
46 2
                $tags[$taskAssignment['task']['id']] = $taskAssignment['task']['name'];
47 2
            });
48
49 2
            return $tags;
50 2
        } catch (AuthenticationException $e) {
51 2
            return [];
52
        }
53
    }
54
55 1
    public function pastTimers()
56
    {
57
        try {
58 1
            $harvestTimers = $this->client->timeEntries()->all([
59 1
                'from' => Carbon::today()->subDays(30),
60 1
                'to' => Carbon::today()
61
            ]);
62
63 1
            return $this->convertToPastTimers($harvestTimers);
64
        } catch (AuthenticationException $e) {
65
            return [];
66
        }
67
    }
68
69 6
    public function startTimer()
70
    {
71
        try {
72 6
            $timer = $this->client->timeEntries()->create([
73 6
                'notes' => getenv('timer_description'),
74 6
                'project_id' => (int) getenv('timer_project_id'),
75 6
                'task_id' => (int) getenv('timer_tag_id'),
76 6
                'spent_date' => date('Y-m-d')
77
            ]);
78
79 6
            if (! isset($timer['id'])) {
80 6
                return false;
81
            }
82
        } catch (ValidationFailedException $e) {
83
            return false;
84
        }
85
86 6
        return $timer['id'];
87
    }
88
89 5
    public function stopCurrentTimer()
90
    {
91 5
        if ($timerId = $this->runningTimer()) {
92 5
            $timer = $this->client->timeEntries()->stop($timerId);
93
94 5
            if (! isset($timer['id'])) {
95
                throw new \Exception("Can't stop current running timer.", 1);
96
97
                return false;
0 ignored issues
show
Unused Code introduced by
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...
98
            }
99
100 5
            return true;
101
        }
102
103 1
        return false;
104
    }
105
106 13
    public function runningTimer()
107
    {
108
        try {
109 13
            $timer = $this->client->timeEntries()->all(['is_running' => true]);
110
111 13
            return $timer[0]['id'] ?? false;
112
        } catch (\Exception $e) {
113
            return false;
114
        }
115
    }
116
117 1
    public function continueTimer($timerId)
118
    {
119 1
        $timer = $this->client->timeEntries()->restart($timerId);
120
121 1
        return $timer['id'] ?? false;
122
    }
123
124 6
    public function deleteTimer($timerId)
125
    {
126
        try {
127 6
            $this->client->timeEntries()->remove($timerId);
128
        } catch (NotFoundException $e) {
129
            return false;
130
        }
131
132 6
        return true;
133
    }
134
135 1
    protected function convertToPastTimers($harvestTimers)
136
    {
137
        return array_map(function ($harvestTimer) {
138 1
            return $this->buildPastTimerObject($harvestTimer);
139 1
        }, $harvestTimers);
140
    }
141
142 1
    protected function buildPastTimerObject($harvestTimer)
143
    {
144 1
        $pastTimer['id'] = $harvestTimer['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...
145 1
        $pastTimer['description'] = $harvestTimer['notes'];
146 1
        $pastTimer['project_id'] = $harvestTimer['project']['id'];
147 1
        $pastTimer['project_name'] = $harvestTimer['project']['name'];
148 1
        $pastTimer['tags'] = $harvestTimer['task']['name'];
149 1
        $pastTimer['duration'] = CarbonInterval::seconds(
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

149
        $pastTimer['duration'] = CarbonInterval::/** @scrutinizer ignore-call */ seconds(
Loading history...
150 1
            floor($harvestTimer['hours'] * 3600)
151 1
        )->cascade()->format('%H:%I:%S');
152
153 1
        return (object) $pastTimer;
154
    }
155
}
156