platform
platform copied to clipboard
Bug when you use yout own Attachment Model
Orchid offers a system to use your own models instead of theirs when you need to add logic to them.
It has always worked well for me but with one of the models it fails. Specifically with the Attachment model.
When in the AppServiceProvider you add the following line:
Dashboard :: useModel (\Orchid\Attachment\Models\Attachment::class, \App\Models\Attachment::class);
trying to upload a file through a DropZone fails.
Browsing the vendor I have verified that the Orchid system is used everywhere:
Dashboard::model(Attachment::class)
But in Orchid\Attachment\File.php file, on line 127 the event is called:
event(new UploadFileEvent ($attachment, $this->engine->time()));
Upon entering that method we see that the constructor has the following structure
use Orchid\Attachment\Models\Attachment;
/**
* ImageAttachment constructor.
*
* @param Attachment $attachment
* @param int $time
*/
public function __construct(Attachment $attachment, int $time)
{
$this->attachment = $attachment;
$this->time = $time;
}
Here it throws an error as the constructor receives an instance of the App/Models/Attachment model but expects an instance of the Orchid\Attachment\Models\Attachment model which throws an error and does not upload the file
I have temporarily fixed it by overwriting the systems / files path causing it to lead to my CustomAttachmentController. This file extends the AttachmentController and in turn calls my CustomFile which in turn extends the File. The CustomFile calls a new upload event called CustomUploadFile in which I modify the constructor to expect an instance of my model instead of Orchid.
routes/platform.php
use App\Orchid\Controllers\CustomAttachmentController;
Route::post('systems/files', [CustomAttachmentController::class, 'upload'])
->name('systems.files.upload');
App\Orchid\Controllers\CustomAttachmentController.php
<?php
namespace App\Orchid\Controllers;
use Orchid\Platform\Http\Controllers\Systems\AttachmentController;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use App\Orchid\Classes\CustomFile;
class CustomAttachmentController extends AttachmentController
{
/**
* @param Request $request
*
* @return JsonResponse
*/
public function upload(Request $request)
{
$attachment = collect($request->allFiles())
->flatten()
->map(function (UploadedFile $file) use ($request) {
return $this->createModel($file, $request);
});
$response = $attachment->count() > 1 ? $attachment : $attachment->first();
return response()->json($response);
}
/**
* @param UploadedFile $file
* @param Request $request
*
* @throws BindingResolutionException
*
* @return mixed
*/
private function createModel(UploadedFile $file, Request $request)
{
$model = app()->make(CustomFile::class, [
'file' => $file,
'disk' => $request->get('storage'),
'group' => $request->get('group'),
])->customLoad();
$model->url = $model->url();
return $model;
}
}
App\Orchid\Classes\CustomFile.php
<?php
namespace App\Orchid\Classes;
use Orchid\Attachment\File;
use Orchid\Platform\Dashboard;
use App\Orchid\Events\CustomUploadFileEvent;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Auth;
use Orchid\Attachment\Models\Attachment;
class CustomFile extends File
{
public function customLoad()
{
$attachment = $this->getMatchesHash();
if (! $this->storage->has($this->engine->path())) {
$this->storage->makeDirectory($this->engine->path());
}
if ($attachment === null) {
return $this->save();
}
$attachment = $attachment->replicate()->fill([
'original_name' => $this->file->getClientOriginalName(),
'sort' => 0,
'user_id' => Auth::id(),
'group' => $this->group,
]);
$attachment->save();
return $attachment;
}
/**
* @return Attachment|null
*/
private function getMatchesHash()
{
return Dashboard::model(Attachment::class)::where('hash', $this->engine->hash())
->where('disk', $this->disk)
->first();
}
/**
* @return Model|Attachment
*/
private function save()
{
$this->storage->putFileAs($this->engine->path(), $this->file, $this->engine->fullName(), [
'mime_type' => $this->engine->mime(),
]);
$attachment = Dashboard::model(Attachment::class)::create([
'name' => $this->engine->name(),
'mime' => $this->engine->mime(),
'hash' => $this->engine->hash(),
'extension' => $this->engine->extension(),
'original_name' => $this->file->getClientOriginalName(),
'size' => $this->file->getSize(),
'path' => Str::finish($this->engine->path(), '/'),
'disk' => $this->disk,
'group' => $this->group,
'user_id' => Auth::id(),
]);
event(new CustomUploadFileEvent($attachment, $this->engine->time()));
return $attachment;
}
}
App\Orchid\Events\CustomUploadFileEvent.php
<?php
namespace App\Orchid\Events;
use Orchid\Platform\Events\UploadFileEvent;
use Illuminate\Queue\SerializesModels;
use App\Models\Attachment;
class CustomUploadFileEvent extends UploadFileEvent
{
use SerializesModels;
/**
* @var Attachment
*/
public $attachment;
/**
* @var int
*/
public $time;
/**
* ImageAttachment constructor.
*
* @param Attachment $attachment
* @param int $time
*/
public function __construct(Attachment $attachment, int $time)
{
$this->attachment = $attachment;
$this->time = $time;
}
}
I hope it can be of help to someone if you need it
Hi @wergh. I understand correctly that we need to remove the explicit definition in this place, and then everything will be okay?
public function __construct($attachment, int $time)
{
$this->attachment = $attachment;
$this->time = $time;
}
Hi @wergh. I understand correctly that we need to remove the explicit definition in this place, and then everything will be okay?
public function __construct($attachment, int $time) { $this->attachment = $attachment; $this->time = $time; }
Yes it is.
If you remove the definition, if i use my custom Attachment Model it will work.
@tabuna this seem still not yet fixed. I found almost three files like this. I can do a PR. Ok?
Hi @thewebartisan7, I don't know how relevant this is.
Because if you inherit from the Attachment model and not just replace it, then this should work well.
Can you check?
Yes you are right. In fact I was already using inheritance, but I was worrying that this could create some issue that I didn't found previously.