Completed
Push — master ( 5a17e3...b0e7fe )
by Guillaume
02:01
created

AlfredTime::isConfigured()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
require 'Toggl.class.php';
4
require 'Harvest.class.php';
5
6
class AlfredTime
7
{
8
    private $config;
9
    private $message;
10
    private $currentImplementation = [
11
        'start' => ['toggl'],
12
        'start_default' => ['toggl', 'harvest'],
13
        'stop' => ['toggl', 'harvest'],
14
        'delete' => ['toggl'],
15
    ];
16
    private $toggl;
17
    private $harvest;
18
19
    public function __construct()
20
    {
21
        $this->config = $this->loadConfiguration();
22
        $this->message = '';
23
        $this->toggl = new Toggl($this->config['toggl']['api_token']);
24
        $this->harvest = new Harvest($this->config['harvest']['domain'], $this->config['harvest']['api_token']);
25
    }
26
27
    public function isConfigured()
28
    {
29
        return $this->config === null ? false : true;
30
    }
31
32
    public function hasTimerRunning()
33
    {
34
        return $this->config['workflow']['is_timer_running'] === false ? false : true;
35
    }
36
37
    public function getTimerDescription()
38
    {
39
        return $this->config['workflow']['timer_description'];
40
    }
41
42
    public function startTimer($description = '', $projectsDefault = null, $tagsDefault = null, $startDefault = false)
43
    {
44
        $message = '';
45
        $startType = $startDefault === true ? 'start_default' : 'start';
46
        $atLeastOneServiceStarted = false;
47
        $implementedServices = $this->implementedServicesForFeature($startType);
48
49
        /**
50
         * When starting a new timer, all the services timer IDs have to be put to null
51
         * so that when the user uses the UNDO feature, it doesn't delete old previous
52
         * other services timers. The timer IDs are used for the UNDO feature and
53
         * should then contain the IDs of the last starts through the workflow, not
54
         * through each individual service
55
         */
56
        if (empty($implementedServices) === false) {
57
            foreach ($this->activatedServices() as $service) {
58
                $this->config['workflow']['timer_' . $service . '_id'] = null;
59
                $this->saveConfiguration();
60
            }
61
        }
62
63
        foreach ($implementedServices as $service) {
64
            $defaultProjectId = isset($projectsDefault[$service]) ? $projectsDefault[$service] : null;
65
            $defaultTags = isset($tagsDefault[$service]) ? $tagsDefault[$service] : null;
66
67
            $functionName = 'start' . ucfirst($service) . 'Timer';
68
            $timerId = call_user_func_array(['AlfredTime', $functionName], [$description, $defaultProjectId, $defaultTags]);
69
            $this->config['workflow']['timer_' . $service . '_id'] = $timerId;
70
            if ($timerId !== null) {
71
                $atLeastOneServiceStarted = true;
72
            }
73
74
            $message .= $this->getLastMessage() . "\r\n";
75
        }
76
77
        if ($atLeastOneServiceStarted === true) {
78
            $this->config['workflow']['timer_description'] = $description;
79
            $this->config['workflow']['is_timer_running'] = true;
80
            $this->saveConfiguration();
81
        }
82
83
        return $message;
84
    }
85
86
    public function startTimerWithDefaultOptions($description)
87
    {
88
        $projectsDefault = [
89
            'toggl' => $this->config['toggl']['default_project_id'],
90
            'harvest' => $this->config['harvest']['default_project_id'],
91
        ];
92
93
        $tagsDefault = [
94
            'toggl' => $this->config['toggl']['default_tags'],
95
            'harvest' => $this->config['harvest']['default_task_id'],
96
        ];
97
98
        return $this->startTimer($description, $projectsDefault, $tagsDefault, true);
99
    }
100
101
    public function stopRunningTimer()
102
    {
103
        $message = '';
104
        $atLeastOneServiceStopped = false;
105
106
        foreach ($this->activatedServices() as $service) {
107
            $functionName = 'stop' . ucfirst($service) . 'Timer';
108
            if (call_user_func(['AlfredTime', $functionName]) === true) {
109
                $atLeastOneServiceStopped = true;
110
            }
111
            $message .= $this->getLastMessage() . "\r\n";
112
        }
113
114 View Code Duplication
        if ($atLeastOneServiceStopped === true) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
115
            $this->config['workflow']['is_timer_running'] = false;
116
            $this->saveConfiguration();
117
        }
118
119
        return $message;
120
    }
121
122
    public function generateDefaultConfigurationFile()
