Completed
Push — master ( 76c0f1...a16dbf )
by Christian
01:43
created

AbstractApi::createHttpClient()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 1
ccs 0
cts 0
cp 0
c 0
b 0
f 0
nc 1
1
<?php
2
3
/*
4
 * This file is part of the XabbuhPandaClient package.
5
 *
6
 * (c) Christian Flothmann <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Xabbuh\PandaClient;
13
14
use Xabbuh\PandaClient\Api\Account;
15
16
/**
17
 * Definition of an algorithm that needs to be implemented to bootstrap an API
18
 * instance.
19
 *
20
 * A concrete implementation must provide implementations for the factory methods
21
 * specified by this AbstractApi. One factory for each of the components used by
22
 * this API must be implemented. The library provides a {@link Api default Api}.
23
 * Custom Api implementations can be built to replace any component with a custom
24
 * implementation.
25
 *
26
 * Basically, the user constructs an Api object by passing a config array to
27
 * its constructor. This configuration should look like this:
28
 *
29
 * - accounts:
30
 *   - an identifier
31
 *     - access_key: your access key
32
 *     - secret_key: your secret key
33
 *     - api_host: the API host to use
34
 * - clouds:
35
 *   - an identifier
36
 *     - id: your cloud id
37
 *     - account: one of your account identifiers as configured above
38
 *
39
 * A sample config can look like this:
40
 *
41
 * <code>
42
 * $config = array(
43
 *     'accounts' => array(
44
 *         'default' => array(
45
 *             'access_key' => ...,
46
 *             'secret_key' => ...,
47
 *             'api_host'   => 'api.pandastream.com',
48
 *         ),
49
 *     ),
50
 *     'clouds' => array(
51
 *         'default' => array(
52
 *             'id'      => ...,
53
 *             'account' => 'default',
54
 *         ),
55
 *     ),
56
 * );
57
 * </code>
58
 *
59
 * @author Christian Flothmann <[email protected]>
60
 */
