Passed
Push — master ( 10f591...07b5ce )
by
unknown
22:43
created

AbstractApiClient::getKeywords()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.7998
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
    ): string {
111
        $response = $this->makeRequest('POST', 'videos', [
112
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
113
            'json' => $this->buildJsonParameters(
114
                compact('fileName'), // Required parameters
115
                compact(
116
                    'title',
117
                    'description',
118
                    'channel',
119
                    'group',
120
                    'keywords',
121
                    'autoPublish'
122
                ) // Optional parameters
123
            ),
124
        ]);
125
126
        $videoLocation = $response->getHeader('location')[0];
127
128
        $pieces = explode('/', $videoLocation);
129
130
        return end($pieces);
131
    }
132
133
    public function getVideos(int $videoManagerId, ?VideosRequestParameters $parameters = null): ArrayCollection
134
    {
135
        $options = [
136
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
137
        ];
138
139
        if ($parameters) {
140
            $query = http_build_query($parameters->getContainer(), '', '&', PHP_QUERY_RFC3986);
141
            $options['query'] = preg_replace('/%5B[0-9]+%5D/simU', '%5B%5D', $query);
142
            $options['query'] = str_replace('channel_id%5B%5D', 'channel_id', $options['query']);
143
        }
144
145
        $response = $this->makeRequest('GET', 'videos', $options);
146
        $response = json_encode(json_decode($response->getBody()->getContents(), true)['videos']);
147
148
        return $this->deserialize($response, 'ArrayCollection<'.Video::class.'>');
149
    }
150
151
    public function getCount(int $videoManagerId, ?VideosRequestParameters $parameters = null): int
152
    {
153
        $options = [
154
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
155
        ];
156
157
        if ($parameters) {
158
            $query = http_build_query($parameters->getContainer(), '', '&', PHP_QUERY_RFC3986);
159
            $options['query'] = preg_replace('/%5B[0-9]+%5D/simU', '%5B%5D', $query);
160
            $options['query'] = str_replace('channel_id%5B%5D', 'channel_id', $options['query']);
161
        }
162
163
        $response = $this->makeRequest('GET', 'videos', $options);
164
165
        return json_decode($response->getBody()->getContents(), true)['total'];
166
    }
167
168
    public function getVideoUploadUrl(int $videoManagerId, string $videoId): string
169
    {
170
        $response = $this->makeRequest('GET', sprintf('videos/%s/url', $videoId), [
171
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
172
        ]);
173
174
        return $response->getHeader('location')[0];
175
    }
176
177
    public function updateVideo(
178
        int $videoManagerId,
179
        string $videoId,
180
        string $title,
181
        string $description,
182
        ?bool $autoPublish = null
183
    ): void {
184
        $this->makeRequest('PATCH', sprintf('videos/%s', $videoId), [
185
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
186
            'json' => $this->buildJsonParameters([], compact('title', 'description', 'autoPublish')),
187
        ]);
188
    }
189
190
    public function addVideoToChannel(int $videoManagerId, string $videoId, int $channelId): void
191
    {
192
        $this->makeRequest('POST', sprintf('channels/%u/videos/%s', $channelId, $videoId), [
193
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
194
        ]);
195
    }
196
197
    public function removeVideoFromChannel(int $videoManagerId, string $videoId, int $channelId): void
198
    {
199
        $this->makeRequest('DELETE', sprintf('channels/%u/videos/%s', $channelId, $videoId), [
200
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
201
        ]);
202
    }
203
204
    public function setCustomMetaData(int $videoManagerId, string $videoId, array $metadata): void
205
    {
206
        $this->makeRequest('PATCH', sprintf('videos/%s/metadata', $videoId), [
207
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
208
            'json' => $metadata,
209
        ]);
210
    }
211
212
    public function getEmbedCode(
213
        int $videoManagerId,
214
        string $videoId,
215
        string $playerDefinitionId,
216
        string $embedType = 'html'
217
    ): EmbedCode {
218
        $url = sprintf(
219
            'videos/%s/embed-codes?player_definition_id=%s&embed_type=%s',
220
            $videoId,
221
            $playerDefinitionId,
222
            $embedType
223
        );
224
225
        if ($this->cacheTtl) {
226
            $url = sprintf('%s&token_lifetime_in_seconds=%s', $url, $this->cacheTtl);
227
        }
228
229
        $response = $this->makeRequest('GET', $url, [self::OPT_VIDEO_MANAGER_ID => $videoManagerId]);
230
231
        $data = \json_decode($response->getBody()->getContents(), true);
232
        $embedCode = new EmbedCode();
233
        $embedCode->setCode($data['embedCode']);
234
235
        return $embedCode;
236
    }
237
238
    public function deleteVideo(int $videoManagerId, string $videoId): void
239
    {
240
        $this->makeRequest('DELETE', sprintf('videos/%s', $videoId), [
241
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
242
        ]);
243
    }
244
245
    public function getVideo(int $videoManagerId, string $videoId, ?VideoRequestParameters $parameters = null): Video
