GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( ac49a8...d1ea4d )
by
unknown
02:44
created

Client::requestRPC()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 2
1
<?php
2
3
namespace Spatie\Dropbox;
4
5
use GuzzleHttp\Client as GuzzleClient;
6
use GuzzleHttp\Exception\ClientException;
7
use GuzzleHttp\Psr7\StreamWrapper;
8
use Psr\Http\Message\ResponseInterface;
9
use Spatie\Dropbox\Exceptions\BadRequest;
10
11
class Client
12
{
13
    const THUMBNAIL_FORMAT_JPEG = 'jpeg';
14
    const THUMBNAIL_FORMAT_PNG = 'png';
15
16
    const THUMBNAIL_SIZE_XS = 'w32h32';
17
    const THUMBNAIL_SIZE_S = 'w64h64';
18
    const THUMBNAIL_SIZE_M = 'w128h128';
19
    const THUMBNAIL_SIZE_L = 'w640h480';
20
    const THUMBNAIL_SIZE_XL = 'w1024h768';
21
22
    protected $accessToken;
23
24
    protected $client;
25
26
    public function __construct(string $accessToken)
27
    {
28
        $this->accessToken = $accessToken;
29
30
        $this->client = new GuzzleClient([
31
            'headers' => [
32
                'Authorization' => "Bearer {$this->accessToken}",
33
            ],
34
        ]);
35
    }
36
37
    /**
38
     * Copy a file or folder to a different location in the user's Dropbox.
39
     * If the source path is a folder all its contents will be copied.
40
     *
41
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-copy
42
     */
43 View Code Duplication
    public function copy(string $path, string $newPath): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
44
    {
45
        $parameters = [
46
            'from_path' => $this->normalizePath($path),
47
            'to_path' => $this->normalizePath($newPath),
48
        ];
49
50
        return $this->rpcEndpointRequest('files/copy', $parameters);
51
    }
52
53
    /**
54
     * Create a folder at a given path.Create a folder at a given path.
55
     *
56
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-create_folder
57
     */
58
    public function createFolder(string $path): array
59
    {
60
        $parameters = [
61
            'path' => $this->normalizePath($path),
62
        ];
63
64
        $object = $this->rpcEndpointRequest('files/create_folder', $parameters);
65
66
        $object['.tag'] = 'folder';
67
68
        return $object;
69
    }
70
71
    /**
72
     * Delete the file or folder at a given path.
73
     * If the path is a folder, all its contents will be deleted too.
74
     * A successful response indicates that the file or folder was deleted.
75
     *
76
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-delete
77
     */
78
    public function delete(string $path): array
79
    {
80
        $parameters = [
81
            'path' => $this->normalizePath($path),
82
        ];
83
84
        return $this->rpcEndpointRequest('files/delete', $parameters);
85
    }
86
87
    /**
88
     * Download a file from a user's Dropbox.
89
     *
90
     * @param string $path
91
     *
92
     * @return resource
93
     *
94
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-download
95
     */
96
    public function download(string $path)
97
    {
98
        $arguments = [
99
            'path' => $this->normalizePath($path),
100
        ];
101
102
        $response = $this->contentEndpointRequest('files/download', $arguments);
103
104
        return StreamWrapper::getResource($response->getBody());
105
    }
106
107
    /**
108
     * Returns the metadata for a file or folder.
109
     * Note: Metadata for the root folder is unsupported.
110
     *
111
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_metadata
112
     */
113
    public function getMetadata(string $path): array
114
    {
115
        $parameters = [
116
            'path' => $this->normalizePath($path),
117
        ];
118
119
        return $this->rpcEndpointRequest('files/get_metadata', $parameters);
120
    }
121
122
    /**
123
     * Get a temporary link to stream content of a file. This link will expire in four hours and afterwards you will get 410 Gone.
124
     * Content-Type of the link is determined automatically by the file's mime type.
125
     *
126
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_temporary_link
127
     */
128 View Code Duplication
    public function getTemporaryLink(string $path): string
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
129
    {
130
        $parameters = [
131
            'path' => $this->normalizePath($path),
132
        ];
133
134
        $body = $this->rpcEndpointRequest('files/get_temporary_link', $parameters);
135
136
        return $body['link'];
137
    }
138
139
    /**
140
     * Get a thumbnail for an image.
141
     * This method currently supports files with the following file extensions: jpg, jpeg, png, tiff, tif, gif and bmp.
142
     * Photos that are larger than 20MB in size won't be converted to a thumbnail.
143
     *
144
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_thumbnail
145
     */
146
    public function getThumbnail(string $path, string $format = 'jpeg', string $size = 'w64h64'): string
147
    {
148
        $arguments = [
149
            'path' => $this->normalizePath($path),
150
            'format' => $format,
151
            'size' => $size
152
        ];
153
154
        $response = $this->contentEndpointRequest('files/get_thumbnail', $arguments);
155
156
        return (string) $response->getBody();
157
    }
158
159
    /**
160
     * Starts returning the contents of a folder. If the result's ListFolderResult.has_more field is true, call
161
     * list_folder/continue with the returned ListFolderResult.cursor to retrieve more entries.
162
     *
163
     * Note: auth.RateLimitError may be returned if multiple list_folder or list_folder/continue calls with same parameters
164
     * are made simultaneously by same API app for same user. If your app implements retry logic, please hold off the retry
165
     * until the previous request finishes.
166
     *
167
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder
168
     */
169 View Code Duplication
    public function listFolder(string $path = '', bool $recursive = false): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
170
    {
171
        $parameters = [
172
            'path' => $this->normalizePath($path),
173
            'recursive' => $recursive,
174
        ];
175
176
        return $this->rpcEndpointRequest('files/list_folder', $parameters);
177
    }
178
179
    /**
180
     * Move a file or folder to a different location in the user's Dropbox.
181
     * If the source path is a folder all its contents will be moved.
182
     *
183
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-move
184
     */
185 View Code Duplication
    public function move(string $path, string $newPath): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
186
    {
187
        $parameters = [
188
            'from_path' => $this->normalizePath($path),
189
            'to_path' => $this->normalizePath($newPath),
190
        ];
191
192
        return $this->rpcEndpointRequest('files/move', $parameters);
193
    }
194
195
    /**
196
     * Create a new file with the contents provided in the request.
197
     * Do not use this to upload a file larger than 150 MB. Instead, create an upload session with upload_session/start.
198
     *
199
     * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload
200
     *
201
     * @param string            $path
202
     * @param string            $mode
203
     * @param string|resource   $contents
204
     *
205
     * @return array
206
     */
207
    public function upload(string $path, string $mode, $contents): array
208
    {
209
        $arguments = [
210
            'path' => $this->normalizePath($path),
211
            'mode' => $mode,
212
        ];
213
214
        $response = $this->contentEndpointRequest('files/upload', $arguments, $contents);
215
216
        $metadata = json_decode($response->getBody(), true);
217
218
        $metadata['.tag'] = 'file';
219
220
        return $metadata;
221
    }
222
223
    /**
224
     * @param string $endpoint
225
     * @param array $arguments
226
     * @param string|resource $body
227
     *
228
     * @return \Psr\Http\Message\ResponseInterface
229
     * 
230
     * @throws \Spatie\Dropbox\Exceptions\BadRequest
231
     */
232
    protected function contentEndpointRequest(string $endpoint, array $arguments, $body = ''): ResponseInterface
233
    {
234
        $headers['Dropbox-API-Arg'] = json_encode($arguments);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$headers was never initialized. Although not strictly required by PHP, it is generally a good practice to add $headers = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
235
236
        if ($body != '') {
237
            $headers['Content-Type'] = 'application/octet-stream';
238
        }
239
240
        try {
241
            $response = $this->client->post("https://content.dropboxapi.com/2/{$endpoint}", [
242
                'headers' => $headers,
243
                'body' => $body,
244
            ]);
245
246
        } catch (ClientException $exception) {
247
            if ($exception->getResponse()->getStatusCode() === 409) {
248
                throw new BadRequest($exception->getResponse());
0 ignored issues
show
Bug introduced by
It seems like $exception->getResponse() can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
249
            }
250
251
            throw $exception;
252
        }
253
254
        return $response;
255
    }
256
257
    protected function normalizePath(string $path): string
258
    {
259
        $path = trim($path,'/');
260
261
        if ($path === '') {
262
            return '';
263
        }
264
265
        return '/'.$path;
266
    }
267
268
    protected function rpcEndpointRequest(string $endpoint, array $parameters): array
269
    {
270
        try {
271
            $response = $this->client->post("https://api.dropboxapi.com/2/{$endpoint}", [
272
                'json' => $parameters
273
            ]);
274
        } catch (ClientException $exception) {
275
            if ($exception->getResponse()->getStatusCode() === 409) {
276
                throw new BadRequest($exception->getResponse());
0 ignored issues
show
Bug introduced by
It seems like $exception->getResponse() can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
277
            }
278
279
            throw $exception;
280
        }
281
282
        return json_decode($response->getBody(), true);
283
    }
284
}
285