Completed
Pull Request — master (#15)
by Mischa
05:52 queued 17s
created

ContentApiSdk::getProtocol()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
/**
4
 * This file is part of the PHP SDK library for the Superdesk Content API.
5
 *
6
 * Copyright 2015 Sourcefabric z.u. and contributors.
7
 *
8
 * For the full copyright and license information, please see the
9
 * AUTHORS and LICENSE files distributed with this source code.
10
 *
11
 * @copyright 2015 Sourcefabric z.ú.
12
 * @license http://www.superdesk.org/license
13
 */
14
15
namespace Superdesk\ContentApiSdk;
16
17
use Superdesk\ContentApiSdk\API\Request;
18
use Superdesk\ContentApiSdk\API\Response;
19
use Superdesk\ContentApiSdk\API\Pagerfanta\ItemAdapter;
20
use Superdesk\ContentApiSdk\API\Pagerfanta\PackageAdapter;
21
use Superdesk\ContentApiSdk\API\Pagerfanta\ResourceCollection;
22
use Superdesk\ContentApiSdk\Client\ApiClientInterface;
23
use Superdesk\ContentApiSdk\Data\Item;
24
use Superdesk\ContentApiSdk\Data\Package;
25
use Superdesk\ContentApiSdk\Exception\ClientException;
26
use Superdesk\ContentApiSdk\Exception\ContentApiException;
27
use Superdesk\ContentApiSdk\Exception\InvalidArgumentException;
28
use Superdesk\ContentApiSdk\Exception\InvalidDataException;
29
use Exception;
30
use stdClass;
31
32
/**
33
 * Superdesk ContentApi class.
34
 */
35
class ContentApiSdk
36
{
37
    /**
38
     * Items endpoint
39
     */
40
    const SUPERDESK_ENDPOINT_ITEMS = '/items';
41
42
    /**
43
     * Package endpoint
44
     */
45
    const SUPERDESK_ENDPOINT_PACKAGES = '/packages';
46
47
    /**
48
     * Type indication for packages
49
     */
50
    const PACKAGE_TYPE_COMPOSITE = 'composite';
51
52
    /**
53
     * Supported API version by this SDK version
54
     */
55
    const API_VERSION = 1;
56
57
    /**
58
     * Useragent string sent to the API when making requests.
59
     */
60
    const USERAGENT = 'Content API SDK v1';
61
62
    /**
63
     * Any (http) client that implements ClientInterface.
64
     *
65
     * @var ApiClientInterface
66
     */
67
    protected $client;
68
69
    /**
70
     * Protocol to reach the api instance.
71
     *
72
     * @var string|null
73
     */
74
    protected $protocol = null;
75
76
    /**
77
     * Hostname of the api instance.
78
     *
79
     * @var string|null
80
     */
81
    protected $host = null;
82
83
    /**
84
     * Port of the api instance.
85
     *
86
     * @var int|null
87
     */
88
    protected $port = null;
89
90
    /**
91
     * Authentication object.
92
     *
93
     * @var AuthenticationInterface
94
     */
95
    protected $authentication = null;
96
97
    /**
98
     * Construct method for class.
99
     *
100
     * @param ApiClientInterface $client
101
     * @param string|null $host
102
     * @param int|null $port
103
     * @param string|null $protocol
104
     */
105
    public function __construct(
106
        ApiClientInterface $client,
107
        $host = null,
108
        $port = null,
109
        $protocol = null
110
    ) {
111
        $this->client = $client;
112
113
        if (!is_null($host)) {
114
            $this->setHost($host);
115
        }
116
117
        if (!is_null($port)) {
118
            $this->setPort($port);
119
        }
120
121
        if (!is_null($protocol)) {
122
            $this->setProtocol($protocol);
123
        }
124
    }
125
126
    /**
127
     * Gets the value of client.
128
     *
129
     * @return ApiClientInterface
130
     */
131
    public function getClient()
132
    {
133
        return $this->client;
134
    }
135
136
    /**
137
     * Sets the value of client.
138
     *
139
     * @param ApiClientInterface $client Value to set
140
     *
141
     * @return self
142
     */
143
    public function setClient(ApiClientInterface $client)
144
    {
145
        $this->client = $client;
146
147
        return $this;
148
    }
149
150
    /**
151
     * Gets the value of apiHost.
152
     *
153
     * @return string|null
154
     */
155
    public function getHost()
156
    {
157
        return $this->host;
158
    }
159
160
    /**
161
     * Sets the value of host.
162
     *
163
     * @param string|null $host Value to set
164
     *
165
     * @return self
166
     */
167
    public function setHost($host)
168
    {
169
        $this->host = $host;
170
171
        return $this;
172
    }
173
174
    /**
175
     * Gets the value of port.
176
     *
177
     * @return int|null
178
     */
179
    public function getPort()
180
    {
181
        return $this->port;
182
    }
183
184
    /**
185
     * Sets the value of port.
186
     *
187
     * @param int|null $port Value to set
188
     *
189
     * @return self
190
     */
191
    public function setPort($port)
192
    {
193
        $this->port = $port;
194
195
        return $this;
196
    }
197
198
    /**
199
     * Gets the value of protocol.
200
     *
201
     * @return string|null
202
     */
203
    public function getProtocol()
204
    {
205
        return $this->protocol;
206
    }
207
208
    /**
209
     * Sets the value of protocol.
210
     *
211
     * @param string|null $protocol Value to set
212
     *
213
     * @return self
214
     */
215
    public function setProtocol($protocol)
216
    {
217
        $this->protocol = $protocol;
218
219
        return $this;
220
    }
221
222
    /**
223
     * Get a single item via id.
224
     *
225
     * @param string $itemId Identifier for item
226
     *
227
     * @return Item
228
     */
229
    public function getItem($itemId)
230
    {
231
        $request = $this->getNewRequest(sprintf('%s/%s', self::SUPERDESK_ENDPOINT_ITEMS, $itemId));
232
233
        try {
234
            $response = $this->client->makeApiCall($request);
235
            $item = new Item($response->getResources());
236
237
            return $item;
238
        } catch (ClientException $e) {
239
            throw new ContentApiException($e->getMessage(), $e->getCode(), $e);
240
        }
241
    }
242
243
    /**
244
     * Get multiple items based on a filter.
245
     *
246
     * @param array $params Filter parameters
247
     *
248
     * @return ResourceCollection
249
     */
250 View Code Duplication
    public function getItems($params)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
251
    {
252
        $itemCollection = new ResourceCollection(
253
            new ItemAdapter(
254
                $this->client,
255
                $this->getNewRequest(self::SUPERDESK_ENDPOINT_ITEMS, $params)
256
            )
257
        );
258
259
        $page = (isset($params['page'])) ? $params['page'] : 1;
260
        $maxResults = (isset($params['max_results'])) ? $params['max_results'] : 25;
261
262
        $itemCollection->setCurrentPage($page);
263
        $itemCollection->setMaxPerPage($maxResults);
264
265
        return $itemCollection;
266
    }
267
268
    /**
269
     * Get package by identifier.
270
     *
271
     * @param string $packageId Package identifier
272
     * @param bool   $resolveAssociations Inject full associations recursively
273
     *                                    instead of references by uri.
274
     *
275
     * @return Package
276
     */
277
    public function getPackage($packageId, $resolveAssociations = false)
278
    {
279
        $request = $this->getNewRequest(sprintf('%s/%s', self::SUPERDESK_ENDPOINT_PACKAGES, $packageId));
280
        $response = $this->client->makeApiCall($request);
281
282
        $package = new Package($response->getResources());
283
284
        // This can be removed once the API fully supports retrieving package associations
285
        if ($resolveAssociations) {
286
            $associations = $this->getAssociationsFromPackage($package);
287
            $package = $this->injectAssociations($package, $associations);
288
        }
289
290
        return $package;
291
    }
292
293
    /**
294
     * Get multiple packages based on a filter.
295
     *
296
     * @param array $params Filter parameters
297
     * @param bool  $resolveAssociations Inject full associations recursively
298
     *                                   instead of references by uri.
299
     *
300
     * @return ResourceCollection
301
     */
302 View Code Duplication
    public function getPackages($params, $resolveAssociations = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
303
    {
304
        $packageCollection = new ResourceCollection(
305
            new PackageAdapter(
306
                $this->client,
307
                $this->getNewRequest(self::SUPERDESK_ENDPOINT_PACKAGES, $params),
308
                $this,
309
                $resolveAssociations
310
            )
311
        );
312
313
        // TODO: Check if we actually need these 5 lines of code
314
        $page = (isset($params['page'])) ? $params['page'] : 1;
315
        $maxResults = (isset($params['max_results'])) ? $params['max_results'] : 25;
316
317
        $packageCollection->setCurrentPage($page);
318
        $packageCollection->setMaxPerPage($maxResults);
319
320
        return $packageCollection;
321
    }
322
323
    /**
324
     * Gets full objects for all associations for a package.
325
     *
326
     * @param Package $package A package
327
     *
328
     * @return stdClass List of associations
329
     */
330
    public function getAssociationsFromPackage(Package $package)
331
    {
332
        $associations = new stdClass();
333
334
        if (isset($package->associations)) {
335
            foreach ($package->associations as $associationGroupName => $associationGroupItems) {
336
337
                $groupAssociations = new stdClass();
338
339
                foreach ($associationGroupItems AS $associatedName => $associatedItem) {
340
                    $associatedId = $this->getIdFromUri($associatedItem->uri);
341
342
                    try {
343
                        if ($associatedItem->type == self::PACKAGE_TYPE_COMPOSITE) {
344
                            $associatedObj = $this->getPackage($associatedId, true);
345
                        } else {
346
                            $associatedObj = $this->getItem($associatedId);
347
                            $associatedObj->type = $associatedItem->type;
348
                        }
349
                    } catch (ContentApiException $e) {
350
                        // If subrequests fail, dont fail main request
351
                    }
352
353
                    $groupAssociations->$associatedName = $associatedObj;
354
                }
355
356
                $associations->$associationGroupName = $groupAssociations;
357
            }
358
        }
359
360
        return $associations;
361
    }
362
363
    /**
364
     * Overwrite the associations links in a packages with the actual association
365
     * data.
366
     *
367
     * @param Package  $package      Package
368
     * @param stdClass $associations Multiple items or packages
369
     *
370
     * @return Package Package with data injected
371
     */
372
    public function injectAssociations(Package $package, stdClass $associations)
373
    {
374
        if (count($package->associations) > 0 && count($associations) > 0) {
375
            $package->associations = $associations;
376
        }
377
378
        return $package;
379
    }
380
381
    /**
382
     * Shortcut method to create new class.
383
     *
384
     * @param  string $uri Uri of the request
385
     * @param  array $parameters Parameters for the request object
386
     *
387
     * @return Request
388
     */
389
    public function getNewRequest($uri, array $parameters = array())
390
    {
391
        try {
392
            $request = new Request($this->host, $uri, $parameters, $this->port, $this->protocol);
393
        } catch (ContentApiException $e) {
394
            throw new ContentApiException($e->getMessage(), $e->getCode(), $e);
395
        }
396
397
        return $request;
398
    }
399
400
    /**
401
     * Tries to find a valid id in an uri, both item as package uris. The id
402
     * is returned urldecoded.
403
     *
404
     * @param string $uri Item or package uri
405
     *
406
     * @return string Urldecoded id
407
     */
408
    public static function getIdFromUri($uri)
409
    {
410
        /*
411
         * Works for package and item uris
412
         *   http://publicapi:5050/packages/tag%3Ademodata.org%2C0012%3Aninjs_XYZ123
413
         *   http://publicapi:5050/items/tag%3Ademodata.org%2C0003%3Aninjs_XYZ123
414
         */
415
416
        $uriPath = parse_url($uri, PHP_URL_PATH);
417
        $objectId = str_replace(self::getAvailableEndpoints(), '', $uriPath);
418
        // Remove possible slashes and spaces, since we're working with urls
419
        $objectId = trim($objectId, '/ ');
420
        $objectId = urldecode($objectId);
421
422
        return $objectId;
423
    }
424
425
    /**
426
     * Returns a list of all supported endpoints for the Superdesk Content API.
427
     *
428
     * @return string[]
429
     */
430
    public static function getAvailableEndpoints()
431
    {
432
        return array(
433
            self::SUPERDESK_ENDPOINT_ITEMS,
434
            self::SUPERDESK_ENDPOINT_PACKAGES,
435
        );
436
    }
437
438
    /**
439
     * Converts json string into StdClass object. Throws an InvalidDataException
440
     * when string could not be converted to object.
441
     *
442
     * @param string $jsonString JSON string
443
     *
444
     * @return object
445
     * @throws Exception|InvalidDataException
446
     */
447
    public static function getValidJsonObj($jsonString)
448
    {
449
        $jsonObj = json_decode($jsonString);
450
        if (is_null($jsonObj) || json_last_error() !== JSON_ERROR_NONE) {
451
            throw new InvalidDataException('Response body is not (valid) json.', json_last_error());
452
        }
453
454
        return $jsonObj;
455
    }
456
457
    /**
458
     * Returns version of api for creating verioned url.
459
     *
460
     * @return string
461
     */
462
    public static function getVersionURL()
463
    {
464
        return sprintf('v%d', self::API_VERSION);
465
    }
466
}
467