246
    {
247
        $options = [
248
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
249
        ];
250
251
        if ($parameters) {
252
            $options['query'] = $parameters->getContainer();
253
        }
254
255
        $response = $this->makeRequest(
256
            'GET',
257
            sprintf('videos/%s', $videoId),
258
            $options
259
        );
260
261
        return $this->deserialize($response->getBody()->getContents(), Video::class);
262
    }
263
264
    /**
265
     * {@inheritdoc}
266
     */
267
    public function getAttachments(int $videoManagerId, string $videoId): ArrayCollection
268
    {
269
        $response = $this->makeRequest(
270
            'GET',
271
            sprintf('videos/%s/attachments', $videoId),
272
            [self::OPT_VIDEO_MANAGER_ID => $videoManagerId]
273
        );
274
275
        $response = $this->normalizeGetAttachmentsResponse($response->getBody()->getContents());
276
277
        return $this->deserialize($response, 'ArrayCollection<'.Attachment::class.'>');
278
    }
279
280
    /**
281
     * {@inheritdoc}
282
     */
283
    public function getChannelAttachments(int $videoManagerId, int $channelId): ArrayCollection
284
    {
285
        $response = $this->makeRequest(
286
            'GET',
287
            sprintf('channels/%u/attachments', $channelId),
288
            [self::OPT_VIDEO_MANAGER_ID => $videoManagerId]
289
        );
290
291
        $response = $this->normalizeGetAttachmentsResponse($response->getBody()->getContents());
292
293
        return $this->deserialize($response, 'ArrayCollection<'.Attachment::class.'>');
294
    }
295
296
    /**
297
     * {@inheritdoc}
298
     */
299
    public function getKeywords(int $videoManagerId, ?string $videoId): ArrayCollection
300
    {
301
        $uri = is_null($videoId)
302
            ? 'keyword/find'
303
            : sprintf('videos/%s/keywords', $videoId);
304
305
        $response = $this->makeRequest(
306
            'GET',
307
            $uri,
308
            [self::OPT_VIDEO_MANAGER_ID => $videoManagerId]
309
        );
310
311
        return $this->deserialize($response->getBody()->getContents(), 'ArrayCollection<'.Keyword::class.'>');
312
    }
313
314
    public function updateKeywords(int $videoManagerId, string $videoId, array $keywords): void
315
    {
316
        //remove all keywords
317
        foreach ($this->getKeywords($videoManagerId, $videoId) as $keyword) {
318
            $this->deleteKeyword($videoManagerId, $videoId, $keyword->getId());
319
        }
320
321
        //add new
322
        foreach ($keywords as $keyword) {
323
            $this->makeRequest('POST', sprintf('videos/%s/keywords', $videoId), [
324
                self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
325
                'json' => ['text' => $keyword],
326
            ]);
327
        }
328
    }
329
330
    public function deleteKeyword(int $videoManagerId, string $videoId, int $keywordId): void
331
    {
332
        $this->makeRequest('DELETE', sprintf('videos/%s/keywords/%s', $videoId, $keywordId), [
333
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
334
        ]);
335
    }
336
337
    public function searchVideos(
338
        int $videoManagerId,
339
        ?VideosRequestParameters $parameters = null,
340
        ?string $searchQuery = null
341
    ): VideoCollection {
342
        $options = $this->getRequestOptionsForSearchVideosEndpoint($videoManagerId, $parameters);
343
        if ($searchQuery) {
344
            $options['query'] = sprintf('(%s) AND (%s)', $options['query'], $searchQuery);
345
        }
346
        $response = $this->makeRequest('POST', 'search', ['json' => $options]);
347
        $response = $this->normalizeSearchVideosResponse($response->getBody()->getContents());
348
349
        return $this->deserialize($response, VideoCollection::class);
350
    }
351
352
    public function searchChannels(
353
        int $videoManagerId,
354
        ?ChannelsRequestParameters $parameters = null
355
    ): ChannelCollection {
356
        $options = $this->getRequestOptionsForSearchChannelsEndpoint($videoManagerId, $parameters);
357
        $response = $this->makeRequest('POST', 'search', ['json' => $options]);
358
        $response = $this->normalizeSearchChannelsResponse($response->getBody()->getContents());
359
        /** @var ChannelCollection $collection */
360
        $collection = $this->deserialize($response, ChannelCollection::class);
361
362
        //builds parent/children relations on all channels
363
        $channels = $this->setChannelRelations($collection->getChannels());
364
        $collection->setChannels($channels);
365
366
        return $collection;
367
    }
368
369
    /**
370
     * {@inheritdoc}
371
     */
372
    public function getVideoManagers(): ArrayCollection
373
    {
374
        $response = $this->makeRequest('GET', '', []);
375
376
        return $this->deserialize($response->getBody()->getContents(), 'ArrayCollection<'.VideoManager::class.'>');
377
    }
378
379
    /**
380
     * {@inheritdoc}
381
     */
382
    public function getVideoDownloadUrls(int $videoManagerId, string $videoId): ArrayCollection
