Skip to content

Commit 830b619

Browse files
Add support for FetchVideoSource in video overlays
1 parent e3ca9f4 commit 830b619

File tree

10 files changed

+149
-20
lines changed

10 files changed

+149
-20
lines changed

src/Transformation/Layer/BaseSourceQualifier.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ class BaseSourceQualifier extends BaseQualifier
2828
*/
2929
protected $sourceType;
3030

31+
/**
32+
* @var string $assetType The type of the asset.
33+
*/
34+
protected $assetType;
35+
3136
/**
3237
* @var string The stack position of the layer.
3338
*/
@@ -75,6 +80,20 @@ public function setStackPosition($stackPosition)
7580
return $this;
7681
}
7782

83+
/**
84+
* Sets the asset type.
85+
*
86+
* @param string $assetType The type of the asset.
87+
*
88+
* @return $this
89+
*/
90+
public function assetType($assetType)
91+
{
92+
$this->assetType = $assetType;
93+
94+
return $this;
95+
}
96+
7897
/**
7998
* Serializes to string.
8099
*
@@ -83,7 +102,8 @@ public function setStackPosition($stackPosition)
83102
public function __toString()
84103
{
85104
$sourceTypeStr = $this->sourceType ? "$this->sourceType:" : '';
105+
$assetTypeStr = $this->assetType && $this->assetType != "image" ? "$this->assetType:" : '';
86106

87-
return empty((string)$this->value) ? '' : "{$this->getSourceKey()}_{$sourceTypeStr}{$this->value}";
107+
return empty((string)$this->value) ? '' : "{$this->getSourceKey()}_$assetTypeStr$sourceTypeStr$this->value";
88108
}
89109
}

src/Transformation/Layer/FetchImageSource.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@
1010

1111
namespace Cloudinary\Transformation;
1212

13-
use Cloudinary\Asset\AssetDescriptor;
14-
use Cloudinary\Asset\BaseAsset;
15-
use Cloudinary\ClassUtils;
16-
1713
/**
1814
* Defines how to manipulate an image layer.
1915
*
@@ -36,12 +32,12 @@ public function setSource($source)
3632
{
3733

3834
if ($source instanceof BaseSourceQualifier) {
39-
$this->getSourceQualifier()->setQualifierValue($source->getValue());
35+
$this->getSourceQualifier()->fetchUrl($source->getValue());
4036

4137
return $this;
4238
}
4339

44-
$this->getSourceQualifier()->setQualifierValue((string)$source);
40+
$this->getSourceQualifier()->fetchUrl((string)$source);
4541

4642

4743
return $this;

src/Transformation/Layer/FetchSourceQualifier.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ public function __construct($fetchUrl)
4646
*/
4747
public function fetchUrl($fetchUrl)
4848
{
49+
if (StringUtils::contains($fetchUrl, ':fetch:')) {
50+
list($this->assetType, $this->sourceType, $fetchUrl) = explode(':', $fetchUrl, 3);
51+
}
52+
4953
$this->setQualifierValue(StringUtils::truncatePrefix($fetchUrl, 'fetch:'));
5054

5155
return $this;
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
/**
3+
* This file is part of the Cloudinary PHP package.
4+
*
5+
* (c) Cloudinary
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
namespace Cloudinary\Transformation;
12+
13+
use Cloudinary\ClassUtils;
14+
15+
/**
16+
* Defines how to manipulate a fetched video layer.
17+
*
18+
* **Learn more**: <a
19+
* href=https://cloudinary.com/documentation/video_layers#layer_transformations target="_blank">
20+
* Video overlays</a>
21+
*
22+
* @api
23+
*/
24+
class FetchVideoSource extends VideoSource
25+
{
26+
/**
27+
* VideoLayer constructor.
28+
*
29+
* @param $source
30+
*/
31+
public function __construct($source)
32+
{
33+
parent::__construct($source);
34+
35+
$this->setSource($source);
36+
}
37+
/**
38+
* Sets the source of the layer.
39+
*
40+
* @param string|FetchSourceQualifier $source The source.
41+
*
42+
* @return $this
43+
*/
44+
public function setSource($source)
45+
{
46+
47+
if ($source instanceof FetchSourceQualifier) {
48+
$this->getSourceQualifier()->fetchUrl($source->getValue());
49+
50+
return $this;
51+
}
52+
53+
$this->getSourceQualifier()->fetchUrl((string)$source);
54+
55+
56+
return $this;
57+
}
58+
59+
/**
60+
* Gets the layer qualifier.
61+
*
62+
* @return FetchSourceQualifier
63+
*
64+
* @internal
65+
*/
66+
protected function getSourceQualifier()
67+
{
68+
if (! isset($this->qualifiers['source'])) {
69+
$this->qualifiers['source'] = (new FetchSourceQualifier(null))->assetType("video");
70+
}
71+
72+
return $this->qualifiers['source'];
73+
}
74+
}

src/Transformation/Layer/LayerQualifierFactory.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,12 @@ protected static function handleQualifierValue($layerQualifiers)
4949
// Handle layer params
5050
if (is_array($layerQualifiers)) {
5151
$resourceType = ArrayUtils::get($layerQualifiers, 'resource_type');
52+
$deliveryType = ArrayUtils::get($layerQualifiers, 'type');
5253

5354
// Fetch layer
54-
$fetch = ArrayUtils::get($layerQualifiers, 'fetch');
55-
if (! empty($fetch) || $resourceType === 'fetch') {
56-
return new FetchSourceQualifier($fetch);
55+
$fetchUrl = ArrayUtils::get($layerQualifiers, 'fetch', ArrayUtils::get($layerQualifiers, 'url'));
56+
if (! empty($fetchUrl) || $deliveryType === 'fetch') {
57+
return (new FetchSourceQualifier($fetchUrl))->assetType($resourceType);
5758
}
5859

5960
$text = ArrayUtils::get($layerQualifiers, 'text');
@@ -100,17 +101,17 @@ protected static function handleQualifierValue($layerQualifiers)
100101
if ($resourceType !== 'image') {
101102
$components[] = $resourceType;
102103
}
103-
$type = ArrayUtils::get($layerQualifiers, 'type');
104-
if ($type !== 'upload') {
105-
$components[] = $type;
104+
105+
if ($deliveryType !== 'upload') {
106+
$components[] = $deliveryType;
106107
}
107108
$components[] = $publicId;
108109

109110
// Build a valid layer string.
110111
$layerQualifiers = ArrayUtils::implodeQualifierValues(...$components);
111112
} elseif (is_string($layerQualifiers)) {
112113
// Handle fetch layer from string definition.
113-
if (StringUtils::startsWith($layerQualifiers, 'fetch:')) {
114+
if (StringUtils::contains($layerQualifiers, 'fetch:')) {
114115
return new FetchSourceQualifier($layerQualifiers);
115116
}
116117
}

src/Transformation/Layer/VideoSourceQualifier.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
class VideoSourceQualifier extends BaseSourceQualifier
1919
{
2020
/**
21-
* @var string $sourceType The type of the layer.
21+
* @var string $assetType The asset type of the layer.
2222
*/
23-
protected $sourceType = 'video';
23+
protected $assetType = 'video';
2424

2525
/**
2626
* VideoSourceQualifier constructor.

src/Transformation/Layer/VideoSourceTrait.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,18 @@ public static function video($videoId = null)
3131
return static::createWithSource(ClassUtils::verifyInstance($videoId, VideoSource::class));
3232
}
3333

34+
/**
35+
* Adds another video layer from a remote URL.
36+
*
37+
* @param string|null $fetchUrl The URL of the asset to fetch.
38+
*
39+
* @return static|FetchVideoSource
40+
*/
41+
public static function fetchVideo($fetchUrl)
42+
{
43+
return static::createWithSource(ClassUtils::verifyInstance($fetchUrl, FetchVideoSource::class));
44+
}
45+
3446
/**
3547
* Adds subtitles to a video.
3648
*

tests/TransformationTestCase.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,21 @@
2626
*/
2727
abstract class TransformationTestCase extends TestCase
2828
{
29-
const ASSET_ID = 'sample';
29+
const ASSET_ID = 'sample';
30+
const VIDEO_ASSET_ID = 'dog';
3031

3132
const IMG_EXT = 'png';
3233
const IMG_EXT_JPG = 'jpg';
3334
const IMG_EXT_GIF = 'gif';
3435
const IMAGE_NAME = self::ASSET_ID . '.' . self::IMG_EXT;
3536
const IMAGE_NAME_GIF = self::ASSET_ID . '.' . self::IMG_EXT_GIF;
3637

38+
const VIDEO_EXT = 'mp4';
39+
const VIDEO_NAME = self::VIDEO_ASSET_ID . '.' . self::VIDEO_EXT;
3740
const FETCH_IMAGE_URL = 'https://res.cloudinary.com/demo/image/upload/' . self::IMAGE_NAME;
41+
const FETCH_VIDEO_URL = 'https://res.cloudinary.com/demo/video/upload/' . self::VIDEO_NAME;
42+
43+
const B64_FETCH_VIDEO_URL = 'aHR0cHM6Ly9yZXMuY2xvdWRpbmFyeS5jb20vZGVtby92aWRlby91cGxvYWQvZG9nLm1wNA==';
3844

3945
/**
4046
* Asserts that string representations of the objects are equal.

tests/Unit/Transformation/Common/ActionFromQualifiersTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,10 @@ public function layersQualifiersDataProvider()
656656
'private' => [['public_id' => 'logo', 'type' => 'private'], 'private:logo'],
657657
'format' => [['public_id' => 'logo', 'format' => 'png'], 'logo.png'],
658658
'video' => [['resource_type' => 'video', 'public_id' => 'cat'], 'video:cat'],
659+
'fetch video' => [
660+
['resource_type' => 'video', 'url' => self::FETCH_VIDEO_URL],
661+
'video:fetch:' . self::B64_FETCH_VIDEO_URL
662+
],
659663
'text' => [
660664
['public_id' => 'logo', 'text' => 'Hello World, Nice to meet you?'],
661665
'text:logo:Hello%20World%252C%20Nice%20to%20meet%20you%3F',
@@ -722,6 +726,10 @@ public function layersQualifiersDataProvider()
722726
'fetch:' . self::FETCH_IMAGE_URL,
723727
'fetch:aHR0cHM6Ly9yZXMuY2xvdWRpbmFyeS5jb20vZGVtby9pbWFnZS91cGxvYWQvc2FtcGxlLnBuZw==',
724728
],
729+
'fetch video url' => [
730+
'video:fetch:' . self::FETCH_VIDEO_URL,
731+
'video:fetch:' . self::B64_FETCH_VIDEO_URL,
732+
],
725733
'logo' => [
726734
['public_id' => 'logo', 'type' => 'upload', 'resource_type' => 'image'],
727735
'logo',

tests/Unit/Transformation/Video/VideoOverlayTest.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
namespace Cloudinary\Test\Unit\Transformation\Video;
1212

13-
use Cloudinary\Transformation\AudioSource;
13+
use Cloudinary\Test\TransformationTestCase;
1414
use Cloudinary\Transformation\Compass;
1515
use Cloudinary\Transformation\CompassPosition;
1616
use Cloudinary\Transformation\Concatenate;
@@ -25,12 +25,11 @@
2525
use Cloudinary\Transformation\VideoOverlay;
2626
use Cloudinary\Transformation\VideoSource;
2727
use Cloudinary\Transformation\VideoTransformation;
28-
use PHPUnit\Framework\TestCase;
2928

3029
/**
3130
* Class VideoOverlayTest
3231
*/
33-
final class VideoOverlayTest extends TestCase
32+
final class VideoOverlayTest extends TransformationTestCase
3433
{
3534
public function testVideoOverlay()
3635
{
@@ -109,6 +108,15 @@ public function testVideoCutter()
109108
);
110109
}
111110

111+
public function testVideoFetch()
112+
{
113+
self::assertEquals(
114+
"l_video:fetch:" . self::B64_FETCH_VIDEO_URL . "/fl_layer_apply",
115+
(string)(new VideoTransformation())
116+
->overlay(Overlay::videoSource(VideoSource::fetchVideo(self::FETCH_VIDEO_URL)))
117+
);
118+
}
119+
112120
public function testAudioOverlay()
113121
{
114122
self::assertEquals(

0 commit comments

Comments
 (0)