# PLATAFORMA — API, Breadcrumbs e Controllers

> Continuação de `03-ROTAS-E-CONTROLADORES.md`. Ver também `03-ROTAS-E-CONTROLADORES.md`.

## 5. `v6/routes/breadcrumbs.php` — substituição de dependência

### 5.1 O problema

O pacote original `davejamesmiller/laravel-breadcrumbs` foi **removido do
GitHub** (404 na API). O upstream foi abandonado e o fork de manutenção
`diglactic/laravel-breadcrumbs` assumiu.

### 5.2 A decisão (arquitetural)

**v6 já usa o fork.** `v6/composer.json:20`:

```json
"diglactic/laravel-breadcrumbs": "^4.0",
```

E `v6/composer.lock` fixa `diglactic/laravel-breadcrumbs 4.2.0`, commit
`368d7b3a2cd21fe2e648756e5d01d3fe4fbe98e1` — **o mesmo commit** do upstream
abandonado.

### 5.3 Por que a troca é invisível

O fork mantém o **namespace original**:

`v6/vendor/diglactic/laravel-breadcrumbs/src/Facades/Breadcrumbs.php:3`:

```php
namespace DaveJamesMiller\Breadcrumbs\Facades;
```

E `v6/routes/breadcrumbs.php:9`:

```php
use DaveJamesMiller\Breadcrumbs\Facades\Breadcrumbs;
```

Resultado: **zero alteração de código-fonte** foi necessária. O arquivo de
configuração `v6/config/breadcrumbs.php:35` aponta para o arquivo de rotas:

```php
'files' => base_path('routes/breadcrumbs.php'),
```

### 5.4 Estado na v5

A v5 sofria com o mesmo problema e foi corrigida em
`dossie_modules/_01_v5_fix/README.md`: `v5/composer.json:20` foi alterado de
`davejamesmiller/laravel-breadcrumbs` para `diglactic/laravel-breadcrumbs ^4.0`
(a v5 não versiona o `composer.lock` — está no `.gitignore`).

### 5.5 Decisão para a v7

**Não replicar a dependência.** O padrão usado nas views é acoplado ao
pacote (`@foreach ($breadcrumbs as $breadcrumb)` + `Breadcrumbs::view()`).
A v7 deve usar um **componente Blade nativo** `<x-breadcrumbs :items="…" />`
alimentado por uma Action dedicada, sem pacote de terceiros.

### 5.6 Trilhas registradas

506 linhas em `v6/routes/breadcrumbs.php`, com `Breadcrumbs::register(...)`
para: `home`, `ouvidoria`, `transparencia-fiscal`, `transparencia-fiscal-show`,
`mapa-site`, `static-ouvidoria`, `static-transparencia`, e mais.

---

## 6. Controllers

### 6.1 Distribuição (v6 vs v5)

| Namespace | v6 | v5 | Δ |
|---|---|---|---|
| `Admin` | 20 | 18 | +2 (`DashboardWidgetController`, `ModulosController`) |
| `Portal` | 48 | 42 | +6 |
| `Prefecture` | 83 | 80 | +3 |
| `Swagger` | 7 | 7 | 0 |
| **Total** | **158** | **147** | +11 |

### 6.2 Classes base

| Classe | Caminho | Papel |
|---|---|---|
| `App\Http\Controllers\Admin\Controller` | `v6/app/Http/Controllers/Admin/Controller.php` | Base do CMS; implementa `getTemplateActived()` (duplicado do trait) e `formatValidationErrors()` |
| `App\Http\Controllers\Prefecture\Controller` | `v6/app/Http/Controllers/Prefecture/Controller.php` | Base do CMS de conteúdo; **aplica `check.route.permission` no construtor**; `formatValidationErrors()` retorna 422 em JSON |
| `App\Http\Controllers\Portal\Controller` | `v6/app/Http/Controllers/Portal/Controller.php` | Base do portal; só os 3 traits padrão do Laravel |

**Duplicação real:** `getTemplateActived()` existe em
`v6/app/Http/Traits/GetInformationsPrefectureTrait.php:92` **e** em
`v6/app/Http/Controllers/Admin/Controller.php:39` — corpo idêntico.

### 6.3 Form Requests e validação

- **78** classes em `v6/app/Http/Requests/`.
- Padrão de retorno de erro (CMS): `v6/app/Http/Controllers/Prefecture/Controller.php:26-38`:

