add controllers, servoices

This commit is contained in:
root
2026-03-09 02:52:13 -04:00
parent c8de5f7edc
commit d76c871cb7
501 changed files with 34439 additions and 21843 deletions
@@ -0,0 +1,45 @@
<?php
namespace App\Services\Files;
use Illuminate\Support\Facades\DB;
class ExamDraftDownloadNameService
{
public function build(string $filename, string $subdir): string
{
$column = $subdir === 'finals' ? 'final_file' : 'teacher_file';
$row = DB::table('exam_drafts as ed')
->select('ed.version', 'ed.exam_type', 'ed.class_section_id', 'cs.class_section_name')
->leftJoin('classSection as cs', 'cs.class_section_id', '=', 'ed.class_section_id')
->where('ed.' . $column, $filename)
->limit(1)
->first();
$row = $row ? (array) $row : [];
$classLabel = trim((string) ($row['class_section_name'] ?? ('Class' . ($row['class_section_id'] ?? '0'))));
$typeLabel = trim((string) ($row['exam_type'] ?? 'Exam'));
$version = 'v' . max(1, (int) ($row['version'] ?? 1));
$parts = array_filter([
$this->slugify($classLabel),
$this->slugify($typeLabel),
$version,
]);
return implode('_', $parts);
}
private function slugify(string $value): string
{
$value = trim($value);
$value = preg_replace('/[^\p{L}\p{N}]+/u', '_', $value);
$value = trim($value, '_');
if ($value === '') {
return 'Exam';
}
return mb_strtolower($value);
}
}
+112
View File
@@ -0,0 +1,112 @@
<?php
namespace App\Services\Files;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
class FileServeService
{
public function meta(string $baseDir, string $name, array $allowedExtensions, ?string $downloadName = null): array
{
return $this->resolveFile($baseDir, $name, $allowedExtensions, $downloadName);
}
public function serveInline(
string $baseDir,
string $name,
array $allowedExtensions,
Request $request,
?string $downloadName = null,
bool $nosniff = false
): Response {
$meta = $this->resolveFile($baseDir, $name, $allowedExtensions, $downloadName);
$ifNoneMatch = trim((string) $request->headers->get('If-None-Match', ''), '"');
$ifModifiedSince = (string) $request->headers->get('If-Modified-Since', '');
$imsTime = $ifModifiedSince !== '' ? strtotime($ifModifiedSince) : false;
if (($ifNoneMatch !== '' && $ifNoneMatch === $meta['etag']) ||
($imsTime !== false && $imsTime >= $meta['mtime'])
) {
return response('', 304, $this->notModifiedHeaders($meta));
}
$headers = [
'Content-Type' => $meta['mime'],
'Content-Disposition' => 'inline; filename="' . $meta['download_name'] . '"',
'Content-Length' => (string) $meta['size'],
'ETag' => $meta['etag'],
'Last-Modified' => $meta['last_modified'],
'Cache-Control' => 'public, max-age=86400',
];
if ($nosniff) {
$headers['X-Content-Type-Options'] = 'nosniff';
}
return response(file_get_contents($meta['path']), 200, $headers);
}
private function resolveFile(string $baseDir, string $name, array $allowedExtensions, ?string $downloadName): array
{
if ($name !== basename($name)) {
throw new HttpException(400, 'Invalid filename');
}
$ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
if (!in_array($ext, $allowedExtensions, true)) {
throw new HttpException(404, 'File not found');
}
$path = rtrim($baseDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $name;
if (!is_file($path)) {
throw new HttpException(404, 'File not found');
}
$mime = $this->detectMime($path);
$mtime = filemtime($path) ?: time();
$size = filesize($path) ?: 0;
$etag = md5($name . '|' . $mtime . '|' . $size);
$downloadName = $downloadName ? $downloadName . '.' . $ext : $name;
return [
'name' => $name,
'path' => $path,
'mime' => $mime,
'mtime' => $mtime,
'size' => $size,
'etag' => $etag,
'download_name' => $downloadName,
'last_modified' => gmdate('D, d M Y H:i:s', $mtime) . ' GMT',
];
}
private function detectMime(string $path): string
{
$mime = 'application/octet-stream';
if (function_exists('finfo_open')) {
$fi = finfo_open(FILEINFO_MIME_TYPE);
if ($fi) {
$detected = finfo_file($fi, $path);
if ($detected) {
$mime = $detected;
}
finfo_close($fi);
}
} elseif (function_exists('mime_content_type')) {
$mime = mime_content_type($path) ?: $mime;
}
return $mime;
}
private function notModifiedHeaders(array $meta): array
{
return [
'ETag' => $meta['etag'],
'Last-Modified' => $meta['last_modified'],
];
}
}