# Perguntas Frequentes — Rotas e Controladores

> **Portal** = `v6/routes/web.php` | **CMS** = `v6/routes/basepro.php` (prefixo `/cms`) |
> **API** = `v6/routes/api.php` (sem endpoint de FAQ).

---

## 1. Rotas do Portal

| Método | URI | Nome | Controller@ação | Observação |
|---|---|---|---|---|
| ANY | `/acesso-rapido/{slug}` | `acesso-rapido.index` | `Portal\QuickAccessController@index` | Rota que serve a FAQ (`slug = perguntas-frequentes`) |
| ANY | `/acessos-rapido/{slug}` | `acessos-rapido.index` | `Portal\QuickAccessController@getIndexStatic` | Variante que **sempre** vai para a página estática |
| ANY | `/portal/perguntas-frequentes` | `conteudo.portal.list` | `Portal\PortalController@contentList` | Redireciona para `acesso-rapido.index` |
| ANY | `/portal/perguntas-frequentes/{slug2}` | `conteudo.portal.show` | `Portal\PortalController@contentList` | Idem (o `switch` precede o tratamento de `$slug2`) |
| ANY | `/buscar` | `search` | `Portal\PortalController@searchContents` | Inclui a categoria `perguntas-frequentes` no filtro |
| ANY | `/buscando` | `search.by.text` | `Portal\PortalController@searchingContents` | Idem |
| ANY | `/buscar/{data}` | `search.show` | `Portal\PortalController@searchContentShow` | Abre o item; view `perguntas-frequentes.show` |

Fontes: `v6/routes/web.php:88-89`, `v6/routes/web.php:92-94`, `v6/routes/web.php:59-61`,
`v6/routes/web.php:191-193`.

```php
// v6/routes/web.php:88-89
Route::prefix('acesso-rapido')->group(function () {
    Route::any('/{slug}', 'Portal\QuickAccessController@index')->name('acesso-rapido.index');
});
```

**Não existe rota pública que aponte para `Portal\CommonQuestionsController`** — o grep em
`v6/routes/` não retorna nenhuma ocorrência do controller.

## 2. Rotas do CMS (`/cms`)

| Método | URI | Nome | Controller@ação |
|---|---|---|---|
| GET | `/cms/conteudos/perguntas-frequentes` | `listar-conteudo` | `Prefecture\ContentController@genericIndex` |
| GET | `/cms/conteudos/cadastrar/perguntas-frequentes` | `cadastrar-conteudo` | `Prefecture\ContentController@genericCreate` |
| GET | `/cms/conteudos/editar/perguntas-frequentes/{id}` | `editar-conteudo` | `Prefecture\ContentController@genericEdit` |
| POST | `/cms/conteudo` | `conteudo.store` | `Prefecture\ContentController@store` |
| PUT/PATCH | `/cms/conteudo/{id}` | `conteudo.update` | `Prefecture\ContentController@update` |
| DELETE | `/cms/conteudo/{id}` | `conteudo.destroy` | `Prefecture\ContentController@destroy` |
| POST | `/cms/conteudo/deleteAll` | `ajax.generic.content.deleteAll` | `Prefecture\ContentController@genericDeleteAll` |
| GET | `/cms/datatable/perguntas_frequentes` | `datatable.perguntas_frequentes` | `Prefecture\DatatableController@get_perguntas_frequentes` |

Fontes: `v6/routes/basepro.php:235-237`, `:174`, `:141`, `:425`.

## 3. `Portal\QuickAccessController` — o controller que serve a FAQ

Arquivo: `v6/app/Http/Controllers/Portal/QuickAccessController.php`

```php
public function index($slug1)
{
    if ($slug1 === 'ouvidoria') {
        return redirect()->to(url('/acessos-rapido/solicitar-informacao'));
    }

    $contentCategoriesNews = $this->getContentNews();
    $contents = $this->getContentByCategory($slug1);

    if (!count($contents)) {
        return $this->getIndexStatic($slug1);
    }

    return view($this->view . $slug1, compact('contentCategoriesNews','contents'));
}
```

Pontos observáveis:

| Aspecto | Comportamento |
|---|---|
| `$this->view` | `"portal.layouts.{$this->getTemplateActived()}.informacoes-instituicao.acesso-rapido."` (linha 26) |
| View final | `informacoes-instituicao.acesso-rapido.perguntas-frequentes` — o **nome do arquivo é o slug** |
| Dados | `contents` (todos os itens da categoria) + `contentCategoriesNews` |
| Fallback | Sem itens na categoria -> `getIndexStatic($slug1)` (página estática) |
| Filtro de status | **Nenhum**: itens com `status = false` também são exibidos |
| `getTemplateActived()` | Lê `configurations.key = 'layout'`; se a view `portal.layouts.{layout}.home.index` não existir, marca o portal em manutenção e devolve 404 (`v6/app/Http/Traits/GetInformationsPrefectureTrait.php:92-102`) |

Fallback (`getIndexStatic`): procura `static_pages` pelo slug, incrementa `clicks`,
carrega `archives` e, se não encontrar, devolve a view de erro
`admin.errors.conteudo-nao-encontrado` (existente em
`v6/resources/views/admin/errors/conteudo-nao-encontrado.blade.php`):

