-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Validator] Add Video
constraint for validating video files
#59042
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
symfonyaml
wants to merge
16
commits into
symfony:7.4
Choose a base branch
from
symfonyaml:video-validator
base: 7.4
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
f6b9168
[Validator] Add the Video constraint for validating video files
c670298
Fix conflicts in CHANGELOG
5b6f30a
Update uuid and add comments
9b9928f
Apply coding standards suggested by fabbot.io
ed02046
Use ::class whenever possible from fabbot.io
21e0c7a
php-ffmpeg in main composer file for dev + check php-ffmpeg is instal…
37a138a
Update src/Symfony/Component/Validator/Constraints/VideoValidator.php
symfonyaml 6d607a1
Use named arguments as Nicolas Grekas suggested
symfonyaml 93c8747
Fix Psalm issue : Cannot find referenced variable $options in Video.php
980eeb8
CI Install ffmpeg in system dependencies for linux and windows tests
e9ebfa2
Video validator test requires extension fileinfo
9b48473
Fix coding standard from fabbot.io
ab74399
Remove group in CI + added phpdoc on video constraints
a083f66
VideoValidatorTest should be skipped if ffmpeg is not available on th…
cf56118
Applied coding standard suggested by fabbot.io
1b26cf2
Replace ctype_digit check with just a lower than comparison
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ CHANGELOG | |
|
||
* Add support for ratio checks for SVG files to the `Image` constraint | ||
* Add the `Slug` constraint | ||
* Add the `Video` constraint for validating video files | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about Add the |
||
|
||
7.2 | ||
--- | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Validator\Constraints; | ||
|
||
use Symfony\Component\Validator\Attribute\HasNamedArguments; | ||
|
||
/** | ||
* @author Kev <https://github.com/symfonyaml> | ||
*/ | ||
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] | ||
class Video extends File | ||
{ | ||
public const SIZE_NOT_DETECTED_ERROR = '5dab98df-43c8-481b-94f9-46a3c958285c'; | ||
public const TOO_WIDE_ERROR = '9e18d6a4-aeda-4644-be8e-9e29dbfd6c4a'; | ||
public const TOO_NARROW_ERROR = 'b267f54b-d994-46d4-9ca6-338fc4f7962f'; | ||
public const TOO_HIGH_ERROR = '44f4c411-0199-48c2-b597-df1f5944ccde'; | ||
public const TOO_LOW_ERROR = '0b6bc3ce-df90-40f9-90aa-5bbb840cb481'; | ||
public const TOO_FEW_PIXEL_ERROR = '510ddf98-2eda-436e-be7e-b6f107bc0e22'; | ||
public const TOO_MANY_PIXEL_ERROR = 'ff0a8ee8-951d-4c97-afe2-03c0d61a2a02'; | ||
public const RATIO_TOO_BIG_ERROR = '5e6b9c21-d4d8-444d-9f4c-e3ff1e25a9a6'; | ||
public const RATIO_TOO_SMALL_ERROR = '26985857-7447-49dc-b271-1477a76cc63c'; | ||
public const SQUARE_NOT_ALLOWED_ERROR = '18500335-b868-4056-b2a2-aa2aeeb0cbdf'; | ||
public const LANDSCAPE_NOT_ALLOWED_ERROR = 'cbf38fbc-04c0-457a-8c29-a6f3080e415a'; | ||
public const PORTRAIT_NOT_ALLOWED_ERROR = '6c3e34a8-94d5-4434-9f20-fb9c0f3ab531'; | ||
public const CORRUPTED_VIDEO_ERROR = '591b9c4d-d357-425f-8672-6b187816550e'; | ||
|
||
// Include the mapping from the base class | ||
|
||
protected const ERROR_NAMES = [ | ||
self::NOT_FOUND_ERROR => 'NOT_FOUND_ERROR', | ||
self::NOT_READABLE_ERROR => 'NOT_READABLE_ERROR', | ||
self::EMPTY_ERROR => 'EMPTY_ERROR', | ||
self::TOO_LARGE_ERROR => 'TOO_LARGE_ERROR', | ||
self::INVALID_MIME_TYPE_ERROR => 'INVALID_MIME_TYPE_ERROR', | ||
self::FILENAME_TOO_LONG => 'FILENAME_TOO_LONG', | ||
self::SIZE_NOT_DETECTED_ERROR => 'SIZE_NOT_DETECTED_ERROR', | ||
self::TOO_WIDE_ERROR => 'TOO_WIDE_ERROR', | ||
self::TOO_NARROW_ERROR => 'TOO_NARROW_ERROR', | ||
self::TOO_HIGH_ERROR => 'TOO_HIGH_ERROR', | ||
self::TOO_LOW_ERROR => 'TOO_LOW_ERROR', | ||
self::TOO_FEW_PIXEL_ERROR => 'TOO_FEW_PIXEL_ERROR', | ||
self::TOO_MANY_PIXEL_ERROR => 'TOO_MANY_PIXEL_ERROR', | ||
self::RATIO_TOO_BIG_ERROR => 'RATIO_TOO_BIG_ERROR', | ||
self::RATIO_TOO_SMALL_ERROR => 'RATIO_TOO_SMALL_ERROR', | ||
self::SQUARE_NOT_ALLOWED_ERROR => 'SQUARE_NOT_ALLOWED_ERROR', | ||
self::LANDSCAPE_NOT_ALLOWED_ERROR => 'LANDSCAPE_NOT_ALLOWED_ERROR', | ||
self::PORTRAIT_NOT_ALLOWED_ERROR => 'PORTRAIT_NOT_ALLOWED_ERROR', | ||
self::CORRUPTED_VIDEO_ERROR => 'CORRUPTED_VIDEO_ERROR', | ||
]; | ||
|
||
public array|string $mimeTypes = 'video/*'; | ||
public ?int $minWidth = null; | ||
public ?int $maxWidth = null; | ||
public ?int $maxHeight = null; | ||
public ?int $minHeight = null; | ||
public int|float|null $maxRatio = null; | ||
public int|float|null $minRatio = null; | ||
public int|float|null $minPixels = null; | ||
public int|float|null $maxPixels = null; | ||
public ?bool $allowSquare = true; | ||
public ?bool $allowLandscape = true; | ||
public ?bool $allowPortrait = true; | ||
|
||
// The constant for a wrong MIME type is taken from the parent class. | ||
public string $mimeTypesMessage = 'This file is not a valid video.'; | ||
public string $sizeNotDetectedMessage = 'The size of the video could not be detected.'; | ||
public string $maxWidthMessage = 'The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.'; | ||
public string $minWidthMessage = 'The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.'; | ||
public string $maxHeightMessage = 'The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.'; | ||
public string $minHeightMessage = 'The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.'; | ||
public string $minPixelsMessage = 'The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels.'; | ||
public string $maxPixelsMessage = 'The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels.'; | ||
public string $maxRatioMessage = 'The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.'; | ||
public string $minRatioMessage = 'The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.'; | ||
public string $allowSquareMessage = 'The video is square ({{ width }}x{{ height }}px). Square videos are not allowed.'; | ||
public string $allowLandscapeMessage = 'The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed.'; | ||
public string $allowPortraitMessage = 'The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed.'; | ||
public string $corruptedMessage = 'The video file is corrupted.'; | ||
|
||
/** | ||
* @param positive-int|string|null $maxSize The max size of the underlying file | ||
* @param bool|null $binaryFormat Pass true to use binary-prefixed units (KiB, MiB, etc.) or false to use SI-prefixed units (kB, MB) in displayed messages. Pass null to guess the format from the maxSize option. (defaults to null) | ||
* @param non-empty-string[]|null $mimeTypes Acceptable media types | ||
* @param positive-int|null $filenameMaxLength Maximum length of the file name | ||
* @param string|null $disallowEmptyMessage Enable empty upload validation with this message in case of error | ||
* @param string|null $uploadIniSizeErrorMessage Message if the file size exceeds the max size configured in php.ini | ||
* @param string|null $uploadFormSizeErrorMessage Message if the file size exceeds the max size configured in the HTML input field | ||
* @param string|null $uploadPartialErrorMessage Message if the file is only partially uploaded | ||
* @param string|null $uploadNoTmpDirErrorMessage Message if there is no upload_tmp_dir in php.ini | ||
* @param string|null $uploadCantWriteErrorMessage Message if the uploaded file can not be stored in the temporary directory | ||
* @param string|null $uploadErrorMessage Message if an unknown error occurred on upload | ||
* @param string[]|null $groups | ||
* @param int<0, int>|null $minWidth Minimum video width | ||
* @param positive-int|null $maxWidth Maximum video width | ||
* @param positive-int|null $maxHeight Maximum video height | ||
* @param int<0, int>|null $minHeight Minimum video weight | ||
* @param positive-int|float|null $maxRatio Maximum video ratio | ||
* @param int<0, max>|float|null $minRatio Minimum video ratio | ||
* @param int<0, max>|float|null $minPixels Minimum amount of pixels | ||
* @param positive-int|float|null $maxPixels Maximum amount of pixels | ||
* @param bool|null $allowSquare Whether to allow a square video (defaults to true) | ||
* @param bool|null $allowLandscape Whether to allow a landscape video (defaults to true) | ||
* @param bool|null $allowPortrait Whether to allow a portrait video (defaults to true) | ||
* @param string|null $sizeNotDetectedMessage Message if the system can not determine video size and there is a size constraint to validate | ||
* | ||
* @see https://www.iana.org/assignments/media-types/media-types.xhtml Existing media types | ||
*/ | ||
#[HasNamedArguments] | ||
public function __construct( | ||
int|string|null $maxSize = null, | ||
?bool $binaryFormat = null, | ||
array|string|null $mimeTypes = null, | ||
?int $filenameMaxLength = null, | ||
?int $minWidth = null, | ||
symfonyaml marked this conversation as resolved.
Show resolved
Hide resolved
|
||
?int $maxWidth = null, | ||
?int $maxHeight = null, | ||
?int $minHeight = null, | ||
int|float|null $maxRatio = null, | ||
int|float|null $minRatio = null, | ||
int|float|null $minPixels = null, | ||
int|float|null $maxPixels = null, | ||
?bool $allowSquare = null, | ||
?bool $allowLandscape = null, | ||
?bool $allowPortrait = null, | ||
?string $notFoundMessage = null, | ||
?string $notReadableMessage = null, | ||
?string $maxSizeMessage = null, | ||
?string $mimeTypesMessage = null, | ||
?string $disallowEmptyMessage = null, | ||
?string $filenameTooLongMessage = null, | ||
?string $uploadIniSizeErrorMessage = null, | ||
?string $uploadFormSizeErrorMessage = null, | ||
?string $uploadPartialErrorMessage = null, | ||
?string $uploadNoFileErrorMessage = null, | ||
?string $uploadNoTmpDirErrorMessage = null, | ||
?string $uploadCantWriteErrorMessage = null, | ||
?string $uploadExtensionErrorMessage = null, | ||
?string $uploadErrorMessage = null, | ||
?string $sizeNotDetectedMessage = null, | ||
?string $maxWidthMessage = null, | ||
?string $minWidthMessage = null, | ||
?string $maxHeightMessage = null, | ||
?string $minHeightMessage = null, | ||
?string $minPixelsMessage = null, | ||
?string $maxPixelsMessage = null, | ||
?string $maxRatioMessage = null, | ||
?string $minRatioMessage = null, | ||
?string $allowSquareMessage = null, | ||
?string $allowLandscapeMessage = null, | ||
?string $allowPortraitMessage = null, | ||
?string $corruptedMessage = null, | ||
?array $groups = null, | ||
mixed $payload = null, | ||
) { | ||
if (!class_exists(\FFMpeg\FFProbe::class)) { | ||
throw new \LogicException('The "php-ffmpeg/php-ffmpeg" library must be installed to use the Video constraint. Try running "composer require php-ffmpeg/php-ffmpeg".'); | ||
} | ||
|
||
parent::__construct( | ||
[], // File constraint do not use named arguments yet | ||
$maxSize, | ||
$binaryFormat, | ||
$mimeTypes, | ||
$filenameMaxLength, | ||
$notFoundMessage, | ||
$notReadableMessage, | ||
$maxSizeMessage, | ||
$mimeTypesMessage, | ||
$disallowEmptyMessage, | ||
$filenameTooLongMessage, | ||
$uploadIniSizeErrorMessage, | ||
$uploadFormSizeErrorMessage, | ||
$uploadPartialErrorMessage, | ||
$uploadNoFileErrorMessage, | ||
$uploadNoTmpDirErrorMessage, | ||
$uploadCantWriteErrorMessage, | ||
$uploadExtensionErrorMessage, | ||
$uploadErrorMessage, | ||
$groups, | ||
$payload | ||
); | ||
|
||
$this->minWidth = $minWidth ?? $this->minWidth; | ||
$this->maxWidth = $maxWidth ?? $this->maxWidth; | ||
$this->maxHeight = $maxHeight ?? $this->maxHeight; | ||
$this->minHeight = $minHeight ?? $this->minHeight; | ||
$this->maxRatio = $maxRatio ?? $this->maxRatio; | ||
$this->minRatio = $minRatio ?? $this->minRatio; | ||
$this->minPixels = $minPixels ?? $this->minPixels; | ||
$this->maxPixels = $maxPixels ?? $this->maxPixels; | ||
$this->allowSquare = $allowSquare ?? $this->allowSquare; | ||
$this->allowLandscape = $allowLandscape ?? $this->allowLandscape; | ||
$this->allowPortrait = $allowPortrait ?? $this->allowPortrait; | ||
$this->sizeNotDetectedMessage = $sizeNotDetectedMessage ?? $this->sizeNotDetectedMessage; | ||
$this->maxWidthMessage = $maxWidthMessage ?? $this->maxWidthMessage; | ||
$this->minWidthMessage = $minWidthMessage ?? $this->minWidthMessage; | ||
$this->maxHeightMessage = $maxHeightMessage ?? $this->maxHeightMessage; | ||
$this->minHeightMessage = $minHeightMessage ?? $this->minHeightMessage; | ||
$this->minPixelsMessage = $minPixelsMessage ?? $this->minPixelsMessage; | ||
$this->maxPixelsMessage = $maxPixelsMessage ?? $this->maxPixelsMessage; | ||
$this->maxRatioMessage = $maxRatioMessage ?? $this->maxRatioMessage; | ||
$this->minRatioMessage = $minRatioMessage ?? $this->minRatioMessage; | ||
$this->allowSquareMessage = $allowSquareMessage ?? $this->allowSquareMessage; | ||
$this->allowLandscapeMessage = $allowLandscapeMessage ?? $this->allowLandscapeMessage; | ||
$this->allowPortraitMessage = $allowPortraitMessage ?? $this->allowPortraitMessage; | ||
$this->corruptedMessage = $corruptedMessage ?? $this->corruptedMessage; | ||
|
||
if (!\in_array('video/*', (array) $this->mimeTypes, true) && null === $mimeTypesMessage) { | ||
$this->mimeTypesMessage = 'The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.'; | ||
} | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nicolas-grekas Thank you for your first review.
I will need some help for CI, to define
ffmpeg
as a system dependency, so the tests can pass.