3131use SixtyEightPublishers \ImageStorage \Bridge \Nette \Application \ImageServerPresenter ;
3232use SixtyEightPublishers \ImageStorage \Bridge \Nette \Application \ImageServerRoute ;
3333use SixtyEightPublishers \ImageStorage \Bridge \Nette \DI \Config \ImageStorageConfig ;
34+ use SixtyEightPublishers \ImageStorage \Bridge \Nette \DI \Config \PresetConfig ;
3435use SixtyEightPublishers \ImageStorage \Bridge \Nette \DI \Config \StorageConfig ;
3536use SixtyEightPublishers \ImageStorage \Bridge \Nette \ImageServer \ResponseFactory ;
3637use SixtyEightPublishers \ImageStorage \Bridge \Symfony \Console \Configurator \CleanCommandConfigurator ;
5253use SixtyEightPublishers \ImageStorage \LinkGenerator \LinkGeneratorInterface ;
5354use SixtyEightPublishers \ImageStorage \Modifier ;
5455use SixtyEightPublishers \ImageStorage \Modifier \Applicator ;
56+ use SixtyEightPublishers \ImageStorage \Modifier \Codec \Codec ;
57+ use SixtyEightPublishers \ImageStorage \Modifier \Codec \PresetCodec ;
5558use SixtyEightPublishers \ImageStorage \Modifier \Collection \ModifierCollection ;
5659use SixtyEightPublishers \ImageStorage \Modifier \Collection \ModifierCollectionFactoryInterface ;
5760use SixtyEightPublishers \ImageStorage \Modifier \Facade \ModifierFacadeFactory ;
5861use SixtyEightPublishers \ImageStorage \Modifier \Facade \ModifierFacadeFactoryInterface ;
5962use SixtyEightPublishers \ImageStorage \Modifier \Facade \ModifierFacadeInterface ;
63+ use SixtyEightPublishers \ImageStorage \Modifier \Preset \Preset ;
6064use SixtyEightPublishers \ImageStorage \Modifier \Preset \PresetCollection ;
6165use SixtyEightPublishers \ImageStorage \Modifier \Preset \PresetCollectionFactoryInterface ;
6266use SixtyEightPublishers \ImageStorage \Modifier \Validator ;
6569use SixtyEightPublishers \ImageStorage \Persistence \ImagePersister ;
6670use SixtyEightPublishers \ImageStorage \Persistence \ImagePersisterInterface ;
6771use SixtyEightPublishers \ImageStorage \Resource \ResourceFactory ;
72+ use SixtyEightPublishers \ImageStorage \Responsive \Descriptor \WDescriptor ;
73+ use SixtyEightPublishers \ImageStorage \Responsive \Descriptor \XDescriptor ;
6874use SixtyEightPublishers \ImageStorage \Responsive \SrcSetGeneratorFactoryInterface ;
75+ use SixtyEightPublishers \ImageStorage \Security \KnownModifiers ;
6976use SixtyEightPublishers \ImageStorage \Security \SignatureStrategy ;
7077use SixtyEightPublishers \ImageStorage \Security \SignatureStrategyInterface ;
7178use function array_diff ;
79+ use function array_fill_keys ;
7280use function array_keys ;
81+ use function array_map ;
82+ use function array_merge ;
83+ use function array_unique ;
7384use function assert ;
7485use function is_array ;
86+ use function is_string ;
87+ use function is_subclass_of ;
7588use function sprintf ;
7689
7790final class ImageStorageExtension extends CompilerExtension implements FileStorageDefinitionFactoryInterface
@@ -120,7 +133,17 @@ public function getConfigSchema(): Schema
120133 'no_image_patterns ' => Expect::arrayOf ('string ' , 'string ' )
121134 ->default ([]),
122135 'presets ' => Expect::arrayOf (
123- Expect::arrayOf (Expect::scalar (), 'string ' ),
136+ Expect::structure ([
137+ 'modifiers ' => Expect::arrayOf (Expect::scalar (), 'string ' ),
138+ 'w ' => Expect::listOf (Expect::int ())->default ([]),
139+ 'x ' => Expect::listOf (Expect::anyOf (Expect::int (), Expect::float ()))->default ([]),
140+ 'defaultW ' => Expect::int ()->nullable (),
141+ 'defaultX ' => Expect::anyOf (Expect::int (), Expect::float ())->nullable (),
142+ ])->castTo (PresetConfig::class)
143+ ->assert (
144+ handler: static fn (PresetConfig $ preset ): bool => !([] !== $ preset ->w && [] !== $ preset ->x ),
145+ description: 'A preset cannot have both "w" and "x" properties. ' ,
146+ ),
124147 'string ' ,
125148 )->default ([]),
126149
@@ -329,13 +352,30 @@ public function createFileStorage(string $name, FileStorageConfig $config): Serv
329352 ->setFactory (Config::class, [$ config ->config ])
330353 ->setAutowired (false );
331354
355+ $ presets = array_map (
356+ callback: static fn (PresetConfig $ preset ): Statement => new Statement (Preset::class, [
357+ 'modifiers ' => $ preset ->modifiers ,
358+ 'descriptor ' => match (true ) {
359+ [] !== $ preset ->w => new Statement (WDescriptor::class, $ preset ->w ),
360+ [] !== $ preset ->x => new Statement (XDescriptor::class, $ preset ->x ),
361+ default => null ,
362+ },
363+ 'defaultDescriptorValue ' => match (true ) {
364+ [] !== $ preset ->w => $ preset ->defaultW ,
365+ [] !== $ preset ->x => $ preset ->defaultX ,
366+ default => null ,
367+ },
368+ ]),
369+ array: $ imageStorageConfig ->presets ,
370+ );
371+
332372 $ builder ->addDefinition ($ this ->prefix ('modifier_facade. ' . $ name ))
333373 ->setType (ModifierFacadeInterface::class)
334374 ->setFactory (new Statement ([$ this ->prefix ('@modifiers.modifier_facade_factory ' ), 'create ' ], [
335375 new Reference ($ this ->prefix ('config. ' . $ name )),
336376 ]))
337377 ->addSetup ('setModifiers ' , [$ imageStorageConfig ->modifiers ])
338- ->addSetup ('setPresets ' , [$ imageStorageConfig -> presets ])
378+ ->addSetup ('setPresets ' , [$ presets ])
339379 ->addSetup ('setApplicators ' , [$ imageStorageConfig ->applicators ])
340380 ->addSetup ('setValidators ' , [$ imageStorageConfig ->validators ])
341381 ->setAutowired (false );
@@ -354,7 +394,13 @@ public function createFileStorage(string $name, FileStorageConfig $config): Serv
354394 $ signatureStrategyDefinition = $ builder ->addDefinition ($ this ->prefix ('signature_strategy. ' . $ name ))
355395 ->setType (SignatureStrategyInterface::class)
356396 ->setFactory (SignatureStrategy::class, [
357- new Reference ($ this ->prefix ('config. ' . $ name )),
397+ 'config ' => new Reference ($ this ->prefix ('config. ' . $ name )),
398+ 'knownModifiers ' => new Statement (KnownModifiers::class, [
399+ 'list ' => $ this ->buildKnownModifiers (
400+ config: $ config ,
401+ extConfig: $ imageStorageConfig ,
402+ ),
403+ ]),
358404 ])
359405 ->setAutowired (false );
360406 }
@@ -506,4 +552,92 @@ private function registerImageServerPresenter(): void
506552
507553 $ this ->imageServerPresenterRegistered = true ;
508554 }
555+
556+ /**
557+ * @return array<string, true>
558+ */
559+ private function buildKnownModifiers (FileStorageConfig $ config , StorageConfig $ extConfig ): array
560+ {
561+ $ presets = array_map (
562+ callback: static function (PresetConfig $ conf ): Preset {
563+ $ descriptor = match (true ) {
564+ [] !== $ conf ->w => new WDescriptor (...$ conf ->w ),
565+ [] !== $ conf ->x => new XDescriptor (...$ conf ->x ),
566+ default => null ,
567+ };
568+
569+ $ defaultDescriptorValue = match (true ) {
570+ [] !== $ conf ->w => $ conf ->defaultW ,
571+ [] !== $ conf ->x => $ conf ->defaultX ,
572+ default => null ,
573+ };
574+
575+ return new Preset (
576+ modifiers: $ conf ->modifiers ,
577+ descriptor: $ descriptor ,
578+ defaultDescriptorValue: $ defaultDescriptorValue ,
579+ );
580+ },
581+ array: $ extConfig ->presets ,
582+ );
583+
584+ $ modifiers = array_map (
585+ callback: static function (Statement $ modifier ): Modifier \ModifierInterface {
586+ $ entity = $ modifier ->getEntity ();
587+ $ params = $ modifier ->arguments ;
588+ assert (is_string ($ entity ) && is_subclass_of ($ entity , Modifier \AbstractModifier::class) && is_array ($ params ));
589+
590+ return new $ entity (...$ params );
591+ },
592+ array: $ extConfig ->modifiers ,
593+ );
594+
595+ $ presetsCollection = new PresetCollection ();
596+
597+ foreach ($ presets as $ name => $ preset ) {
598+ $ presetsCollection ->add (presetAlias: $ name , preset: $ preset );
599+ }
600+
601+ $ modifierCollection = new ModifierCollection ();
602+
603+ foreach ($ modifiers as $ modifier ) {
604+ $ modifierCollection ->add (modifier: $ modifier );
605+ }
606+
607+ $ cnf = new Config ($ config ->config );
608+
609+ $ codec = new PresetCodec (
610+ codec: new Codec (
611+ config: $ cnf ,
612+ modifierCollection: $ modifierCollection ,
613+ ),
614+ config: $ cnf ,
615+ modifierCollection: $ modifierCollection ,
616+ presetCollection: $ presetsCollection ,
617+ );
618+
619+ $ known = [];
620+
621+ foreach ($ presets as $ preset ) {
622+ if (null === $ preset ->descriptor ) {
623+ $ known [] = $ codec ->modifiersToPath ($ preset ->modifiers );
624+
625+ continue ;
626+ }
627+
628+ $ modifiers = $ preset ->modifiers ;
629+
630+ foreach ($ preset ->descriptor ->iterateModifiers ($ modifierCollection ) as $ mod ) {
631+ $ known [] = $ codec ->modifiersToPath (array_merge (
632+ $ modifiers ,
633+ $ mod ,
634+ ));
635+ }
636+ }
637+
638+ return array_fill_keys (
639+ keys: array_unique ($ known ),
640+ value: true ,
641+ );
642+ }
509643}
0 commit comments