123
    {
124
        $this->config = [
125
            'workflow' => [
126
                'is_timer_running' => false,
127
                'timer_toggl_id' => null,
128
                'timer_harvest_id' => null,
129
                'timer_description' => '',
130
            ],
131
            'toggl' => [
132
                'is_active' => true,
133
                'api_token' => '',
134
                'default_project_id' => '',
135
                'default_tags' => '',
136
            ],
137
            'harvest' => [
138
                'is_active' => true,
139
                'domain' => '',
140
                'api_token' => '',
141
                'default_project_id' => '',
142
                'default_task_id' => '',
143
            ],
144
        ];
145
146
        $this->saveConfiguration();
147
    }
148
149
    public function activatedServices()
150
    {
151
        $services = [];
152
153
        if ($this->isTogglActive() === true) {
154
            array_push($services, 'toggl');
155
        }
156
157
        if ($this->isHarvestActive() === true) {
158
            array_push($services, 'harvest');
159
        }
160
161
        return $services;
162
    }
163
164
    public function servicesToUndo()
165
    {
166
        $services = [];
167
168
        foreach ($this->activatedServices() as $service) {
169
            if ($this->config['workflow']['timer_' . $service . '_id'] !== null) {
170
                array_push($services, $service);
171
            }
172
        }
173
174
        return $services;
175
    }
176
177
    public function syncOnlineDataToLocalCache()
178
    {
179
        $message = '';
180
181
        if ($this->isTogglActive() === true) {
182
            $message .= $this->syncTogglOnlineDataToLocalCache();
183
        }
184
185
        return $message;
186
    }
187
188
    public function getProjects()
189
    {
190
        $projects = [];
191
192
        if ($this->isTogglActive() === true) {
193
            $projects = array_merge($projects, $this->getTogglProjects());
194
        }
195
196
        return $projects;
197
    }
198
199
    public function getTags()
200
    {
201
        $tags = [];
202
203
        if ($this->isTogglActive() === true) {
204
            $tags = array_merge($tags, $this->getTogglTags());
205
        }
206
207
        return $tags;
208
    }
209
210
    public function UndoTimer()
211
    {
212
        $message = '';
213
214
        if ($this->hasTimerRunning() === true) {
215
            $this->stopRunningTimer();
216
        }
217
218
        $atLeastOneTimerDeleted = false;
219
        foreach ($this->servicesToUndo() as $service) {
220
            $functionName = 'delete' . ucfirst($service) . 'Timer';
221
            if (call_user_func_array(['AlfredTime', $functionName], [$this->config['workflow']['timer_' . $service . '_id']]) === true) {
222
                $this->config['workflow']['timer_' . $service . '_id'] = null;
223
                $atLeastOneTimerDeleted = true;
224
            }
225
226
            $message .= $this->getLastMessage() . "\r\n";
227
        }
228
229
        if ($atLeastOneTimerDeleted === true) {
230
            $this->saveConfiguration();
231
        }
232
233
        return $message;
234
    }
235
236
    public function getRecentTimers()
237
    {
238
        $timers = [];
239
240
        if ($this->isTogglActive() === true) {
241
            $timers = array_merge($timers, $this->getRecentTogglTimers());
242
        }
243
244
        return $timers;
245
    }
246
247
    public function deleteTimer($timerId)
248
    {
249
        $message = '';
250
251
        $atLeastOneTimerDeleted = false;
252
        foreach ($this->implementedServicesForFeature('delete') as $service) {
253
            $functionName = 'delete' . ucfirst($service) . 'Timer';
254
            if (call_user_func_array(['AlfredTime', $functionName], [$timerId]) === true) {
255
                $this->config['workflow']['timer_' . $service . '_id'] = null;
256
                $atLeastOneTimerDeleted = true;
257
            }
258
259
            $message .= $this->getLastMessage() . "\r\n";
260
        }
261
262 View Code Duplication
        if ($atLeastOneTimerDeleted === true) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
263
            $this->config['workflow']['is_timer_running'] = false;
264
            $this->saveConfiguration();
265
        }
266
267
        return $message;
268
    }
269
270
    public function implementedServicesForFeature($feature = null)
271
    {
272
        $services = [];
273
274
        if (isset($this->currentImplementation[$feature]) === true) {
275
            $services = $this->currentImplementation[$feature];
276
        }
277
278
        return $services;
279
    }
280
281
    public function getProjectName($projectId)
282
    {
283
        $projectName = '';
284
285
        $projects = $this->getProjects();
286
        foreach ($projects as $project) {
287
            if ($project['id'] === $projectId) {
288
                $projectName = $project['name'];
289
                break;
290
            }
291
        }
292
293
        return $projectName;
294
    }
295
296
    private function getRecentTogglTimers()
297
    {
298
        return $this->toggl->getRecentTimers();
299
    }
300
301
    private function getLastMessage()
302
    {
303
        return $this->message;
304
    }
305
306
    private function deleteTogglTimer($togglId)
307
    {
308
        $res = $this->toggl->deleteTimer($togglId);
309
        $this->message = $this->toggl->getLastMessage();
310
311
        return $res;
312
    }
