diff --git a/src/JoliMediaBundle.php b/src/JoliMediaBundle.php index be98c1d5..2f82292e 100644 --- a/src/JoliMediaBundle.php +++ b/src/JoliMediaBundle.php @@ -14,6 +14,7 @@ use JoliCode\MediaBundle\Doctrine\Type\MediaType; use JoliCode\MediaBundle\Doctrine\Types; use JoliCode\MediaBundle\Model\Format; +use JoliCode\MediaBundle\Model\Media; use JoliCode\MediaBundle\PreProcessor\HeifPreProcessor; use JoliCode\MediaBundle\Processor\Imagine; use JoliCode\MediaBundle\Transformer\Resize\Mode; @@ -39,6 +40,7 @@ public function boot(): void // doctrine media type $resolverInitializer = fn (): ?object => $this->container->get('joli_media.resolver'); + Media::$resolverInitializer = $resolverInitializer; MediaType::$resolverInitializer = $resolverInitializer; MediaLongType::$resolverInitializer = $resolverInitializer; } diff --git a/src/Model/Media.php b/src/Model/Media.php index cf590955..8956c917 100644 --- a/src/Model/Media.php +++ b/src/Model/Media.php @@ -3,13 +3,22 @@ namespace JoliCode\MediaBundle\Model; use JoliCode\MediaBundle\Binary\Binary; +use JoliCode\MediaBundle\Exception\MediaNotFoundException; use JoliCode\MediaBundle\Library\Library; +use JoliCode\MediaBundle\Resolver\Resolver; use JoliCode\MediaBundle\Storage\OriginalStorage; use JoliCode\MediaBundle\Variation\Variation; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; class Media implements StorableInterface { + /** + * @var callable(): Resolver|null + */ + public static $resolverInitializer; + + private static Resolver $resolver; + /** * @var array */ @@ -26,7 +35,35 @@ public function __construct( public function __serialize(): array { - return [$this->path, $this->storage->getLibrary()->getName()]; + return [ + 'path' => $this->path, + 'library' => $this->storage->getLibrary()->getName(), + ]; + } + + /** + * @param array $data + */ + public function __unserialize(array $data): void + { + $path = $data['path'] ?? $data[0] ?? null; + $libraryName = $data['library'] ?? $data[1] ?? null; + + if (!\is_string($path) || !\is_string($libraryName)) { + throw new \UnexpectedValueException('Invalid serialized media payload.'); + } + + try { + $resolvedMedia = $this->getResolver()->resolveMedia($path, $libraryName); + } catch (MediaNotFoundException) { + $resolvedMedia = $this->getResolver()->createUnresolvedMedia($path, $libraryName); + } + + $this->path = $resolvedMedia->path; + $this->storage = $resolvedMedia->storage; + $this->binary = null; + $this->stored = null; + $this->variations = []; } public function addVariation(MediaVariation $variation): void @@ -214,4 +251,17 @@ public function store(?Binary $binary = null): void $this->storage->createMediaFromBinary($this->path, $this->binary); $this->stored = true; } + + private function getResolver(): Resolver + { + if (!isset(self::$resolver)) { + if (!isset(self::$resolverInitializer)) { + throw new \LogicException('Resolver Initializer is not set.'); + } + + self::$resolver = (self::$resolverInitializer)(); + } + + return self::$resolver; + } } diff --git a/tests/src/Bridge/EasyAdmin/Controller/MediaAdminControllerTest.php b/tests/src/Bridge/EasyAdmin/Controller/MediaAdminControllerTest.php index d0a27fbd..f8e994ad 100644 --- a/tests/src/Bridge/EasyAdmin/Controller/MediaAdminControllerTest.php +++ b/tests/src/Bridge/EasyAdmin/Controller/MediaAdminControllerTest.php @@ -119,7 +119,7 @@ public function testUploadAtRoot(): void $responseContent = $this->client->getResponse()->getContent(); $this->assertIsString($responseContent); - $response = json_decode($responseContent, true); + $response = json_decode((string) $responseContent, true); $this->assertArrayHasKey('files', $response); $this->assertCount(1, $response['files']); @@ -192,7 +192,7 @@ protected static function getKernelClass(): string private function findInGalleryFromName(Crawler $crawler, string $name): Crawler { return $crawler->filter('ul.gallery-grid--files .gallery-grid-item__link') - ->reduce(static fn (Crawler $node): bool => str_contains($node->filter('.gallery-grid-item__name')->text(), $name)) + ->reduce(static fn (Crawler $node): bool => str_contains((string) $node->filter('.gallery-grid-item__name')->text(), $name)) ; } } diff --git a/tests/src/Model/MediaTest.php b/tests/src/Model/MediaTest.php index 35a4091d..205519cf 100644 --- a/tests/src/Model/MediaTest.php +++ b/tests/src/Model/MediaTest.php @@ -7,6 +7,7 @@ use JoliCode\MediaBundle\Binary\Binary; use JoliCode\MediaBundle\Model\Format; use JoliCode\MediaBundle\Model\Media; +use JoliCode\MediaBundle\Resolver\Resolver; use JoliCode\MediaBundle\Tests\BaseTestCase; class MediaTest extends BaseTestCase @@ -160,4 +161,29 @@ public function testStoreWithNoBinary(): void $media->store(); } + + public function testSerializeUnserializeRestoresMedia(): void + { + Media::$resolverInitializer = fn (): Resolver => $this->resolver; + + $restored = unserialize(serialize($this->media)); + + self::assertInstanceOf(Media::class, $restored); + self::assertSame('test.jpg', $restored->getPath()); + self::assertSame('default', $restored->getLibrary()->getName()); + } + + public function testUnserializeSupportsLegacyIndexedPayload(): void + { + Media::$resolverInitializer = fn (): Resolver => $this->resolver; + + $restored = (new \ReflectionClass(Media::class))->newInstanceWithoutConstructor(); + $restored->__unserialize([ + 0 => 'test.jpg', + 1 => 'default', + ]); + + self::assertSame('test.jpg', $restored->getPath()); + self::assertSame('default', $restored->getLibrary()->getName()); + } } diff --git a/tests/src/Storage/CacheKeyWithSubfolderTest.php b/tests/src/Storage/CacheKeyWithSubfolderTest.php index d0ba9c01..a2835bf4 100644 --- a/tests/src/Storage/CacheKeyWithSubfolderTest.php +++ b/tests/src/Storage/CacheKeyWithSubfolderTest.php @@ -34,8 +34,6 @@ class CacheKeyWithSubfolderTest extends TestCase protected function setUp(): void { - parent::setUp(); - $this->cache = new ArrayAdapter(); $this->filesystem = new Filesystem(new InMemoryFilesystemAdapter()); $this->mimeTypeGuesser = new MimeTypeGuesser(new MimeTypes(), new FileBinaryMimeTypeGuesser()); diff --git a/tests/src/Twig/Component/ImgTest.php b/tests/src/Twig/Component/ImgTest.php index 8b81aa96..3492a5dd 100644 --- a/tests/src/Twig/Component/ImgTest.php +++ b/tests/src/Twig/Component/ImgTest.php @@ -31,8 +31,6 @@ class ImgTest extends BaseTestCase public static function setUpBeforeClass(): void { - parent::setUpBeforeClass(); - $container = static::getContainer(); /** @var Converter */ @@ -78,8 +76,6 @@ public static function setUpBeforeClass(): void public static function tearDownAfterClass(): void { - parent::tearDownAfterClass(); - $container = static::getContainer(); /** @var LibraryContainer */ @@ -106,7 +102,7 @@ public function testComponents(string $component, array $configuration, string $ ); $crawler = new Crawler(\sprintf('%s', $rendered)); $img = $crawler->filterXPath('//body/*')->first(); - $html = preg_replace(['/(\n\s*)+/', '/\s+/'], ['', ' '], $img->outerHtml()); + $html = preg_replace(['/(\n\s*)+/', '/\s+/'], ['', ' '], (string) $img->outerHtml()); if ($expected !== $html) { echo "\n\n" . $html . "\n\n"; diff --git a/tests/src/Twig/Component/PictureTest.php b/tests/src/Twig/Component/PictureTest.php index 9bdcac0e..6b516df1 100644 --- a/tests/src/Twig/Component/PictureTest.php +++ b/tests/src/Twig/Component/PictureTest.php @@ -104,7 +104,7 @@ public function testComponents(string $component, array $configuration, string $ ); $crawler = new Crawler(\sprintf('%s', $rendered)); $img = $crawler->filterXPath('//body/*')->first(); - $html = preg_replace(['/(\n\s*)+/', '/\s+/'], ['', ' '], $img->outerHtml()); + $html = preg_replace(['/(\n\s*)+/', '/\s+/'], ['', ' '], (string) $img->outerHtml()); // @phpstan-ignore-next-line if (Kernel::MAJOR_VERSION < 8 && !(Kernel::MAJOR_VERSION === 7 && Kernel::MINOR_VERSION === 4 && \PHP_VERSION_ID >= 80400)) {