2026-10-13 12:44:00 +02:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
|
|
|
|
|
|
|
|
use App\Models\Devoir;
|
|
|
|
|
|
use App\Models\Eleve;
|
|
|
|
|
|
use App\Models\RenduDevoir;
|
2026-10-14 09:52:15 +02:00
|
|
|
|
use App\Services\Stockage\StockageTravauxEleves;
|
2026-10-13 12:44:00 +02:00
|
|
|
|
use Illuminate\Http\RedirectResponse;
|
|
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
|
|
use Illuminate\View\View;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Côté élève des devoirs maison (chantier « vrai cockpit », étape 3) :
|
|
|
|
|
|
* rendu en texte libre, une seule fois par devoir, avant l'échéance.
|
|
|
|
|
|
*/
|
|
|
|
|
|
class DevoirEleveController extends Controller
|
|
|
|
|
|
{
|
|
|
|
|
|
public function show(Devoir $devoir): View
|
|
|
|
|
|
{
|
|
|
|
|
|
$eleve = $this->verifierAppartenance($devoir);
|
|
|
|
|
|
|
|
|
|
|
|
return view('devoirs.eleve', [
|
|
|
|
|
|
'devoir' => $devoir,
|
|
|
|
|
|
'rendu' => RenduDevoir::where('devoir_id', $devoir->id)->where('eleve_id', $eleve->id)->first(),
|
2026-10-14 09:52:15 +02:00
|
|
|
|
'depotFichierDisponible' => StockageTravauxEleves::disponible(),
|
2026-10-13 12:44:00 +02:00
|
|
|
|
]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function rendre(Request $request, Devoir $devoir): RedirectResponse
|
|
|
|
|
|
{
|
|
|
|
|
|
$eleve = $this->verifierAppartenance($devoir);
|
|
|
|
|
|
abort_if($devoir->echeanceDepassee(), 409, 'L’échéance est dépassée.');
|
|
|
|
|
|
|
2026-10-14 09:52:15 +02:00
|
|
|
|
$donnees = $request->validate([
|
|
|
|
|
|
'reponse' => ['nullable', 'required_without:fichier', 'string', 'max:10000'],
|
|
|
|
|
|
'fichier' => [
|
|
|
|
|
|
'nullable', 'required_without:reponse', 'file',
|
|
|
|
|
|
'max:'.(int) (StockageTravauxEleves::TAILLE_MAX_OCTETS / 1024),
|
|
|
|
|
|
'mimes:'.implode(',', StockageTravauxEleves::EXTENSIONS_ACCEPTEES),
|
|
|
|
|
|
],
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
if ($request->hasFile('fichier') && ! StockageTravauxEleves::disponible()) {
|
|
|
|
|
|
abort(503, 'Le dépôt de fichier n’est pas disponible pour le moment.');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$ancienRendu = RenduDevoir::where('devoir_id', $devoir->id)->where('eleve_id', $eleve->id)->first();
|
|
|
|
|
|
|
|
|
|
|
|
$valeurs = ['reponse' => $donnees['reponse'] ?? null, 'rendu_a' => now()];
|
|
|
|
|
|
|
|
|
|
|
|
// Pas de nouveau fichier : celui déjà rendu (s'il existe) reste en
|
|
|
|
|
|
// place, updateOrCreate ne touche pas aux colonnes absentes de $valeurs.
|
|
|
|
|
|
if ($request->hasFile('fichier')) {
|
|
|
|
|
|
$fichier = StockageTravauxEleves::stocker($request->file('fichier'), (string) $devoir->id, (string) $eleve->id);
|
|
|
|
|
|
$valeurs['fichier_chemin'] = $fichier['chemin'];
|
|
|
|
|
|
$valeurs['fichier_nom_original'] = $fichier['nom_original'];
|
|
|
|
|
|
$valeurs['fichier_taille_octets'] = $fichier['taille_octets'];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RenduDevoir::updateOrCreate(['devoir_id' => $devoir->id, 'eleve_id' => $eleve->id], $valeurs);
|
2026-10-13 12:44:00 +02:00
|
|
|
|
|
2026-10-14 09:52:15 +02:00
|
|
|
|
// Un nouveau fichier remplace l'ancien : celui-ci n'a plus de raison
|
|
|
|
|
|
// d'exister sur Object Storage.
|
|
|
|
|
|
if ($request->hasFile('fichier') && $ancienRendu?->fichier_chemin) {
|
|
|
|
|
|
StockageTravauxEleves::supprimer($ancienRendu->fichier_chemin);
|
|
|
|
|
|
}
|
2026-10-13 12:44:00 +02:00
|
|
|
|
|
|
|
|
|
|
return redirect()->route('devoirs.eleve.show', $devoir)->with('rendu_envoye', true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private function verifierAppartenance(Devoir $devoir): Eleve
|
|
|
|
|
|
{
|
|
|
|
|
|
$eleve = Auth::guard('eleve')->user();
|
|
|
|
|
|
abort_if($devoir->classe_id !== $eleve->classe_id, 403);
|
|
|
|
|
|
|
|
|
|
|
|
return $eleve;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|