Test Failed
Pull Request — master (#38)
by Patrick
03:34
created

ProjektronApi::sendActivity()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 15
c 0
b 0
f 0
nc 3
nop 2
dl 0
loc 25
rs 9.7666
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
    ) { $this->setCsrfFromCookie();  }
26
27
    public function writeActivities(ActivityDtoCollection $activityDtoCollection): int
28
    {
29
        $savedActivities = 0;
30
        foreach ($activityDtoCollection as $activityDto) {
31
            $activityDto->created->sub(new \DateInterval('P1D')); // give projektron a date, and it adds +1 day, so remove one day of the time entry, HAHAHA
32
            $activityDto->created->setTime(22, 0, 0); // projektron doesnt save the entry if the time is not 22:00 HAHAHA
33
            $payloadDto = new PayloadDto(
34
                $activityDto->needle,
35
                $this->csrf,$this->username,
36
                $activityDto->created->getTimestamp().'000',
37
                (string)intdiv($activityDto->duration, 60),
38
                (string)($activityDto->duration%60),
39
                $activityDto->description
40
            );
41
            $this->sendActivity($this->projektronApiEndpoint.'?oid='.$activityDto->needle, $payloadDto);
42
            ++$savedActivities;
43
        }
44
45
        return $savedActivities;
46
    }
47
48
    private function sendActivity(string $path, PayloadDto $payloadDto): string
49
    {
50
        $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...
51
            'Cookie: '.$this->projektronCookieHeaderValue,
52
            'User-Agent: ArchUser/1337',
53
        ];
54
55
        $ch = curl_init($path);
56
        curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);
57
        curl_setopt($ch, CURLOPT_POST, true);
58
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payloadDto->getEncodedData());
59
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
60
61
        $response = curl_exec($ch);
62
63
        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

63
        if (!$this->isProjektronActivitySuccess(/** @scrutinizer ignore-type */ $response)) {
Loading history...
64
            throw new \Exception('Could not send activity to projektron.');
65
        }
66
67
        if (curl_errno($ch)) {
68
            throw new \Exception(curl_error($ch));
69
        }
70
        curl_close($ch);
71
72
        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...
73
    }
74
75
    private function isProjektronActivitySuccess(string $response): bool
76
    {
77
        return strpos($response, '<div class="msg affirmation">') !== false;
78
    }
79
80
    private function setCsrfFromCookie() {
81
        $pattern = '/CSRF_Token=([^;]+)/';
82
        if (preg_match($pattern, $this->projektronCookieHeaderValue, $matches)) {
83
            $this->csrf = $matches[1];
84
        } else {
85
            new \Exception('Projektron API error. CSRF_Token not found in cookie header.');
86
        }
87
    }
88
}
89