# Telefones Úteis — Rotas e Controladores

## 1. Rotas públicas (portal)

| Método | URI | Nome | Controller@ação | Middleware | Arquivo |
|---|---|---|---|---|---|
| any | `/telefones-uteis` | `telefones-uteis.index` | `Portal\UsefulPhonesController@getIndex` | grupo com `check.site.manutention` | `v6/routes/web.php:97` |

Trecho real (`v6/routes/web.php:97`):

```php
Route::any('/telefones-uteis', 'Portal\UsefulPhonesController@getIndex')->name('telefones-uteis.index');
```

Observações:

- `Route::any` aceita GET e POST na mesma URI; o controller **ignora** o método e sempre devolve a listagem.
- O controller resolve o layout dinamicamente com `getTemplateActived()` (helper de `GetInformationsPrefectureTrait`), que lê a configuração `layout` do banco; por isso a view mora em `portal.layouts.<layout>.informacoes-instituicao.telefones-uteis.index`.
- Se o layout configurado não tiver a pasta `informacoes-instituicao/telefones-uteis`, a página quebra com erro de view inexistente (não há fallback, ao contrário de `ContentPresenter::getTemplate()` que checa `View::exists`).

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

| Método | URI | Nome | Controller@ação | Observação |
|---|---|---|---|---|
| get | `/cms/conteudos/{slug}` | `listar-conteudo` | `Prefecture\ContentController@genericIndex` | `slug = telefones-uteis` -> view de listagem |
| get | `/cms/conteudos/cadastrar/{slug}` | `cadastrar-conteudo` | `Prefecture\ContentController@genericCreate` | renderiza o formulário de criação |
| get | `/cms/conteudos/editar/{slug}/{id}` | `editar-conteudo` | `Prefecture\ContentController@genericEdit` | renderiza o formulário de edição |
| resource | `/cms/conteudo` | `conteudo.*` | `Prefecture\ContentController` | `store` (POST), `update` (PUT), `destroy` (DELETE) |
| post | `/cms/conteudo/deleteAll` | `ajax.generic.content.deleteAll` | `Prefecture\ContentController@genericDeleteAll` | exclusão em lote |
| get | `/cms/datatable/telefones_uteis` | `datatable.telefones_uteis` | `Prefecture\DatatableController@get_telefones_uteis` | fonte da tabela do CMS |

Trecho real (`v6/routes/basepro.php`):

```php
Route::get('conteudos/{slug}', ['uses' => 'Prefecture\ContentController@genericIndex'])->name('listar-conteudo');
Route::get('conteudos/cadastrar/{slug}', ['uses' => 'Prefecture\ContentController@genericCreate'])->name('cadastrar-conteudo');
Route::get('conteudos/editar/{slug}/{id}', ['uses' => 'Prefecture\ContentController@genericEdit'])->name('editar-conteudo');
```

```php
Route::get('/telefones_uteis', 'Prefecture\DatatableController@get_telefones_uteis')->name('telefones_uteis');
```

> Observação: o grupo de DataTables está declarado como `prefix => 'datatable'`, `as => 'datatable.'`, mas a rota usa `->name('telefones_uteis')` explicitamente. No Laravel 5.5 o `name()` explícito sobrescreve o prefixo do grupo, então o nome efetivo da rota é `telefones_uteis`, não `datatable.telefones_uteis`. O JavaScript do módulo chama a URL por caminho (`/cms/datatable/telefones_uteis`), o que evita o problema.

## 3. Controladores

### 3.1 `Portal\UsefulPhonesController`

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

| Elemento | Descrição |
|---|---|
| Trait | `GetInformationsPrefectureTrait` |
| Dependências injetadas | `Content $content`, `CategoryContent $categoryContent` (as duas são guardadas mas **não usadas** no método) |
| Ação `getIndex()` | busca os conteúdos da categoria e renderiza a view do layout ativo |
| Validação | nenhuma (não há Form Request no portal) |

### 3.2 `Prefecture\ContentController` (trechos usados pelo módulo)

Arquivo: `v6/app/Http/Controllers/Prefecture/ContentController.php`

