Issues (7)

Client.php (7 issues)

1
<?php
2
3
namespace SchulIT\IdpExchange;
4
5
use GuzzleHttp\Client as GuzzleClient;
6
use GuzzleHttp\Exception\GuzzleException;
7
use JMS\Serializer\DeserializationContext;
8
use JMS\Serializer\SerializationContext;
9
use JMS\Serializer\SerializerInterface;
10
use Psr\Log\LoggerInterface;
11
use Psr\Log\NullLogger;
12
use SchulIT\IdpExchange\Request\Builder\UpdatedUsersRequestBuilder;
13
use SchulIT\IdpExchange\Request\Builder\UserRequestBuilder;
14
use SchulIT\IdpExchange\Request\Builder\UsersRequestBuilder;
15
use SchulIT\IdpExchange\Response\UpdatedUsersResponse;
16
use SchulIT\IdpExchange\Response\UserResponse;
17
use SchulIT\IdpExchange\Response\UsersResponse;
18
19
class Client {
20
    private const TOKEN_HEADER = 'X-Token';
21
    private const UPDATED_USERS_ENDPOINT = '/exchange/updated_users';
22
    private const USERS_ENDPOINT = '/exchange/users';
23
    private const USER_ENDPOINT = '/exchange/user';
24
25
    private $endpoint;
26
    private $token;
27
    private $guzzle;
28
    private $serializer;
29
    private $logger;
30
31 12
    public function __construct(string $endpoint, string $token, GuzzleClient $guzzle, SerializerInterface $serializer, LoggerInterface $logger = null) {
32 12
        $this->endpoint = $endpoint;
33 12
        $this->token = $token;
34 12
        $this->guzzle = $guzzle;
35 12
        $this->serializer = $serializer;
36 12
        $this->logger = $logger ?? new NullLogger();
37 12
    }
38
39
    /**
40
     * @param $request
41
     * @param string $endpoint
42
     * @return mixed|\Psr\Http\Message\ResponseInterface
43
     * @throws ClientException
44
     * @throws GuzzleException
45
     */
46 12
    private function request($request, string $endpoint) {
47 12
        $context = (new SerializationContext())
48 12
            ->setSerializeNull(true);
49
50 12
        $jsonBody = $this->serializer->serialize($request, 'json', $context);
51
52 12
        $response = $this->guzzle->request('POST', $this->getEndpointFor($endpoint), [
53
            'headers' => [
54 12
                static::TOKEN_HEADER => $this->token
55
            ],
56 12
            'accept' => 'application/json',
57 12
            'body' => $jsonBody
58
        ]);
59
60 6
        if($response->getStatusCode() !== 200) {
61 3
            $this->logger->debug(sprintf('Request failed with response code %d', $response->getStatusCode()), [
62 3
                'response' => $response->getBody()->getContents()
63
            ]);
64
65 3
            throw new ClientException(sprintf('Request failed with response code %d', $response->getStatusCode()));
66
        }
67
68 3
        return $response;
69
    }
70
71
    /**
72
     * @param string $json
73
     * @param string $type
74
     * @return array|\JMS\Serializer\scalar|mixed|object
0 ignored issues
show
The type JMS\Serializer\scalar was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
75
     */
76 3
    private function deserialize(string $json, string $type) {
77 3
        $object = $this->serializer->deserialize($json, $type, 'json');
78 3
        return $object;
79
    }
80
81 12
    private function getEndpointFor(string $endpoint): string {
82 12
        return sprintf('%s%s', $this->endpoint, $endpoint);
83
    }
84
85
    /**
86
     * @param string[] $users
87
     * @param \DateTime $since
88
     * @return UpdatedUsersResponse
89
     * @throws ClientException
90
     */
91 4
    public function getUpdatedUsers(array $users, \DateTime $since): UpdatedUsersResponse {
92 4
        $this->logger->debug('getUpdatedUsers() started');
93
94
        try {
95 4
            $request = (new UpdatedUsersRequestBuilder())
96 4
                ->addUsers($users)
97 4
                ->since($since)
98 4
                ->build();
99
100 4
            $response = $this->request($request, static::UPDATED_USERS_ENDPOINT);
101
102 1
            return $this->deserialize($response->getBody()->getContents(), UpdatedUsersResponse::class);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->deserializ...edUsersResponse::class) could return the type array which is incompatible with the type-hinted return SchulIT\IdpExchange\Response\UpdatedUsersResponse. Consider adding an additional type-check to rule them out.
Loading history...
103 3
        } catch (GuzzleException $e) {
104 2
            $this->logger->error('Request failed with exception', [
105 2
                'exception' => $e
106
            ]);
107
108 2
            throw new ClientException($e->getMessage(), $e->getCode(), $e);
109
        } finally {
110 4
            $this->logger->debug('getUpdatedUsers() finished');
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return SchulIT\IdpExchange\Response\UpdatedUsersResponse. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
111
        }
112
    }
113
114
    /**
115
     * @param string[] $users
116
     * @return UsersResponse
117
     * @throws ClientException
118
     */
119 4
    public function getUsers(array $users): UsersResponse {
120 4
        $this->logger->debug('getUsers() started');
121
122
        try {
123 4
            $request = (new UsersRequestBuilder())
124 4
                ->addUsers($users)
125 4
                ->build();
126
127 4
            $response = $this->request($request, static::USERS_ENDPOINT);
128
129 1
            return $this->deserialize($response->getBody()->getContents(), UsersResponse::class);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->deserializ...e\UsersResponse::class) could return the type array which is incompatible with the type-hinted return SchulIT\IdpExchange\Response\UsersResponse. Consider adding an additional type-check to rule them out.
Loading history...
130 3
        } catch (GuzzleException $e) {
131 2
            $this->logger->error('Request failed with exception', [
132 2
                'exception' => $e
133
            ]);
134
135 2
            throw new ClientException($e->getMessage(), $e->getCode(), $e);
136
        } finally {
137 4
            $this->logger->debug('getUsers() finished');
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return SchulIT\IdpExchange\Response\UsersResponse. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
138
        }
139
    }
140
141
    /**
142
     * @param string $username
143
     * @return UserResponse
144
     * @throws ClientException
145
     */
146 4
    public function getUser(string $username): UserResponse {
147 4
        $this->logger->debug('getUser() started');
148
149
        try {
150 4
            $request = (new UserRequestBuilder())
151 4
                ->setUsername($username)
152 4
                ->build();
153
154 4
            $response = $this->request($request, static::USER_ENDPOINT);
155
156 1
            return $this->deserialize($response->getBody()->getContents(), UserResponse::class);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->deserializ...se\UserResponse::class) could return the type array which is incompatible with the type-hinted return SchulIT\IdpExchange\Response\UserResponse. Consider adding an additional type-check to rule them out.
Loading history...
157 3
        } catch (GuzzleException $e) {
158 2
            $this->logger->error('Request failed with exception', [
159 2
                'exception' => $e
160
            ]);
161
162 2
            throw new ClientException($e->getMessage(), $e->getCode(), $e);
163
        } finally {
164 4
            $this->logger->debug('getUser() finished');
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return SchulIT\IdpExchange\Response\UserResponse. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
165
        }
166
    }
167
}