Completed
Push — master ( f70872...360715 )
by Guillaume
02:04
created

AlfredTime::hasTimerRunning()   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
    /**
9
     * @var mixed
10
     */
11
    private $config;
12
13
    /**
14
     * @var array
15
     */
16
    private $currentImplementation = [
17
        'start'         => ['toggl'],
18
        'start_default' => ['toggl', 'harvest'],
19
        'stop'          => ['toggl', 'harvest'],
20
        'delete'        => ['toggl'],
21
    ];
22
23
    /**
24
     * @var mixed
25
     */
26
    private $harvest;
27
28
    /**
29
     * @var mixed
30
     */
31
    private $message;
32
33
    /**
34
     * @var mixed
35
     */
36
    private $toggl;
37
38
    public function __construct()
39
    {
40
        $this->config = $this->loadConfiguration();
41
        $this->message = '';
42
        $this->toggl = new Toggl($this->config['toggl']['api_token']);
43
        $this->harvest = new Harvest($this->config['harvest']['domain'], $this->config['harvest']['api_token']);
44
    }
45
46
    /**
47
     * @return mixed
48
     */
49
    public function activatedServices()
50
    {
51
        $services = [];
52
53
        if ($this->isTogglActive() === true) {
54
            array_push($services, 'toggl');
55
        }
56
57
        if ($this->isHarvestActive() === true) {
58
            array_push($services, 'harvest');
59
        }
60
61
        return $services;
62
    }
63
64
    /**
65
     * @param  $timerId
66
     * @return mixed
67
     */
68
    public function deleteTimer($timerId)
69
    {
70
        $message = '';
71
72
        $atLeastOneTimerDeleted = false;
73
74 View Code Duplication
        foreach ($this->implementedServicesForFeature('delete') as $service) {
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...
75
            $functionName = 'delete' . ucfirst($service) . 'Timer';
76
77
            if (call_user_func_array(['AlfredTime', $functionName], [$timerId]) === true) {
78
                if ($timerId === $this->config['workflow']['timer_' . $service . '_id']) {
79
                    $this->config['workflow']['timer_' . $service . '_id'] = null;
80
                    $atLeastOneTimerDeleted = true;
81
                }
82
            }
83
84
            $message .= $this->getLastMessage() . "\r\n";
85
        }
86
87 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...
88
            $this->config['workflow']['is_timer_running'] = false;
89
            $this->saveConfiguration();
90
        }
91
92
        return $message;
93
    }
94
95
    public function generateDefaultConfigurationFile()
96
    {
97
        $this->config = [
98
            'workflow' => [
99
                'is_timer_running'  => false,
100
                'timer_toggl_id'    => null,
101
                'timer_harvest_id'  => null,
102
                'timer_description' => '',
103
            ],
104
            'toggl'    => [
105
                'is_active'          => true,
106
                'api_token'          => '',
107
                'default_project_id' => '',
108
                'default_tags'       => '',
109
            ],
110
            'harvest'  => [
111
                'is_active'          => true,
112
                'domain'             => '',
113
                'api_token'          => '',
114
                'default_project_id' => '',
115
                'default_task_id'    => '',
116
            ],
117
        ];
118
119
        $this->saveConfiguration();
120
    }
121
122
    /**
123
     * @param  $projectId
124
     * @return mixed
125
     */
126
    public function getProjectName($projectId)
127
    {
128
        $projectName = '';
129
130
        $projects = $this->getProjects();
131
132
        foreach ($projects as $project) {
133
            if ($project['id'] === $projectId) {
134
                $projectName = $project['name'];
135
                break;
136
            }
137
        }
138
139
        return $projectName;
140
    }
141
142
    /**
143
     * @return mixed
144
     */
145
    public function getProjects()
146
    {
147
        $projects = [];
148
149
        if ($this->isTogglActive() === true) {
150
            $projects = array_merge($projects, $this->getTogglProjects());
151
        }
152
153
        return $projects;
154
    }
155
156
    /**
157
     * @return mixed
158
     */
