Issues (6)

src/utils/Api.php (4 issues)

1
<?php
2
3
namespace cmzn\Autentique\Utils;
4
5
use CURLFile;
6
use CurlHandle;
7
use Exception;
8
9
use cmzn\Autentique\exceptions\EmptyTokenException;
10
use cmzn\Autentique\exceptions\EmptyQueryException;
11
use cmzn\Autentique\exceptions\ContentTypeException;
12
use cmzn\Autentique\exceptions\EmptyAutentiqueResponseException;
13
use cmzn\Autentique\exceptions\EmptyAutentiqueUrlException;
14
use cmzn\Autentique\exceptions\InvalidAutentiqueUrlException;
15
16
class Api
17
{
18
    const ACCEPT_CONTENTS = ["json", "form"];
19
20
    private $url;
21
22
    private $timeout = 60;
23
24
    /**
25
     * @param string $url Autentique API URL
26
     * @param int $timeout=60 seconds to timeout request
27
     */
28
    public function __construct(string $url, int $timeout = 60)
29
    {
30
        $this->url = $this->setUrl($url);
31
        $this->timeout = $timeout;
32
    }
33
34
    /**
35
     * @param string $token
36
     * @param string $query
37
     * @param string $contentType json|form
38
     * @param string|null $pathFile
39
     * @return array
40
     */
41
    public function request(
42
        string $token,
43
        string $query,
44
        string $contentType,
45
        string $pathFile = null
46
    ): array {
47
        if (empty($token)) {
48
            throw new EmptyTokenException();
49
        }
50
51
        $this->validateParams($contentType, $query);
52
53
        $httpHeader = ["Authorization: Bearer {$token}"];
54
55
        $fields = '{"query":' . $query . "}";
56
57
        if ($contentType == "json") {
58
            $contentType = $this->requestJson();
59
        } else {
60
            $contentType = $this->requestFormData();
61
            $fields = [
62
                "operations" => $fields,
63
                "map" => '{"file": ["variables.file"]}',
64
                "file" => new CURLFile($pathFile),
65
            ];
66
        }
67
68
        array_push($httpHeader, $contentType);
69
70
        return $this->connect($httpHeader, $fields);
71
    }
72
73
    /**
74
     * @param array $httpHeader
75
     * @param string|array $fields
76
     * @return array $response
77
     */
78
    private function connect(array $httpHeader, $fields): array
79
    {
80
        $curl = curl_init();
81
82
        curl_setopt_array(
83
            /** @scrutinizer ignore-type */
84
            $curl,
85
            [
86
                CURLOPT_URL => $this->url,
87
                CURLOPT_RETURNTRANSFER => true,
88
                CURLOPT_ENCODING => "",
89
                CURLOPT_MAXREDIRS => 10,
90
                CURLOPT_CONNECTTIMEOUT => $this->timeout,
91
                CURLOPT_TIMEOUT => $this->timeout,
92
                CURLOPT_FOLLOWLOCATION => true,
93
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
94
                CURLOPT_CUSTOMREQUEST => "POST",
95
                CURLOPT_POSTFIELDS => $fields,
96
                CURLOPT_HTTPHEADER => $httpHeader,
97
                CURLOPT_CAINFO => __DIR__ . "/../../ssl/ca-bundle.crt",
98
            ]
99
        );
100
        if(PHP_VERSION_ID >= 80000){
101
102
            $response = $this->executeCurl($curl);
0 ignored issues
show
It seems like $curl can also be of type resource; however, parameter $curl of cmzn\Autentique\Utils\Api::executeCurl() does only seem to accept CurlHandle, 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

102
            $response = $this->executeCurl(/** @scrutinizer ignore-type */ $curl);
Loading history...
103
104
            $errorNo = $this->getErrorNo($curl);
0 ignored issues
show
It seems like $curl can also be of type resource; however, parameter $curl of cmzn\Autentique\Utils\Api::getErrorNo() does only seem to accept CurlHandle, 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

104
            $errorNo = $this->getErrorNo(/** @scrutinizer ignore-type */ $curl);
Loading history...
105
106
        } else {
107
            
108
            $response = $this->executeCurlLegacy($curl);
109
110
            $errorNo = $this->getErrorNoLegacy($curl);
111
112
        }
113
        
114
115
        if ($response == "[]") {
116
            throw new EmptyAutentiqueResponseException();
117
        }
118
119
        if ($errorNo) {
120
            throw new Exception(curl_error($curl));
121
        }
122
123
        curl_close(
124
            /** @scrutinizer ignore-type */
125
            $curl
126
        );
127
128
        return json_decode($response, true);
129
    }
130
131
    private function setUrl(string $url): string
132
    {
133
        if (empty($url)) {
134
            throw new EmptyAutentiqueUrlException();
135
        }
136
137
        return $url;
138
    }
139
140
    private function validateParams(string $contentType, string $query): void
141
    {
142
        if (!in_array($contentType, self::ACCEPT_CONTENTS)) {
143
            throw new ContentTypeException();
144
        }
145
146
        if (empty($query)) {
147
            throw new EmptyQueryException();
148
        }
149
150
        if (!filter_var($this->url, FILTER_VALIDATE_URL)) {
151
            throw new InvalidAutentiqueUrlException();
152
        }
153
    }
154
155
    private function requestJson(): string
156
    {
157
        return "Content-Type: application/json";
158
    }
159
160
    private function requestFormData(): string
161
    {
162
        return "Content-Type: multipart/form-data";
163
    }
164
    public function getErrorNo(CurlHandle $curl): int
165
    {
166
        return curl_errno(
167
            /** @scrutinizer ignore-type */
168
            $curl
169
        );
170
    }
171
    public function getErrorNoLegacy($curl): int
172
    {
173
        return curl_errno(
174
            /** @scrutinizer ignore-type */
175
            $curl
176
        );
177
    }
178
    public function executeCurl(CurlHandle $curl): string
179
    {
180
        return curl_exec(
0 ignored issues
show
Bug Best Practice introduced by
The expression return curl_exec($curl) 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...
181
            /** @scrutinizer ignore-type */
182
            $curl
183
        );
184
    }
185
    public function executeCurlLegacy($curl): string
186
    {
187
        return curl_exec(
0 ignored issues
show
Bug Best Practice introduced by
The expression return curl_exec($curl) 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...
188
            /** @scrutinizer ignore-type */
189
            $curl
190
        );
191
    }
192
    /**
193
     * Get the value of url
194
     * @return string
195
     *
196
     * @codeCoverageIgnore
197
     */
198
    public function getUrl(): string
199
    {
200
        return $this->url;
201
    }
202
}
203