@@ -73,15 +73,15 @@ public function mount(?int $modelId = null, ?string $modelClass = null): void
7373
7474 $ this ->modelClass = $ this ->modelClass ? str_replace ('\\\\' , '\\' , $ this ->modelClass ) : null ;
7575
76- if ($ this ->modelClass && ! class_exists ($ this ->modelClass )) {
76+ if ($ this ->modelClass && !class_exists ($ this ->modelClass )) {
7777 throw new \Exception (__ ('media::fields.class_not_found ' , ['class ' => $ this ->modelClass ]));
7878 }
7979
8080 if ($ this ->modelId && $ this ->modelClass ) {
8181 $ this ->model = app ($ this ->modelClass )::find ($ this ->modelId );
8282 }
8383
84- if (! $ this ->modelId || ! $ this ->model ) {
84+ if (!$ this ->modelId || !$ this ->model ) {
8585 $ this ->modelId = 0 ;
8686 }
8787 }
@@ -91,13 +91,34 @@ public function form(Form $form): Form
9191 $ upload = FileUpload::make (__ ('files ' ))
9292 ->label (__ ('media::fields.upload ' ))
9393 ->afterStateUpdated (function ($ state ) {
94- if (! $ state ) {
94+ if (!$ state ) {
9595 return ;
9696 }
9797
9898 $ processedFiles = session ('processed_files ' , []);
9999
100- if (! is_array ($ state )) {
100+ if (!is_array ($ state )) {
101+ $ fileHash = hash_file ('sha256 ' , $ state ->getRealPath ());
102+ $ fileName = $ state ->getClientOriginalName ();
103+
104+ $ existingMedia = Media::whereHas ('translations ' , function ($ query ) use ($ fileName ) {
105+ $ query ->where ('name ' , $ fileName );
106+ })->orWhere (function ($ query ) use ($ fileHash ) {
107+ $ query ->where ('custom_properties->file_hash ' , $ fileHash );
108+ })->first ();
109+
110+ if ($ existingMedia ) {
111+ \Filament \Notifications \Notification::make ()
112+ ->warning ()
113+ ->title (__ ('media::fields.duplicate_file ' ))
114+ ->body (__ ('media::fields.duplicate_file_message ' , [
115+ 'fileName ' => $ fileName ,
116+ ]))
117+ ->persistent ()
118+ ->send ();
119+ return ;
120+ }
121+
101122 $ model = new Media ;
102123 $ model ->exists = true ;
103124
@@ -116,6 +137,8 @@ public function form(Form $form): Form
116137 $ media ->uploader_type = $ user ? get_class ($ user ) : null ;
117138 $ media ->uploader_id = $ user ?->id;
118139
140+ $ media ->setCustomProperty ('file_hash ' , $ fileHash );
141+
119142 if (str_starts_with ($ media ->mime_type , 'image/ ' )) {
120143 [$ width , $ height ] = getimagesize ($ media ->getPath ());
121144 $ media ->setCustomProperty ('dimensions ' , [
@@ -131,6 +154,27 @@ public function form(Form $form): Form
131154 continue ;
132155 }
133156
157+ $ fileHash = hash_file ('sha256 ' , $ tempFile ->getRealPath ());
158+ $ fileName = $ tempFile ->getClientOriginalName ();
159+
160+ $ existingMedia = Media::whereHas ('translations ' , function ($ query ) use ($ fileName ) {
161+ $ query ->where ('name ' , $ fileName );
162+ })->orWhere (function ($ query ) use ($ fileHash ) {
163+ $ query ->where ('custom_properties->file_hash ' , $ fileHash );
164+ })->first ();
165+
166+ if ($ existingMedia ) {
167+ \Filament \Notifications \Notification::make ()
168+ ->warning ()
169+ ->title (__ ('media::fields.duplicate_file ' ))
170+ ->body (__ ('media::fields.duplicate_file_message ' , [
171+ 'fileName ' => $ fileName ,
172+ ]))
173+ ->persistent ()
174+ ->send ();
175+ continue ;
176+ }
177+
134178 $ model = new Media ;
135179 $ model ->exists = true ;
136180
@@ -149,6 +193,8 @@ public function form(Form $form): Form
149193 $ media ->uploader_type = $ user ? get_class ($ user ) : null ;
150194 $ media ->uploader_id = $ user ?->id;
151195
196+ $ media ->setCustomProperty ('file_hash ' , $ fileHash );
197+
152198 if (str_starts_with ($ media ->mime_type , 'image/ ' )) {
153199 [$ width , $ height ] = getimagesize ($ media ->getPath ());
154200 $ media ->setCustomProperty ('dimensions ' , [
@@ -241,7 +287,7 @@ public function toggleMediaSelection(int $mediaId)
241287 $ this ->selectedMediaIds [] = $ mediaId ;
242288 }
243289 } else {
244- if (! empty ($ this ->selectedMediaIds ) && $ this ->selectedMediaIds [0 ] === $ mediaId ) {
290+ if (!empty ($ this ->selectedMediaIds ) && $ this ->selectedMediaIds [0 ] === $ mediaId ) {
245291 $ this ->selectedMediaIds = [];
246292 } else {
247293 $ this ->selectedMediaIds = [$ mediaId ];
@@ -256,7 +302,7 @@ public function toggleMediaSelection(int $mediaId)
256302 if (isset ($ media ->uploader ->name )) {
257303 $ uploaderName = $ media ->uploader ->name ;
258304 } elseif (isset ($ media ->uploader ->first_name ) && isset ($ media ->uploader ->last_name )) {
259- $ uploaderName = $ media ->uploader ->first_name . ' ' . $ media ->uploader ->last_name ;
305+ $ uploaderName = $ media ->uploader ->first_name . ' ' . $ media ->uploader ->last_name ;
260306 }
261307 }
262308
@@ -301,7 +347,7 @@ public function applySelection()
301347 $ selectedMedia = Media::whereIn ('id ' , $ this ->selectedMediaIds )->get ();
302348
303349 if ($ selectedMedia ->isNotEmpty ()) {
304- if (! $ this ->multiple ) {
350+ if (!$ this ->multiple ) {
305351 $ media = $ selectedMedia ->first ();
306352 $ this ->dispatch ('mediaSelected ' , [
307353 'id ' => $ media ->id ,
@@ -311,7 +357,7 @@ public function applySelection()
311357 'name ' => $ media ->getAttribute ('name ' ),
312358 ]);
313359 } else {
314- $ selectedMediaData = $ selectedMedia ->map (fn ($ media ) => [
360+ $ selectedMediaData = $ selectedMedia ->map (fn ($ media ) => [
315361 'id ' => $ media ->id ,
316362 'url ' => $ media ->getUrl (),
317363 'file_name ' => $ media ->file_name ,
@@ -364,10 +410,10 @@ public function render()
364410 $ media = Media::query ()
365411 ->when ($ this ->searchQuery , function ($ query ) {
366412 $ query ->where (function ($ subQuery ) {
367- $ subQuery ->where ('file_name ' , 'like ' , '% ' . $ this ->searchQuery . '% ' )
368- ->orWhereRaw ('LOWER(JSON_EXTRACT(translations, "$.*.title")) LIKE ? ' , ['% ' . strtolower ($ this ->searchQuery ). '% ' ])
369- ->orWhereRaw ('LOWER(JSON_EXTRACT(translations, "$.*.description")) LIKE ? ' , ['% ' . strtolower ($ this ->searchQuery ). '% ' ])
370- ->orWhereRaw ('LOWER(JSON_EXTRACT(translations, "$.*.alt")) LIKE ? ' , ['% ' . strtolower ($ this ->searchQuery ). '% ' ]);
413+ $ subQuery ->where ('file_name ' , 'like ' , '% ' . $ this ->searchQuery . '% ' )
414+ ->orWhereRaw ('LOWER(JSON_EXTRACT(translations, "$.*.title")) LIKE ? ' , ['% ' . strtolower ($ this ->searchQuery ) . '% ' ])
415+ ->orWhereRaw ('LOWER(JSON_EXTRACT(translations, "$.*.description")) LIKE ? ' , ['% ' . strtolower ($ this ->searchQuery ) . '% ' ])
416+ ->orWhereRaw ('LOWER(JSON_EXTRACT(translations, "$.*.alt")) LIKE ? ' , ['% ' . strtolower ($ this ->searchQuery ) . '% ' ]);
371417 });
372418 })
373419 ->when ($ this ->fileTypeFilter , function ($ query ) {
@@ -446,25 +492,25 @@ public function render()
446492 $ uploader = $ media ->uploader ;
447493 if ($ uploader && method_exists ($ uploader , 'getName ' )) {
448494 return [
449- 'id ' => $ media ->uploader_type . ':: ' . $ media ->uploader_id ,
495+ 'id ' => $ media ->uploader_type . ':: ' . $ media ->uploader_id ,
450496 'name ' => $ uploader ->getName (),
451497 ];
452498 }
453499 if ($ uploader && isset ($ uploader ->name )) {
454500 return [
455- 'id ' => $ media ->uploader_type . ':: ' . $ media ->uploader_id ,
501+ 'id ' => $ media ->uploader_type . ':: ' . $ media ->uploader_id ,
456502 'name ' => $ uploader ->name ,
457503 ];
458504 }
459505
460506 return null ;
461507 })
462508 ->filter ()
463- ->unique (fn (array $ item ): string => $ item ['id ' ])
509+ ->unique (fn (array $ item ): string => $ item ['id ' ])
464510 ->pluck ('name ' , 'id ' )
465511 ->toArray ();
466512
467- if (! empty ($ uploaders )) {
513+ if (!empty ($ uploaders )) {
468514 $ typeName = class_basename ($ type );
469515 $ uploaderOptions [$ typeName ] = $ uploaders ;
470516 }
0 commit comments