Completed
Push — master ( 591d30...9b4fec )
by Vinicius Morais
16s queued 14s
created

Api::getUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace vinicinbgs\Autentique\Utils;
4
5
use CURLFile;
6
use CurlHandle;
7
use Exception;
8
9
use vinicinbgs\Autentique\exceptions\EmptyTokenException;
10
use vinicinbgs\Autentique\exceptions\EmptyQueryException;
11
use vinicinbgs\Autentique\exceptions\ContentTypeException;
12
use vinicinbgs\Autentique\exceptions\EmptyAutentiqueResponseException;
13
use vinicinbgs\Autentique\exceptions\EmptyAutentiqueUrlException;
14
use vinicinbgs\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
101
        $response = $this->executeCurl($curl);
0 ignored issues
show
Bug introduced by
It seems like $curl can also be of type resource; however, parameter $curl of vinicinbgs\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

101
        $response = $this->executeCurl(/** @scrutinizer ignore-type */ $curl);
Loading history...
102
103
        $errorNo = $this->getErrorNo($curl);
0 ignored issues
show
Bug introduced by
It seems like $curl can also be of type resource; however, parameter $curl of vinicinbgs\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

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