# Glossário — Arquitetura

> Versão analisada: `v6` (idêntico em `v5`). Slug do módulo CMS: `glossario`
> (tabela `modulos`, id 24) | Categoria de conteúdo: `category_contents.id = 11`.

---

## 1. Visão geral

O Glossário é uma *feature* de conteúdo genérico. Não existe model, controller ou
tabela própria de verbetes: tudo é resolvido pelo par

- `category_contents` (id 11, slug `glossario`) — classifica o registro;
- `contents` — armazena o verbete (`title` = termo, `text` = definição).

Dois fluxos independentes consomem essa categoria:

| Fluxo | Entrada | Saída | Quem consome |
|---|---|---|---|
| Portal (público) | `GET /glossario`, `GET /glossario-ajax/{letra}` | HTML + JSON | Cidadão |
| CMS (admin) | `GET /cms/conteudos/glossario`, resource `conteudo` | HTML + DataTable JSON | Operador |

## 2. Fluxo da requisição — Portal

```
Navegador
  │ GET /glossario
  ▼
Route::get('/glossario', 'Portal\GlossaryController@index')      v6/routes/web.php:124
  │ middleware: check.site.manutention (grupo do portal)
  ▼
GlossaryController@index                                         v6/app/Http/Controllers/Portal/GlossaryController.php:19
  │ $azRange = range('A','Z')
  │ view('portal.layouts.{getTemplateActived()}.transparencia.glossario')
  ▼
Blade (modelo1..modelo6 / newsbit) desenha apenas o índice A–Z
  │ $(document).ready -> getGlossarioByLetter('all')
  ▼
GET /glossario-ajax/{letra}  →  GlossaryController@showByLetterAjax   v6/routes/web.php:125
  │ Content::whereHas('categoryContents', bySlug('glossario'))
  │        ->where('title','like', $letra.'%')->get()
  ▼
JSON {"letterActive": "A", "contentGlossary": [ <modelo Content> ]}
  ▼
JS monta <li><h5>termo</h5><p>definição</p></li> em .contentGlossary
```

## 3. Fluxo da requisição — CMS

```
Operador
  │ GET /cms/conteudos/glossario
  ▼
Route::get('conteudos/{slug}') → ContentController@genericIndex      v6/routes/basepro.php:235
  │ if ($slug === 'glossario') return $this->returnIndex('Glossário', $slug);
  ▼
view('prefecture.contents.glossario.index')  + DataTable AJAX
  │ GET /cms/datatable/glossario
  ▼
DatatableController@get_glossario                                   v6/app/Http/Controllers/Prefecture/DatatableController.php:222
  │ DB::table("glossario")->get()   ← view SQL, não a tabela
  │ struct_views($dados, 'glossario')  → colunas edit/delete/active/inactivate por permissão
  ▼
JSON server-side (yajra/laravel-datatables-oracle)
```

Cadastro/edição:

```
POST /cms/conteudo          (Route::resource('conteudo'))            v6/routes/basepro.php:174
PUT  /cms/conteudo/{id}
  ▼
ContentController@store / @update                                   v6/app/Http/Controllers/Prefecture/ContentController.php
  │ ContentRequest (FormRequest) → slug resolvido por category_contents_id
  │ regra padrão: title required|max:120, category_contents_id required|numeric
  ▼
Content::create($contentData) / update  → tabela contents
```

## 4. Classes envolvidas

| Classe | Caminho | Papel |
|---|---|---|
| `Portal\GlossaryController` | `v6/app/Http/Controllers/Portal/GlossaryController.php` | `index` (render do índice) e `showByLetterAjax` (filtro por inicial) |
| `Prefecture\ContentController` | `v6/app/Http/Controllers/Prefecture/ContentController.php` | CRUD genérico dirigido por slug; `genericIndex` (linha 96), `genericGenerate` (linha 169) |
| `Prefecture\DatatableController` | `v6/app/Http/Controllers/Prefecture/DatatableController.php` | `get_glossario` (linha 222) monta o DataTable do CMS |
| `App\Http\Requests\ContentRequest` | `v6/app/Http/Requests/ContentRequest.php` | Regras por slug; `glossario` cai no `default:` (linhas 308-314) |
| `App\Prefecture\Content` | `v6/app/Http/Model/Prefecture/Content.php` | Model do verbete; `categoryContents()`, `linksUnique()`, scopes `bySlug`, `byStatus`, `byOrder` |
| `App\Prefecture\CategoryContent` | `v6/app/Http/Model/Prefecture/CategoryContent.php` | Categoria; `scopeBySlug` (linhas 164-167) usado no filtro do portal |
| `ContentPresenter` | `v6/app/Http/Presenters/ContentPresenter.php` | Formatação do model via `PresentableTrait` |
| `App\Repositories\Eloquent\Prefecture\Content\ContentRepositoryDefaultImpl` | `v6/app/Repositories/Eloquent/Prefecture/Content/ContentRepositoryDefaultImpl.php` | Repositório genérico de conteúdo (`upInsert`) |
| `App\Http\Filter\FilterSearchAllSite` | `v6/app/Http/Filter/FilterSearchAllSite.php` | Filtro de busca global que inclui a categoria `glossario` |
| `Portal\PortalController` | `v6/app/Http/Controllers/Portal/PortalController.php` | `contentList` (linha 321: `glossario` -> redirect), `searchContentShow` + `getViewToBeReturned` (linhas 391-402, `11 => 'glossario.show'`) |
| `App\Providers\MenuServiceProvider` | `v6/app/Providers/MenuServiceProvider.php:271-273` | Item de menu do CMS "Glossário" |

## 5. Dependências externas

| Pacote | Uso no módulo |
|---|---|
| `yajra/laravel-datatables-oracle` | `DataTables::of($dados)->make(true)` no `DatatableController` |
| `laracasts/presenter` | `PresentableTrait` + `ContentPresenter` no model `Content` |
| `cartalyst/sentinel` | `has_access(['glossario.create'])` nos botões do CMS |
| `laravelcollective/html` | `Form::open` / `Form::model` nas views de cadastro/edição |
| jquery | AJAX do portal (`$.ajax`) e DataTable (`runDatatables`) |

## 6. Diagrama de dependências (Mermaid)

```mermaid
graph TD
  R1[web.php: /glossario] --> GC[GlossaryController]
  R2[web.php: /glossario-ajax/{slug}] --> GC
  GC --> C[App\Prefecture\Content]
  GC --> CC[App\Prefecture\CategoryContent]
  R3[basepro.php: /cms/conteudos/glossario] --> CTC[ContentController]
  CTC --> CR[ContentRequest]
  CTC --> C
  R4[basepro.php: /cms/datatable/glossario] --> DTC[DatatableController]
  DTC --> VIEW[(view SQL glossario)]
  R5[basepro.php: resource conteudo] --> CTC
  CR --> C
  C --> T[(contents)]
  CC --> T2[(category_contents)]
  VIEW --> T
  VIEW --> T2
```

## 7. Observações de arquitetura

- O módulo **não** possui service dedicado nem policy própria: as regras são herdadas do CRUD
  genérico de `contents` e do middleware `check.route.permission`.
- O portal lê a tabela `contents` diretamente (Eloquent) enquanto o CMS lê a **view** `glossario`:
  a view reflete o mesmo conjunto, mas a ordenação do CMS é por `value` (row_number sobre
  `created_at DESC`), enquanto o portal ordena pela letra e não impõe ordenação.
- A listagem do CMS é server-side (DataTables) e a do portal é client-side (JSON + JS).
