1 | <?php declare(strict_types=1); |
||
14 | class IteratePagesService |
||
15 | { |
||
16 | /** |
||
17 | * @var RequestService |
||
18 | */ |
||
19 | private $requestService; |
||
20 | |||
21 | /** |
||
22 | * @var AsyncSchedulerInterface |
||
23 | */ |
||
24 | private $scheduler; |
||
25 | |||
26 | /** |
||
27 | * @param RequestService $requestService |
||
28 | * @param AsyncSchedulerInterface $scheduler |
||
29 | */ |
||
30 | 1 | public function __construct(RequestService $requestService, AsyncSchedulerInterface $scheduler = null) |
|
31 | { |
||
32 | 1 | $this->scheduler = $scheduler ?: Scheduler::getAsync(); |
|
33 | 1 | $this->requestService = $requestService; |
|
34 | 1 | } |
|
35 | |||
36 | 1 | public function iterate(string $path): Observable |
|
37 | { |
||
38 | 1 | $paths = new Subject(); |
|
39 | |||
40 | 1 | return Observable::of($path, $this->scheduler) |
|
41 | 1 | ->merge($paths) |
|
42 | 1 | ->flatMap(function ($path) { |
|
43 | 1 | return Observable::fromPromise($this->requestService->request(new Request('GET', $path))); |
|
44 | 1 | }) |
|
45 | 1 | ->do(function (ResponseInterface $response) use ($paths) { |
|
46 | 1 | if (!$response->hasHeader('link')) { |
|
47 | $paths->onCompleted(); |
||
48 | |||
49 | return; |
||
50 | } |
||
51 | |||
52 | 1 | $parsedLinks = parseLinks($response->getHeaderLine('link')); |
|
53 | $links = [ |
||
54 | 1 | 'next' => $parsedLinks->getByRel('next'), |
|
55 | 1 | 'last' => $parsedLinks->getByRel('last'), |
|
56 | ]; |
||
57 | |||
58 | 1 | if ($links['next'] === null || $links['last'] === null) { |
|
59 | 1 | $paths->onCompleted(); |
|
60 | |||
61 | 1 | return; |
|
62 | } |
||
63 | |||
64 | 1 | $this->scheduler->schedule(function () use ($paths, $links) { |
|
65 | 1 | $paths->onNext($links['next']->getUri()); |
|
66 | 1 | }); |
|
67 | 1 | }) |
|
68 | 1 | ->map(function (ResponseInterface $response) { |
|
69 | 1 | return $response->getBody()->getParsedContents(); |
|
|
|||
70 | 1 | }); |
|
71 | } |
||
72 | |||
73 | private function sendRequest(string $path, Subject $subject) |
||
87 | |||
88 | private function handleResponse( |
||
89 | ResponseInterface $response, |
||
118 | } |
||
119 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the interface: