laravel-vue-file-share/app/Http/Requests/UploadFiles.php
2023-10-17 22:45:04 -07:00

126 lines
4.5 KiB
PHP

<?php
namespace App\Http\Requests;
use App\Http\Requests\ParentId;
use App\Models\File;
use Illuminate\Support\Facades\Auth;
class UploadFiles extends ParentId
{
// authorization handled by ParentId
// validation
protected function prepareForValidation() {
$paths = array_filter($this->paths ?? [],
fn($f) => $f != null
);
$this->merge([
'file_paths' => $paths,
'folder_name' => $this->getFolder($paths)
]);
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return array_merge(parent::rules(),
[
'files.*' => [
'required',
'file',
function ($attribute, $value, $fail) {
// if this is not a folder, apply file validation to file
if (!$this->folder_name) {
// find if a file with the same parameters already exists
$file = File::query()
->where('name', $value->getClientOriginalName())
->where('created_by', Auth::id())
->where('parent_id', $this->parent_id)
->whereNull('deleted_at');
if ($file->exists()) {
$fail('File already exists.');
}
}
}
],
'folder_name' => [
'nullable',
'string',
function ($attribute, $value, $fail) {
// if the folder name was passed in, that is if the path was not empty
if ($value) {
// find if a folder with the same parameters already exists
$folder = File::query()
->where('name', $value)
->where('created_by', Auth::id())
->where('parent_id', $this->parent_id)
->whereNull('deleted_at');
if ($folder->exists()) {
$fail('Folder already exists.');
}
}
}
]
]);
}
protected function passedValidation() {
// get validated data
$data = $this->validated();
// replace object with file tree (function below)
$this->replace([
'file_tree' => $this->makeTree($this->file_paths, $data['files'])
]);
}
// returns folder path for uploaded file
public function getFolder($paths) {
if (!$paths) return null;
$url = explode("/", $paths[0]);
return $url[0];
}
// makes file tree from paths and files
private function makeTree($paths, $files) {
// match $paths array count to $files array count in case there is a difference between the two
$paths = array_slice($paths, 0, count($files));
// filter away empty values
$paths = array_filter($paths, fn($path) => $path != null);
// build the tree
$fileTree = [];
foreach ($paths as $index => $path) {
// get full path as array of url components separated by slashes
$url = explode("/", $path);
$node = &$fileTree; // get node on file tree - passed by reference for modification
foreach ($url as $urlIndex => $urlComponent) {
// if there is no node value at the current $urlIndex, make empty array for value
// example: /test/file.png
// $node[$urlComponent] at test becomes empty array holding the files inside
if(!isset($node[$urlComponent])) {
$node[$urlComponent] = [];
}
// if at the last index in $url, the current index is the uploaded file itself
// file can be found at the files array at the same index as $index since $paths has been filtered
// otherwise, set $node to current node and continue loop
$urlIndex == (count($url) - 1) ? $node[$urlComponent] = $files[$index] : $node = &$node[$urlComponent];
}
}
// return completed $fileTree after loop complete and nodes are made for every file
return $fileTree;
}
}