initial commit
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class CreateCommentRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'diseaseId' => $this->route('diseaseId')
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'diseaseId' => 'required|exists:diseases,id',
|
||||
'content' => 'required|string|max:1000',
|
||||
'parent_id' => 'nullable|exists:comments,id',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use App\Helpers\ResponseJson;
|
||||
use App\Models\Disease;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class CreateDiseaseRecordRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'diseaseId' => $this->route('diseaseId')
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
|
||||
$mimeTypeMap = [
|
||||
'audio' => [
|
||||
'aac', 'midi', 'mp3', 'ogg', 'wav', 'webm', 'flac', 'aiff', 'amr', 'opus'
|
||||
],
|
||||
'video' => [
|
||||
'mp4', 'avi', 'mkv', 'webm', 'ogg', '3gp', 'flv', 'mov',
|
||||
'wmv', 'mpg', 'mpeg', 'm4v', 'h264', 'hevc'
|
||||
],
|
||||
'image' => [
|
||||
'jpeg', 'jpg', 'png', 'gif', 'bmp', 'webp', 'tiff', 'svg', 'heif', 'heic',
|
||||
'ico', 'jp2', 'j2k', 'avif'
|
||||
],
|
||||
'text-document' => [
|
||||
'pdf', 'doc', 'docx', 'txt'
|
||||
],
|
||||
'compressed-document' => [
|
||||
'zip', '7z', 'tar', 'gz', 'rar', 'bz2', 'xz'
|
||||
],
|
||||
'spreadsheet' => [
|
||||
'xls', 'xlsx', 'csv', 'ods'
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
|
||||
$rules = [
|
||||
'diseaseId' => 'required|integer|exists:diseases,id',
|
||||
];
|
||||
|
||||
if ($this->filled('diseaseId')) {
|
||||
try {
|
||||
$disease = Disease::findOrFail($this->route('diseaseId'));
|
||||
|
||||
if ($disease && isset($disease->schema['columns'])){
|
||||
foreach ($disease->schema['columns'] as $column) {
|
||||
$columnName = $column['name'];
|
||||
$columnRules = [];
|
||||
|
||||
// Base validation based on type
|
||||
switch ($column['type']) {
|
||||
case 'string':
|
||||
case 'text':
|
||||
$columnRules[] = 'required|string';
|
||||
break;
|
||||
case 'integer':
|
||||
$columnRules[] = 'required|integer';
|
||||
break;
|
||||
case 'decimal':
|
||||
case 'float':
|
||||
$columnRules[] = 'required|numeric';
|
||||
break;
|
||||
case 'datetime':
|
||||
case 'date':
|
||||
$columnRules[] = 'required|date';
|
||||
break;
|
||||
case 'time':
|
||||
$columnRules[] = 'required|date_format:H:i';
|
||||
break;
|
||||
case 'file':
|
||||
$columnRules[] = 'required';
|
||||
|
||||
if (!empty($column['multiple'])) {
|
||||
// Multiple file upload handling
|
||||
$rules[$columnName] = 'required|array|min:1';
|
||||
|
||||
$fileRules = ['file', 'max:20480'];
|
||||
|
||||
if (!empty($column['format'])) {
|
||||
$category = trim($column['format'], '.');
|
||||
if (array_key_exists($category, $mimeTypeMap)) {
|
||||
$formats = $mimeTypeMap[$category];
|
||||
$fileRules[] = 'mimes:' . implode(',', $formats);
|
||||
} else {
|
||||
Log::warning("Unsupported format '{$column['format']}' for column '{$columnName}'");
|
||||
}
|
||||
}
|
||||
$rules[$columnName . '.*'] = implode('|', $fileRules);
|
||||
// print_r($rules);
|
||||
} else {
|
||||
// Single file upload handling.
|
||||
$columnRules[] = 'required|file|max:20480';
|
||||
|
||||
if (!empty($column['format'])) {
|
||||
$category = trim($column['format'], '.');
|
||||
if (array_key_exists($category, $mimeTypeMap)) {
|
||||
$formats = $mimeTypeMap[$category];
|
||||
$columnRules[] = 'mimes:' . implode(',', $formats);
|
||||
} else {
|
||||
Log::warning("Unsupported format '{$column['format']}' for column '{$columnName}'");
|
||||
}
|
||||
}
|
||||
|
||||
$rules[$columnName] = implode('|', $columnRules);
|
||||
// print_r($rules);
|
||||
}
|
||||
|
||||
// print_r($columnRules);
|
||||
break;
|
||||
case 'boolean':
|
||||
$columnRules[] = 'required|boolean';
|
||||
break;
|
||||
case 'enum':
|
||||
if (!empty($column['options']) && is_array($column['options'])) {
|
||||
$columnRules[] = 'required|string';
|
||||
$columnRules[] = 'in:' . implode(',', $column['options']);
|
||||
}
|
||||
break;
|
||||
case 'email':
|
||||
$columnRules[] = 'required|email';
|
||||
break;
|
||||
case 'phone':
|
||||
$columnRules[] = 'required|string';
|
||||
$columnRules[] = 'regex:/^([0-9\s\-\+\(\)]*)$/';
|
||||
break;
|
||||
}
|
||||
|
||||
if (!empty($columnRules)) {
|
||||
$rules[$columnName] = implode('|', $columnRules);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('Error loading disease schema: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
|
||||
public function validated($key = null, $default = null): array
|
||||
{
|
||||
$validated = parent::validated();
|
||||
|
||||
return [
|
||||
'diseaseId' => $validated['diseaseId'],
|
||||
'data' => collect($validated)
|
||||
->except('diseaseId')
|
||||
->toArray()
|
||||
];
|
||||
}
|
||||
|
||||
protected function failedValidation(Validator $validator)
|
||||
{
|
||||
throw new HttpResponseException(
|
||||
ResponseJson::failedResponse('Validation error', $validator->errors()->toArray())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// public function messages(): array
|
||||
// {
|
||||
// return [
|
||||
// 'diseaseId.required' => 'ID penyakit harus diisi.',
|
||||
// 'diseaseId.integer' => 'ID penyakit harus berupa angka.',
|
||||
// 'diseaseId.exists' => 'ID penyakit tidak ditemukan dalam database.',
|
||||
|
||||
// 'data.*.required' => ':attribute harus diisi.',
|
||||
// 'data.*.string' => ':attribute harus berupa teks.',
|
||||
// 'data.*.integer' => ':attribute harus berupa angka bulat.',
|
||||
// 'data.*.numeric' => ':attribute harus berupa angka.',
|
||||
// 'data.*.date' => ':attribute harus berupa tanggal yang valid.',
|
||||
// 'data.*.date_format' => ':attribute harus dalam format waktu yang valid (HH:MM:SS).',
|
||||
// 'data.*.boolean' => ':attribute harus berupa benar atau salah.',
|
||||
// 'data.*.in' => ':attribute harus salah satu dari pilihan yang tersedia: :values.',
|
||||
// 'data.*.email' => ':attribute harus berupa alamat email yang valid.',
|
||||
// 'data.*.regex' => ':attribute harus berupa nomor telepon yang valid.',
|
||||
|
||||
// // 'data.*.file' => ':attribute harus berupa file.',
|
||||
// // 'data.*.mimes' => ':attribute harus bertipe: :values.',
|
||||
|
||||
// // 'data.*.array' => ':attribute harus dalam format array jika berisi banyak file.',
|
||||
// // Uncommented additional validation for required/nullable
|
||||
// // 'data.*.nullable' => ':attribute boleh dikosongkan.',
|
||||
// // Rules for minimum and maximum values
|
||||
// // 'data.*.min' => ':attribute harus minimal :min.',
|
||||
// // 'data.*.min_digits' => ':attribute harus minimal :min digit.',
|
||||
// // 'data.*.max' => ':attribute maksimal :max.',
|
||||
// // 'data.*.max_digits' => ':attribute maksimal :max digit.',
|
||||
// ];
|
||||
// }
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use App\Helpers\ResponseJson;
|
||||
|
||||
class CreateDiseaseRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string|max:255',
|
||||
'deskripsi' => 'nullable|string|max:65535',
|
||||
'visibilitas' => 'required|in:publik,privat',
|
||||
'schema' => 'required|array',
|
||||
'schema.columns' => 'required|array',
|
||||
'schema.columns.*.name' => [
|
||||
'required',
|
||||
'string',
|
||||
'regex:/^[a-zA-Z0-9_]+$/',
|
||||
'distinct'
|
||||
],
|
||||
'schema.columns.*.type' => 'required|string|in:string,text,integer,decimal,float,date,datetime,time,file,boolean,email,phone',
|
||||
//'schema.columns.*.type' => 'required|string|in:string,integer,enum,decimal,date,file,time,datetime,boolean,array,float,text,email,phone,json,range',
|
||||
'schema.columns.*.options' => 'required_if:schema.columns.*.type,enum|array',
|
||||
'schema.columns.*.format' => 'required_if:schema.columns.*.type,file|string',
|
||||
'schema.columns.*.multiple' => 'boolean|nullable',
|
||||
'schema.columns.*.is_visible' => 'boolean|nullable',
|
||||
//'schema.columns.*.required' => 'boolean|nullable',
|
||||
//'schema.columns.*.min' => 'numeric|nullable',
|
||||
//'schema.columns.*.max' => 'numeric|nullable',
|
||||
//'schema.columns.*.step' => 'numeric|nullable',
|
||||
//'schema.columns.*.default' => 'nullable',
|
||||
//'schema.columns.*.description' => 'string|nullable',
|
||||
//'schema.columns.*.unit' => 'string|nullable',
|
||||
'cover_page' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
|
||||
];
|
||||
}
|
||||
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'name.required' => 'Nama penyakit harus diisi.',
|
||||
'name.max' => 'Nama penyakit maksimal 255 karakter.',
|
||||
'deskripsi.max' => 'Deskripsi penyakit maksimal 65535 karakter.',
|
||||
'schema.required' => 'Schema harus diisi.',
|
||||
'schema.array' => 'Schema harus dalam format yang valid.',
|
||||
'schema.columns.required' => 'Columns dalam schema harus diisi.',
|
||||
'schema.columns.array' => 'Columns harus dalam format array.',
|
||||
'schema.columns.*.name.required' => 'Nama kolom harus diisi.',
|
||||
'schema.columns.*.name.distinct' => 'Nama kolom tidak boleh duplikat',
|
||||
'schema.columns.*.name.regex' => 'Nama kolom hanya boleh berisi huruf, angka, dan underscore tanpa spasi.',
|
||||
'schema.columns.*.type.required' => 'Tipe kolom harus diisi.',
|
||||
'schema.columns.*.type.in' => 'Tipe kolom tidak valid.',
|
||||
'schema.columns.*.options.required_if' => 'Options harus diisi untuk tipe enum.',
|
||||
'schema.columns.*.format.required_if' => 'Format harus diisi untuk tipe file.',
|
||||
'cover_page.image' => 'Cover page harus berupa file gambar.',
|
||||
'cover_page.mimes' => 'Cover page harus berupa file bertipe: jpeg, png, jpg, gif, atau svg.',
|
||||
'cover_page.max' => 'Ukuran cover page maksimal 2MB.',
|
||||
];
|
||||
}
|
||||
|
||||
protected function failedValidation(Validator $validator)
|
||||
{
|
||||
$errors = $validator->errors()->toArray();
|
||||
$pesan = "Field Error";
|
||||
|
||||
foreach ($errors as $field => $message) {
|
||||
if ($message[0] === 'Nama kolom tidak boleh duplikat') {
|
||||
$pesan .= " - Nama kolom tidak boleh duplikat";
|
||||
}
|
||||
|
||||
throw new HttpResponseException(ResponseJson::failedResponse($pesan, [$field => $message[0]]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use App\Helpers\ResponseJson;
|
||||
|
||||
|
||||
class CreateUserRequest extends FormRequest
|
||||
{
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string|max:100',
|
||||
'email' => 'required|email|unique:users,email|max:100',
|
||||
'password' => 'required|string|min:8|max:64|confirmed',
|
||||
// Front end add 'password_confirmation' field
|
||||
'role' => 'required|in:admin,operator,peneliti',
|
||||
'institution' => 'nullable|string|max:255',
|
||||
'gender' => 'nullable|in:male,female,prefer not to say',
|
||||
'phone_number' => 'nullable|string|max:50',
|
||||
'tujuan_permohonan' => 'nullable|string|max:65535',
|
||||
'disease_id' => 'required_if:role,operator|integer|exists:diseases,id'
|
||||
];
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'name.required' => 'Nama harus diisi.',
|
||||
'name.max' => 'Nama maksimal 100 karakter',
|
||||
'email.required' => 'Email harus diisi.',
|
||||
'email.email' => 'Email tidak valid.',
|
||||
'email.max' => 'Email maksimal 100 karakter',
|
||||
'email.unique' => 'Email tersebut sudah terdaftar',
|
||||
'password.required' => 'Password harus diisi.',
|
||||
'password.confirmed' => 'Password konfirmasi tidak sesuai.',
|
||||
'password.min' => 'Password minimal 8 karakter',
|
||||
'password.max' => 'Password maksimal 64 karakter',
|
||||
'role.required' => 'Role harus diisi',
|
||||
'role.in' => 'Role tidak sesuai',
|
||||
'institution.max' => 'Institusi maksimal 255 karakter.',
|
||||
'gender.in' => 'Gender tidak sesuai.',
|
||||
'phone_number.max' => 'Nomor telepon maksimal 50 karakter.',
|
||||
'tujuan_permohonan.max' => 'Tujuan permohonan maksimal 65535 karakter',
|
||||
'disease_id.required_if' => 'Disease IDs harus diisi jika role adalah operator.',
|
||||
'disease_id.integer' => 'Disease IDs harus berupa integer.',
|
||||
'disease_id.*.exists' => 'Setiap Disease ID yang dipilih harus valid dan ada dalam database.',
|
||||
];
|
||||
}
|
||||
|
||||
protected function failedValidation(Validator $validator)
|
||||
{
|
||||
$errors = $validator->errors()->toArray();
|
||||
|
||||
foreach ($errors as $field => $message) {
|
||||
throw new HttpResponseException(ResponseJson::failedResponse("field error", [$field => $message[0]]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class DeleteCommentRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'diseaseId' => $this->route('diseaseId'),
|
||||
'commentId' => $this->route('commentId')
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'diseaseId' => 'required|exists:diseases,id',
|
||||
'commentId' => 'required|exists:comments,id',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use App\Helpers\ResponseJson;
|
||||
|
||||
class DeleteDiseaseRecordRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'diseaseId' => $this->route('diseaseId'),
|
||||
'recordId' => $this->route('recordId'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'diseaseId' => 'required|integer|exists:diseases,id',
|
||||
'recordId' => [
|
||||
'required',
|
||||
'integer',
|
||||
'exists:disease_records,id',
|
||||
function ($attribute, $value, $fail) {
|
||||
$exists = \App\Models\DiseaseRecord::where('id', $value)
|
||||
->where('disease_id', $this->route('diseaseId'))
|
||||
->exists();
|
||||
|
||||
if (!$exists) {
|
||||
$fail('The selected record does not belong to the specified disease.');
|
||||
}
|
||||
},
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
protected function failedValidation(Validator $validator)
|
||||
{
|
||||
throw new HttpResponseException(
|
||||
ResponseJson::failedResponse('Validation error', $validator->errors()->toArray())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use App\Helpers\ResponseJson;
|
||||
|
||||
class DiseaseIdRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'diseaseId' => $this->route('diseaseId'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'diseaseId' => 'required|integer|exists:diseases,id',
|
||||
];
|
||||
}
|
||||
|
||||
protected function failedValidation(Validator $validator)
|
||||
{
|
||||
throw new HttpResponseException(
|
||||
ResponseJson::failedResponse('Validation error', $validator->errors()->toArray())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class EditCommentRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'diseaseId' => $this->route('diseaseId'),
|
||||
'commentId' => $this->route('commentId')
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'diseaseId' => 'required|integer|exists:diseases,id',
|
||||
'commentId' => 'required|integer|exists:comments,id',
|
||||
'content' => 'required|string|max:1000',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use App\Helpers\ResponseJson;
|
||||
use App\Models\Disease;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class EditDiseaseRecordRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'diseaseId' => $this->route('diseaseId'),
|
||||
'recordId' => $this->route('recordId')
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
|
||||
$mimeTypeMap = [
|
||||
'audio' => [
|
||||
'aac', 'midi', 'mp3', 'ogg', 'wav', 'webm', 'flac', 'aiff', 'amr', 'opus'
|
||||
],
|
||||
'video' => [
|
||||
'mp4', 'avi', 'mkv', 'webm', 'ogg', '3gp', 'flv', 'mov',
|
||||
'wmv', 'mpg', 'mpeg', 'm4v', 'h264', 'hevc'
|
||||
],
|
||||
'image' => [
|
||||
'jpeg', 'jpg', 'png', 'gif', 'bmp', 'webp', 'tiff', 'svg', 'heif', 'heic',
|
||||
'ico', 'jp2', 'j2k', 'avif'
|
||||
],
|
||||
'text-document' => [
|
||||
'pdf', 'doc', 'docx', 'txt'
|
||||
],
|
||||
'compressed-document' => [
|
||||
'zip', '7z', 'tar', 'gz', 'rar', 'bz2', 'xz'
|
||||
],
|
||||
'spreadsheet' => [
|
||||
'xls', 'xlsx', 'csv', 'ods'
|
||||
],
|
||||
];
|
||||
|
||||
$rules = [
|
||||
'diseaseId' => 'required|integer|exists:diseases,id',
|
||||
'recordId' => [
|
||||
'required',
|
||||
'integer',
|
||||
'exists:disease_records,id',
|
||||
function ($attribute, $value, $fail) {
|
||||
$exists = \App\Models\DiseaseRecord::where('id', $value)
|
||||
->where('disease_id', $this->route('diseaseId'))
|
||||
->exists();
|
||||
|
||||
if (!$exists) {
|
||||
$fail('The selected record does not belong to the specified disease.');
|
||||
}
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
if ($this->filled('diseaseId')) {
|
||||
try {
|
||||
$disease = Disease::findOrFail($this->route('diseaseId'));
|
||||
if ($disease && isset($disease->schema['columns'])) {
|
||||
|
||||
foreach ($disease->schema['columns'] as $column) {
|
||||
$columnName = $column['name'];
|
||||
$columnRules = [];
|
||||
|
||||
switch ($column['type']) {
|
||||
case 'string':
|
||||
case 'text':
|
||||
$columnRules[] = 'sometimes|required|string';
|
||||
break;
|
||||
case 'integer':
|
||||
$columnRules[] = 'sometimes|required|integer';
|
||||
break;
|
||||
case 'decimal':
|
||||
case 'float':
|
||||
$columnRules[] = 'sometimes|required|numeric';
|
||||
break;
|
||||
case 'datetime':
|
||||
case 'date':
|
||||
$columnRules[] = 'sometimes|required|date';
|
||||
break;
|
||||
case 'time':
|
||||
$columnRules[] = 'sometimes|required|date_format:H:i';
|
||||
break;
|
||||
case 'file':
|
||||
$columnRules[] = 'sometimes|required'; // Ensures a file is uploaded.
|
||||
|
||||
// Check if a 'format' is defined in the schema for the column.
|
||||
if (!empty($column['multiple'])) {
|
||||
// Ensure the field is an array of files.
|
||||
$rules[$columnName] = 'sometimes|required|array|min:1';
|
||||
|
||||
// Apply validation to each file in the array.
|
||||
$fileRules = ['file', 'max:20480']; // Start with basic file validation.
|
||||
|
||||
// Add MIME type validation if a format is specified.
|
||||
if (!empty($column['format'])) {
|
||||
$category = trim($column['format'], '.'); // Strip the dot from the format.
|
||||
if (array_key_exists($category, $mimeTypeMap)) {
|
||||
$formats = $mimeTypeMap[$category];
|
||||
$fileRules[] = 'mimes:' . implode(',', $formats);
|
||||
} else {
|
||||
Log::warning("Unsupported format '{$column['format']}' for column '{$columnName}'");
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the rules to each file in the array.
|
||||
$rules[$columnName . '.*'] = implode('|', $fileRules);
|
||||
// print_r($rules);
|
||||
} else {
|
||||
// Single file upload handling.
|
||||
$columnRules[] = 'sometimes|required|file|max:20480';
|
||||
|
||||
// Add MIME type validation if a format is specified.
|
||||
if (!empty($column['format'])) {
|
||||
$category = trim($column['format'], '.'); // Strip the dot from the format.
|
||||
if (array_key_exists($category, $mimeTypeMap)) {
|
||||
$formats = $mimeTypeMap[$category];
|
||||
$columnRules[] = 'mimes:' . implode(',', $formats);
|
||||
} else {
|
||||
Log::warning("Unsupported format '{$column['format']}' for column '{$columnName}'");
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the accumulated rules for a single file.
|
||||
$rules[$columnName] = implode('|', $columnRules);
|
||||
// print_r($rules);
|
||||
}
|
||||
|
||||
// print_r($columnRules);
|
||||
break;
|
||||
case 'boolean':
|
||||
$columnRules[] = 'sometimes|required|boolean';
|
||||
break;
|
||||
case 'enum':
|
||||
if (!empty($column['options']) && is_array($column['options'])) {
|
||||
$columnRules[] = 'sometimes|required|string';
|
||||
$columnRules[] = 'in:' . implode(',', $column['options']);
|
||||
}
|
||||
break;
|
||||
case 'email':
|
||||
$columnRules[] = 'sometimes|required|email';
|
||||
break;
|
||||
case 'phone':
|
||||
$columnRules[] = 'sometimes|required|string';
|
||||
$columnRules[] = 'regex:/^([0-9\s\-\+\(\)]*)$/';
|
||||
break;
|
||||
}
|
||||
|
||||
// // Add required/nullable validation
|
||||
// if (!empty($column['required'])) {
|
||||
// $columnRules[] = 'required';
|
||||
// } else {
|
||||
// $columnRules[] = 'nullable';
|
||||
// }
|
||||
|
||||
// // Add min/max validation if specified
|
||||
// if (!empty($column['min'])) {
|
||||
// switch ($column['type']) {
|
||||
// case 'string':
|
||||
// case 'text':
|
||||
// $columnRules[] = 'min:' . $column['min'];
|
||||
// break;
|
||||
// case 'integer':
|
||||
// case 'decimal':
|
||||
// case 'float':
|
||||
// $columnRules[] = 'min_digits:' . $column['min'];
|
||||
// break;
|
||||
// case 'file':
|
||||
// $columnRules[] = 'min:' . $column['min']; // min in kilobytes
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (!empty($column['max'])) {
|
||||
// switch ($column['type']) {
|
||||
// case 'string':
|
||||
// case 'text':
|
||||
// $columnRules[] = 'max:' . $column['max'];
|
||||
// break;
|
||||
// case 'integer':
|
||||
// case 'decimal':
|
||||
// case 'float':
|
||||
// $columnRules[] = 'max_digits:' . $column['max'];
|
||||
// break;
|
||||
// case 'file':
|
||||
// $columnRules[] = 'max:' . $column['max']; // max in kilobytes
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!empty($columnRules)) {
|
||||
$rules[$columnName] = implode('|', $columnRules);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('Error loading disease schema: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
public function validated($key = null, $default = null): array
|
||||
{
|
||||
$validated = parent::validated();
|
||||
|
||||
return [
|
||||
'diseaseId' => $validated['diseaseId'],
|
||||
'data' => collect($validated)
|
||||
->except('diseaseId', 'recordId')
|
||||
->toArray()
|
||||
];
|
||||
}
|
||||
|
||||
protected function failedValidation(Validator $validator)
|
||||
{
|
||||
throw new HttpResponseException(
|
||||
ResponseJson::failedResponse('Validation error', $validator->errors()->toArray())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use App\Helpers\ResponseJson;
|
||||
|
||||
class EditDiseaseRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'diseaseId' => $this->route('diseaseId'),
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'diseaseId' => 'required|integer|exists:diseases,id',
|
||||
'name' => 'sometimes|required|string|max:255',
|
||||
'deskripsi' => 'sometimes|nullable|string|max:65535',
|
||||
'visibilitas' => 'sometimes|required|in:publik,privat',
|
||||
//'schema' => 'required|json',
|
||||
'cover_page' => 'sometimes|nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
|
||||
];
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'name.required' => 'Nama penyakit harus diisi.',
|
||||
'name.max' => 'Nama penyakit maksimal 255 karakter.',
|
||||
'deskripsi.max' => 'Deskripsi penyakit maksimal 65535 karakter.',
|
||||
//'schema.required' => 'Schema harus diisi.',
|
||||
//'schema.json' => 'Schema harus dalam format JSON yang valid.',
|
||||
'cover_page.image' => 'Cover page harus berupa file gambar.',
|
||||
'cover_page.mimes' => 'Cover page harus berupa file bertipe: jpeg, png, jpg, gif, atau svg.',
|
||||
'cover_page.max' => 'Ukuran cover page maksimal 2MB.',
|
||||
];
|
||||
}
|
||||
|
||||
protected function failedValidation(Validator $validator)
|
||||
{
|
||||
$errors = $validator->errors()->toArray();
|
||||
|
||||
foreach ($errors as $field => $message) {
|
||||
throw new HttpResponseException(ResponseJson::failedResponse("field error", [$field => $message[0]]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use App\Helpers\ResponseJson;
|
||||
use App\Models\User;
|
||||
|
||||
class EditUserRequest extends FormRequest
|
||||
{
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
|
||||
$user = $this->route('userId');
|
||||
$userRecord = User::find($user);
|
||||
$userRole = $userRecord ? $userRecord->role : null;
|
||||
|
||||
return [
|
||||
'name' => 'sometimes|required|string|max:100',
|
||||
'email' => 'sometimes|nullable|email|unique:users,email,' . $user . '|max:100',
|
||||
'password' => 'sometimes|nullable|string|min:8|max:64|confirmed',
|
||||
'role' => 'sometimes|required|in:admin,operator,peneliti',
|
||||
'institution' => 'nullable|string|max:255',
|
||||
'gender' => 'nullable|in:male,female,prefer not to say',
|
||||
'phone_number' => 'nullable|string|max:50',
|
||||
'approval_status' => 'sometimes|in:approved,pending,rejected',
|
||||
'disease_id' => 'sometimes|integer|exists:diseases,id|required_if:role,operator'
|
||||
];
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'name.required' => 'Nama harus diisi.',
|
||||
'name.max' => 'Nama maksimal 100 karakter',
|
||||
'email.email' => 'Email tidak valid.',
|
||||
'email.max' => 'Email maksimal 100 karakter',
|
||||
'email.unique' => 'Email tersebut sudah terdaftar',
|
||||
'password.min' => 'Password minimal 8 karakter',
|
||||
'password.max' => 'Password maksimal 64 karakter',
|
||||
'password.confirmed' => 'Password konfirmasi tidak sesuai.',
|
||||
'role.required' => 'Role harus diisi',
|
||||
'role.in' => 'Role tidak sesuai',
|
||||
'institution.max' => 'Institusi maksimal 255 karakter.',
|
||||
'gender.in' => 'Gender tidak sesuai.',
|
||||
'phone_number.max' => 'Nomor telepon maksimal 50 karakter.',
|
||||
'approval_status.required' => 'Status Approval harus diisi.',
|
||||
'approval_status.in' => 'Status Approval tidak sesuai.',
|
||||
'disease_id.required_if' => 'Disease IDs harus diisi jika role adalah operator.',
|
||||
'disease_id.integer' => 'Disease IDs harus berupa integer.',
|
||||
'disease_id.*.exists' => 'Setiap Disease ID yang dipilih harus valid dan ada dalam database.',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function failedValidation(Validator $validator)
|
||||
{
|
||||
$errors = $validator->errors()->toArray();
|
||||
|
||||
foreach ($errors as $field => $message) {
|
||||
throw new HttpResponseException(ResponseJson::failedResponse("field error", [$field => $message[0]]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use App\Helpers\ResponseJson;
|
||||
|
||||
class IndexDiseaseRecordRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'diseaseId' => $this->route('diseaseId'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'diseaseId' => 'required|integer|exists:diseases,id',
|
||||
];
|
||||
}
|
||||
|
||||
protected function failedValidation(Validator $validator)
|
||||
{
|
||||
throw new HttpResponseException(
|
||||
ResponseJson::failedResponse('Validation error', $validator->errors()->toArray())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use App\Helpers\ResponseJson;
|
||||
|
||||
|
||||
class LoginUserRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'email' => 'required|email|max:100',
|
||||
'password' => 'required|min:8|max:64',
|
||||
];
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'email.required' => 'Email harus diisi',
|
||||
'email.email' => 'Email tidak valid',
|
||||
'email.max' => 'Email Maksimal 100 Karakter',
|
||||
'password.required' => 'Password Harus diisi',
|
||||
'password.min' => 'Password Minimal 8 Karakter',
|
||||
'password.max' => 'Password Maksimal 64 Karakter',
|
||||
];
|
||||
}
|
||||
|
||||
protected function failedValidation(Validator $validator)
|
||||
{
|
||||
$errors = $validator->errors()->toArray();
|
||||
|
||||
foreach ($errors as $field => $message) {
|
||||
throw new HttpResponseException(ResponseJson::failedResponse("field error", [$field => $message[0]]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use App\Helpers\ResponseJson;
|
||||
|
||||
class RegisterUserRequest extends FormRequest
|
||||
{
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string|max:100',
|
||||
'email' => 'required|email|unique:users,email|max:100',
|
||||
'password' => 'required|string|min:8|max:64|confirmed',
|
||||
//Front end include: 'password_confirmation' field
|
||||
'institution' => 'required|string|max:255',
|
||||
'gender' => 'required|in:male,female,prefer not to say',
|
||||
'phone_number' => 'required|string|max:50',
|
||||
'tujuan_permohonan' => 'required|string|max:65535',
|
||||
];
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'name.required' => 'Nama harus diisi.',
|
||||
'name.max' => 'Nama maksimal 100 karakter',
|
||||
'email.required' => 'Email harus diisi.',
|
||||
'email.email' => 'Email tidak valid.',
|
||||
'email.max' => 'Email maksimal 100 karakter',
|
||||
'email.unique' => 'Email tersebut sudah terdaftar, silahkan login.',
|
||||
'password.required' => 'Password harus diisi.',
|
||||
'password.confirmed' => 'Password konfirmasi tidak sesuai.',
|
||||
'password.min' => 'Password minimal 8 karakter',
|
||||
'password.max' => 'Password maksimal 64 karakter',
|
||||
'institution.max' => 'Institusi maksimal 255 karakter.',
|
||||
'gender.in' => 'Gender tidak sesuai.',
|
||||
'phone_number.max' => 'Nomor telepon maksimal 50 karakter.',
|
||||
'tujuan_permohonan.max' => 'Tujuan permohonan maksimal 65535 karakter',
|
||||
];
|
||||
}
|
||||
|
||||
protected function failedValidation(Validator $validator)
|
||||
{
|
||||
$errors = $validator->errors()->toArray();
|
||||
|
||||
foreach ($errors as $field => $message) {
|
||||
throw new HttpResponseException(ResponseJson::failedResponse("field error", [$field => $message[0]]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use App\Helpers\ResponseJson;
|
||||
|
||||
class ShowDiseaseRecordRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'diseaseId' => $this->route('diseaseId'),
|
||||
'recordId' => $this->route('recordId')
|
||||
]);
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'diseaseId' => 'required|integer|exists:diseases,id',
|
||||
'recordId' => [
|
||||
'required',
|
||||
'integer',
|
||||
'exists:disease_records,id',
|
||||
function ($attribute, $value, $fail) {
|
||||
$exists = \App\Models\DiseaseRecord::where('id', $value)
|
||||
->where('disease_id', $this->route('diseaseId'))
|
||||
->exists();
|
||||
|
||||
if (!$exists) {
|
||||
$fail('The selected record does not belong to the specified disease.');
|
||||
}
|
||||
},
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
protected function failedValidation(Validator $validator)
|
||||
{
|
||||
throw new HttpResponseException(
|
||||
ResponseJson::failedResponse('Validation error', $validator->errors()->toArray())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use App\Helpers\ResponseJson;
|
||||
|
||||
class UserIdRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'userId' => $this->route('userId'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'userId' => 'required|integer|exists:users,id',
|
||||
];
|
||||
}
|
||||
|
||||
protected function failedValidation(Validator $validator)
|
||||
{
|
||||
throw new HttpResponseException(
|
||||
ResponseJson::failedResponse('Validation error', $validator->errors()->toArray())
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user