diff --git a/databox/api/config/services.yaml b/databox/api/config/services.yaml index 4c13a3c69..b00efb993 100644 --- a/databox/api/config/services.yaml +++ b/databox/api/config/services.yaml @@ -131,3 +131,5 @@ services: $decorated: '@.inner' Alchemy\RenditionFactory\Templating\TemplateResolverInterface: '@App\Asset\Attribute\TemplateResolver' + + App\Validator\ValidRenditionDefinitionConstraintValidator: ~ diff --git a/databox/api/config/validator/validation.yaml b/databox/api/config/validator/validation.yaml index 240e6e38b..74292be91 100644 --- a/databox/api/config/validator/validation.yaml +++ b/databox/api/config/validator/validation.yaml @@ -127,7 +127,6 @@ App\Entity\Core\RenditionDefinition: - workspace - class.workspace - parent.workspace - - App\Validator\ValidRenditionDefinitionConstraint: ~ properties: class: - NotNull: ~ @@ -177,8 +176,8 @@ App\Entity\Core\Tag: errorPath: name App\Entity\Integration\WorkspaceIntegration: - constraints: - - App\Validator\ValidIntegrationOptionsConstraint: ~ + constraints: + - App\Validator\ValidIntegrationOptionsConstraint: ~ App\Entity\Integration\IntegrationData: properties: diff --git a/databox/api/src/Command/DocumentationDumperCommand.php b/databox/api/src/Command/DocumentationDumperCommand.php index d08905d68..6d28742b0 100644 --- a/databox/api/src/Command/DocumentationDumperCommand.php +++ b/databox/api/src/Command/DocumentationDumperCommand.php @@ -8,14 +8,14 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Alchemy\RenditionFactory\DocumentationDumper as RenditionFactoryDocumentationDumper; +use Alchemy\RenditionFactory\RenditionBuilderConfigurationDocumentation; #[AsCommand('app:documentation:dump')] class DocumentationDumperCommand extends Command { public function __construct( - private readonly RenditionFactoryDocumentationDumper $renditionFactoryDocumentationDumper, + private readonly RenditionBuilderConfigurationDocumentation $renditionBuilderConfigurationDocumentation, ) { parent::__construct(); @@ -24,16 +24,12 @@ public function __construct( protected function configure(): void { parent::configure(); - - $this - ->setName('app:documentation:dump') - ; } protected function execute(InputInterface $input, OutputInterface $output): int { - $output->writeln('# ' . $this->renditionFactoryDocumentationDumper::getName()); - $output->writeln($this->renditionFactoryDocumentationDumper->dump()); + $output->writeln('# ' . $this->renditionBuilderConfigurationDocumentation::getName()); + $output->writeln($this->renditionBuilderConfigurationDocumentation->generate()); return 0; } diff --git a/databox/api/src/Entity/Core/RenditionDefinition.php b/databox/api/src/Entity/Core/RenditionDefinition.php index e0231b57c..d0df77b6b 100644 --- a/databox/api/src/Entity/Core/RenditionDefinition.php +++ b/databox/api/src/Entity/Core/RenditionDefinition.php @@ -5,6 +5,8 @@ namespace App\Entity\Core; use Alchemy\CoreBundle\Entity\AbstractUuidEntity; +use Alchemy\CoreBundle\Entity\Traits\CreatedAtTrait; +use Alchemy\CoreBundle\Entity\Traits\UpdatedAtTrait; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; @@ -16,10 +18,8 @@ use App\Api\Model\Input\RenditionDefinitionInput; use App\Api\Provider\RenditionDefinitionCollectionProvider; use App\Controller\Core\RenditionDefinitionSortAction; - -use Alchemy\CoreBundle\Entity\Traits\CreatedAtTrait; -use Alchemy\CoreBundle\Entity\Traits\UpdatedAtTrait; use App\Entity\Traits\WorkspaceTrait; +use App\Validator as CustomAssert; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection as DoctrineCollection; use Doctrine\DBAL\Types\Types; @@ -153,6 +153,7 @@ class RenditionDefinition extends AbstractUuidEntity implements \Stringable #[Groups([RenditionDefinition::GROUP_LIST, RenditionDefinition::GROUP_READ, RenditionDefinition::GROUP_WRITE])] #[ORM\Column(type: Types::TEXT, nullable: true)] #[ApiProperty(security: self::GRANT_ADMIN_PROP)] + #[CustomAssert\ValidRenditionDefinitionConstraint] private ?string $definition = null; #[Groups([RenditionDefinition::GROUP_READ])] diff --git a/databox/api/src/Validator/ValidRenditionDefinitionConstraint.php b/databox/api/src/Validator/ValidRenditionDefinitionConstraint.php index 75b0096e1..ecf01a68c 100644 --- a/databox/api/src/Validator/ValidRenditionDefinitionConstraint.php +++ b/databox/api/src/Validator/ValidRenditionDefinitionConstraint.php @@ -6,10 +6,12 @@ use Symfony\Component\Validator\Constraint; +/** @uses ValidRenditionDefinitionConstraintValidator */ +#[\Attribute] class ValidRenditionDefinitionConstraint extends Constraint { public function getTargets(): string|array { - return self::CLASS_CONSTRAINT; + return self::PROPERTY_CONSTRAINT; } } diff --git a/databox/api/src/Validator/ValidRenditionDefinitionConstraintValidator.php b/databox/api/src/Validator/ValidRenditionDefinitionConstraintValidator.php index 0bb44994f..ff74af98b 100644 --- a/databox/api/src/Validator/ValidRenditionDefinitionConstraintValidator.php +++ b/databox/api/src/Validator/ValidRenditionDefinitionConstraintValidator.php @@ -4,33 +4,31 @@ namespace App\Validator; - -use Alchemy\RenditionFactory\Config\Validator; +use Alchemy\RenditionFactory\Config\buildConfigValidator; use Alchemy\RenditionFactory\Config\YamlLoader; -use App\Entity\Core\RenditionDefinition; -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; class ValidRenditionDefinitionConstraintValidator extends ConstraintValidator { - public function __construct(private readonly YamlLoader $yamlLoader, private readonly Validator $validator) + /** @uses buildConfigValidator */ + public function __construct(private readonly YamlLoader $yamlLoader, private readonly buildConfigValidator $validator) { } /** - * @param RenditionDefinition $value + * @param string $value * @param ValidRenditionDefinitionConstraint $constraint */ public function validate($value, Constraint $constraint): void { - if(!($definition = $value->getDefinition())) { + if(!$value) { return; } try { - $config = $this->yamlLoader->parse($definition); + $config = $this->yamlLoader->parse($value); $this->validator->validate($config); - } catch (\Throwable $e) { + } catch (\Exception $e) { $this->context ->buildViolation($e->getMessage()) ->addViolation(); diff --git a/lib/php/rendition-factory-bundle/Resources/config/services.yaml b/lib/php/rendition-factory-bundle/Resources/config/services.yaml index 36fff1986..48489bec2 100644 --- a/lib/php/rendition-factory-bundle/Resources/config/services.yaml +++ b/lib/php/rendition-factory-bundle/Resources/config/services.yaml @@ -94,6 +94,7 @@ services: tags: - { name: !php/const Alchemy\RenditionFactory\Transformer\Video\Format\FormatInterface::TAG } + Alchemy\RenditionFactory\Transformer\Video\Format\OutputFormatsDocumentation: ~ Imagine\Imagick\Imagine: ~ Imagine\Image\ImagineInterface: '@Imagine\Imagick\Imagine' @@ -103,8 +104,6 @@ services: Alchemy\RenditionFactory\Format\FormatFactory: ~ Alchemy\RenditionFactory\Config\ModuleOptionsResolver: ~ - Alchemy\RenditionFactory\DocumentationDumper: - tags: - - { name: 'documentation.dumper' } + Alchemy\RenditionFactory\RenditionBuilderConfigurationDocumentation: ~ - Alchemy\RenditionFactory\Config\Validator: ~ + Alchemy\RenditionFactory\Config\buildConfigValidator: ~ diff --git a/lib/php/rendition-factory/src/Command/ConfigurationValidateCommand.php b/lib/php/rendition-factory/src/Command/ConfigurationValidateCommand.php index 6d8785b58..c6d3d8d8b 100644 --- a/lib/php/rendition-factory/src/Command/ConfigurationValidateCommand.php +++ b/lib/php/rendition-factory/src/Command/ConfigurationValidateCommand.php @@ -4,7 +4,7 @@ namespace Alchemy\RenditionFactory\Command; -use Alchemy\RenditionFactory\Config\Validator; +use Alchemy\RenditionFactory\Config\buildConfigValidator; use Alchemy\RenditionFactory\Config\YamlLoader; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; @@ -17,7 +17,7 @@ class ConfigurationValidateCommand extends Command { public function __construct( private readonly YamlLoader $yamlLoader, - private readonly Validator $validator, + private readonly buildConfigValidator $validator, ) { parent::__construct(); } diff --git a/lib/php/rendition-factory/src/Config/Validator.php b/lib/php/rendition-factory/src/Config/buildConfigValidator.php similarity index 96% rename from lib/php/rendition-factory/src/Config/Validator.php rename to lib/php/rendition-factory/src/Config/buildConfigValidator.php index 81ee26dcd..3421df9ce 100644 --- a/lib/php/rendition-factory/src/Config/Validator.php +++ b/lib/php/rendition-factory/src/Config/buildConfigValidator.php @@ -10,13 +10,12 @@ use Symfony\Component\DependencyInjection\Attribute\TaggedLocator; use Symfony\Component\DependencyInjection\ServiceLocator; -class Validator +readonly class buildConfigValidator { public function __construct( #[TaggedLocator(TransformerModuleInterface::TAG, defaultIndexMethod: 'getName')] - private readonly ServiceLocator $transformers, + private ServiceLocator $transformers, ) { - } public function getTransformers(): ServiceLocator diff --git a/lib/php/rendition-factory/src/DocumentationDumper.php b/lib/php/rendition-factory/src/RenditionBuilderConfigurationDocumentation.php similarity index 60% rename from lib/php/rendition-factory/src/DocumentationDumper.php rename to lib/php/rendition-factory/src/RenditionBuilderConfigurationDocumentation.php index 5bec29b1b..5ff25d4fc 100644 --- a/lib/php/rendition-factory/src/DocumentationDumper.php +++ b/lib/php/rendition-factory/src/RenditionBuilderConfigurationDocumentation.php @@ -4,18 +4,15 @@ use Alchemy\RenditionFactory\Transformer\Documentation; use Alchemy\RenditionFactory\Transformer\TransformerModuleInterface; -use Alchemy\RenditionFactory\Transformer\Video\Format\FormatInterface; use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper; use Symfony\Component\DependencyInjection\Attribute\TaggedLocator; use Symfony\Component\DependencyInjection\ServiceLocator; -final readonly class DocumentationDumper +final readonly class RenditionBuilderConfigurationDocumentation { public function __construct( #[TaggedLocator(TransformerModuleInterface::TAG, defaultIndexMethod: 'getName')] private ServiceLocator $transformers, - #[TaggedLocator(FormatInterface::TAG, defaultIndexMethod: 'getFormat')] - private ServiceLocator $formats, ) { } @@ -24,7 +21,7 @@ public static function getName(): string return 'rendition-factory'; } - public function dump(): string + public function generate(): string { $text = ''; foreach ($this->transformers->getProvidedServices() as $transformerName => $transformerFqcn) { @@ -32,40 +29,6 @@ public function dump(): string $transformer = $this->transformers->get($transformerName); $text .= $this->getTransformerDocumentation($transformerName, $transformer); } - $text .= $this->listFormats(); - - return $text; - } - - private function listFormats(): string - { - $formats = []; - foreach ($this->formats->getProvidedServices() as $formatName => $formatFqcn) { - /** @var FormatInterface $format */ - $format = $this->formats->get($formatName); - $family = $format->getFamily()->value; - if (!array_key_exists($family, $formats)) { - $formats[$family] = []; - } - $formats[$family][] = $format; - } - ksort($formats); - - $text = "## Video transformers output `format`s.\n"; - $text .= "| Family | Format | Mime type | Extensions |\n"; - $text .= "|-|-|-|-|\n"; - foreach ($formats as $familyFormats) { - $text .= sprintf("| %s ||||\n", - $familyFormats[0]->getFamily()->value, - ); - foreach ($familyFormats as $format) { - $text .= sprintf("|| %s | %s | %s |\n", - $format->getFormat(), - $format->getMimeType(), - implode(', ', $format->getAllowedExtensions()) - ); - } - } return $text; } diff --git a/lib/php/rendition-factory/src/Transformer/TransformerConfigHelper.php b/lib/php/rendition-factory/src/Transformer/TransformerConfigHelper.php deleted file mode 100644 index d71896ef2..000000000 --- a/lib/php/rendition-factory/src/Transformer/TransformerConfigHelper.php +++ /dev/null @@ -1,64 +0,0 @@ -children = []; - } - - public function addChild(TransformerConfigHelper $child): void - { - $this->children[] = $child; - } - - public function getChildren(): array - { - return $this->children; - } - - public function getHeader(): string - { - return $this->header; - } - - public function getFooter(): string - { - return $this->footer; - } - - /** - * helper to create a base tree for a module, including common options. - */ - public static function createBaseTree(string $name): TreeBuilder - { - $treeBuilder = new TreeBuilder('root'); - $rootNode = $treeBuilder->getRootNode(); - // @formatter:off - $rootNode - ->children() - ->scalarNode('module') - ->isRequired() - ->defaultValue($name) - ->end() - ->scalarNode('description') - ->info('Description of the module action') - ->end() - ->scalarNode('enabled') - ->defaultTrue() - ->info('Whether to enable this module') - ->end() - ->end() - ; - // @formatter:on - - return $treeBuilder; - } -} diff --git a/lib/php/rendition-factory/src/Transformer/Video/FFMpegTransformerModule.php b/lib/php/rendition-factory/src/Transformer/Video/FFMpegTransformerModule.php index e803112b2..db6dac5f1 100644 --- a/lib/php/rendition-factory/src/Transformer/Video/FFMpegTransformerModule.php +++ b/lib/php/rendition-factory/src/Transformer/Video/FFMpegTransformerModule.php @@ -12,6 +12,14 @@ use Alchemy\RenditionFactory\Transformer\TransformerModuleInterface; use Alchemy\RenditionFactory\Transformer\Video\FFMpeg\Filter\ResizeFilter; use Alchemy\RenditionFactory\Transformer\Video\Format\FormatInterface; +use Alchemy\RenditionFactory\Transformer\Video\Format\MkvFormat; +use Alchemy\RenditionFactory\Transformer\Video\Format\Mp3Format; +use Alchemy\RenditionFactory\Transformer\Video\Format\Mpeg4Format; +use Alchemy\RenditionFactory\Transformer\Video\Format\MpegFormat; +use Alchemy\RenditionFactory\Transformer\Video\Format\OutputFormatsDocumentation; +use Alchemy\RenditionFactory\Transformer\Video\Format\QuicktimeFormat; +use Alchemy\RenditionFactory\Transformer\Video\Format\WavFormat; +use Alchemy\RenditionFactory\Transformer\Video\Format\WebmFormat; use FFMpeg; use FFMpeg\Coordinate\TimeCode; use FFMpeg\Format\FormatInterface as FFMpegFormatInterface; @@ -31,6 +39,7 @@ public function __construct(#[AutowireLocator(FormatInterface::TAG, defaultIndexMethod: 'getFormat')] private ServiceLocator $formats, private ModuleOptionsResolver $optionsResolver, private ImagineInterface $imagine, + private OutputFormatsDocumentation $outputFormatsDocumentation, ) { } @@ -39,6 +48,19 @@ public static function getName(): string return 'ffmpeg'; } + private static function getSupportedOutputFormats(): array + { + return [ + MkvFormat::getFormat(), + Mpeg4Format::getFormat(), + MpegFormat::getFormat(), + QuicktimeFormat::getFormat(), + WebmFormat::getFormat(), + WavFormat::getFormat(), + Mp3Format::getFormat(), + ]; + } + public function getDocumentation(): Documentation { $treeBuilder = Documentation::createBaseTree(self::getName()); @@ -48,6 +70,7 @@ public function getDocumentation(): Documentation <<
outputFormatsDocumentation->listFormats(self::getSupportedOutputFormats()). <<