| Método | Linha | Comportamento relevante |
|---|---|---|
| `genericIndex($slug)` | 91-119 | mapeia `telefones-uteis` -> `returnIndex('Telefones Úteis', $slug)` |
| `returnIndex($title, $slug, $alt_click)` | 121-126 | registra log de atividade, chama `menuClicks($slug)` e renderiza `prefecture.contents.$slug.index` |
| `genericCreate($slug)` / `genericEdit($slug,$id)` | 140-161 | delegam para `genericGenerate` |
| `genericGenerate($slug,$id)` | 163-239 | `telefones-uteis` -> `returnData('Telefones Úteis', $slug, null, [], $id)` (linha 172) |
| `returnData($title,$slug,$self,$extra,$id)` | 275-312 | monta `categoryContent`, `content`, `archives`, `gallery`, `destaque`; escolhe `create` ou `edit` |
| `store(ContentRequest)` | 616 | grava `contents`; `text` = `text` do formulário (o campo `phone` também sobrescreve `text` quando enviado) |
| `update(ContentRequest,$id)` | 937 | atualiza `contents` e mantém o `links` associado |
| `genericDeleteAll(Request)` | 70-78 | executa `$this->contentRepository->destroyAll($request->toDelete)` |

Ponto sensível no `store` (`v6/app/Http/Controllers/Prefecture/ContentController.php:662-663`):

```php
//Verifica se é telefone
if (!empty($request->get('phone'))) $contentData['text'] = $request->get('phone');
```

O formulário de telefones úteis **não** envia um campo `phone` (o input se chama `text`), portanto esse
branch nunca é acionado por este módulo.

### 3.3 `Prefecture\DatatableController@get_telefones_uteis`

Arquivo: `v6/app/Http/Controllers/Prefecture/DatatableController.php:122-126`

```php
public function get_telefones_uteis()
{
    $publicacoes = DB::table('telefones_uteis')->get();
    return DataTables::of($this->struct_views($publicacoes, 'telefones-uteis'))->make(true);
}
```

`struct_views($data, 'telefones-uteis')` acrescenta a cada linha as chaves `edit`, `delete`,
`active` e `inactivate`, derivadas de `has_access()`.

## 4. Form Request e validação

`v6/app/Http/Requests/ContentRequest.php` escolhe o conjunto de regras pelo `slug` da categoria.
Para telefones úteis (linhas 288-297):

```php
case 'perguntas-frequentes':
case 'telefones-uteis':
case 'glossario':

    $rules = [
        "title" => "required|max:120",
        "category_contents_id" => "required|numeric",
        "text" => "required",
    ];
    break;
```

| Campo | Regra | Mensagem (se aplicável) |
|---|---|---|
| `title` | `required|max:120` | “Por favor, informe um título.” / “O campo título ultrapassou o número máximo de caracteres permitidos.” |
| `category_contents_id` | `required|numeric` | “Não foi possível recuperar a categoria selecionada, tente novamente.” |
| `text` | `required` | “Por favor, digite algum texto.” |

Observações:

- `authorize()` retorna `true` sempre: a autorização real vem do middleware `check.route.permission` e de `has_access` na view.
- A máscara `advanced-phone` é aplicada **apenas no cliente** (input com classe `advanced-phone`), não há validação de formato no servidor.
- A mensagem de erro para `phone.required` existe no `ContentRequest`, mas o campo `phone` não é validado em nenhuma regra — resíduo de uma versão anterior do formulário.

## 5. API

Não há endpoint público de API para telefones úteis. As rotas de `v6/routes/api.php` (Swagger `v1`)
cobrem notícias, publicações, legislação, órgãos e secretarias; telefones não estão incluídos.

## 6. Permissões exigidas

| Permissão | Efeito |
|---|---|
| `telefones-uteis.create` | exibe o botão “Cadastrar Telefone” |
| `telefones-uteis.edit` | exibe o botão de editar por linha |
| `telefones-uteis.delete` | exibe o botão de excluir e a seleção múltipla |
| `telefones-uteis.restore` / `telefones-uteis.inactivate` | colunas `active`/`inactivate` do DataTable |

As permissões são avaliadas por `has_access()` (`v6/app/Library/Helper/appHelpers.php:22`) e
definidas pelos seeds `v6/database/seeds/ResourcesTableSeeder.php` e
`v6/database/seeds/RolesTableSeeder.php`.
