@@ -75,6 +75,29 @@ public function testCropModeMapsFocalPointToClampedCropOriginGravity(): void
7575 ], $ transform ->gravity , 0.0001 );
7676 }
7777
78+ public function testGetTransformUrlDoesNotLeakGravityBetweenAssets (): void
79+ {
80+ $ transform = new ImageTransform ([
81+ 'mode ' => 'crop ' ,
82+ 'position ' => 'top-center ' ,
83+ 'width ' => 1200 ,
84+ 'height ' => 750 ,
85+ ]);
86+
87+ $ firstAsset = $ this ->makeUrlAssetStub (1 , 'first.jpg ' , 3402 , 4253 , ['x ' => 0.57 , 'y ' => 0.7707 ]);
88+ $ secondAsset = $ this ->makeUrlAssetStub (2 , 'second.jpg ' , 3402 , 4253 , ['x ' => 0.4631 , 'y ' => 0.308 ]);
89+
90+ $ transformer = new UrlTestImageTransformer ();
91+
92+ $ firstUrl = $ transformer ->getTransformUrl ($ firstAsset , $ transform , true );
93+ $ secondUrl = $ transformer ->getTransformUrl ($ secondAsset , $ transform , true );
94+
95+ $ this ->assertStringContainsString ('gravity%5Bx%5D=0.57 ' , $ firstUrl );
96+ $ this ->assertStringContainsString ('gravity%5By%5D=0.9999999999999992 ' , $ firstUrl );
97+ $ this ->assertStringContainsString ('gravity%5Bx%5D=0.4631 ' , $ secondUrl );
98+ $ this ->assertStringNotContainsString ('gravity%5Bx%5D=0.57 ' , $ secondUrl );
99+ }
100+
78101 private function makeAssetStub (int $ width , int $ height , array $ focalPoint ): Asset
79102 {
80103 return new class ($ width , $ height , $ focalPoint ) extends Asset {
@@ -109,6 +132,62 @@ public function getHeight(mixed $transform = null): ?int
109132 };
110133 }
111134
135+ private function makeUrlAssetStub (int $ id , string $ filename , int $ width , int $ height , array $ focalPoint ): Asset
136+ {
137+ return new class ($ id , $ filename , $ width , $ height , $ focalPoint ) extends Asset {
138+ public function __construct (
139+ int $ id ,
140+ private string $ filenameValue ,
141+ private int $ widthValue ,
142+ private int $ heightValue ,
143+ private array $ focalPointValue ,
144+ ) {
145+ parent ::__construct ();
146+ $ this ->id = $ id ;
147+ $ this ->kind = self ::KIND_IMAGE ;
148+ }
149+
150+ public function getHasFocalPoint (): bool
151+ {
152+ return true ;
153+ }
154+
155+ public function getFocalPoint (bool $ asCss = false ): array |string |null
156+ {
157+ if ($ asCss ) {
158+ return ($ this ->focalPointValue ['x ' ] * 100 ) . '% ' . ($ this ->focalPointValue ['y ' ] * 100 ) . '% ' ;
159+ }
160+
161+ return $ this ->focalPointValue ;
162+ }
163+
164+ public function getWidth (array |string |\craft \models \ImageTransform $ transform = null ): ?int
165+ {
166+ return $ this ->widthValue ;
167+ }
168+
169+ public function getHeight (mixed $ transform = null ): ?int
170+ {
171+ return $ this ->heightValue ;
172+ }
173+
174+ public function getFilename (bool $ withExtension = true ): string
175+ {
176+ return $ this ->filenameValue ;
177+ }
178+
179+ public function getPath (): ?string
180+ {
181+ return 'tests/ ' . $ this ->filenameValue ;
182+ }
183+
184+ public function getMimeType (mixed $ transform = null ): ?string
185+ {
186+ return 'image/jpeg ' ;
187+ }
188+ };
189+ }
190+
112191}
113192
114193class TestImageTransformer extends ImageTransformer
@@ -118,3 +197,14 @@ public function applyFocalPointGravity(Asset $asset, ImageTransform $imageTransf
118197 $ this ->applyAssetFocalPointGravity ($ asset , $ imageTransform );
119198 }
120199}
200+
201+ class UrlTestImageTransformer extends ImageTransformer
202+ {
203+ public function getTransformUrl (Asset $ asset , \craft \models \ImageTransform $ imageTransform , bool $ immediately ): string
204+ {
205+ $ imageTransform = \Craft::createObject (ImageTransform::class, [$ imageTransform ->toArray ()]);
206+ $ this ->applyAssetFocalPointGravity ($ asset , $ imageTransform );
207+
208+ return (string ) \League \Uri \Components \Query::fromVariable ($ imageTransform ->toOptions ());
209+ }
210+ }
0 commit comments