159
    public function getRecentTimers()
160
    {
161
        $timers = [];
162
163
        if ($this->isTogglActive() === true) {
164
            $timers = array_merge($timers, $this->getRecentTogglTimers());
165
        }
166
167
        return $timers;
168
    }
169
170
    /**
171
     * @return mixed
172
     */
173
    public function getTags()
174
    {
175
        $tags = [];
176
177
        if ($this->isTogglActive() === true) {
178
            $tags = array_merge($tags, $this->getTogglTags());
179
        }
180
181
        return $tags;
182
    }
183
184
    /**
185
     * @return mixed
186
     */
187
    public function getTimerDescription()
188
    {
189
        return $this->config['workflow']['timer_description'];
190
    }
191
192
    /**
193
     * @return mixed
194
     */
195
    public function hasTimerRunning()
196
    {
197
        return $this->config['workflow']['is_timer_running'] === false ? false : true;
198
    }
199
200
    /**
201
     * @param  $feature
202
     * @return mixed
203
     */
204
    public function implementedServicesForFeature($feature = null)
205
    {
206
        $services = [];
207
208
        if (isset($this->currentImplementation[$feature]) === true) {
209
            $services = $this->currentImplementation[$feature];
210
        }
211
212
        return $services;
213
    }
214
215
    /**
216
     * @return mixed
217
     */
218
    public function isConfigured()
219
    {
220
        return $this->config === null ? false : true;
221
    }
222
223
    /**
224
     * @return mixed
225
     */
226
    public function servicesToUndo()
227
    {
228
        $services = [];
229
230
        foreach ($this->activatedServices() as $service) {
231
            if ($this->config['workflow']['timer_' . $service . '_id'] !== null) {
232
                array_push($services, $service);
233
            }
234
        }
235
236
        return $services;
237
    }
238
239
    /**
240
     * @param  $description
241
     * @param  $projectsDefault
242
     * @param  null               $tagsDefault
243
     * @param  null               $startDefault
244
     * @return mixed
245
     */
246
    public function startTimer($description = '', $projectsDefault = null, $tagsDefault = null, $startDefault = false)
247
    {
248
        $message = '';
249
        $startType = $startDefault === true ? 'start_default' : 'start';
250
        $atLeastOneServiceStarted = false;
251
        $implementedServices = $this->implementedServicesForFeature($startType);
252
253
/*
254
 * When starting a new timer, all the services timer IDs have to be put to null
255
 * so that when the user uses the UNDO feature, it doesn't delete old previous
256
 * other services timers. The timer IDs are used for the UNDO feature and
257
 * should then contain the IDs of the last starts through the workflow, not
258
 * through each individual service
259
 */
260
        if (empty($implementedServices) === false) {
261
            foreach ($this->activatedServices() as $service) {
262
                $this->config['workflow']['timer_' . $service . '_id'] = null;
263
                $this->saveConfiguration();
264
            }
265
        }
266
267
        foreach ($implementedServices as $service) {
268
            $defaultProjectId = isset($projectsDefault[$service]) ? $projectsDefault[$service] : null;
269
            $defaultTags = isset($tagsDefault[$service]) ? $tagsDefault[$service] : null;
270
271
            $functionName = 'start' . ucfirst($service) . 'Timer';
272
            $timerId = call_user_func_array(['AlfredTime', $functionName], [$description, $defaultProjectId, $defaultTags]);
273
            $this->config['workflow']['timer_' . $service . '_id'] = $timerId;
274
275
            if ($timerId !== null) {
276
                $atLeastOneServiceStarted = true;
277
            }
278
279
            $message .= $this->getLastMessage() . "\r\n";
280
        }
281
282
        if ($atLeastOneServiceStarted === true) {
283
            $this->config['workflow']['timer_description'] = $description;
284
            $this->config['workflow']['is_timer_running'] = true;
285
            $this->saveConfiguration();
286
        }
287
288
        return $message;
289
    }
290
291
    /**
292
     * @param  $description
293
     * @return mixed
294
     */
