233 lines
6.9 KiB
PHP
233 lines
6.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Repositories;
|
|
|
|
use App\Models\File;
|
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Database\Eloquent\Collection;
|
|
|
|
class FileRepository extends BaseRepository implements FileRepositoryInterface
|
|
{
|
|
public function __construct(File $model)
|
|
{
|
|
parent::__construct($model);
|
|
}
|
|
|
|
/**
|
|
* Get paginated files with filtering
|
|
*/
|
|
public function paginate(int $perPage = 15, array $filters = []): LengthAwarePaginator
|
|
{
|
|
$query = $this->model->newQuery();
|
|
|
|
// Apply filters
|
|
if (!empty($filters['search'])) {
|
|
$query->where('file_name', 'like', '%' . $filters['search'] . '%');
|
|
}
|
|
|
|
if (!empty($filters['mime_type'])) {
|
|
$query->where('mime_type', 'like', '%' . $filters['mime_type'] . '%');
|
|
}
|
|
|
|
if (!empty($filters['uploaded_by'])) {
|
|
$query->where('uploaded_by', $filters['uploaded_by']);
|
|
}
|
|
|
|
if (!empty($filters['category'])) {
|
|
// Extract category from storage_uri path
|
|
$query->where('storage_uri', 'like', '%/' . $filters['category'] . '/%');
|
|
}
|
|
|
|
if (!empty($filters['client_id'])) {
|
|
// Extract client files from storage path
|
|
$query->where('storage_uri', 'like', '%/client/' . $filters['client_id'] . '/%');
|
|
}
|
|
|
|
// Date range filter
|
|
if (!empty($filters['date_from'])) {
|
|
$query->whereDate('uploaded_at', '>=', $filters['date_from']);
|
|
}
|
|
|
|
if (!empty($filters['date_to'])) {
|
|
$query->whereDate('uploaded_at', '<=', $filters['date_to']);
|
|
}
|
|
|
|
// Apply sorting
|
|
$sortField = $filters['sort_by'] ?? 'uploaded_at';
|
|
$sortDirection = $filters['sort_direction'] ?? 'desc';
|
|
$query->orderBy($sortField, $sortDirection);
|
|
|
|
return $query->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* Get files by category/type (e.g., devis, facture)
|
|
*/
|
|
public function getByCategory(string $category, int $perPage = 15): LengthAwarePaginator
|
|
{
|
|
return $this->model->newQuery()
|
|
->where('storage_uri', 'like', '%/' . $category . '/%')
|
|
->orderBy('uploaded_at', 'desc')
|
|
->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* Get files by client ID
|
|
*/
|
|
public function getByClient(int $clientId, int $perPage = 15): LengthAwarePaginator
|
|
{
|
|
return $this->model->newQuery()
|
|
->where('storage_uri', 'like', '%/client/' . $clientId . '/%')
|
|
->orderBy('uploaded_at', 'desc')
|
|
->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* Get files by user/uploader
|
|
*/
|
|
public function getByUploader(int $uploaderId, int $perPage = 15): LengthAwarePaginator
|
|
{
|
|
return $this->model->newQuery()
|
|
->where('uploaded_by', $uploaderId)
|
|
->orderBy('uploaded_at', 'desc')
|
|
->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* Search files by filename
|
|
*/
|
|
public function search(string $searchTerm, int $perPage = 15): LengthAwarePaginator
|
|
{
|
|
return $this->model->newQuery()
|
|
->where('file_name', 'like', '%' . $searchTerm . '%')
|
|
->orWhere('storage_uri', 'like', '%' . $searchTerm . '%')
|
|
->orderBy('uploaded_at', 'desc')
|
|
->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* Get recent files
|
|
*/
|
|
public function getRecent(int $limit = 10): Collection
|
|
{
|
|
return $this->model->newQuery()
|
|
->orderBy('uploaded_at', 'desc')
|
|
->limit($limit)
|
|
->get();
|
|
}
|
|
|
|
/**
|
|
* Get files by storage path pattern
|
|
*/
|
|
public function getByPathPattern(string $pattern, int $perPage = 15): LengthAwarePaginator
|
|
{
|
|
return $this->model->newQuery()
|
|
->where('storage_uri', 'like', '%' . $pattern . '%')
|
|
->orderBy('uploaded_at', 'desc')
|
|
->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* Get files organized by path structure
|
|
*/
|
|
public function getOrganizedFiles(): Collection
|
|
{
|
|
$files = $this->model->newQuery()
|
|
->orderBy('storage_uri')
|
|
->get();
|
|
|
|
// Group files by their organized path structure
|
|
$organized = collect();
|
|
|
|
foreach ($files as $file) {
|
|
$pathParts = explode('/', $file->storage_uri);
|
|
|
|
// Skip if not enough path parts
|
|
if (count($pathParts) < 3) {
|
|
continue;
|
|
}
|
|
|
|
// Extract structure like: category/subcategory/filename
|
|
$category = $pathParts[count($pathParts) - 3] ?? 'root';
|
|
$subcategory = $pathParts[count($pathParts) - 2] ?? 'general';
|
|
|
|
$key = $category . '/' . $subcategory;
|
|
|
|
if (!$organized->has($key)) {
|
|
$organized->put($key, collect([
|
|
'category' => $category,
|
|
'subcategory' => $subcategory,
|
|
'files' => collect(),
|
|
'count' => 0
|
|
]));
|
|
}
|
|
|
|
$group = $organized->get($key);
|
|
$group['files']->push($file);
|
|
$group['count']++;
|
|
}
|
|
|
|
return $organized;
|
|
}
|
|
|
|
/**
|
|
* Get storage usage statistics
|
|
*/
|
|
public function getStorageStats(): array
|
|
{
|
|
$totalFiles = $this->model->newQuery()->count();
|
|
$totalSize = $this->model->newQuery()->sum('size_bytes');
|
|
|
|
$byType = $this->model->newQuery()
|
|
->selectRaw('mime_type, COUNT(*) as count, SUM(size_bytes) as total_size')
|
|
->groupBy('mime_type')
|
|
->get();
|
|
|
|
$byCategory = $this->model->newQuery()
|
|
->selectRaw('storage_uri, COUNT(*) as count, SUM(size_bytes) as total_size')
|
|
->get()
|
|
->map(function ($item) {
|
|
$pathParts = explode('/', $item->storage_uri);
|
|
$category = $pathParts[count($pathParts) - 3] ?? 'root';
|
|
return [
|
|
'category' => $category,
|
|
'count' => $item->count,
|
|
'total_size' => $item->total_size,
|
|
];
|
|
})
|
|
->groupBy('category')
|
|
->map(function ($items) {
|
|
return [
|
|
'count' => $items->sum('count'),
|
|
'total_size' => $items->sum('total_size'),
|
|
];
|
|
});
|
|
|
|
return [
|
|
'total_files' => $totalFiles,
|
|
'total_size_bytes' => $totalSize,
|
|
'total_size_formatted' => $this->formatBytes($totalSize),
|
|
'by_type' => $byType,
|
|
'by_category' => $byCategory,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Format bytes to human readable format
|
|
*/
|
|
private function formatBytes(int $bytes, int $precision = 2): string
|
|
{
|
|
if ($bytes === 0) {
|
|
return '0 B';
|
|
}
|
|
|
|
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
$base = 1024;
|
|
$factor = floor((strlen($bytes) - 1) / 3);
|
|
|
|
return sprintf("%.{$precision}f", $bytes / pow($base, $factor)) . ' ' . $units[$factor];
|
|
}
|
|
}
|