313
314
    private function deleteHarvestTimer($harvestId)
315
    {
316
        $res = false;
317
318
        $domain = $this->config['harvest']['domain'];
319
320
        $url = 'https://' . $domain . '.harvestapp.com/daily/delete/' . $harvestId;
321
322
        $base64Token = $this->config['harvest']['api_token'];
323
324
        $headers = [
325
            "Content-type: application/json",
326
            "Accept: application/json",
327
            'Authorization: Basic ' . $base64Token,
328
        ];
329
330
        $ch = curl_init($url);
331
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
332
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
333
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
334
        $response = curl_exec($ch);
335
        $lastHttpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
336
        curl_close($ch);
337
338
        if ($response === false || $lastHttpCode !== 200) {
339
            $this->message = '- Could not delete Harvest timer!';
340
        } else {
341
            $this->message = '- Harvest timer deleted';
342
            $res = true;
343
        }
344
345
        return $res;
346
    }
347
348
    private function syncTogglOnlineDataToLocalCache()
349
    {
350
        $data = $this->toggl->getOnlineData();
351
        $this->message = $this->toggl->getLastMessage();
352
353
        if (empty($data) === false) {
354
            $this->saveTogglDataCache($data);
355
        }
356
357
        return $this->message;
358
    }
359
360
    private function saveTogglDataCache($data)
361
    {
362
        $cacheFile = getenv('alfred_workflow_data') . '/toggl_cache.json';
363
        file_put_contents($cacheFile, json_encode($data));
364
    }
365
366
    private function loadConfiguration()
367
    {
368
        $config = null;
369
        $configFile = getenv('alfred_workflow_data') . '/config.json';
370
371
        if (file_exists($configFile)) {
372
            $config = json_decode(file_get_contents($configFile), true);
373
        }
374
375
        return $config;
376
    }
377
378
    private function saveConfiguration()
379
    {
380
        $workflowDir = getenv('alfred_workflow_data');
381
        $configFile = $workflowDir . '/config.json';
382
383
        if (file_exists($workflowDir) === false) {
384
            mkdir($workflowDir);
385
        }
386
387
        file_put_contents($configFile, json_encode($this->config, JSON_PRETTY_PRINT));
388
    }
389
390
    private function startTogglTimer($description, $projectId, $tagNames)
391
    {
392
        $togglId = $this->toggl->startTimer($description, $projectId, $tagNames);
393
        $this->message = $this->toggl->getLastMessage();
394
395
        return $togglId;
396
    }
397
398 View Code Duplication
    private function stopTogglTimer()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
399
    {
400
        $togglId = $this->config['workflow']['timer_toggl_id'];
401
402
        $res = $this->toggl->stopTimer($togglId);
403
        $this->message = $this->toggl->getLastMessage();
404
405
        return $res;
406
    }
407
408
    private function startHarvestTimer($description, $projectId, $taskId)
409
    {
410
        $harvestId = $this->harvest->startTimer($description, $projectId, $taskId);
411
        $this->message = $this->harvest->getLastMessage();
412
413
        return $harvestId;
414
    }
415
416 View Code Duplication
    private function stopHarvestTimer()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
417
    {
418
        $harvestId = $this->config['workflow']['timer_harvest_id'];
419
420
        $res = $this->harvest->stopTimer($harvestId);
421
        $this->message = $this->harvest->getLastMessage();
422
423
        return $res;
424
    }
425
426
    private function getTogglProjects()
427
    {
428
        $cacheData = [];
429
        $cacheFile = getenv('alfred_workflow_data') . '/toggl_cache.json';
430
431
        if (file_exists($cacheFile)) {
432
            $cacheData = json_decode(file_get_contents($cacheFile), true);
433
        }
434
435
        /**
436
         * To only show projects that are currently active
437
         * The Toggl API is slightly weird on that
438
         */
439
        foreach ($cacheData['data']['projects'] as $key => $project) {
440
            if (isset($project['server_deleted_at']) === true) {
441
                unset($cacheData['data']['projects'][$key]);
442
            }
443
        }
444
445
        return $cacheData['data']['projects'];
446
    }
447
448
    private function getTogglTags()
449
    {
450
        $cacheFile = getenv('alfred_workflow_data') . '/toggl_cache.json';
451
        $cacheData = [];
452
453
        if (file_exists($cacheFile)) {
454
            $cacheData = json_decode(file_get_contents($cacheFile), true);
455
        }
456
457
        return $cacheData['data']['tags'];
458
    }
459
460
    private function isTogglActive()
461
    {
462
        return $this->config['toggl']['is_active'];
463
    }
464
465
    private function isHarvestActive()
466
    {
467
        return $this->config['harvest']['is_active'];
468
    }
469
}
470