```php
protected function formatValidationErrors(Validator $validator): array
{
    $status = 422;
    return [
        "message" => $status . " error",
        "errors" => [
            "message" => $validator->getMessageBag()->first(),
            "info" => [$validator->getMessageBag()->keys()[0]],
        ],
        "status_code" => $status
    ];
}
```

- Validador global: `App\Validators\CustomValidator` registrado no
  `AppServiceProvider::boot()` — adiciona suporte a **CNPJ alfanumérico**.
- Regras próprias: `v6/app/Rules/Validate_cpf.php`, `Validate_cnpj.php`,
  `ConditionalRequiredSlug.php`, `ConditionalRequiredLink.php`, `SelectRule.php`.
- **Problema:** vários Form Requests condicionam a validação pelo **nome da
  rota** (ex.: `v6/app/Http/Requests/ContentRequest.php:73,100,131,159,174,281`),
  o que torna a regra dependente do nome e não do método HTTP.

### 6.4 API Resources

21 classes em `v6/app/Http/Resources/`:

- 6 para a API Swagger: `Swagger/V1/Portal/{NewResource, PublicationResource, LegislationResource, OrgaoResource, SecretariaResource, ArchiveResource}`.
- 13 para Formulários Dinâmicos (`Prefecture/DynamicForms/**`).
- 2 para o Diário Oficial (`DiarioOficial/GetDiarioResource`, `ListAreaContentResource`).

Formato real — `v6/app/Http/Resources/Swagger/V1/Portal/NewResource.php`:

```php
public function toArray($request)
{
    $autor = data_get($this, "author");
    $fonte = data_get($this, "source");
    $publication = data_get($this, "publication_date") ? data_get($this, "publication_date")->format("d/m/Y H:i:s") : '';
    $description = strip_tags(trim(data_get($this, "text")));
    return [
        "titulo" => data_get($this, "title"),
        "autor" => $this->when(!empty($autor), $autor),
        "fonte" => $this->when(!empty($fonte), $fonte),
        "data_publicacao" => $this->when($publication != '', $publication),
        "descricao" => $this->when($description != "", $description),
        "interacoes" => data_get($this, "clicks"),
        "slug" => data_get($this, "slug"),
        "arquivos" => ArchiveResource::collection($this->whenLoaded("archives"))
    ];
}
```

**Contrato público:** os nomes das chaves JSON (`titulo`, `autor`, `fonte`,
`data_publicacao`, `descricao`, `interacoes`, `slug`, `arquivos`) são
**públicos e consumed por terceiros** — não podem mudar na v7 sem versãoção.

### 6.5 Permissões exigidas (papel/guard)

- **Guard:** Sentinel (único). Não há `guards` customizados; tudo usa o
  sentinel default (`v6/config/cartalyst.sentinel.php`).
- **Papel de bypass:** `super-admin` ignora `check.route.permission`.
- **Permissões por nome de rota:** `has_access("$menu->slug.index")` no
  `MenuServiceProvider`; `Sentinel::check()->hasAnyAccess([$access, $accessSegment])`
  no `CheckRoutePermission`.
- **Papéis padrão:** `administrador` (papel com maior número de permissões,
  reatribuídas pelos seeders), `super-admin`.

---

## 7. Referências

| Item | Caminho |
|---|---|
| Rotas do portal | `v6/routes/web.php` |
| Rotas do CMS | `v6/routes/basepro.php` |
| Rotas da API | `v6/routes/api.php` |
| Rotas da carta de serviços | `v6/routes/service_letter.php` |
| Rotas mortas | `v6/routes/prefecture.php` |
| Trilhas de breadcrumb | `v6/routes/breadcrumbs.php` |
| Config do pacote de breadcrumb | `v6/config/breadcrumbs.php` |
| Carregamento das rotas | `v6/app/Providers/RouteServiceProvider.php` |
| Middleware de permissão | `v6/app/Http/Middleware/CheckRoutePermission.php` |
| Middleware de login | `v6/app/Http/Middleware/CheckLogged.php` |
| Middleware de manutenção | `v6/app/Http/Middleware/CheckSiteManutention.php` |
| Middleware de landing | `v6/app/Http/Middleware/ActiveLanding.php` |
| Kernel | `v6/app/Http/Kernel.php` |
| Controller base do CMS | `v6/app/Http/Controllers/Prefecture/Controller.php` |
| Geração do OpenAPI | `v6/app/Console/Commands/GenerateSwagger.php` |
| Bootstrap do OpenAPI | `v6/swagger-bootstrap/variables.php` |
