ApiConnector   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 176
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 37
c 0
b 0
f 0
dl 0
loc 176
ccs 37
cts 37
cp 1
rs 10
wmc 12

7 Methods

Rating   Name   Duplication   Size   Complexity  
A updateResource() 0 27 4
A createRequest() 0 5 1
A createUri() 0 5 1
A setOption() 0 5 1
A getOption() 0 3 1
A createAuthorizationHeader() 0 11 3
A __construct() 0 12 1
1
<?php declare(strict_types=1);
2
3
namespace BabDev\Transifex;
4
5
use BabDev\Transifex\Exception\InvalidFileTypeException;
6
use BabDev\Transifex\Exception\MissingCredentialsException;
7
use BabDev\Transifex\Exception\MissingFileException;
8
use Psr\Http\Client\ClientInterface;
9
use Psr\Http\Message\RequestFactoryInterface;
10
use Psr\Http\Message\RequestInterface;
11
use Psr\Http\Message\ResponseInterface;
12
use Psr\Http\Message\StreamFactoryInterface;
13
use Psr\Http\Message\UriFactoryInterface;
14
use Psr\Http\Message\UriInterface;
15
16
/**
17
 * Base API connector class.
18
 */
19
abstract class ApiConnector
20
{
21
    /**
22
     * The HTTP client.
23
     *
24
     * @var ClientInterface
25
     */
26
    protected $client;
27
28
    /**
29
     * The request factory.
30
     *
31
     * @var RequestFactoryInterface
32
     */
33
    protected $requestFactory;
34
35
    /**
36
     * The stream factory.
37
     *
38
     * @var StreamFactoryInterface
39
     */
40
    protected $streamFactory;
41
42
    /**
43
     * The URI factory.
44
     *
45
     * @var UriFactoryInterface
46
     */
47
    protected $uriFactory;
48
49
    /**
50
     * Options for the Transifex object.
51
     *
52
     * @var array
53
     */
54
    protected $options;
55
56
    /**
57
     * @param ClientInterface         $client         The HTTP client
58
     * @param RequestFactoryInterface $requestFactory The request factory
59
     * @param StreamFactoryInterface  $streamFactory  The stream factory
60
     * @param UriFactoryInterface     $uriFactory     The URI factory
61
     * @param array                   $options        Transifex options array
62
     */
63 92
    public function __construct(
64
        ClientInterface $client,
65
        RequestFactoryInterface $requestFactory,
66
        StreamFactoryInterface $streamFactory,
67
        UriFactoryInterface $uriFactory,
68
        array $options = []
69
    ) {
70 92
        $this->client         = $client;
71 92
        $this->requestFactory = $requestFactory;
72 92
        $this->streamFactory  = $streamFactory;
73 92
        $this->uriFactory     = $uriFactory;
74 92
        $this->options        = $options;
75 92
    }
76
77
    /**
78
     * Creates the Authorization header for the request
79
     *
80
     * @return string
81
     *
82
     * @throws MissingCredentialsException if credentials are not set
83
     */
84 79
    protected function createAuthorizationHeader(): string
85
    {
86 79
        $username = $this->getOption('api.username');
87 79
        $password = $this->getOption('api.password');
88
89
        // The API requires HTTP Basic Authentication, we can't proceed without credentials
90 79
        if ($username === null || $password === null) {
91 1
            throw new MissingCredentialsException('Missing credentials for API authentication.');
92
        }
93
94 78
        return 'Basic ' . \base64_encode("$username:$password");
95
    }
96
97
    /**
98
     * Create a Request object for the given URI
99
     *
100
     * This method will also set the Authorization header for the request
101
     *
102
     * @param string       $method
103
     * @param UriInterface $uri
104
     *
105
     * @return RequestInterface
106
     */
107 79
    protected function createRequest(string $method, UriInterface $uri): RequestInterface
108
    {
109 79
        $request = $this->requestFactory->createRequest($method, $uri);
110
111 79
        return $request->withHeader('Authorization', $this->createAuthorizationHeader());
112
    }
113
114
    /**
115
     * Create a Uri object for the path
116
     *
117
     * @param string $path
118
     *
119
     * @return UriInterface
120
     */
121 81
    protected function createUri(string $path): UriInterface
122
    {
123 81
        $baseUrl = $this->getOption('base_uri', 'https://www.transifex.com');
124
125 81
        return $this->uriFactory->createUri($baseUrl . $path);
126
    }
127
128
    /**
129
     * Get an option from the options store.
130
     *
131
     * @param string $key     The name of the option to get
132
     * @param mixed  $default The default value if the option is not set
133
     *
134
     * @return mixed The option value
135
     */
136 81
    protected function getOption(string $key, $default = null)
137
    {
138 81
        return $this->options[$key] ?? $default;
139
    }
140
141
    /**
142
     * Set an option for the Transifex instance.
143
     *
144
     * @param string $key   The name of the option to set
145
     * @param mixed  $value The option value to set
146
     *
147
     * @return $this
148
     */
149 6
    protected function setOption(string $key, $value): self
150
    {
151 6
        $this->options[$key] = $value;
152
153 6
        return $this;
154
    }
155
156
    /**
157
     * Update an API endpoint with resource content.
158
     *
159
     * @param UriInterface $uri     URI object representing the API path to request
160
     * @param string       $content The content of the resource, this can either be a string of data or a file path
161
     * @param string       $type    The type of content in the $content variable, this should be either string or file
162
     *
163
     * @return ResponseInterface
164
     *
165
     * @throws InvalidFileTypeException
166
     * @throws MissingFileException
167
     */
168 10
    protected function updateResource(UriInterface $uri, string $content, string $type): ResponseInterface
169
    {
170
        // Verify the content type is allowed
171 10
        if (!\in_array($type, ['string', 'file'])) {
172 2
            throw new InvalidFileTypeException('The content type must be specified as file or string.');
173
        }
174
175 8
        $request = $this->createRequest('PUT', $uri);
176 8
        $request = $request->withHeader('Content-Type', 'application/json');
177
178 8
        if ($type == 'file') {
179 4
            if (!\file_exists($content)) {
180 2
                throw new MissingFileException(
181 2
                    \sprintf('The specified file, "%s", does not exist.', $content)
182
                );
183
            }
184
185 2
            $request = $request->withBody($this->streamFactory->createStreamFromFile($content));
186
        } else {
187
            $data = [
188 4
                'content' => $content,
189
            ];
190
191 4
            $request = $request->withBody($this->streamFactory->createStream(\json_encode($data)));
192
        }
193
194 6
        return $this->client->sendRequest($request);
195
    }
196
}
197