Passed
Pull Request — master (#89)
by
unknown
23:39
created

AbstractApiClient::updateThumbnail()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

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