diff --git a/src/Models/Media.php b/src/Models/Media.php index 0b1e967..bf2d09f 100644 --- a/src/Models/Media.php +++ b/src/Models/Media.php @@ -249,10 +249,27 @@ public function dispatchConversion(string $conversion): ?PendingDispatch return null; } + public function getOrExecuteConversion(string $name): ?MediaConversion + { + if ($conversion = $this->getConversion($name)) { + return $conversion; + } + + return $this->executeConversion($name); + } + public function executeConversion(string $conversion): ?MediaConversion { if ($definition = $this->getConversionDefinition($conversion)) { - return $definition->execute($this, $this->getParentConversion($conversion)); + + if (str_contains($conversion, '.')) { + $parent = $this->getOrExecuteConversion(str($conversion)->beforeLast('.')); + } else { + $parent = null; + } + + return $definition->execute($this, $parent); + } return null; diff --git a/tests/Feature/HasMediaTest.php b/tests/Feature/HasMediaTest.php index a637d31..f3feea2 100644 --- a/tests/Feature/HasMediaTest.php +++ b/tests/Feature/HasMediaTest.php @@ -147,6 +147,27 @@ }); +it('generates non existing parents conversions when executing nested conversion', function () { + Storage::fake('media'); + $model = new Test; + $model->save(); + + $media = $model->addMedia( + file: $this->getTestFile('videos/horizontal.mp4'), + collectionName: 'conversions-delayed', + disk: 'media' + ); + + expect($media->conversions)->toHaveLength(0); + + $media->executeConversion('poster.360'); + + expect($media->conversions)->toHaveLength(2); + + expect($media->getConversion('poster'))->not->toBe(null); + expect($media->getConversion('poster.360'))->not->toBe(null); +}); + it('deletes old media when adding to single collection', function () { Storage::fake('media'); $model = new Test; diff --git a/tests/Models/Test.php b/tests/Models/Test.php index 3f46682..ddb4f75 100644 --- a/tests/Models/Test.php +++ b/tests/Models/Test.php @@ -94,6 +94,27 @@ public function registerMediaCollections(): Arrayable|iterable|null ), ] ), + new MediaCollection( + name: 'conversions-delayed', + single: false, + public: false, + conversions: [ + new MediaConversionPoster( + name: 'poster', + queued: false, + immediate: false, + conversions: [ + new MediaConversionImage( + name: '360', + width: 360, + queued: false, + immediate: true, + ), + ] + ), + + ] + ), ]; } }