# 🚩 Ejercicio 4 · El formulario que confía

**Clase 4 — Vistas Blade, formularios y validación**
· Dificultad: 🟠 medio-alto · Tiempo estimado: 60–90 min

---

## La situación

El alta de empleados del Liquidador está andando… y ese es el problema. Anda
**demasiado**: acepta cualquier cosa.

```
todo mal           200 con HTML  ← debería redirigir
legajo repetido    200 con HTML  ← debería redirigir
todo bien          200 con HTML  ← debería redirigir
```

Un empleado llamado `Al`, con legajo `1234` y correo `no-es-mail` entra sin
problema. Y hay algo peor, que vas a ver apenas lo corras:

```
  Se dio de alta a alguien llamado:  <script>alert(1)</script>

  Tu vista genera:
  <li><script>alert(1)</script> — L-9999</li>

  ⚠ El navegador va a EJECUTAR ese script. Eso es un XSS.
```

## Lo que hace especial a este ejercicio

Antes de cada corrida vas a ver **tu plantilla Blade convertida en PHP**:

```
  → <?php foreach ($empleados as $empleado): ?>
  → <li><?= $empleado['nombre'] ?> — <?= e($empleado['legajo']) ?></li>
```

Mirá esas dos salidas en la misma línea: una pasa por `e()` y la otra no. Ahí
está, literal, la diferencia entre `{{ }}` y `{!! !!}`.

Blade no es magia: es un traductor. El traductor está en `src/nucleo/Blade.php`,
son 40 líneas y se leen en cinco minutos.

## Tus cinco tareas

| # | Dónde | Qué |
|---|---|---|
| 1 | `vistas/empleados/crear.blade.php` | Tapar el **XSS**: escapar la salida |
| 2 | `app/Controllers/EmpleadoController.php` | Completar las **reglas de validación** |
| 3 | `vistas/empleados/crear.blade.php` | Que el formulario **conserve lo tipeado** (`old()`) |
| 4 | `vistas/empleados/crear.blade.php` | **Mostrar los mensajes de error** |
| 5 | `app/Controllers/EmpleadoController.php` | **Flash + redirect** al guardar bien |

### Lo que pide RRHH para el alta

> - **nombre** → obligatorio, al menos 3 caracteres
> - **legajo** → obligatorio, con formato `L-1234`, y **que no exista ya otro igual**
> - **email** → obligatorio y con formato de correo válido

Las reglas disponibles están documentadas arriba de `src/nucleo/Validador.php`.

## Cómo correrlo

```bash
docker compose run --rm ejercicio
```

Cada corrida te muestra el PHP compilado, la prueba del XSS, qué pasa con tres
envíos distintos, y en qué paso vas. Con los cinco en verde aparece tu bandera
`ipap{c04-xxxxxxxxxx}`, que —como siempre— **no está escrita en ningún archivo**.

> **Sin Docker:** `cd src && php index.php`

## Lo que vas a practicar

| Paso | Concepto de la clase |
|------|----------------------|
| 1 | **`{{ }}` vs `{!! !!}`**: por qué el escapado es el que está por defecto |
| 2 | **Validación en el servidor**, con reglas declarativas |
| 3 | **`old()`**: no hacerle perder al usuario lo que ya escribió |
| 4 | Mostrar los **errores** donde corresponde |
| 5 | **Flash messages** y el patrón **POST → redirect → GET** |

## Si te trabás

1. **El XSS.** Buscá en la vista la línea que usa `{!! !!}`. Está señalada con un
   comentario. Compará con la línea de al lado, que sí escapa.
2. **Las reglas.** El formato del legajo se valida con `'formato:/…/'` y una
   expresión regular. Una `L`, un guion y cuatro dígitos.
3. **`old()`.** El helper ya existe. Va en el atributo `value` del input —el
   comentario del archivo te muestra exactamente cómo.
4. **Los errores.** El helper `error('campo')` devuelve el mensaje o `null`.
   Combinalo con `@if`.
5. **El redirect.** Fijate en `Respuesta::redirigir()` y en `Sesion::guardarFlash()`.
   El listado ya está preparado para mostrar el flash: solo hay que dejárselo.

## Dos trampas que conviene conocer

**El `old()` también hay que escaparlo.** Si lo ponés con `{!! !!}` para "que no
se rompa", acabás de abrir el mismo agujero por otra puerta: alguien puede cerrar
el atributo `value="` y meter un `onerror=`. El verificador lo comprueba.

**La regla `unico` se prueba aparte.** Un legajo como `1234` falla por *formato*
antes de que se llegue a mirar si está repetido. Para saber si tu regla de
unicidad anda de verdad, hay que mandar un legajo bien formado que ya exista.

---

## Lo interesante

Fijate dónde terminó cada responsabilidad:

- **La vista** decide cómo se muestra, y escapa por defecto.
- **El validador** dice qué datos son aceptables, en forma declarativa.
- **El controller** solo coordina: valida, guarda y redirige.

Ninguno de los tres sabe demasiado del otro. Cuando en la Clase 10 veamos
**Form Requests**, lo único que va a pasar es que las reglas se mudan del
controller a una clase propia — el resto ya está en su lugar.

Y el patrón POST → redirect → GET no es un detalle de purista: es lo que evita
que apretar F5 después de guardar cree un empleado duplicado.
