Completed
Push — master ( 7d3761...62ec31 )
by Jérémy
03:30
created

Client::createV3()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace JDecool\Clubhouse;
6
7
use Http\Client\Common\HttpMethodsClient;
8
use JDecool\Clubhouse\{
9
    Exception\ClubhouseException,
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, JDecool\Clubhouse\ClubhouseException. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
10
    Exception\ResourceNotExist,
11
    Exception\SchemaMismatch,
12
    Exception\TooManyRequest,
13
    Exception\Unprocessable
14
};
15
use Psr\Http\Message\ResponseInterface;
16
use RuntimeException;
17
18
class Client
19
{
20
    private const ENDPOINT_V1 = 'https://api.clubhouse.io/api/v1';
21
    private const ENDPOINT_V2 = 'https://api.clubhouse.io/api/v2';
22
    private const ENDPOINT_V3 = 'https://api.clubhouse.io/api/v3';
23
    private const ENDPOINT_BETA = 'https://api.clubhouse.io/api/beta';
24
25
    private $http;
26
    private $baseUri;
27
    private $token;
28
29
    public static function createV1(HttpMethodsClient $http, string $token): self
30
    {
31
        return new self($http, self::ENDPOINT_V1, $token);
32
    }
33
34
    public static function createV2(HttpMethodsClient $http, string $token): self
35
    {
36
        return new self($http, self::ENDPOINT_V2, $token);
37
    }
38
39
    public static function createV3(HttpMethodsClient $http, string $token): self
40
    {
41
        return new self($http, self::ENDPOINT_V3, $token);
42
    }
43
44
    public static function createBeta(HttpMethodsClient $http, string $token): self
45
    {
46
        return new self($http, self::ENDPOINT_BETA, $token);
47
    }
48
49
    public function __construct(HttpMethodsClient $http, string $baseUri, string $token)
50
    {
51
        if (false === filter_var($baseUri, FILTER_VALIDATE_URL)) {
52
            throw new RuntimeException('Invalid Clubouse base URI.');
53
        }
54
55
        if ('' === trim($token)) {
56
            throw new RuntimeException('API token is required.');
57
        }
58
59
        $this->http = $http;
60
        $this->baseUri = $baseUri;
61
        $this->token = $token;
62
    }
63
64
    public function get(string $uri): array
65
    {
66
        $response = $this->http->get(
67
            $this->endpoint($uri)
68
        );
69
70
        if (200 !== $response->getStatusCode()) {
71
            throw $this->createExceptionFromResponse($response);
72
        }
73
74
        return json_decode($response->getBody()->getContents(), true);
75
    }
76
77
    public function post(string $uri, array $data): array
78
    {
79
        $response = $this->http->post(
80
            $this->endpoint($uri),
81
            ['Content-Type' => 'application/json'],
82
            json_encode($data)
83
        );
84
85
        if (201 !== $response->getStatusCode()) {
86
            throw $this->createExceptionFromResponse($response);
87
        }
88
89
        return json_decode($response->getBody()->getContents(), true);
90
    }
91
92
    public function put(string $uri, array $data): array
93
    {
94
        $response = $this->http->put(
95
            $this->endpoint($uri),
96
            ['Content-Type' => 'application/json'],
97
            json_encode($data)
98
        );
99
100
        if (200 !== $response->getStatusCode()) {
101
            throw $this->createExceptionFromResponse($response);
102
        }
103
104
        return json_decode($response->getBody()->getContents(), true);
105
    }
106
107
    public function delete(string $uri): void
108
    {
109
        $response = $this->http->delete(
110
            $this->endpoint($uri)
111
        );
112
113
        if (204 !== $response->getStatusCode()) {
114
            throw $this->createExceptionFromResponse($response);
115
        }
116
    }
117
118
    private function endpoint(string $uri): string
119
    {
120
        return sprintf(
121
            '%s/%s?token=%s',
122
            rtrim($this->baseUri, '/'),
123
            ltrim($uri, '/'),
124
            $this->token
125
        );
126
    }
127
128
    private function createExceptionFromResponse(ResponseInterface $response): ClubhouseException
129
    {
130
        $content = json_decode($response->getBody()->getContents(), true);
131
        $message = $content['message'] ?? 'An error occured.';
132
133
        switch ($response->getStatusCode()) {
134
            case 400:
135
                return new SchemaMismatch($message);
136
137
            case 404:
138
                return new ResourceNotExist($message);
139
140
            case 422:
141
                return new Unprocessable($message);
142
143
            case 429:
144
                return new TooManyRequest($message);
145
        }
146
147
        return new ClubhouseException($message);
148
    }
149
}
150