Passed
Pull Request — master (#8)
by Thomas
02:26 queued 55s
created

RequestBuilder::setPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 7
rs 10
cc 1
nc 1
nop 2
1
<?php
2
/**
3
 * Copyright © Thomas Klein, All rights reserved.
4
 * See LICENSE bundled with this library for license details.
5
 */
6
declare(strict_types=1);
7
8
namespace Zoho\Desk\Client;
9
10
use Zoho\OAuth\Utility\ZohoOAuthConstants;
11
use Zoho\Desk\Api\Metadata;
12
use Zoho\Desk\Exception\Exception;
13
use Zoho\Desk\Exception\InvalidArgumentException;
14
use Zoho\Desk\OAuth\ClientInterface;
15
16
use function array_keys;
17
use function array_map;
18
use function array_merge;
19
use function array_values;
20
use function curl_init;
21
use function curl_setopt;
22
use function http_build_query;
23
use function is_array;
24
use function is_numeric;
25
use function json_encode;
26
use function sprintf;
27
use function str_replace;
28
29
use const CURLOPT_CUSTOMREQUEST;
30
use const CURLOPT_HEADER;
31
use const CURLOPT_HTTPHEADER;
32
use const CURLOPT_URL;
33
34
/**
35
 * @api
36
 */
37
final class RequestBuilder
38
{
39
    public const HTTP_GET = 'GET';
40
    public const HTTP_POST = 'POST';
41
    public const HTTP_PATCH = 'PATCH';
42
    public const HTTP_DELETE = 'DELETE';
43
44
    private const MANDATORY_FIELDS = ['entityType', 'method'];
45
46
    private ClientInterface $client;
47
48
    /**
49
     * @var resource
50
     */
51
    private $curl;
52
53
    /**
54
     * @var string[]
55
     */
56
    private array $mandatoryData;
57
58
    /**
59
     * @var array
60
     */
61
    private array $data;
62
63
    public function __construct(ClientInterface $client, array $mandatoryData = [])
64
    {
65
        $this->client = $client;
66
        $this->mandatoryData = array_merge(self::MANDATORY_FIELDS, $mandatoryData);
67
        $this->data = [];
68
    }
69
70
    /**
71
     * @deprecated
72
     */
73
    public function setEntityType(string $entityType): self
74
    {
75
        $this->data['entityType'] = $entityType;
76
77
        return $this;
78
    }
79
80
    public function setPath(string $path, array $bind = []): self
81
    {
82
        $search = array_map(static function (string $variable): string {
83
            return '{' . $variable . '}';
84
        }, array_keys($bind));
85
86
        return $this->setEntityType(str_replace($search, array_values($bind), $path));
0 ignored issues
show
Deprecated Code introduced by
The function Zoho\Desk\Client\RequestBuilder::setEntityType() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

86
        return /** @scrutinizer ignore-deprecated */ $this->setEntityType(str_replace($search, array_values($bind), $path));
Loading history...
87
    }
88
89
    public function setMethod(string $method): self
90
    {
91
        $this->data['method'] = $method;
92
93
        return $this;
94
    }
95
96
    public function setArguments(array $arguments): self
97
    {
98
        $this->data['arguments'] = $arguments;
99
100
        return $this;
101
    }
102
103
    public function setQueryParameters(array $params): self
104
    {
105
        $this->data['queryParameters'] = $params;
106
107
        return $this;
108
    }
109
110
    public function setFields(array $fields): self
111
    {
112
        $this->data['fields'] = $fields;
113
114
        return $this;
115
    }
116
117
    /**
118
     * @return RequestInterface
119
     * @throws InvalidArgumentException|Exception
120
     */
121
    public function create(): RequestInterface
122
    {
123
        foreach ($this->mandatoryData as $mandatory) {
124
            if (!isset($this->data[$mandatory])) {
125
                throw InvalidArgumentException::createMandatoryFieldException($mandatory);
126
            }
127
        }
128
129
        $this->curl = curl_init();
0 ignored issues
show
Documentation Bug introduced by
It seems like curl_init() can also be of type CurlHandle. However, the property $curl is declared as type resource. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
130
        curl_setopt($this->curl, CURLOPT_URL, $this->buildUrl());
131
        curl_setopt($this->curl, CURLOPT_COOKIESESSION, true);
132
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
133
        curl_setopt($this->curl, CURLOPT_HEADER, 1);
134
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $this->buildHeaders());
135
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $this->data['method']);
136
137
        if ($this->data['method'] !== self::HTTP_GET) {
138
            curl_setopt($this->curl, CURLOPT_POST, true);
139
            curl_setopt($this->curl, CURLOPT_POSTFIELDS, json_encode($this->data['fields']));
140
        }
141
142
        $request = new Request($this->curl);
143
144
        $this->curl = null;
145
        $this->data = [];
146
147
        return $request;
148
    }
149
150
    /**
151
     * @return string[]
152
     * @throws Exception
153
     */
154
    private function buildHeaders(): array
155
    {
156
        $headers = [
157
            ZohoOAuthConstants::AUTHORIZATION . ':' . ZohoOAuthConstants::OAUTH_HEADER_PREFIX . $this->client->getAccessToken(),
158
            'Content-Type:application/json'
159
        ];
160
161
        if ($this->client->getOrgId()) {
162
            $headers[] = Metadata::ORG_ID . ':' . $this->client->getOrgId();
163
        }
164
165
        return $headers;
166
    }
167
168
    private function buildUrl(): string
169
    {
170
        $url = sprintf(
171
            'https://%s/%s/%s',
172
            $this->client->getApiBaseUrl(),
173
            $this->client->getApiVersion(),
174
            $this->data['entityType']
175
        );
176
177
        if (isset($this->data['arguments']) && is_array($this->data['arguments'])) {
178
            foreach ($this->data['arguments'] as $key => $argument) {
179
                if (!is_numeric($key)) {
180
                    $url .= '/' . $key;
181
                }
182
                $url .= '/' . $argument;
183
            }
184
        }
185
        if (isset($this->data['queryParameters']) && is_array($this->data['queryParameters'])) {
186
            $url .= '?' . http_build_query($this->data['queryParameters']);
187
        }
188
189
        return $url;
190
    }
191
}
192