61
abstract class AbstractApi
62
{
63
    /**
64
     * @var \Xabbuh\PandaClient\Transformer\TransformerRegistryInterface
65
     */
66
    protected $transformers;
67
68
    /**
69
     * @var \Xabbuh\PandaClient\Api\AccountManagerInterface
70
     */
71
    protected $accountManager;
72
73
    /**
74
     * @var \Xabbuh\PandaClient\Api\CloudManagerInterface
75
     */
76
    protected $cloudManager;
77
78 8
    final public function __construct(array $config)
79
    {
80
        // create the transformation layer
81 8
        $this->transformers = $this->createTransformerRegistry();
82 8
        $this->transformers->setCloudTransformer($this->createCloudTransformer());
83 8
        $this->transformers->setEncodingTransformer($this->createEncodingTransformer());
84 8
        $this->transformers->setNotificationsTransformer($this->createNotificationsTransformer());
85 8
        $this->transformers->setProfileTransformer($this->createProfileTransformer());
86 8
        $this->transformers->setVideoTransformer($this->createVideoTransformer());
87
88
        // register the accounts
89 8
        $this->accountManager = $this->createAccountManager();
90 8
        $this->accountManager->setDefaultAccount(
91 8
            isset($config['default_account']) ? $config['default_account'] : 'default'
92
        );
93 8
        $this->processAccountConfig($config);
94
95
        // register the clouds
96 7
        $this->cloudManager = $this->createCloudManager();
97 7
        $this->cloudManager->setDefaultCloud(
98 7
            isset($config['default_cloud']) ? $config['default_cloud'] : 'default'
99
        );
100 7
        $this->processCloudConfig($config);
101 5
    }
102
103
    /**
104
     * @param array $config
105
     *
106
     * @throws \InvalidArgumentException
107
     */
108 8
    protected function processAccountConfig(array $config)
109
    {
110 8
        if (!isset($config['accounts']) || !is_array($config['accounts'])) {
111 1
            throw new \InvalidArgumentException('No account configuration given.');
112
        }
113
114 7
        foreach ($config['accounts'] as $name => $accountConfig) {
115 7
            $this->validateMandatoryOptions($accountConfig, 'account', $name, array('access_key', 'secret_key', 'api_host'));
116
117 7
            $this->accountManager->registerAccount(
118
                $name,
119 7
                $this->createAccount(
120 7
                    $accountConfig['access_key'],
121 7
                    $accountConfig['secret_key'],
122 7
                    $accountConfig['api_host']
123
                )
124
            );
125
        }
126 7
    }
127
128
    /**
129
     * @param array $config
130
     *
131
     * @throws \InvalidArgumentException
132
     */
133 7
    protected function processCloudConfig(array $config)
134
    {
135 7
        if (!isset($config['clouds']) || !is_array($config['clouds'])) {
136 1
            throw new \InvalidArgumentException('No cloud configuration given.');
137
        }
138
139 6
        foreach ($config['clouds'] as $name => $cloudConfig) {
140 6
            $this->validateMandatoryOptions($cloudConfig, 'cloud', $name, array('id', 'account'));
141
142
            try {
143 5
                $account = $this->accountManager->getAccount($cloudConfig['account']);
144
            } catch (\InvalidArgumentException $e) {
145
                throw new \InvalidArgumentException(
146
                    sprintf('Invalid account %s for cloud %s', $name, $cloudConfig['account'])
147
                );
148
            }
149
150 5
            $httpClient = $this->createHttpClient($account, $cloudConfig['id']);
151 5
            $cloud = $this->createCloud();
152 5
            $cloud->setHttpClient($httpClient);
153 5
            $cloud->setTransformers($this->transformers);
154 5
            $this->cloudManager->registerCloud($name, $cloud);
155
        }
156 5
    }
157
158
    /**
159
     * Creates the {@link AccountManager} that manages the configured accounts.
160
     *
161
     * @return \Xabbuh\PandaClient\Api\AccountManagerInterface
162
     */
163
    abstract protected function createAccountManager();
164
165
    /**
166
     * Creates an {@link Account} for the given configuration.
167
     *
168
     * @param string $accessKey The access key
169
     * @param string $secretKey The secret key
170
     * @param string $apiHost   The API host
171
     *
172
     * @return \Xabbuh\PandaClient\Api\Account The created account
173
     */
174 7
    protected function createAccount($accessKey, $secretKey, $apiHost)
175
    {
176 7
        return new Account($accessKey, $secretKey, $apiHost);
177
    }
178
179
    /**
180
     * Creates the {@link CloudManager} that manages the configured clouds.
181
     *
182
     * @return \Xabbuh\PandaClient\Api\CloudManagerInterface
183
     */
184
    abstract protected function createCloudManager();
185
186
    /**
187
     * Creates the {@link HttpClientInterface HttpClient} that performs the HTTP
188
     * requests.
189
     *
190
     * @param Account $account Account authentication data
191
     * @param string  $cloudId Id of the cloud to access
192
     *
193
     * @return \Xabbuh\PandaClient\Api\HttpClientInterface
194
     */
195
    abstract protected function createHttpClient(Account $account, $cloudId);
196
197
    /**
198
     * Creates a {@link Cloud} instances that maps Panda API REST endpoints to
199
     * method calls.
200
     *
201
     * @return \Xabbuh\PandaClient\Api\CloudInterface
202
     */
203
    abstract protected function createCloud();
204
205
    /**
206
     * Creates the {@link TransformerRegistryInterface registry} that manages
207
     * the keeps track of the different transformers.
208
     *
209
     * @return \Xabbuh\PandaClient\Transformer\TransformerRegistryInterface
210
     */
211
    abstract protected function createTransformerRegistry();
212
213
    /**
214
     * Creates a transformer that transforms between the native API format and
215
     * {@link Cloud} instances an vice versa.
216
     *
217
     * @return \Xabbuh\PandaClient\Transformer\CloudTransformerInterface
218
     */
219
    abstract protected function createCloudTransformer();
220
221
    /**
222
     * Creates a transformer that transforms between the native API format and
223
     * {@link Encoding} instances an vice versa.
224
     *
225
     * @return \Xabbuh\PandaClient\Transformer\EncodingTransformerInterface
226
     */
227
    abstract protected function createEncodingTransformer();
228
229
    /**
230
     * Creates a transformer that transforms between the native API format and
231
     * {@link Notifications} instances an vice versa.
232
     *
233
     * @return \Xabbuh\PandaClient\Transformer\NotificationsTransformerInterface
234
     */
235
    abstract protected function createNotificationsTransformer();
236
237
    /**
238
     * Creates a transformer that transforms between the native API format and
239
     * {@link Profile} instances an vice versa.
240
     *
241
     * @return \Xabbuh\PandaClient\Transformer\ProfileTransformerInterface
242
     */
243
    abstract protected function createProfileTransformer();
244
245
    /**
246
     * Creates a transformer that transforms between the native API format and
247
     * {@link Video} instances an vice versa.
248
     *
249
     * @return \Xabbuh\PandaClient\Transformer\VideoTransformerInterface
250
     */
251
    abstract protected function createVideoTransformer();
252
253
    /**
254
     * Returns the created {@link AccountManagerInterface AccountManager}.
255
     *
256
     * @return \Xabbuh\PandaClient\Api\AccountManagerInterface
257
     */
258 2
    public function getAccountManager()
259
    {
260 2
        return $this->accountManager;
261
    }
262
263
    /**
264
     * Returns the created {@link CloudManagerInterface CloudManager}.
265
     *
266
     * @return \Xabbuh\PandaClient\Api\CloudManagerInterface
267
     */
268 2
    public function getCloudManager()
269
    {
270 2
        return $this->cloudManager;
271
    }
272
273
    /**
274
     * Returns a {@link Cloud} by its configured name.
275
     *
276
     * @param string $name The configured name of the Cloud
277
     *
278
     * @return \Xabbuh\PandaClient\Api\CloudInterface
279
     */
280 2
    public function getCloud($name)
281
    {
282 2
        return $this->cloudManager->getCloud($name);
283
    }
284
285
    /**
286
     * Creates a cloud.
287
     *
288
     * @param string $accessKey The access key
289
     * @param string $secretKey The secret key
290
     * @param string $apiHost   The api host
291
     * @param string $cloudId   The cloud id
292
     *
293
     * @return \Xabbuh\PandaClient\Api\CloudInterface The cloud
294
     */
295
    public static function getCloudInstance($accessKey, $secretKey, $apiHost, $cloudId)
296
    {
297
        $config = array(
298
            'accounts' => array(
299
                'default' => array(
300
                    'access_key' => $accessKey,
301
                    'secret_key' => $secretKey,
302
                    'api_host' => $apiHost,
303
                ),
304
            ),
305
            'clouds' => array(
306
                'default' => array(
307
                    'id' => $cloudId,
308
                    'account' => 'default',
309
                )
310
            ),
311
        );
312
313
        /** @var \Xabbuh\PandaClient\AbstractApi $api */
314
        $api = new static($config);
315
316
        return $api->getCloud('default');
317
    }
318
319 7
    private function validateMandatoryOptions(array $config, $section, $name, array $options)
320
    {
321 7
        foreach ($options as $option) {
322 7
            if (!isset($config[$option])) {
323 1
                throw new \InvalidArgumentException(
324 7
                    sprintf('Missing option %s for %s %s', $option, $section, $name)
325
                );
326
            }
327
        }
328 7
    }
329
}
330