383
    {
384
        $options = [
385
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
386
        ];
387
388
        $response = $this->makeRequest(
389
            'GET',
390
            sprintf('videos/%s/download-urls', $videoId),
391
            $options
392
        );
393
394
        return $this->deserialize($response->getBody()->getContents(), 'ArrayCollection<'.VideoDownloadUrl::class.'>');
395
    }
396
397
    public function createThumbnailByTimestamp(int $videoManagerId, string $videoId, int $timestamp): ?ThumbnailInterface
398
    {
399
        $options = [
400
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
401
        ];
402
403
        $response = $this->makeRequest(
404
            'POST',
405
            'videos/'.$videoId.'/thumbnails?timestamp='.$timestamp,
406
            $options
407
        );
408
409
        if (preg_match('/\/thumbnails\/([0-9]*)/', $response->getHeader('Location')[0], $match)) {
410
            return (new Thumbnail())->setId(intval($match[1]));
411
        }
412
413
        return null;
414
    }
415
416
    public function getThumbnail(int $videoManagerId, string $videoId, int $thumbnailId): ?ThumbnailInterface
417
    {
418
        $options = [
419
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
420
        ];
421
422
        $response = $this->makeRequest(
423
            'GET',
424
            'videos/'.$videoId.'/thumbnails/'.$thumbnailId.'/url',
425
            $options
426
        );
427
428
        $result = \json_decode($response->getBody()->getContents(), true);
429
430
        if (isset($result['downloadUrl'])) {
431
            return (new Thumbnail())
432
                ->setId($thumbnailId)
433
                ->setUrl($result['downloadUrl']);
434
        }
435
436
        return null;
437
    }
438
439
    public function updateThumbnail(int $videoManagerId, string $videoId, int $thumbnailId, bool $active): void
440
    {
441
        $options = [
442
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
443
            'json' => ['active' => $active],
444
        ];
445
446
        $this->makeRequest(
447
            'PATCH',
448
            'videos/'.$videoId.'/thumbnails/'.$thumbnailId,
449
            $options
450
        );
451
    }
452
453
    public function getUserInfo(string $token): UserInfo
454
    {
455
        $options = [
456
            'body' => json_encode(['jwt_id_token' => $token]),
457
            'headers' => [
458
                'Content-Type' => 'application/json',
459
            ],
460
        ];
461
462
        $response = $this->makeRequest('POST', 'corp-tube-admin/user-info', $options);
463
464
        /** @var UserInfo $userInfo */
465
        $userInfo = $this->deserialize($response->getBody()->getContents(), UserInfo::class);
466
467
        $userInfo->validate();
468
469
        return $userInfo;
470
    }
471
472
    /**
473
     * {@inheritdoc}
474
     */
475
    public function getTranscodingStatus(int $videoManagerId, string $videoId): ArrayCollection
476
    {
477
        $options = [
478
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
479
        ];
480
481
        $response = $this->makeRequest(
482
            'GET',
483
            'videos/'.$videoId.'/transcoding-status',
484
            $options
485
        );
486
487
        $response = $response->getBody()->getContents();
488
489
        return $this->deserialize($response, 'ArrayCollection<'.Transcode::class.'>');
490
    }
491
492
    public function getPlayers(int $videoManagerId): ArrayCollection
493
    {
494
        $options = [self::OPT_VIDEO_MANAGER_ID => $videoManagerId];
495
496
        $response = $this->makeRequest(
497
            'GET',
498
            'players',
499
            $options
500
        );
501
502
        $response = $response->getBody()->getContents();
503
504
        return $this->deserialize($response, 'ArrayCollection<'.Player::class.'>');
505
    }
506
507
    public function getCorporateTubeMetadata(int $videoManagerId, string $videoId): CorporateTubeMetaData
508
    {
509
        $options = [
510
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
511
        ];
512
513
        $response = $this->makeRequest(
514
            'GET',
515
            'videos/'.$videoId.'/metadata/corporate-tube',
516
            $options
517
        );
518
519
        return $this->deserialize($response->getBody()->getContents(), CorporateTubeMetaData::class);
520
    }
521
522
    public function updateCorporateTubeMetadata(
523
        int $videoManagerId,
524
        string $videoId,
525
        CorporateTubeMetaData $corporateTubeMetaData
526
    ): void {
527
528
        $fields = [
529
            'uploaderUserId' => $corporateTubeMetaData->getUploaderUserId(),
530
            'inChargeUserId' => $corporateTubeMetaData->getInChargeUserId(),
531
        ];
532
533
        if ($corporateTubeMetaData->getUploadDate()) {
534
            $fields['uploadDate'] = $corporateTubeMetaData->getUploadDate()->format('c');
535
        }
536
537
        $options = [
538
            self::OPT_VIDEO_MANAGER_ID => $videoManagerId,
539
            'json' => $fields
540
        ];
541
542
        $this->makeRequest(
543
            'PATCH',
544
            'videos/'.$videoId.'/metadata/corporate-tube',
545
            $options
546
        );
547
    }
548
}
549