Passed
Pull Request — master (#89)
by
unknown
22:08
created

AbstractApiClient::getChannel()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MovingImage\Client\VMPro\ApiClient;
6
7
use Doctrine\Common\Collections\ArrayCollection;
8
use MovingImage\Client\VMPro\Collection\ChannelCollection;
9
use MovingImage\Client\VMPro\Collection\VideoCollection;
10
use MovingImage\Client\VMPro\Entity\Attachment;
11
use MovingImage\Client\VMPro\Entity\Channel;
12
use MovingImage\Client\VMPro\Entity\ChannelsRequestParameters;
13
use MovingImage\Client\VMPro\Entity\CorporateTubeMetaData;
14
use MovingImage\Client\VMPro\Entity\EmbedCode;
15
use MovingImage\Client\VMPro\Entity\Keyword;
16
use MovingImage\Client\VMPro\Entity\Player;
17
use MovingImage\Client\VMPro\Entity\Thumbnail;
18
use MovingImage\Client\VMPro\Entity\Transcode;
19
use MovingImage\Client\VMPro\Entity\UserInfo;
20
use MovingImage\Client\VMPro\Entity\Video;
21
use MovingImage\Client\VMPro\Entity\VideoDownloadUrl;
22
use MovingImage\Client\VMPro\Entity\VideoManager;
23
use MovingImage\Client\VMPro\Entity\VideoRequestParameters;
24
use MovingImage\Client\VMPro\Entity\VideosRequestParameters;
25
use MovingImage\Client\VMPro\Exception\NotFoundException;
26
use MovingImage\Client\VMPro\Interfaces\ApiClientInterface;
27
use MovingImage\Client\VMPro\Util\ChannelTrait;
28
use MovingImage\Client\VMPro\Util\Logging\Traits\LoggerAwareTrait;
29
use MovingImage\Client\VMPro\Util\SearchEndpointTrait;
30
use MovingImage\Meta\Interfaces\ThumbnailInterface;
31
32
abstract class AbstractApiClient extends AbstractCoreApiClient implements ApiClientInterface
33
{
34
    use LoggerAwareTrait;
35
    use SearchEndpointTrait;
36
    use ChannelTrait;
37
38
    /**
39
     * @throws \Exception
40
     */
41
    public function getChannels(int $videoManagerId): Channel
42
    {
43
        $response = $this->makeRequest('GET', 'channels', [
44
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
45
        ]);
46
47
        $rootChannel = $this->deserialize($response->getBody()->getContents(), Channel::class);
48
        $rootChannel->setChildren($this->sortChannels($rootChannel->getChildren()));
49
50
        return $rootChannel;
51
    }
52
53
    public function getChannel(int $videoManagerId, int $channelId): Channel
54
    {
55
        $channel = $this->findChannel($this->getChannels($videoManagerId), $channelId);
56
57
        if (!$channel instanceof Channel) {
58
            throw new NotFoundException('channel not found');
59
        }
60
61
        return $channel;
62
    }
63
64
    private function findChannel(Channel $rootChannel, int $channelId): ?Channel
65
    {
66
        if ($rootChannel->getId() === $channelId) {
67
            return $rootChannel;
68
        }
69
70
        foreach ($rootChannel->getChildren() as $child) {
71
            $foundChannel = $this->findChannel($child, $channelId);
72
            if ($foundChannel instanceof Channel) {
73
                return $foundChannel;
74
            }
75
        }
76
77
        return null;
78
    }
79
80
    /**
81
     * Since the VMPro API doesn't sort any more the returned channels, we have to do it on our side.
82
     *
83
     * @throws \Exception
84
     */
85
    protected function sortChannels(ArrayCollection $channels)
86
    {
87
        $channels->map(function ($channel) {
88
            $channel->setChildren($this->sortChannels($channel->getChildren()));
89
        });
90
91
        $iterator = $channels->getIterator();
92
        $iterator->uasort(function ($a, $b) {
93
            /* @var Channel $a */
94
            /* @var Channel $b */
95
            return $a->getName() > $b->getName();
96
        });
97
98
        return new ArrayCollection(iterator_to_array($iterator));
99
    }
100
101
    public function createVideo(
102
        int $videoManagerId,
103
        string $fileName,
104
        ?string $title = '',
105
        ?string $description = '',
106
        ?int $channel = null,
107
        ?string $group = null,
108
        ?array $keywords = [],
109
        ?bool $autoPublish = null,
110
        ?int $ownerGroupId = null
111
    ): string {
112
        $response = $this->makeRequest('POST', 'videos', [
113
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
114
            'json' => $this->buildJsonParameters(
115
                compact('fileName'), // Required parameters
116
                compact(
117
                    'title',
118
                    'description',
119
                    'channel',
120
                    'group',
121
                    'keywords',
122
                    'autoPublish',
123
                    'ownerGroupId'
124
                ) // Optional parameters
125
            ),
126
        ]);
127
128
        $videoLocation = $response->getHeader('location')[0];
129
130
        $pieces = explode('/', $videoLocation);
131
132
        return end($pieces);
133
    }
134
135
    public function getVideos(int $videoManagerId, ?VideosRequestParameters $parameters = null): ArrayCollection
136
    {
137
        $options = [
138
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
139
        ];
140
141
        if ($parameters) {
142
            $query = http_build_query($parameters->getContainer(), '', '&', PHP_QUERY_RFC3986);
143
            $options['query'] = preg_replace('/%5B[0-9]+%5D/simU', '%5B%5D', $query);
144
            $options['query'] = str_replace('channel_id%5B%5D', 'channel_id', $options['query']);
145
        }
146
147
        $response = $this->makeRequest('GET', 'videos', $options);
148
        $response = json_encode(json_decode($response->getBody()->getContents(), true)['videos']);
149
150
        return $this->deserialize($response, 'ArrayCollection<'.Video::class.'>');
151
    }
152
153
    public function getCount(int $videoManagerId, ?VideosRequestParameters $parameters = null): int
154
    {
155
        $options = [
156
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
157
        ];
158
159
        if ($parameters) {
160
            $query = http_build_query($parameters->getContainer(), '', '&', PHP_QUERY_RFC3986);
161
            $options['query'] = preg_replace('/%5B[0-9]+%5D/simU', '%5B%5D', $query);
162
            $options['query'] = str_replace('channel_id%5B%5D', 'channel_id', $options['query']);
163
        }
164
165
        $response = $this->makeRequest('GET', 'videos', $options);
166
167
        return json_decode($response->getBody()->getContents(), true)['total'];
168
    }
169
170
    public function getVideoUploadUrl(int $videoManagerId, string $videoId): string
171
    {
172
        $response = $this->makeRequest('GET', sprintf('videos/%s/url', $videoId), [
173
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
174
        ]);
175
176
        return $response->getHeader('location')[0];
177
    }
178
179
    public function updateVideo(
180
        int $videoManagerId,
181
        string $videoId,
182
        string $title,
183
        string $description,
184
        ?bool $autoPublish = null
185
    ): void {
186
        $this->makeRequest('PATCH', sprintf('videos/%s', $videoId), [
187
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
188
            'json' => $this->buildJsonParameters([], compact('title', 'description', 'autoPublish')),
189
        ]);
190
    }
191
192
    public function addVideoToChannel(int $videoManagerId, string $videoId, int $channelId): void
193
    {
194
        $this->makeRequest('POST', sprintf('channels/%u/videos/%s', $channelId, $videoId), [
195
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
196
        ]);
197
    }
198
199
    public function removeVideoFromChannel(int $videoManagerId, string $videoId, int $channelId): void
200
    {
201
        $this->makeRequest('DELETE', sprintf('channels/%u/videos/%s', $channelId, $videoId), [
202
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
203
        ]);
204
    }
205
206
    public function setCustomMetaData(int $videoManagerId, string $videoId, array $metadata): void
207
    {
208
        $this->makeRequest('PATCH', sprintf('videos/%s/metadata', $videoId), [
209
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
210
            'json' => $metadata,
211
        ]);
212
    }
213
214
    public function getEmbedCode(
215
        int $videoManagerId,
216
        string $videoId,
217
        string $playerDefinitionId,
218
        string $embedType = 'html'
219
    ): EmbedCode {
220
        $url = sprintf(
221
            'videos/%s/embed-codes?player_definition_id=%s&embed_type=%s',
222
            $videoId,
223
            $playerDefinitionId,
224
            $embedType
225
        );
226
227
        if ($this->cacheTtl) {
228
            $url = sprintf('%s&token_lifetime_in_seconds=%s', $url, $this->cacheTtl);
229
        }
230
231
        $response = $this->makeRequest('GET', $url, [self::OPT_VIDEO_MANAGER_ID => $videoManagerId]);
232
233
        $data = \json_decode($response->getBody()->getContents(), true);
234
        $embedCode = new EmbedCode();
235
        $embedCode->setCode($data['embedCode']);
236
237
        return $embedCode;
238
    }
239
240
    public function deleteVideo(int $videoManagerId, string $videoId): void
241
    {
242
        $this->makeRequest('DELETE', sprintf('videos/%s', $videoId), [
243
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
244
        ]);
245
    }
246
247
    public function getVideo(int $videoManagerId, string $videoId, ?VideoRequestParameters $parameters = null): Video
248
    {
249
        $options = [
250
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
251
        ];
252
253
        if ($parameters) {
254
            $options['query'] = $parameters->getContainer();
255
        }
256
257
        $response = $this->makeRequest(
258
            'GET',
259
            sprintf('videos/%s', $videoId),
260
            $options
261
        );
262
263
        return $this->deserialize($response->getBody()->getContents(), Video::class);
264
    }
265
266
    /**
267
     * {@inheritdoc}
268
     */
269
    public function getAttachments(int $videoManagerId, string $videoId): ArrayCollection
270
    {
271
        $response = $this->makeRequest(
272
            'GET',
273
            sprintf('videos/%s/attachments', $videoId),
274
            [self::OPT_VIDEO_MANAGER_ID => $videoManagerId]
275
        );
276
277
        $response = $this->normalizeGetAttachmentsResponse($response->getBody()->getContents());
278
279
        return $this->deserialize($response, 'ArrayCollection<'.Attachment::class.'>');
280
    }
281
282
    /**
283
     * {@inheritdoc}
284
     */
285
    public function getChannelAttachments(int $videoManagerId, int $channelId): ArrayCollection
286
    {
287
        $response = $this->makeRequest(
288
            'GET',
289
            sprintf('channels/%u/attachments', $channelId),
290
            [self::OPT_VIDEO_MANAGER_ID => $videoManagerId]
291
        );
292
293
        $response = $this->normalizeGetAttachmentsResponse($response->getBody()->getContents());
294
295
        return $this->deserialize($response, 'ArrayCollection<'.Attachment::class.'>');
296
    }
297
298
    /**
299
     * {@inheritdoc}
300
     */
301
    public function getKeywords(int $videoManagerId, ?string $videoId): ArrayCollection
302
    {
303
        $uri = is_null($videoId)
304
            ? 'keyword/find'
305
            : sprintf('videos/%s/keywords', $videoId);
306
307
        $response = $this->makeRequest(
308
            'GET',
309
            $uri,
310
            [self::OPT_VIDEO_MANAGER_ID => $videoManagerId]
311
        );
312
313
        return $this->deserialize($response->getBody()->getContents(), 'ArrayCollection<'.Keyword::class.'>');
314
    }
315
316
    public function updateKeywords(int $videoManagerId, string $videoId, array $keywords): void
317
    {
318
        //remove all keywords
319
        foreach ($this->getKeywords($videoManagerId, $videoId) as $keyword) {
320
            $this->deleteKeyword($videoManagerId, $videoId, $keyword->getId());
321
        }
322
323
        //add new
324
        foreach ($keywords as $keyword) {
325
            $this->makeRequest('POST', sprintf('videos/%s/keywords', $videoId), [
326
                self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
327
                'json' => ['text' => $keyword],
328
            ]);
329
        }
330
    }
331
332
    public function deleteKeyword(int $videoManagerId, string $videoId, int $keywordId): void
333
    {
334
        $this->makeRequest('DELETE', sprintf('videos/%s/keywords/%s', $videoId, $keywordId), [
335
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
336
        ]);
337
    }
338
339
    public function searchVideos(
340
        int $videoManagerId,
341
        ?VideosRequestParameters $parameters = null,
342
        ?string $searchQuery = null
343
    ): VideoCollection {
344
        $options = $this->getRequestOptionsForSearchVideosEndpoint($videoManagerId, $parameters);
345
        if ($searchQuery) {
346
            $options['query'] = sprintf('(%s) AND (%s)', $options['query'], $searchQuery);
347
        }
348
        $response = $this->makeRequest('POST', 'search', ['json' => $options]);
349
        $response = $this->normalizeSearchVideosResponse($response->getBody()->getContents());
350
351
        return $this->deserialize($response, VideoCollection::class);
352
    }
353
354
    public function searchChannels(
355
        int $videoManagerId,
356
        ?ChannelsRequestParameters $parameters = null
357
    ): ChannelCollection {
358
        $options = $this->getRequestOptionsForSearchChannelsEndpoint($videoManagerId, $parameters);
359
        $response = $this->makeRequest('POST', 'search', ['json' => $options]);
360
        $response = $this->normalizeSearchChannelsResponse($response->getBody()->getContents());
361
        /** @var ChannelCollection $collection */
362
        $collection = $this->deserialize($response, ChannelCollection::class);
363
364
        //builds parent/children relations on all channels
365
        $channels = $this->setChannelRelations($collection->getChannels());
366
        $collection->setChannels($channels);
367
368
        return $collection;
369
    }
370
371
    /**
372
     * {@inheritdoc}
373
     */
374
    public function getVideoManagers(): ArrayCollection
375
    {
376
        $response = $this->makeRequest('GET', '', []);
377
378
        return $this->deserialize($response->getBody()->getContents(), 'ArrayCollection<'.VideoManager::class.'>');
379
    }
380
381
    /**
382
     * {@inheritdoc}
383
     */
384
    public function getVideoDownloadUrls(int $videoManagerId, string $videoId): ArrayCollection
385
    {
386
        $options = [
387
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
388
        ];
389
390
        $response = $this->makeRequest(
391
            'GET',
392
            sprintf('videos/%s/download-urls', $videoId),
393
            $options
394
        );
395
396
        return $this->deserialize($response->getBody()->getContents(), 'ArrayCollection<'.VideoDownloadUrl::class.'>');
397
    }
398
399
    public function createThumbnailByTimestamp(int $videoManagerId, string $videoId, int $timestamp): ?ThumbnailInterface
400
    {
401
        $options = [
402
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
403
        ];
404
405
        $response = $this->makeRequest(
406
            'POST',
407
            'videos/'.$videoId.'/thumbnails?timestamp='.$timestamp,
408
            $options
409
        );
410
411
        if (preg_match('/\/thumbnails\/([0-9]*)/', $response->getHeader('Location')[0], $match)) {
412
            return (new Thumbnail())->setId(intval($match[1]));
413
        }
414
415
        return null;
416
    }
417
418
    public function getThumbnail(int $videoManagerId, string $videoId, int $thumbnailId): ?ThumbnailInterface
419
    {
420
        $options = [
421
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
422
        ];
423
424
        $response = $this->makeRequest(
425
            'GET',
426
            'videos/'.$videoId.'/thumbnails/'.$thumbnailId.'/url',
427
            $options
428
        );
429
430
        $result = \json_decode($response->getBody()->getContents(), true);
431
432
        if (isset($result['downloadUrl'])) {
433
            return (new Thumbnail())
434
                ->setId($thumbnailId)
435
                ->setUrl($result['downloadUrl']);
436
        }
437
438
        return null;
439
    }
440
441
    public function updateThumbnail(int $videoManagerId, string $videoId, int $thumbnailId, bool $active): void
442
    {
443
        $options = [
444
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
445
            'json' => ['active' => $active],
446
        ];
447
448
        $this->makeRequest(
449
            'PATCH',
450
            'videos/'.$videoId.'/thumbnails/'.$thumbnailId,
451
            $options
452
        );
453
    }
454
455
    public function getUserInfo(string $token): UserInfo
456
    {
457
        $options = [
458
            'body' => json_encode(['jwt_id_token' => $token]),
459
            'headers' => [
460
                'Content-Type' => 'application/json',
461
            ],
462
        ];
463
464
        $response = $this->makeRequest('POST', 'corp-tube-admin/user-info', $options);
465
466
        /** @var UserInfo $userInfo */
467
        $userInfo = $this->deserialize($response->getBody()->getContents(), UserInfo::class);
468
469
        $userInfo->validate();
470
471
        return $userInfo;
472
    }
473
474
    /**
475
     * {@inheritdoc}
476
     */
477
    public function getTranscodingStatus(int $videoManagerId, string $videoId): ArrayCollection
478
    {
479
        $options = [
480
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
481
        ];
482
483
        $response = $this->makeRequest(
484
            'GET',
485
            'videos/'.$videoId.'/transcoding-status',
486
            $options
487
        );
488
489
        $response = $response->getBody()->getContents();
490
491
        return $this->deserialize($response, 'ArrayCollection<'.Transcode::class.'>');
492
    }
493
494
    public function getPlayers(int $videoManagerId): ArrayCollection
495
    {
496
        $options = [self::OPT_VIDEO_MANAGER_ID => $videoManagerId];
497
498
        $response = $this->makeRequest(
499
            'GET',
500
            'players',
501
            $options
502
        );
503
504
        $response = $response->getBody()->getContents();
505
506
        return $this->deserialize($response, 'ArrayCollection<'.Player::class.'>');
507
    }
508
509
    public function getCorporateTubeMetadata(int $videoManagerId, string $videoId): CorporateTubeMetaData
510
    {
511
        $options = [
512
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
513
        ];
514
515
        $response = $this->makeRequest(
516
            'GET',
517
            'videos/'.$videoId.'/metadata/corporate-tube',
518
            $options
519
        );
520
521
        return $this->deserialize($response->getBody()->getContents(), CorporateTubeMetaData::class);
522
    }
523
524
    public function updateCorporateTubeMetadata(
525
        int $videoManagerId,
526
        string $videoId,
527
        CorporateTubeMetaData $corporateTubeMetaData
528
    ): void {
529
530
        $fields = [
531
            'uploaderUserId' => $corporateTubeMetaData->getUploaderUserId(),
532
            'inChargeUserId' => $corporateTubeMetaData->getInChargeUserId(),
533
        ];
534
535
        if ($corporateTubeMetaData->getUploadDate()) {
536
            $fields['uploadDate'] = $corporateTubeMetaData->getUploadDate()->format('c');
537
        }
538
539
        $options = [
540
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
541
            'json' => $fields
542
        ];
543
544
        $this->makeRequest(
545
            'PATCH',
546
            'videos/'.$videoId.'/metadata/corporate-tube',
547
            $options
548
        );
549
    }
550
}
551