Skip to content

Commit 78bf97b

Browse files
committed
fix: repair uc relationships, improve retreiving uuids
1 parent 7c636c4 commit 78bf97b

File tree

8 files changed

+729
-111
lines changed

8 files changed

+729
-111
lines changed

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
"Backstage\\Fields\\": "packages/fields/src/",
7575
"Backstage\\Fields\\Database\\Factories\\": "packages/fields/database/factories/",
7676
"Backstage\\Media\\": "packages/media/src/",
77+
"Backstage\\UploadcareField\\": "packages/uploadcare-field/src/",
7778
"Backstage\\Database\\Factories\\": "database/factories/",
7879
"Backstage\\Database\\Seeders\\": "database/seeders/"
7980
},
@@ -83,7 +84,8 @@
8384
},
8485
"autoload-dev": {
8586
"psr-4": {
86-
"Backstage\\Tests\\": "tests/"
87+
"Backstage\\Tests\\": "tests/",
88+
"Backstage\\UploadcareField\\Tests\\": "packages/uploadcare-field/tests/"
8789
}
8890
},
8991
"scripts": {

packages/filament-uploadcare-field/src/Forms/Components/Uploadcare.php

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)