Skip to content

Commit

Permalink
added docs and optimized
Browse files Browse the repository at this point in the history
  • Loading branch information
krishzzi committed Oct 18, 2024
1 parent 561b4e0 commit 7ed7097
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 109 deletions.
70 changes: 43 additions & 27 deletions src/Actions/SpatieMediaAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,58 +9,74 @@
use Filament\Forms\Components\Actions\Action;
use FilamentTiptapEditor\TiptapEditor;

/**
* Class SpatieMediaAction
*
* Handles media-related actions within the Tiptap editor using Spatie's media handling.
* This action enables users to insert media such as images or videos into the editor.
*/
class SpatieMediaAction extends Action
{
use HasMediaActionSupport, HasMediaActionFormSchema;

use HasMediaActionSupport,HasMediaActionFormSchema;

/**
* Constant defining the column layout for the form schema.
*/
public const FORM_COLUMN = 5;

/**
* Provides the default action name.
*
* @return string|null The default name of the action.
*/
public static function getDefaultName(): ?string
{
return 'filament_tiptap_media';
}





/**
* Set up the action with view, arguments, and other form settings.
*/
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))

;
->view('asdf') // View to be rendered, should be replaced with the actual view path
->arguments(TipTapMedia::getTipTapEditorDefaultArguments()) // Default arguments for TipTap editor
->modalWidth('fit') // Modal width setting
->slideOver() // Modal behavior
->form(fn (TiptapEditor $component, ComponentContainer $form) => $this->getFormSchema($component, $form)) // Form schema definition
->mountUsing(fn (TiptapEditor $component, ComponentContainer $form, array $arguments) => $this->getMountWith($component, $form, $arguments)) // Mount form with provided arguments
->modalHeading(fn (array $arguments) => 'Media Manager') // Modal heading definition
->action(fn(TiptapEditor $component, array $data) => $this->handleTipTapMediaAction($component, $data)); // Action handling for media insertion
}

/**
* Handles the action of inserting media into the editor.
*
* @param TiptapEditor $component The editor component instance.
* @param array $data The media data collected from the form.
*/
protected function handleTipTapMediaAction(TiptapEditor $component, array $data): void
{
// Clean the source URL before saving
$source = $this->getCleanSourceOnSave($data);

// Dispatch the media insertion event to the Livewire component
$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,
],
'src' => $source, // Source URL of the media
'alt' => $data['alt'] ?? null, // Alt text for the media
'title' => $data['title'], // Title for the media
'width' => $data['width'], // Width of the media
'height' => $data['height'], // Height of the media
'lazy' => $data['lazy'] ?? false, // Lazy loading flag
'link_text' => $data['link_text'] ?? null, // Link text for the media, if applicable
]
);
}


}
}
72 changes: 39 additions & 33 deletions src/TipTapMedia.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
namespace FilamentTiptapEditor;

use FilamentTiptapEditor\TiptapEditor;

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

