@@ -282,6 +282,28 @@ public function getState(): mixed
282282 {
283283 $ state = parent ::getState ();
284284
285+ // Handle double-encoded JSON or JSON strings
286+ if (is_string ($ state ) && json_validate ($ state )) {
287+ $ state = json_decode ($ state , true );
288+ }
289+
290+ // Resolve Backstage Media ULIDs (26-char) into Uploadcare CDN URLs / UUIDs,
291+ // so the widget can show a preview even when the database stores ULIDs.
292+ if (is_array ($ state ) && ! empty ($ state ) && self ::isListOfUlids ($ state )) {
293+ $ resolved = self ::resolveUlidsToUploadcareState ($ state );
294+ if (! empty ($ resolved )) {
295+ $ state = $ resolved ;
296+ }
297+ }
298+
299+ // Handle array of file objects (extract UUIDs / URLs)
300+ if (is_array ($ state ) && ! empty ($ state )) {
301+ $ values = self ::extractValues ($ state );
302+ if (! empty ($ values )) {
303+ $ state = $ values ;
304+ }
305+ }
306+
285307 if ($ state === '[] ' || $ state === '"" ' || $ state === null || $ state === '' ) {
286308 return null ;
287309 }
@@ -298,6 +320,102 @@ public function getState(): mixed
298320 return $ state ;
299321 }
300322
323+ private static function isListOfUlids (array $ state ): bool
324+ {
325+ if (! isset ($ state [0 ]) || ! is_string ($ state [0 ])) {
326+ return false ;
327+ }
328+
329+ return (bool ) preg_match ('/^[0-9A-HJKMNP-TV-Z]{26}$/i ' , $ state [0 ]);
330+ }
331+
332+ private static function extractUuidFromString (string $ value ): ?string
333+ {
334+ if (preg_match ('/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/i ' , $ value , $ matches )) {
335+ return $ matches [1 ];
336+ }
337+
338+ return null ;
339+ }
340+
341+ private static function resolveUlidsToUploadcareState (array $ ulids ): array
342+ {
343+ $ mediaModel = config ('backstage.media.model ' , \Backstage \Media \Models \Media::class);
344+
345+ if (! is_string ($ mediaModel ) || ! class_exists ($ mediaModel )) {
346+ return [];
347+ }
348+
349+ $ mediaItems = $ mediaModel ::whereIn ('ulid ' , array_filter ($ ulids , 'is_string ' ))
350+ ->get ()
351+ ->keyBy ('ulid ' );
352+
353+ $ resolved = [];
354+
355+ foreach ($ ulids as $ ulid ) {
356+ if (! is_string ($ ulid )) {
357+ continue ;
358+ }
359+
360+ $ media = $ mediaItems ->get ($ ulid );
361+ if (! $ media ) {
362+ continue ;
363+ }
364+
365+ $ metadata = $ media ->metadata ?? null ;
366+ if (is_string ($ metadata )) {
367+ $ metadata = json_decode ($ metadata , true );
368+ }
369+ $ metadata = is_array ($ metadata ) ? $ metadata : [];
370+
371+ $ editMeta = $ media ->edit ?? null ;
372+ if (is_string ($ editMeta )) {
373+ $ editMeta = json_decode ($ editMeta , true );
374+ }
375+ if (is_array ($ editMeta )) {
376+ $ metadata = array_merge ($ metadata , $ editMeta );
377+ }
378+
379+ $ cdnUrl = $ metadata ['cdnUrl ' ] ?? ($ metadata ['fileInfo ' ]['cdnUrl ' ] ?? null );
380+ $ uuid = $ metadata ['uuid ' ] ?? ($ metadata ['fileInfo ' ]['uuid ' ] ?? null );
381+
382+ if (! $ uuid && is_string ($ media ->filename ?? null )) {
383+ $ uuid = self ::extractUuidFromString ($ media ->filename );
384+ }
385+ if (! $ uuid && is_string ($ cdnUrl )) {
386+ $ uuid = self ::extractUuidFromString ($ cdnUrl );
387+ }
388+
389+ if ((! $ cdnUrl || ! filter_var ($ cdnUrl , FILTER_VALIDATE_URL )) && $ uuid ) {
390+ $ cdnUrl = 'https://ucarecdn.com/ ' . $ uuid . '/ ' ;
391+ }
392+
393+ if (is_string ($ cdnUrl ) && filter_var ($ cdnUrl , FILTER_VALIDATE_URL )) {
394+ $ resolved [] = $ cdnUrl ;
395+ } elseif ($ uuid ) {
396+ $ resolved [] = $ uuid ;
397+ }
398+ }
399+
400+ return $ resolved ;
401+ }
402+
403+ private static function extractValues (array $ state ): array
404+ {
405+ $ keys = ['cdnUrl ' , 'ucarecdn ' , 'uuid ' , 'filename ' ];
406+
407+ foreach ($ keys as $ key ) {
408+ $ values = \Illuminate \Support \Arr::pluck ($ state , $ key );
409+ $ filtered = array_filter ($ values );
410+
411+ if (! empty ($ filtered )) {
412+ return array_values ($ filtered );
413+ }
414+ }
415+
416+ return [];
417+ }
418+
301419 private function transformUrls ($ value , string $ from , string $ to ): mixed
302420 {
303421 $ decodeIfJson = function ($ v ) use (&$ decodeIfJson ) {
0 commit comments