From 561b4e0d366834d091ae7cba0eafb39de19791fb Mon Sep 17 00:00:00 2001 From: Krishanu <36711704+krishzzi@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:12:56 +0530 Subject: [PATCH] spatie media support added --- src/Actions/SpatieMediaAction.php | 66 ++++++++++ src/TipTapMedia.php | 97 +++++++++++++++ src/Traits/HasMediaActionFormSchema.php | 155 ++++++++++++++++++++++++ src/Traits/HasMediaActionSupport.php | 59 +++++++++ 4 files changed, 377 insertions(+) create mode 100644 src/Actions/SpatieMediaAction.php create mode 100644 src/TipTapMedia.php create mode 100644 src/Traits/HasMediaActionFormSchema.php create mode 100644 src/Traits/HasMediaActionSupport.php diff --git a/src/Actions/SpatieMediaAction.php b/src/Actions/SpatieMediaAction.php new file mode 100644 index 00000000..c9a0c8db --- /dev/null +++ b/src/Actions/SpatieMediaAction.php @@ -0,0 +1,66 @@ +view('asdf') + ->arguments(TipTapMedia::getTipTapEditorDefaultArguments()) + ->modalWidth('fit') + ->slideOver() + ->form(fn(TiptapEditor $component,ComponentContainer $form) => $this->getFormSchema($component,$form)) + ->mountUsing(fn (TiptapEditor $component, ComponentContainer $form, array $arguments) => $this->getMountWith($component,$form,$arguments)) + ->modalHeading(fn (array $arguments) => 'Media Manager') + ->action(fn(TiptapEditor $component, array $data) => $this->handleTipTapMediaAction($component,$data)) + + ; + } + + protected function handleTipTapMediaAction(TiptapEditor $component, array $data): void + { + $source = $this->getCleanSourceOnSave($data); + + $component->getLivewire()->dispatch( + event: 'insertFromAction', + type: 'media', + statePath: $component->getStatePath(), + media: [ + 'src' => $source, + 'alt' => $data['alt'] ?? null, + 'title' => $data['title'], + 'width' => $data['width'], + 'height' => $data['height'], + 'lazy' => $data['lazy'] ?? false, + 'link_text' => $data['link_text'] ?? null, + ], + ); + } + + +} \ No newline at end of file diff --git a/src/TipTapMedia.php b/src/TipTapMedia.php new file mode 100644 index 00000000..b0da60fc --- /dev/null +++ b/src/TipTapMedia.php @@ -0,0 +1,97 @@ + '', + 'alt' => '', + 'title' => '', + 'width' => '', + 'height' => '', + 'lazy' => null, + ]; + } + + + /** + * @param Model|TiptapEditor|null $component + * @return string + */ + public static function mediaCollection(null|Model|TiptapEditor $component = null): string + { + if ($component instanceof TiptapEditor) + { + return Str::afterLast($component->getModel(), '\\') . 'TipTapMedia'; + }elseif($component instanceof Model) + { + return Str::afterLast(get_class($component), '\\') . 'TipTapMedia'; + }else{ + return 'TipTapMedia'; + } + + } + + + /** + * @param Model $record + * @param array $columns + * @return void + */ + public static function OnCreated(Model $record,array $columns): void + { + foreach ($columns as $column) + { + preg_match_all('@/]*/?>@Ui', $record->{$column}, $allPreviousMatchedImages); + $images = $allPreviousMatchedImages[1]; + + foreach ($images as $image) + { + $cleanImagePath = Storage::path('public'.Str::remove(config('app.url').'/storage',$image)); + $spatieMedia = $record->addMedia($cleanImagePath)->toMediaCollection(self::mediaCollection($record)); + $newUrl = $spatieMedia->getUrl(); + // Update Content + $record->{$column} = Str::replace($image,$newUrl,$record->{$column}); + + } + } + $record->save(); + } + + + public static function OnSaved(Model $record,array $columns): void + { + $record->load([ + 'media' => fn($query) => $query->where('collection_name',self::mediaCollection($record)) + ]); + + $spatieMediaList = $record->media->mapWithKeys(function ($media) { + return [$media->uuid => $media->getUrl()]; + })->toArray(); + + foreach ($columns as $column) + { + preg_match_all('@/]*/?>@Ui', $record->{$column}, $allPreviousMatchedImages); + $images = $allPreviousMatchedImages[1]; + $deletable = array_diff($spatieMediaList,$images); + if (!empty($deletable)) + { + $deletableSpatieRecords = $record->media->whereIn('uuid',array_keys($deletable)); + $deletableSpatieRecords->each->delete(); + } + } + } + + +} diff --git a/src/Traits/HasMediaActionFormSchema.php b/src/Traits/HasMediaActionFormSchema.php new file mode 100644 index 00000000..8df149be --- /dev/null +++ b/src/Traits/HasMediaActionFormSchema.php @@ -0,0 +1,155 @@ + 1 + ])->schema(array_merge($this->getFileUploadFieldSchema($component),$this->getDefaultTipTapFormSchema())) + ]; + } + + + /** + * @return array + */ + public function getDefaultTipTapFormSchema(): array + { + return [ + TextInput::make('link_text') + ->label(trans('filament-tiptap-editor::media-modal.labels.link_text')) + ->required() + ->visible(fn (callable $get) => $get('type') == 'document'), + TextInput::make('alt') + ->label(trans('filament-tiptap-editor::media-modal.labels.alt')) + ->hidden(fn (callable $get) => $get('type') == 'document') + ->hintAction( + Action::make('alt_hint_action') + ->label('?') + ->color('primary') + ->url('https://www.w3.org/WAI/tutorials/images/decision-tree', true) + ), + TextInput::make('title') + ->label(trans('filament-tiptap-editor::media-modal.labels.title')), + Checkbox::make('lazy') + ->label(trans('filament-tiptap-editor::media-modal.labels.lazy')) + ->default(false), + Group::make([ + TextInput::make('width'), + TextInput::make('height'), + ])->columns(), + Hidden::make('type') + ->default('document'), + ]; + } + + + /** + * @param TiptapEditor $component + * @return array + */ + public function getFileUploadFieldSchema(TiptapEditor $component): array + { + return [ + FileUpload::make('src') + ->label(trans('filament-tiptap-editor::media-modal.labels.file')) + ->disk($component->getDisk()) + ->visibility(config('filament-tiptap-editor.visibility')) + ->preserveFilenames(config('filament-tiptap-editor.preserve_file_names')) + ->acceptedFileTypes($component->getAcceptedFileTypes()) + ->maxFiles(1) + ->maxSize($component->getMaxFileSize()) + ->imageResizeMode(config('filament-tiptap-editor.image_resize_mode')) + ->imageCropAspectRatio(config('filament-tiptap-editor.image_crop_aspect_ratio')) + ->imageResizeTargetWidth(config('filament-tiptap-editor.image_resize_target_width')) + ->imageResizeTargetHeight(config('filament-tiptap-editor.image_resize_target_height')) + ->required() + ->live() + ->imageEditor() + ->afterStateUpdated(function (TemporaryUploadedFile $state, callable $set) { + $set('type', Str::contains($state->getMimeType(), 'image') ? 'image' : 'document'); + if ($dimensions = $state->dimensions()) { + $set('width', $dimensions[0]); + $set('height', $dimensions[1]); + } + }) + ->saveUploadedFileUsing(static function (BaseFileUpload $component, TemporaryUploadedFile $file, ?Model $record) { + return is_null($record) ? self::OnCreate($component,$file,$record) : self::OnUpdate($component,$file,$record); + }) + ]; + } + + + /** + * @param BaseFileUpload $component + * @param TemporaryUploadedFile $file + * @param Model|null $record + * @return mixed + */ + protected static function OnUpdate(BaseFileUpload $component, TemporaryUploadedFile $file, ?Model $record) + { + $filename = $component->shouldPreserveFilenames() ? pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME) : Str::uuid(); + $extension = $file->getClientOriginalExtension(); + $filename = $filename . '-' . time() . '.' . $extension; + $mediaInstance = $record->addMedia($file) + ->usingFileName($filename) + ->toMediaCollection(TipTapMedia::mediaCollection($record)); + + return $mediaInstance->getUrl(); + } + + + /** + * @param BaseFileUpload $component + * @param TemporaryUploadedFile $file + * @param Model|null $record + * @return mixed + */ + protected static function OnCreate(BaseFileUpload $component, TemporaryUploadedFile $file, ?Model $record) + { + $filename = $component->shouldPreserveFilenames() ? pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME) : Str::uuid(); + $storeMethod = $component->getVisibility() === 'public' ? 'storePubliclyAs' : 'storeAs'; + $extension = $file->getClientOriginalExtension(); + if (Storage::disk($component->getDiskName())->exists(ltrim($component->getDirectory() . '/' . $filename . '.' . $extension, '/'))) { + $filename = $filename . '-' . time(); + } + + $upload = $file->{$storeMethod}($component->getDirectory(), $filename . '.' . $extension, $component->getDiskName()); + + return Storage::disk($component->getDiskName())->url($upload); + } + + + + + + +} diff --git a/src/Traits/HasMediaActionSupport.php b/src/Traits/HasMediaActionSupport.php new file mode 100644 index 00000000..cd3cbb28 --- /dev/null +++ b/src/Traits/HasMediaActionSupport.php @@ -0,0 +1,59 @@ +getDirectory() . Str::of($source) + ->after($component->getDirectory()) + : null; + return Str::afterLast($source,'storage/'); + } + + + + public function getCleanSourceOnSave(array $data) + { + if (config('filament-tiptap-editor.use_relative_paths')) { + $source = Str::of($data['src']) + ->replace(config('app.url'), '') + ->ltrim('/') + ->prepend('/'); + } else { + $source = str_starts_with($data['src'], 'http') + ? $data['src'] + : Storage::disk(config('filament-tiptap-editor.disk'))->url($data['src']); + } + + return $source; + } + + + + protected function getMountWith(TiptapEditor $component, ComponentContainer $form, array $arguments): void + { + $source = $this->getCleanSource($component, $arguments['src']); + + $form->fill([ + 'src' => $source, + 'alt' => $arguments['alt'] ?? '', + 'title' => $arguments['title'] ?? '', + 'width' => $arguments['width'] ?? '', + 'height' => $arguments['height'] ?? '', + 'lazy' => $arguments['lazy'] ?? false, + ]); + } + + + +}