Completed
Push — master ( 285fdb...fc4358 )
by Hans
02:33
created

Api::getNextItems()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 26
ccs 0
cts 15
cp 0
rs 8.8571
cc 3
eloc 14
nc 3
nop 1
crap 12
1
<?php
2
3
/*
4
 * This file is part of the Pinterest PHP library.
5
 *
6
 * (c) Hans Ott <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.md.
10
 *
11
 * Source: https://github.com/hansott/pinterest-php
12
 */
13
14
namespace Pinterest;
15
16
use InvalidArgumentException;
17
use Pinterest\Http\Exceptions\RateLimitedReached;
18
use Pinterest\Http\Request;
19
use Pinterest\Http\Response;
20
use Pinterest\Objects\Board;
21
use Pinterest\Objects\PagedList;
22
use Pinterest\Objects\Pin;
23
use Pinterest\Objects\User;
24
25
/**
26
 * The api client.
27
 *
28
 * @author Hans Ott <[email protected]>
29
 * @author Toon Daelman <[email protected]>
30
 */
31
class Api
32
{
33
    /**
34
     *  The authentication client.
35
     *
36
     * @var Authentication
37
     */
38
    private $auth;
39
40
    /**
41
     * The constructor.
42
     *
43
     * @param Authentication $auth The authentication client.
44
     */
45 32
    public function __construct(Authentication $auth)
46
    {
47 32
        $this->auth = $auth;
48 32
    }
49
50
    /**
51
     * Processes a response.
52
     *
53
     * @param Response $response  The response object.
54
     * @param callable $processor The response processor.
55
     *
56
     * @return Response The response.
57
     */
58 30
    private function processResponse(Response $response, $processor)
59
    {
60 30
        if ($response->ok()) {
61 30
            $result = $processor($response);
62 30
            $response->setResult($result);
63 30
        }
64
65 30
        return $response;
66
    }
67
68
    /**
69
     * Execute the given http request.
70
     *
71
     * @param Request       $request
72
     * @param callable|null $processor
73
     *
74
     * @throws RateLimitedReached
75
     *
76
     * @return Response The response.
77
     */
78 32
    public function execute(Request $request, $processor = null)
79
    {
80 32
        $response = $this->auth->execute($request);
81
82 32
        if ($response->rateLimited()) {
83
            throw new RateLimitedReached($response);
84
        }
85
86 32
        if (is_callable($processor)) {
87 30
            $response = $this->processResponse($response, $processor);
88 30
        }
89
90 32
        return $response;
91
    }
92
93
    /**
94
     * Fetch a single user and processes the response.
95
     *
96
     * @param Request $request
97
     *
98
     * @return Response The response.
99
     */
100 4 View Code Duplication
    private function fetchUser(Request $request)
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...
101
    {
102 4
        $request->setFields(User::fields());
103
104
        return $this->execute($request, function (Response $response) {
105 4
            $mapper = new Mapper(new User());
106
107 4
            return $mapper->toSingle($response);
108 4
        });
109
    }
110
111
    /**
112
     * Fetch a single board and processes the response.
113
     *
114
     * @param Request $request
115
     *
116
     * @throws RateLimitedReached
117
     *
118
     * @return Response The response.
119
     */
120 4 View Code Duplication
    private function fetchBoard(Request $request)
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...
121
    {
122 4
        $request->setFields(Board::fields());
123
124
        return $this->execute($request, function (Response $response) {
125 4
            $mapper = new Mapper(new Board());
126
127 4
            return $mapper->toSingle($response);
128 4
        });
129
    }
130
131
    /**
132
     * Fetch a single pin and processes the response.
133
     *
134
     * @param Request $request
135
     *
136
     * @throws RateLimitedReached
137
     *
138
     * @return Response The response.
139
     */
140 8 View Code Duplication
    private function fetchPin(Request $request)
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...
141
    {
142 8
        $request->setFields(Pin::fields());
143
144
        return $this->execute($request, function (Response $response) {
145 8
            $mapper = new Mapper(new Pin());
146
147 8
            return $mapper->toSingle($response);
148 8
        });
149
    }
150
151
    /**
152
     * Fetch multiple boards and processes the response.
153
     *
154
     * @param Request    $request
155
     * @param array|null $fields
156
     *
157
     * @throws RateLimitedReached
158
     *
159
     * @return Response The response.
160
     */
161 6 View Code Duplication
    private function fetchMultipleBoards(Request $request, array $fields = null)
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...
162
    {
163 6
        $fields = $fields ? $fields : Board::fields();
164 6
        $request->setFields($fields);
165
166
        return $this->execute($request, function (Response $response) {
167 6
            $mapper = new Mapper(new Board());
168
169 6
            return $mapper->toList($response);
170 6
        });
171
    }
172
173
    /**
174
     * Fetch multiple users and processes the response.
175
     *
176
     * @param Request $request
177
     *
178
     * @throws RateLimitedReached
179
     *
180
     * @return Response The response.
181
     */
182 4 View Code Duplication
    private function fetchMultipleUsers(Request $request)
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...
183
    {
184 4
        $request->setFields(User::fields());
185
186
        return $this->execute($request, function (Response $response) {
187 4
            $mapper = new Mapper(new User());
188
189 4
            return $mapper->toList($response);
190 4
        });
191
    }
192
193
    /**
194
     * Fetches multiple pins and processes the response.
195
     *
196
     * @param Request $request
197
     * @param $fields array The fields to require.
198
     *
199
     * @throws RateLimitedReached
200
     *
201
     * @return Response The response.
202
     */
203 4 View Code Duplication
    private function fetchMultiplePins(Request $request, array $fields = null)
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...
204
    {
205 4
        $fields = $fields ? $fields : Pin::fields();
206 4
        $request->setFields($fields);
207
208
        return $this->execute($request, function (Response $response) {
209 4
            $mapper = new Mapper(new Pin());
210
211 4
            return $mapper->toList($response);
212 4
        });
213
    }
214
215
    /**
216
     * Get a user.
217
     *
218
     * @param string $usernameOrId The username or identifier of the user.
219
     *
220
     * @return Response
221
     */
222 2
    public function getUser($usernameOrId)
223
    {
224 2
        if (empty($usernameOrId)) {
225 2
            throw new InvalidArgumentException('The username or id should not be empty.');
226
        }
227
228 2
        $request = new Request('GET', sprintf('users/%s/', $usernameOrId));
229
230 2
        return $this->fetchUser($request);
231
    }
232
233
    /**
234
     * Get a board.
235
     *
236
     * @param string $boardId The board id.
237
     *
238
     * @return Response
239
     */
240 2
    public function getBoard($boardId)
241
    {
242 2
        if (empty($boardId)) {
243
            throw new InvalidArgumentException('The board id should not be empty.');
244
        }
245
246 2
        $request = new Request('GET', sprintf('boards/%s/', $boardId));
247
248 2
        return $this->fetchBoard($request);
249
    }
250
251
    /**
252
     * Update a board.
253
     *
254
     * @param Board $board The updated board.
255
     *
256
     * @return Response
257
     */
258 2
    public function updateBoard(Board $board)
259
    {
260 2
        $params = array();
261
262 2
        if (empty($board->id)) {
263
            throw new InvalidArgumentException('The board id is required.');
264
        }
265
266 2
        if (!empty($board->name)) {
267 2
            $params['name'] = (string) $board->name;
268 2
        }
269
270 2
        if (!empty($board->description)) {
271 2
            $params['description'] = (string) $board->description;
272 2
        }
273
274 2
        $request = new Request('PATCH', sprintf('boards/%s/', $board->id), $params);
275
276 2
        return $this->fetchBoard($request);
277
    }
278
279
    /**
280
     * Get the boards of the authenticated user.
281
     *
282
     * @return Response
283
     */
284 2
    public function getUserBoards()
285
    {
286 2
        $request = new Request('GET', 'me/boards/');
287
288 2
        return $this->fetchMultipleBoards($request);
289
    }
290
291
    /**
292
     * Get the pins of the authenticated user.
293
     *
294
     * @returnResponse
295
     */
296 2
    public function getUserLikes()
297
    {
298 2
        $request = new Request('GET', 'me/likes/');
299
300 2
        return $this->fetchMultiplePins($request);
301
    }
302
303
    /**
304
     * Get the pins of the authenticated user.
305
     *
306
     * @return Response
307
     */
308 2
    public function getUserPins()
309
    {
310 2
        $request = new Request('GET', 'me/pins/');
311
312 2
        return $this->fetchMultiplePins($request);
313
    }
314
315
    /**
316
     * Get the authenticated user.
317
     *
318
     * @return Response
319
     */
320 2
    public function getCurrentUser()
321
    {
322 2
        $request = new Request('GET', 'me/');
323
324 2
        return $this->fetchUser($request);
325
    }
326
327
    /**
328
     * Get the followers of the authenticated user.
329
     *
330
     * @return Response
331
     */
332 2
    public function getUserFollowers()
333
    {
334 2
        $request = new Request('GET', 'me/followers/');
335
336 2
        return $this->fetchMultipleUsers($request);
337
    }
338
339
    /**
340
     * Get the boards that the authenticated user follows.
341
     *
342
     * @return Response
343
     */
344 2
    public function getUserFollowingBoards()
345
    {
346 2
        $request = new Request('GET', 'me/following/boards/');
347
348 2
        return $this->fetchMultipleBoards($request);
349
    }
350
351
    /**
352
     * Get the users that the authenticated user follows.
353
     *
354
     * @return Response
355
     */
356 2
    public function getUserFollowing()
357
    {
358 2
        $request = new Request('GET', 'me/following/users/');
359
360 2
        return $this->fetchMultipleUsers($request);
361
    }
362
363
    /**
364
     * Get the interests that the authenticated user follows.
365
     *
366
     * @link https://www.pinterest.com/explore/901179409185
367
     *
368
     * @return Response
369
     */
370 2
    public function getUserInterests()
371
    {
372 2
        $request = new Request('GET', 'me/following/interests/');
373
374 2
        return $this->fetchMultipleBoards($request, array('id', 'name'));
375
    }
376
377
    /**
378
     * Follow a user.
379
     *
380
     * @param string $username The username of the user to follow.
381
     *
382
     * @return Response
383
     */
384 2 View Code Duplication
    public function followUser($username)
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...
385
    {
386 2
        if (empty($username)) {
387 2
            throw new InvalidArgumentException('Username is required.');
388
        }
389
390 2
        $request = new Request(
391 2
            'POST',
392 2
            'me/following/users/',
393
            array(
394 2
                'user' => (string) $username,
395
            )
396 2
        );
397
398 2
        return $this->execute($request);
399
    }
400
401
    /**
402
     * Create a board.
403
     *
404
     * @param string $name        The board name.
405
     * @param string $description The board description.
406
     *
407
     * @return Response
408
     */
409 2
    public function createBoard($name, $description = null)
410
    {
411 2
        if (empty($name)) {
412
            throw new InvalidArgumentException('The name should not be empty.');
413
        }
414
415
        $params = array(
416 2
            'name' => (string) $name,
417 2
        );
418
419 2
        if (!empty($description)) {
420 2
            $params['description'] = (string) $description;
421 2
        }
422
423 2
        $request = new Request('POST', 'boards/', $params);
424
425 2
        return $this->fetchBoard($request);
426
    }
427
428
    /**
429
     * Delete a board.
430
     *
431
     * @param int $boardId The board id.
432
     *
433
     * @return Response
434
     */
435 2 View Code Duplication
    public function deleteBoard($boardId)
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...
436
    {
437 2
        if (empty($boardId)) {
438
            throw new InvalidArgumentException('The board id should not be empty.');
439
        }
440
441 2
        $request = new Request('DELETE', sprintf('boards/%d/', $boardId));
442
443 2
        return $this->execute($request);
444
    }
445
446
    /**
447
     * Create a pin on a board.
448
     *
449
     * @param string      $boardId The board id.
450
     * @param string      $note    The note.
451
     * @param Image       $image   The image.
452
     * @param string|null $link    The link (Optional).
453
     *
454
     * @return Response
455
     */
456 8
    public function createPin($boardId, $note, Image $image, $link = null)
457
    {
458 8
        if (empty($boardId)) {
459
            throw new InvalidArgumentException('The board id should not be empty.');
460
        }
461
462 8
        if (empty($note)) {
463
            throw new InvalidArgumentException('The note should not be empty.');
464
        }
465
466
        $params = array(
467 8
            'board' => (int) $boardId,
468 8
            'note' => (string) $note,
469 8
        );
470
471 8
        if (!empty($link)) {
472
            $params['link'] = (string) $link;
473
        }
474
475 8
        $imageKey = $image->isUrl() ? 'image_url' : ($image->isBase64() ? 'image_base64' : 'image');
476
477 8
        if ($image->isFile()) {
478 2
            $params[$imageKey] = $image;
479 2
        } else {
480 6
            $params[$imageKey] = $image->getData();
481
        }
482
483 8
        $request = new Request('POST', 'pins/', $params);
484
485 8
        return $this->fetchPin($request);
486
    }
487
488
    /**
489
     * Delete a Pin.
490
     *
491
     * @param string $pinId The id of the pin to delete.
492
     *
493
     * @return Response
494
     */
495 8 View Code Duplication
    public function deletePin($pinId)
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...
496
    {
497 8
        if (empty($pinId)) {
498
            throw new InvalidArgumentException('The pin id should not be empty.');
499
        }
500
501 8
        $request = new Request('DELETE', sprintf('pins/%d/', $pinId));
502
503 8
        return $this->execute($request);
504
    }
505
506
    /**
507
     * Get the next items for a paged list.
508
     *
509
     * @param PagedList $pagedList
510
     *
511
     * @return Response
512
     */
513
    public function getNextItems(PagedList $pagedList)
514
    {
515
        if (!$pagedList->hasNext()) {
516
            throw new InvalidArgumentException('The list has no more items');
517
        }
518
519
        $items = $pagedList->items();
520
521
        if (empty($items)) {
522
            throw new InvalidArgumentException(
523
                'Unable to detect object type because the list contains no items'
524
            );
525
        }
526
527
        $item = reset($items);
528
        $objectClassName = get_class($item);
529
        $objectInstance = new $objectClassName();
530
531
        $request = $this->buildRequestForPagedList($pagedList);
532
533
        return $this->execute($request, function (Response $response) use ($objectInstance) {
534
            $mapper = new Mapper($objectInstance);
535
536
            return $mapper->toList($response);
537
        });
538
    }
539
540
    /**
541
     * Build a request to get the next items of a paged list.
542
     *
543
     * @param PagedList $pagedList
544
     *
545
     * @return Request
546
     */
547
    private function buildRequestForPagedList(PagedList $pagedList)
548
    {
549
        $nextItemsUri = $pagedList->getNextUrl();
550
551
        if (strpos($nextItemsUri, Authentication::BASE_URI) !== 0) {
552
            throw new InvalidArgumentException(
553
                'The paged list has an invalid uri'
554
            );
555
        }
556
557
        $params = array();
558
        $components = parse_url($nextItemsUri);
559
        parse_str($components['query'], $params);
560
561
        $path = $components['path'];
562
        $versionPath = '/v1/';
563
        $versionPathLength = strlen($versionPath);
564
        $path = substr($path, $versionPathLength);
565
566
        return new Request('GET', $path, $params);
0 ignored issues
show
Bug introduced by
It seems like $params can also be of type null; however, Pinterest\Http\Request::__construct() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
567
    }
568
}
569