295
    public function startTimerWithDefaultOptions($description)
296
    {
297
        $projectsDefault = [
298
            'toggl'   => $this->config['toggl']['default_project_id'],
299
            'harvest' => $this->config['harvest']['default_project_id'],
300
        ];
301
302
        $tagsDefault = [
303
            'toggl'   => $this->config['toggl']['default_tags'],
304
            'harvest' => $this->config['harvest']['default_task_id'],
305
        ];
306
307
        return $this->startTimer($description, $projectsDefault, $tagsDefault, true);
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a false|null.

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...
308
    }
309
310
    /**
311
     * @return mixed
312
     */
313
    public function stopRunningTimer()
314
    {
315
        $message = '';
316
        $atLeastOneServiceStopped = false;
317
318
        foreach ($this->activatedServices() as $service) {
319
            $functionName = 'stop' . ucfirst($service) . 'Timer';
320
321
            if (call_user_func(['AlfredTime', $functionName]) === true) {
322
                $atLeastOneServiceStopped = true;
323
            }
324
325
            $message .= $this->getLastMessage() . "\r\n";
326
        }
327
328 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...
329
            $this->config['workflow']['is_timer_running'] = false;
330
            $this->saveConfiguration();
331
        }
332
333
        return $message;
334
    }
335
336
    /**
337
     * @return mixed
338
     */
339
    public function syncOnlineDataToLocalCache()
340
    {
341
        $message = '';
342
343
        if ($this->isTogglActive() === true) {
344
            $message .= $this->syncTogglOnlineDataToLocalCache();
345
        }
346
347
        return $message;
348
    }
349
350
    /**
351
     * @return mixed
352
     */
353
    public function undoTimer()
354
    {
355
        $message = '';
356
357
        if ($this->hasTimerRunning() === true) {
358
            $this->stopRunningTimer();
359
        }
360
361
        $atLeastOneTimerDeleted = false;
362
363 View Code Duplication
        foreach ($this->servicesToUndo() as $service) {
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...
364
            $functionName = 'delete' . ucfirst($service) . 'Timer';
365
366
            if (call_user_func_array(['AlfredTime', $functionName], [$this->config['workflow']['timer_' . $service . '_id']]) === true) {
367
                $this->config['workflow']['timer_' . $service . '_id'] = null;
368
                $atLeastOneTimerDeleted = true;
369
            }
370
371
            $message .= $this->getLastMessage() . "\r\n";
372
        }
373
374
        if ($atLeastOneTimerDeleted === true) {
375
            $this->saveConfiguration();
376
        }
377
378
        return $message;
379
    }
380
381
    /**
382
     * @param  $harvestId
383
     * @return mixed
384
     */
385
    private function deleteHarvestTimer($harvestId)
386
    {
387
        $res = $this->harvest->deleteTimer($harvestId);
388
        $this->message = $this->harvest->getLastMessage();
389
390
        return $res;
391
    }
392
393
    /**
394
     * @param  $togglId
395
     * @return mixed
396
     */
397
    private function deleteTogglTimer($togglId)
398
    {
399
        $res = $this->toggl->deleteTimer($togglId);
400
        $this->message = $this->toggl->getLastMessage();
401
402
        return $res;
403
    }
404
405
    /**
406
     * @return mixed
407
     */
408
    private function getLastMessage()
409
    {
410
        return $this->message;
411
    }
412
413
    /**
414
     * @return mixed
415
     */
416
    private function getRecentTogglTimers()
417
    {
418
        return $this->toggl->getRecentTimers();
419
    }
420
421
    /**
422
     * @return mixed
423
     */
424
    private function getTogglProjects()
425
    {
426
        $cacheData = [];
427
        $cacheFile = getenv('alfred_workflow_data') . '/toggl_cache.json';
428
429
        if (file_exists($cacheFile)) {
430
            $cacheData = json_decode(file_get_contents($cacheFile), true);
431
        }
432
433
/*
434
 * To only show projects that are currently active
435
 * The Toggl API is slightly weird on that
436
 */
437
        foreach ($cacheData['data']['projects'] as $key => $project) {
438
            if (isset($project['server_deleted_at']) === true) {
439
                unset($cacheData['data']['projects'][$key]);
440
            }
441
        }
442
443
        return $cacheData['data']['projects'];
444
    }
