From 82ba9bdd523a7d6169c4a20ab02faff231d15b21 Mon Sep 17 00:00:00 2001 From: Constantine Nathanson Date: Tue, 28 Nov 2023 20:14:16 +0200 Subject: [PATCH] Add support for `useFetchFormat` in `VideoTag` --- src/Asset/BaseMediaAsset.php | 12 +++-- src/Asset/Descriptor/AssetDescriptor.php | 4 +- src/Configuration/TagConfig.php | 25 +++++++++++ src/Configuration/TagConfigTrait.php | 57 ++++++++++++++++++++++++ src/Tag/BaseTag.php | 20 +++++++++ src/Tag/ImageTagDeliveryTypeTrait.php | 2 +- src/Tag/VideoSourceTag.php | 5 ++- src/Tag/VideoTag.php | 31 +++++++++++-- src/Tag/VideoThumbnailTag.php | 3 +- tests/Unit/Tag/TagFromParamsTest.php | 17 +++++++ tests/Unit/Tag/VideoTagTest.php | 56 +++++++++++++++++------ 11 files changed, 206 insertions(+), 26 deletions(-) create mode 100644 src/Configuration/TagConfigTrait.php diff --git a/src/Asset/BaseMediaAsset.php b/src/Asset/BaseMediaAsset.php index 3b5acff6..bdfebf80 100644 --- a/src/Asset/BaseMediaAsset.php +++ b/src/Asset/BaseMediaAsset.php @@ -12,6 +12,7 @@ use Cloudinary\ArrayUtils; use Cloudinary\Configuration\Configuration; +use Cloudinary\Configuration\TagConfig; use Cloudinary\Exception\ConfigurationException; use Cloudinary\Transformation\BaseAction; use Cloudinary\Transformation\CommonTransformation; @@ -136,13 +137,14 @@ public function addAction($action) * For non-fetched assets sets the filename extension. * For remotely fetched assets sets the 'f_' transformation parameter. * - * @param string $format The format to set. + * @param string $format The format to set. + * @param bool $useFetchFormat Whether to force fetch format behavior. * * @return static */ - public function setFormat($format) + public function setFormat($format, $useFetchFormat = false) { - if ($this->asset->deliveryType == DeliveryType::FETCH) { + if ($useFetchFormat || $this->asset->deliveryType == DeliveryType::FETCH) { $this->addTransformation(Delivery::format($format)); } else { $this->asset->extension = $format; @@ -203,7 +205,9 @@ public function toUrl($withTransformation = null, $append = true) */ private static function setFormatParameter($params) { - if (ArrayUtils::get($params, DeliveryType::KEY) !== DeliveryType::FETCH) { + if (ArrayUtils::get($params, DeliveryType::KEY) !== DeliveryType::FETCH + && ! ArrayUtils::get($params, TagConfig::USE_FETCH_FORMAT, false) + ) { return $params; } diff --git a/src/Asset/Descriptor/AssetDescriptor.php b/src/Asset/Descriptor/AssetDescriptor.php index e040789c..dcba07fd 100644 --- a/src/Asset/Descriptor/AssetDescriptor.php +++ b/src/Asset/Descriptor/AssetDescriptor.php @@ -225,7 +225,9 @@ public static function fromParams($source, $params = []) = FileUtils::splitPathFilenameExtension($source); // Explicit 'format' parameter overrides extension. (Fetch URLs are not affected). - if ($assetJson['delivery_type'] != DeliveryType::FETCH) { + if ($assetJson['delivery_type'] != DeliveryType::FETCH + || ! ArrayUtils::get($params, 'use_fetch_format', false) + ) { ArrayUtils::addNonEmpty($assetJson, 'extension', ArrayUtils::get($params, 'format')); } diff --git a/src/Configuration/TagConfig.php b/src/Configuration/TagConfig.php index 46d8c0d8..315050c1 100644 --- a/src/Configuration/TagConfig.php +++ b/src/Configuration/TagConfig.php @@ -26,6 +26,8 @@ */ class TagConfig extends BaseConfigSection { + use TagConfigTrait; + const CONFIG_NAME = 'tag'; const DEFAULT_VIDEO_POSTER_FORMAT = Format::JPG; @@ -43,6 +45,7 @@ class TagConfig extends BaseConfigSection const CLIENT_HINTS = 'client_hints'; const UNSIGNED_UPLOAD = 'unsigned_upload'; const VIDEO_POSTER_FORMAT = 'video_poster_format'; + const USE_FETCH_FORMAT = 'use_fetch_format'; const QUOTES_TYPE = 'quotes_type'; const VOID_CLOSING_SLASH = 'void_closing_slash'; const SORT_ATTRIBUTES = 'sort_attributes'; @@ -118,6 +121,13 @@ class TagConfig extends BaseConfigSection */ protected $videoPosterFormat; + /** + * Whether to use fetch format transformation ("f_") instead of file extension. + * + * @var string $useFetchFormat + */ + public $useFetchFormat; + /** * Sets the type of the quotes to use (single or double). Default: BaseTag::DOUBLE_QUOTES. * @@ -154,4 +164,19 @@ class TagConfig extends BaseConfigSection * @var string $contentDelimiter */ protected $contentDelimiter; + + /** + * Sets the Tag configuration key with the specified value. + * + * @param string $configKey The configuration key. + * @param mixed $configValue THe configuration value. + * + * @return $this + * + * @internal + */ + public function setTagConfig($configKey, $configValue) + { + return $this->setConfig($configKey, $configValue); + } } diff --git a/src/Configuration/TagConfigTrait.php b/src/Configuration/TagConfigTrait.php new file mode 100644 index 00000000..c35b513e --- /dev/null +++ b/src/Configuration/TagConfigTrait.php @@ -0,0 +1,57 @@ +setTagConfig(TagConfig::VIDEO_POSTER_FORMAT, $format); + } + + + /** + * Use fetch format transformation ("f_") instead of file extension. + * + * @param bool $useFetchFormat + * + * @return $this + */ + public function useFetchFormat($useFetchFormat = true) + { + return $this->setTagConfig(TagConfig::USE_FETCH_FORMAT, $useFetchFormat); + } + + /** + * Sets the Tag configuration key with the specified value. + * + * @param string $configKey The configuration key. + * @param mixed $configValue THe configuration value. + * + * @return $this + * + * @internal + */ + abstract public function setTagConfig($configKey, $configValue); +} diff --git a/src/Tag/BaseTag.php b/src/Tag/BaseTag.php index bcf4dbef..a80f7034 100644 --- a/src/Tag/BaseTag.php +++ b/src/Tag/BaseTag.php @@ -13,6 +13,7 @@ use Cloudinary\ArrayUtils; use Cloudinary\Asset\AssetQualifiers; use Cloudinary\Configuration\Configuration; +use Cloudinary\Configuration\TagConfigTrait; use Cloudinary\Transformation\QualifiersAction; use Cloudinary\Utils; use UnexpectedValueException; @@ -24,6 +25,8 @@ */ abstract class BaseTag { + use TagConfigTrait; + const SINGLE_QUOTES = 'single_quotes'; const DOUBLE_QUOTES = 'double_quotes'; @@ -360,6 +363,23 @@ protected static function fromParamsDefaultConfig() return $configuration; } + /** + * Sets the Tag configuration key with the specified value. + * + * @param string $configKey The configuration key. + * @param mixed $configValue THe configuration value. + * + * @return $this + * + * @internal + */ + public function setTagConfig($configKey, $configValue) + { + $this->config->tag->setTagConfig($configKey, $configValue); + + return $this; + } + /** * Serializes the tag to string. * diff --git a/src/Tag/ImageTagDeliveryTypeTrait.php b/src/Tag/ImageTagDeliveryTypeTrait.php index 35027d2f..65418946 100644 --- a/src/Tag/ImageTagDeliveryTypeTrait.php +++ b/src/Tag/ImageTagDeliveryTypeTrait.php @@ -121,7 +121,7 @@ public static function youTube($videoId, $configuration = null) */ public static function hulu($videoId, $configuration = null) { - return new static(Image::youTube($videoId, $configuration)); + return new static(Image::hulu($videoId, $configuration)); } /** diff --git a/src/Tag/VideoSourceTag.php b/src/Tag/VideoSourceTag.php index 5f90c3d3..d107a13c 100644 --- a/src/Tag/VideoSourceTag.php +++ b/src/Tag/VideoSourceTag.php @@ -97,7 +97,6 @@ public function video($video, $configuration = null) public function type($type, $codecs = null) { $this->sourceType = ClassUtils::verifyInstance($type, VideoSourceType::class, null, $codecs); - $this->video->setFormat($this->sourceType->type); return $this; } @@ -112,7 +111,9 @@ public function type($type, $codecs = null) public function serializeAttributes($attributes = []) { if (! empty((string)$this->video)) { - $attributes['src'] = $this->video->toUrl($this->additionalTransformation); + $toSerialize = new Video($this->video); + $toSerialize->setFormat($this->sourceType->type, $this->config->tag->useFetchFormat); + $attributes['src'] = $toSerialize->toUrl($this->additionalTransformation); } if (! empty((string)$this->sourceType)) { diff --git a/src/Tag/VideoTag.php b/src/Tag/VideoTag.php index 1fb2abe8..38c9a08f 100644 --- a/src/Tag/VideoTag.php +++ b/src/Tag/VideoTag.php @@ -17,6 +17,7 @@ use Cloudinary\Asset\Video; use Cloudinary\Configuration\AssetConfigTrait; use Cloudinary\Configuration\Configuration; +use Cloudinary\Configuration\TagConfigTrait; use Cloudinary\Transformation\BaseAction; use Cloudinary\Transformation\CommonTransformation; use Cloudinary\Transformation\ImageTransformation; @@ -47,6 +48,7 @@ class VideoTag extends BaseTag implements VideoTransformationInterface use VideoTransformationTrait; use AssetDescriptorTrait; use AssetConfigTrait; + use TagConfigTrait; const NAME = 'video'; @@ -156,7 +158,7 @@ public function sources($sourcesDefinitions) * @param string $source The public ID of the asset. * @param array $params The asset parameters. * - * @return mixed + * @return static */ public static function fromParams($source, $params = []) @@ -213,7 +215,9 @@ protected static function generateVideoPosterAttr($source, &$videoParams, $confi if (! array_key_exists('poster', $videoParams)) { // set default poster based on the video - return Image::fromParams($source, $videoParams); + $videoPosterParams = $videoParams; + ArrayUtils::setDefaultValue($videoPosterParams, 'use_fetch_format', $configuration->tag->useFetchFormat); + return Image::fromParams($source, $videoPosterParams); } // Custom poster @@ -301,7 +305,7 @@ public function serializeAttributes($attributes = []) if (! array_key_exists('poster', $this->attributes)) { $poster = new Image($this->video); - $poster->setFormat($this->config->tag->videoPosterFormat); + $poster->setFormat($this->config->tag->videoPosterFormat, $this->config->tag->useFetchFormat); $attributes['poster'] = $poster; } @@ -410,6 +414,27 @@ public function setUrlConfig($configKey, $configValue) return $this->applyAssetModification('setUrlConfig', $configKey, $configValue); } + /** + * Sets the Tag configuration key with the specified value. + * + * @param string $configKey The configuration key. + * @param mixed $configValue THe configuration value. + * + * @return $this + * + * @internal + */ + public function setTagConfig($configKey, $configValue) + { + $this->config->tag->setTagConfig($configKey, $configValue); + + foreach ($this->sources as $source) { + $source->setTagConfig($configKey, $configValue); + } + + return $this; + } + /** * Applies modification to the asset and to all sources. * diff --git a/src/Tag/VideoThumbnailTag.php b/src/Tag/VideoThumbnailTag.php index e5c155f1..a1d46b8d 100644 --- a/src/Tag/VideoThumbnailTag.php +++ b/src/Tag/VideoThumbnailTag.php @@ -14,7 +14,6 @@ use Cloudinary\Asset\AssetType; use Cloudinary\Asset\Video; use Cloudinary\Configuration\Configuration; -use Cloudinary\Configuration\TagConfig; /** * @@ -36,7 +35,7 @@ public function image($source, $configuration = null) { parent::image(new Video($source, $configuration), $configuration); - $this->image->setFormat($configuration->tag->videoPosterFormat); + $this->image->setFormat($configuration->tag->videoPosterFormat, $configuration->tag->useFetchFormat); return $this; } diff --git a/tests/Unit/Tag/TagFromParamsTest.php b/tests/Unit/Tag/TagFromParamsTest.php index 4cad621f..8b236917 100644 --- a/tests/Unit/Tag/TagFromParamsTest.php +++ b/tests/Unit/Tag/TagFromParamsTest.php @@ -535,6 +535,23 @@ public function testVideoTagFetch() ); } + public function testVideoTagUseFetchFormat() + { + $videoId = self::VIDEO_NAME; + $prefixUrl = self::VIDEO_UPLOAD_PATH; + + Configuration::instance()->importJson(['use_fetch_format' => true]); + + self::assertStrEquals( + "', + VideoTag::fromParams($videoId) + ); + } + public function testVideoTagWithAttributes() { //test video attributes diff --git a/tests/Unit/Tag/VideoTagTest.php b/tests/Unit/Tag/VideoTagTest.php index 71677198..a75e84ac 100644 --- a/tests/Unit/Tag/VideoTagTest.php +++ b/tests/Unit/Tag/VideoTagTest.php @@ -11,6 +11,7 @@ namespace Cloudinary\Test\Unit\Tag; use Cloudinary\Asset\Video; +use Cloudinary\Configuration\Configuration; use Cloudinary\Configuration\UrlConfig; use Cloudinary\Tag\VideoTag; use Cloudinary\Transformation\Angle; @@ -23,22 +24,25 @@ */ final class VideoTagTest extends TagTestCase { - const FETCH_VIDEO_URL_PREFIX = 'https://res.cloudinary.com/test123/video/fetch/'; + const VIDEO_URL_PREFIX = 'https://res.cloudinary.com/test123/video/'; + const FETCH_VIDEO_URL_PREFIX = self::VIDEO_URL_PREFIX . 'fetch/'; + const UPLOAD_VIDEO_URL_PREFIX = self::VIDEO_URL_PREFIX . 'upload/'; + protected $video; - protected $defaultSourcesStr = - '' . "\n" . - '' . "\n" . - '' . "\n" . - ''; + protected $defaultSourcesStr + = '' . "\n" . + '' . "\n" . + '' . "\n" . + ''; protected $posterAttr = 'poster="https://res.cloudinary.com/test123/video/upload/sample.jpg"'; public function setUp() { - parent::setUp(); // TODO: Change the autogenerated stub + parent::setUp(); $this->video = new Video(self::VIDEO_NAME); } @@ -83,6 +87,32 @@ public function testVideoTagFetchVideo() ); } + public function testVideoTagUseFetchFormat() + { + $videoPubId = self::FOLDER . '/' . self::VIDEO_NAME; + $urlPref = self::UPLOAD_VIDEO_URL_PREFIX; + + $expected = "'; + + self::assertStrEquals( + $expected, + VideoTag::upload($videoPubId)->useFetchFormat() + ); + + $conf = Configuration::instance(); + $conf->tag->useFetchFormat(); + + self::assertStrEquals( + $expected, + VideoTag::upload($videoPubId, $conf) + ); + } + public function testVideoTagWithTransformation() { $video = (new Video(self::VIDEO_NAME))->rotate(Rotate::byAngle(17))->resize(Scale::scale(500)); @@ -99,12 +129,12 @@ public function testVideoTagWithTransformation() public function testVideoTagBuilders() { - $host = UrlConfig::DEFAULT_SHARED_HOST; + $host = UrlConfig::DEFAULT_SHARED_HOST; $cloudName = 'test321'; - $trStr = (new Transformation())->rotate(Rotate::byAngle(17))->resize(Scale::scale(500))->toUrl(); - $ver = 17; + $trStr = (new Transformation())->rotate(Rotate::byAngle(17))->resize(Scale::scale(500))->toUrl(); + $ver = 17; $assetType = 'video/upload'; - $publicId = self::ASSET_ID; + $publicId = self::ASSET_ID; $tag = (new VideoTag(self::VIDEO_NAME)) ->rotate(Rotate::byAngle(17)) // transformation