-
database/migrations/2020_06_30_000000_create_attachments_table.php
Open in GitHubpublic function up(): void { Schema::create('attachments', function (Blueprint $table) { $table->increments('id'); $table->morphs('attachable'); $table->string('file'); $table->timestamps(); $table->softDeletes(); }); }
-
app/Models/Attachment.php
Open in GitHubuse Azuriom\Models\Traits\HasImage; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class Attachment extends Model { use HasImage; use SoftDeletes; protected string $imageKey = 'file'; public function attachable() { return $this->morphTo('attachable'); } protected function resolveImagePath(string $path = ''): string { return $this->attachable->getAttachmentsPath().'/'.$path; } }
-
app/Models/Traits/Attachable.php
Open in GitHubuse Azuriom\Models\Attachment; use Azuriom\Models\PendingAttachment; use Illuminate\Http\UploadedFile; use Illuminate\Support\Str; trait Attachable { public static function bootAttachable(): void { static::updated(function (self $model) { $content = $model->getAttribute($model->getAttachmentsKey()); if ($model->getOriginal($model->getAttachmentsKey()) === $content) { return; } $attachments = $model->attachments()->withTrashed()->get(); foreach ($attachments as $attachment) { if (Str::contains($content, $attachment->file)) { if ($attachment->trashed()) { $attachment->restore(); } } elseif (! $attachment->trashed()) { $attachment->delete(); } } }); static::deleted(function (self $model) { $attachments = $model->attachments()->withTrashed()->get(); foreach ($attachments as $attachment) { $attachment->setRelation('attachable', $model)->forceDelete(); } }); } public static function storePendingAttachment(string $pendingId, UploadedFile $file): string { $attachment = new PendingAttachment([ 'pending_id' => $pendingId, 'pending_type' => (new self())->getAttachmentsType(), ]); return $attachment->storeImage($file, true); } public function persistPendingAttachments(?string $pendingId): void { if ($pendingId === null) { return; } $attachments = PendingAttachment::where('pending_id', $pendingId) ->where('pending_type', $this->getAttachmentsType()) ->get(); $content = $this->getAttribute($this->getAttachmentsKey()); foreach ($attachments as $attachment) { if (Str::contains($content, $attachment->file)) { $this->attachments() ->make() ->forceFill(['file' => $attachment->file]) ->save(); // We don't want to delete the file since now a permanent attachment use it $attachment->forceFill(['file' => null]); } // Delete the pending attachment, and the file if it was not used $attachment->delete(); } } public function storeAttachment(UploadedFile $file): string { /** @var \Azuriom\Models\Attachment $attachment */ $attachment = $this->attachments()->make(); return $attachment->storeImage($file, true); } public function attachments() { return $this->morphMany(Attachment::class, 'attachable'); } public function getAttachmentsKey(): string { return 'content'; } public function getAttachmentsType(): string { return (new self())->getMorphClass(); } public function getAttachmentsPath(): string { return Str::replace('_', '/', $this->getTable()).'/attachments'; } }
-
app/Http/Controllers/Admin/PageAttachmentController.php
Open in GitHubuse Azuriom\Http\Controllers\Controller; use Azuriom\Http\Requests\AttachmentRequest; use Azuriom\Models\Page; class PageAttachmentController extends Controller { public function store(AttachmentRequest $request, Page $page) { $imageUrl = $page->storeAttachment($request->file('file')); return response()->json(['location' => $imageUrl]); } // ... }
-
app/Models/Page.php
Open in GitHubclass Page extends Model { use Attachable; use Loggable; // ...
-
app/Models/Post.php
Open in GitHubclass Post extends Model { use Attachable; use HasFactory; use HasImage; use HasUser; use Loggable; // ...