ProjektronApi::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 4
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of forecast.it.fill project.
7
 * (c) Patrick Jaja <[email protected]>
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace ForecastAutomation\ProjektronClient\Business;
13
14
use ForecastAutomation\Activity\Shared\Dto\ActivityDto;
15
use ForecastAutomation\Activity\Shared\Dto\ActivityDtoCollection;
16
17
class ProjektronApi
18
{
19
    private string $csrf;
20
21
    public function __construct(
22
        private string $projektronApiEndpoint,
23
        private string $projektronCookieHeaderValue,
24
        private string $username,
25
        private string $catchAllTask
26
    ) { $this->setCsrfFromCookie();  }
27
28
    public function writeActivities(ActivityDtoCollection $activityDtoCollection): int
29
    {
30
        $savedActivities = 0;
31
        foreach ($activityDtoCollection as $activityDto) {
32
            $activityDto->needle = $this->setCatchAllOnUnknownTask($activityDto->needle);
33
            $activityDto->created->sub(new \DateInterval('P1D')); // give projektron a date, and it adds +1 day, so remove one day of the time entry, HAHAHA
34
            $activityDto->created->setTime(22, 0, 0); // projektron doesnt save the entry if the time is not 22:00 HAHAHA
35
            $payloadDto = new PayloadDto(
36
                $activityDto->needle,
37
                $this->csrf,$this->username,
38
                $activityDto->created->getTimestamp().'000',
39
                (string)intdiv($activityDto->duration, 60),
40
                (string)($activityDto->duration%60),
41
                $activityDto->description
42
            );
43
            $this->sendActivity($this->projektronApiEndpoint.'?oid='.$activityDto->needle, $payloadDto);
44
            ++$savedActivities;
45
        }
46
47
        return $savedActivities;
48
    }
49
50
    private function sendActivity(string $path, PayloadDto $payloadDto): string
51
    {
52
        $this->headers = [
0 ignored issues
show
Bug Best Practice introduced by
The property headers does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
53
            'Cookie: '.$this->projektronCookieHeaderValue,
54
            'User-Agent: ArchUser/1337',
55
        ];
56
57
        $ch = curl_init($path);
58
        curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);
59
        curl_setopt($ch, CURLOPT_POST, true);
60
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payloadDto->getEncodedData());
61
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
62
63
        $response = curl_exec($ch);
64
65
        if (!$this->isProjektronActivitySuccess($response)) {
0 ignored issues
show
Bug introduced by
It seems like $response can also be of type true; however, parameter $response of ForecastAutomation\Proje...ektronActivitySuccess() does only seem to accept string, 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

65
        if (!$this->isProjektronActivitySuccess(/** @scrutinizer ignore-type */ $response)) {
Loading history...
66
            throw new \Exception('Could not send activity to projektron.');
67
        }
68
69
        if (curl_errno($ch)) {
70
            throw new \Exception(curl_error($ch));
71
        }
72
        curl_close($ch);
73
74
        return $response;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $response could return the type true which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
75
    }
76
77
    private function isProjektronActivitySuccess(string $response): bool
78
    {
79
        return strpos($response, '<div class="msg affirmation">') !== false;
80
    }
81
82
    private function setCsrfFromCookie() {
83
        $pattern = '/CSRF_Token=([^;]+)/';
84
        if (preg_match($pattern, $this->projektronCookieHeaderValue, $matches)) {
85
            $this->csrf = $matches[1];
86
        } else {
87
            new \Exception('Projektron API error. CSRF_Token not found in cookie header.');
88
        }
89
    }
90
91
    private function setCatchAllOnUnknownTask(string $projektronTaskId):string {
92
        if (\strpos($projektronTaskId, '_JTask') === false) {
93
            return $this->catchAllTask;
94
        } else {
95
            return $projektronTaskId;
96
        }
97
    }
98
}
99