Skip to content

Commit

Permalink
spatie media support added
Browse files Browse the repository at this point in the history
  • Loading branch information
krishzzi committed Oct 18, 2024
1 parent 2fac924 commit 561b4e0
Show file tree
Hide file tree
Showing 4 changed files with 377 additions and 0 deletions.
66 changes: 66 additions & 0 deletions src/Actions/SpatieMediaAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace FilamentTiptapEditor\Actions;

use FilamentTiptapEditor\Traits\HasMediaActionFormSchema;
use FilamentTiptapEditor\Traits\HasMediaActionSupport;
use FilamentTiptapEditor\TipTapMedia;
use Filament\Forms\ComponentContainer;
use Filament\Forms\Components\Actions\Action;
use FilamentTiptapEditor\TiptapEditor;

class SpatieMediaAction extends Action
{

use HasMediaActionSupport,HasMediaActionFormSchema;

public const FORM_COLUMN = 5;

public static function getDefaultName(): ?string
{
return 'filament_tiptap_media';
}





protected function setUp(): void
{
parent::setUp();

$this
->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,
],
);
}


}
97 changes: 97 additions & 0 deletions src/TipTapMedia.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

namespace FilamentTiptapEditor;

use FilamentTiptapEditor\TiptapEditor;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class TipTapMedia
{


public static function getTipTapEditorDefaultArguments(): array
{
return [
'src' => '',
'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('@<img.*src="([^"]*)"[^>/]*/?>@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('@<img.*src="([^"]*)"[^>/]*/?>@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();
}
}
}


}
155 changes: 155 additions & 0 deletions src/Traits/HasMediaActionFormSchema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php

namespace FilamentTiptapEditor\Traits;


use Filament\Forms\ComponentContainer;
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Components\BaseFileUpload;
use Filament\Forms\Components\Checkbox;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Grid;
use Filament\Forms\Components\Group;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\TextInput;
use FilamentTiptapEditor\TiptapEditor;
use FilamentTiptapEditor\TipTapMedia;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;

trait HasMediaActionFormSchema
{


/**
* @param TiptapEditor $component
* @param ComponentContainer $form
* @return array
*/
protected function getFormSchema(TiptapEditor $component,ComponentContainer $form): array
{
return [
Grid::make([
'md' => 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);
}






}
59 changes: 59 additions & 0 deletions src/Traits/HasMediaActionSupport.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace FilamentTiptapEditor\Traits;

use Filament\Forms\ComponentContainer;
use FilamentTiptapEditor\TiptapEditor;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

trait HasMediaActionSupport
{


protected function getCleanSource(TiptapEditor $component,?string $source=null):?string
{
$source = $source !== ''
? $component->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,
]);
}



}

0 comments on commit 561b4e0

Please sign in to comment.