445
446
    /**
447
     * @return mixed
448
     */
449
    private function getTogglTags()
450
    {
451
        $cacheFile = getenv('alfred_workflow_data') . '/toggl_cache.json';
452
        $cacheData = [];
453
454
        if (file_exists($cacheFile)) {
455
            $cacheData = json_decode(file_get_contents($cacheFile), true);
456
        }
457
458
        return $cacheData['data']['tags'];
459
    }
460
461
    /**
462
     * @return mixed
463
     */
464
    private function isHarvestActive()
465
    {
466
        return $this->config['harvest']['is_active'];
467
    }
468
469
    /**
470
     * @return mixed
471
     */
472
    private function isTogglActive()
473
    {
474
        return $this->config['toggl']['is_active'];
475
    }
476
477
    /**
478
     * @return mixed
479
     */
480
    private function loadConfiguration()
481
    {
482
        $config = null;
483
        $configFile = getenv('alfred_workflow_data') . '/config.json';
484
485
        if (file_exists($configFile)) {
486
            $config = json_decode(file_get_contents($configFile), true);
487
        }
488
489
        return $config;
490
    }
491
492
    private function saveConfiguration()
493
    {
494
        $workflowDir = getenv('alfred_workflow_data');
495
        $configFile = $workflowDir . '/config.json';
496
497
        if (file_exists($workflowDir) === false) {
498
            mkdir($workflowDir);
499
        }
500
501
        file_put_contents($configFile, json_encode($this->config, JSON_PRETTY_PRINT));
502
    }
503
504
    /**
505
     * @param $data
506
     */
507
    private function saveTogglDataCache($data)
508
    {
509
        $cacheFile = getenv('alfred_workflow_data') . '/toggl_cache.json';
510
        file_put_contents($cacheFile, json_encode($data));
511
    }
512
513
    /**
514
     * @param  $description
515
     * @param  $projectId
516
     * @param  $taskId
517
     * @return mixed
518
     */
519
    private function startHarvestTimer($description, $projectId, $taskId)
520
    {
521
        $harvestId = $this->harvest->startTimer($description, $projectId, $taskId);
522
        $this->message = $this->harvest->getLastMessage();
523
524
        return $harvestId;
525
    }
526
527
    /**
528
     * @param  $description
529
     * @param  $projectId
530
     * @param  $tagNames
531
     * @return mixed
532
     */
533
    private function startTogglTimer($description, $projectId, $tagNames)
534
    {
535
        $togglId = $this->toggl->startTimer($description, $projectId, $tagNames);
536
        $this->message = $this->toggl->getLastMessage();
537
538
        return $togglId;
539
    }
540
541
    /**
542
     * @return mixed
543
     */
544 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...
545
    {
546
        $harvestId = $this->config['workflow']['timer_harvest_id'];
547
548
        $res = $this->harvest->stopTimer($harvestId);
549
        $this->message = $this->harvest->getLastMessage();
550
551
        return $res;
552
    }
553
554
    /**
555
     * @return mixed
556
     */
557 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...
558
    {
559
        $togglId = $this->config['workflow']['timer_toggl_id'];
560
561
        $res = $this->toggl->stopTimer($togglId);
562
        $this->message = $this->toggl->getLastMessage();
563
564
        return $res;
565
    }
566
567
    /**
568
     * @return mixed
569
     */
570
    private function syncTogglOnlineDataToLocalCache()
571
    {
572
        $data = $this->toggl->getOnlineData();
573
574
        $this->message = $this->toggl->getLastMessage();
575
576
        if (empty($data) === false) {
577
            $this->saveTogglDataCache($data);
578
        }
579
580
        return $this->message;
581
    }
582
}
583