```php
// v6/app/Http/Controllers/Portal/QuickAccessController.php:45-56
$contents = $this->getStaticPageData($slug1);
$this->updateClickStaticPage($contents->id);
$archives = Archive::where('static_pages_id', $contents->id)->where('highlight', null)->get();
$view_pdf = Archive::where('static_pages_id', $contents->id)->where('view_pdf', true)->first();

if (!$contents) {
    return view("admin.errors.conteudo-nao-encontrado");
}
```

## 4. `Portal\CommonQuestionsController` — feature morta

Arquivo: `v6/app/Http/Controllers/Portal/CommonQuestionsController.php`

```php
public function index()
{
    $title = 'Perguntas Frequentes';
    $selectQuestions = 'sel-shortcuts';
    return view('portal.layouts.default.pages.common-questions', compact('selectQuestions', 'title'));
}
```

| Verificação | Resultado |
|---|---|
| Rota registrada | **Não** (nenhuma ocorrência em `v6/routes/`) |
| View `portal.layouts.default.pages.common-questions` | **Não existe** em `v6/resources/views/portal/` |
| Mesma classe na v5 | Sim, idêntica (`v5/app/Http/Controllers/Portal/CommonQuestionsController.php`) |

Consequência: se alguém registrar a rota, a resposta será **500** (view inexistente).

## 5. Controller do CMS — `Prefecture\ContentController`

| Método | Linha | Comportamento |
|---|---|---|
| `genericIndex($slug)` | 88-119 | `if ($slug === 'perguntas-frequentes') return $this->returnIndex('Perguntas Frequentes', $slug);` (linha 97) |
| `genericGenerate($slug, $id)` | 170+ | `if ($slug === 'perguntas-frequentes') return $this->returnData('Perguntas Frequentes', $slug, null, [], $id);` (linha 170) |
| `store` / `update` / `destroy` | ~600-1300 | CRUD genérico de `contents` |

`returnData` entrega à view `$categoryContent` (a categoria 12) e `$content` (na edição),
que o formulário usa no campo oculto `category_contents_id`.

## 6. Controller do CMS — `Prefecture\DatatableController`

```php
// v6/app/Http/Controllers/Prefecture/DatatableController.php:216-220
public function get_perguntas_frequentes()
{
    $perguntas_frequentes = DB::table("perguntas_frequentes")->get();
    return DataTables::of($this->struct_views($perguntas_frequentes, 'perguntas-frequentes'))->make(true);
}
```

`struct_views` (linhas 504-520) injeta por linha as flags `edit`, `delete`, `active` e
`inactivate` a partir das permissões `perguntas-frequentes.*`.

## 7. Form Request e validação

`v6/app/Http/Requests/ContentRequest.php` — `perguntas-frequentes` **não tem `case`
próprio** e cai no `default:` (linhas 308-314):

```php
default:
    $rules = [
        "title" => "required|max:120",
        "category_contents_id" => "required|numeric",
        "archive.*.0" => "mimes:jpg,jpeg,png,bmp,gif,rar,zip,doc,docx,pdf,odt,xls,xlsx,xlsb,xslm,ppt,pptx,ods,wav,mp3,wma,mp4,mpg4,mkv,flv",
        "archive_highlight" => "max:20000|mimes:jpg,jpeg,png,gif,webp",
    ];
```

| Regra | Efeito |
|---|---|
| `title` required, max 120 | A pergunta é obrigatória (o formulário usa `Form::text` sem `maxlen`, logo o limite só existe no servidor) |
| `category_contents_id` required numeric | Amarra o item à categoria FAQ |
| `text` **não** validado | A resposta é obrigatória só no markup do formulário |

## 8. Breadcrumbs

`v6/routes/breadcrumbs.php:254-261`:

```php
// Home > Perguntas Frequentes
Breadcrumbs::register('perguntas-frequentes', function ($breadcrumbs) {
    $breadcrumbs->parent('home');
    $breadcrumbs->push('Perguntas Frequentes', url('/acesso-rapido/perguntas-frequentes'));
});

// Home > Perguntas Frequentes > Pergunta
Breadcrumbs::register('pergunta', function ($breadcrumbs, $content) {
    $breadcrumbs->parent('perguntas-frequentes');
    $breadcrumbs->push(str_limit($content->title, 20));
});
```

O breadcrumb `pergunta` (usado na página de item da busca) depende de `str_limit`, helper
removido no Laravel 6+ — na v7 precisa ser `Str::limit`.

## 9. Permissões exigidas

| Permissão | Onde |
|---|---|
| `perguntas-frequentes.create` | Botão "Cadastrar Pergunta" (`v6/resources/views/prefecture/contents/perguntas-frequentes/index.blade.php:11`) |
| `perguntas-frequentes.edit` | Botão de edição por linha (`v6/public/assets/js/custom/contents/perguntas-frequentes/datatable.js:14`) |
| `perguntas-frequentes.delete` | Exclusão individual e em lote (`index.blade.php:16`) |
| `check.route.permission` | Middleware de todas as rotas do CMS (`v6/app/Http/Controllers/Prefecture/ContentController.php:59`) |

## 10. API

Não há rota de FAQ em `v6/routes/api.php`. Para a v7, recomenda-se
`GET /api/v1/perguntas-frequentes` com paginação e busca por texto.