class TipTapMedia
{


/**
* Get the default arguments for the TipTap editor.
*
* @return array
*/
public static function getTipTapEditorDefaultArguments(): array
{
return [
Expand All @@ -24,74 +26,78 @@ public static function getTipTapEditorDefaultArguments(): array
];
}


/**
* Get the media collection name based on the model or editor.
*
* @param Model|TiptapEditor|null $component
* @return string
*/
public static function mediaCollection(null|Model|TiptapEditor $component = null): string
{
if ($component instanceof TiptapEditor)
{
if ($component instanceof TiptapEditor) {
return Str::afterLast($component->getModel(), '\\') . 'TipTapMedia';
}elseif($component instanceof Model)
{
} elseif ($component instanceof Model) {
return Str::afterLast(get_class($component), '\\') . 'TipTapMedia';
}else{
} else {
return 'TipTapMedia';
}

}


/**
* @param Model $record
* @param array $columns
* Handle media creation and update image URLs in the given columns.
*
* @param Model $record The Eloquent model instance.
* @param array $columns The columns to check for images.
* @return void
*/
public static function OnCreated(Model $record,array $columns): void
public static function OnCreated(Model $record, array $columns): void
{
foreach ($columns as $column)
{
foreach ($columns as $column) {
// Find all images in the content
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));
foreach ($images as $image) {
$cleanImagePath = Storage::path('public' . Str::remove(config('app.url') . '/storage', $image));
// Add media to the collection
$spatieMedia = $record->addMedia($cleanImagePath)->toMediaCollection(self::mediaCollection($record));
$newUrl = $spatieMedia->getUrl();
// Update Content
$record->{$column} = Str::replace($image,$newUrl,$record->{$column});

// Update the content with the new media URL
$record->{$column} = Str::replace($image, $newUrl, $record->{$column});
}
}
$record->save();
}


public static function OnSaved(Model $record,array $columns): void
/**
* Handle media updates after saving the record.
*
* @param Model $record The Eloquent model instance.
* @param array $columns The columns to check for images.
* @return void
*/
public static function OnSaved(Model $record, array $columns): void
{
$record->load([
'media' => fn($query) => $query->where('collection_name',self::mediaCollection($record))
'media' => fn ($query) => $query->where('collection_name', self::mediaCollection($record)),
]);

// Create a map of UUIDs to media URLs
$spatieMediaList = $record->media->mapWithKeys(function ($media) {
return [$media->uuid => $media->getUrl()];
})->toArray();

foreach ($columns as $column)
{
foreach ($columns as $column) {
// Find all images in the content
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));

// Determine the deletable media (not present in the content anymore)
$deletable = array_diff($spatieMediaList, $images);
if (!empty($deletable)) {
$deletableSpatieRecords = $record->media->whereIn('uuid', array_keys($deletable));
$deletableSpatieRecords->each->delete();
}
}
}


}
65 changes: 31 additions & 34 deletions src/Traits/HasMediaActionFormSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace FilamentTiptapEditor\Traits;


use Filament\Forms\ComponentContainer;
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Components\BaseFileUpload;
Expand All @@ -21,25 +20,25 @@

trait HasMediaActionFormSchema
{


/**
* @param TiptapEditor $component
* @param ComponentContainer $form
* @return array
* Get the form schema for the media action.
*
* @param TiptapEditor $component The editor component.
* @param ComponentContainer $form The form container.
* @return array The form schema.
*/
protected function getFormSchema(TiptapEditor $component,ComponentContainer $form): array
protected function getFormSchema(TiptapEditor $component, ComponentContainer $form): array
{
return [
Grid::make([
'md' => 1
])->schema(array_merge($this->getFileUploadFieldSchema($component),$this->getDefaultTipTapFormSchema()))
Grid::make(['md' => 1])
->schema(array_merge($this->getFileUploadFieldSchema($component), $this->getDefaultTipTapFormSchema()))
];
}


/**
* @return array
* Get the default form schema for TipTap media modal.
*
* @return array The default form schema.
*/
public function getDefaultTipTapFormSchema(): array
{
Expand All @@ -66,15 +65,15 @@ public function getDefaultTipTapFormSchema(): array
TextInput::make('width'),
TextInput::make('height'),
])->columns(),
Hidden::make('type')
->default('document'),
Hidden::make('type')->default('document'),
];
}


/**
* @param TiptapEditor $component
* @return array
* Get the file upload field schema for media action.
*
* @param TiptapEditor $component The editor component.
* @return array The file upload field schema.
*/
public function getFileUploadFieldSchema(TiptapEditor $component): array
{
Expand Down Expand Up @@ -102,42 +101,46 @@ public function getFileUploadFieldSchema(TiptapEditor $component): array
}
})
->saveUploadedFileUsing(static function (BaseFileUpload $component, TemporaryUploadedFile $file, ?Model $record) {
return is_null($record) ? self::OnCreate($component,$file,$record) : self::OnUpdate($component,$file,$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
* Handle file update for the media action.
*
* @param BaseFileUpload $component The file upload component.
* @param TemporaryUploadedFile $file The uploaded file.
* @param Model|null $record The model instance.
* @return mixed The URL of the updated media.
*/
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
* Handle file creation for the media action.
*
* @param BaseFileUpload $component The file upload component.
* @param TemporaryUploadedFile $file The uploaded file.
* @param Model|null $record The model instance.
* @return mixed The URL of the newly uploaded file.
*/
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();
}
Expand All @@ -146,10 +149,4 @@ protected static function OnCreate(BaseFileUpload $component, TemporaryUploadedF

return Storage::disk($component->getDiskName())->url($upload);
}






}
Loading

0 comments on commit 7ed7097

Please sign in to comment.