# Drive — Arquitetura

## 1. Visão geral

O “Drive” do CMS **não possui modelo, tabela nem controller próprios**. Ele é uma das três
modalidades de uso da mesma infraestrutura de arquivos (`archives` + `galeria.*`):

| Modalidade | Como se distingue | Quem usa |
|---|---|---|
| Galeria de um conteúdo | `table = content` + `id` do conteúdo | Notícias, secretarias, agenda, unidades de atendimento, pauta do dia |
| Galeria de página estática | `table = static_pages` + `id` | Páginas estáticas |
| **Drive (biblioteca global)** | sem `table` e sem `id` | Menu “Drive” do CMS |

Todas as três usam exatamente o mesmo JavaScript (`assets/js/custom/contents/midias/index.js`) e as
mesmas rotas `galeria.*`.

## 2. Fluxo de requisição

### 2.1 Abrir a tela do Drive

```
GET /cms/conteudos/cadastrar/midias
  -> routes/basepro.php:236  Route::get('conteudos/cadastrar/{slug}') name=cadastrar-conteudo
  -> Prefecture\ContentController@genericCreate('midias')
       -> genericGenerate('midias')
            -> if ($slug === 'midias') return $this->returnData('Drive', $slug, null, [], $id);
            -> returnData(): $slug == 'midias' -> $target = 'edit'
            -> view prefecture.contents.midias.edit
```

Trecho real (`v6/app/Http/Controllers/Prefecture/ContentController.php:177` e `:302`):

```php
if ($slug === 'midias') return $this->returnData('Drive', $slug, null, [], $id);
```

```php
$slug == 'midias' || isset($id) ? $target = 'edit' :  $target = 'create';
```

### 2.2 Listar os arquivos

```
GET /cms/galeria/            (ou /cms/galeria/{column}/{id})
  -> routes/basepro.php (prefixo 'galeria')
  -> Prefecture\ArchiveController@getArchivesFromGalleryOrDriver($column = null, $id = null)
       -> Archive::orderBy('id','DESC')->where('extension','!=',null)->get(['id','path','extension','name'])
       -> response()->json(['data' => $data])
```

O JavaScript consome esse JSON e monta a grade.

### 2.3 Enviar arquivos

```
POST /cms/galeria   (multipart, campo 'file', com _token, id e table)
  -> Prefecture\ArchiveController@saveArchivesFromGalleryOrDriver(Request)
       -> sem 'table': $dir = '/content/midias'; $path = 'storage/content/midias'
       -> $name = $this->saveUpload($request->file, $dir, null, null, true)
       -> Archive::create(['name','path','extension','type','hash'])
       -> response()->json(['success' => 'Imagem foi cadastrada com sucesso!', 'data' => $archive], 200)
```

### 2.4 Excluir um arquivo

```
POST /cms/galeria/delete/{id}
  -> ArchiveController@deleteArchives($id)
       -> Archive::destroy($id)      // soft delete
       -> response()->json(['success' => 'Arquivo deletado com sucesso.'], 200)
```

### 2.5 Ações por arquivo (no cliente)

| Ação | Implementação |
|---|---|
| Copiar | monta `https://<host>/<path>` e usa `document.execCommand('copy')` |
| Baixar | link com atributo `download` apontando para `/<path>` |
| Visualizar | link para `/<path>` em nova aba |
| Excluir | `POST /cms/galeria/delete/{id}` |

## 3. Classes envolvidas

| Classe | Caminho | Papel |
|---|---|---|
| `Prefecture\ArchiveController` | `v6/app/Http/Controllers/Prefecture/ArchiveController.php` | upload, listagem, exclusão, título e ordem |
| `Prefecture\ContentController` | `v6/app/Http/Controllers/Prefecture/ContentController.php` | entrega a tela do Drive (`slug = midias`) |
| `App\Prefecture\Archive` | `v6/app/Http/Model/Prefecture/Archive.php` | model da tabela `archives` (SoftDeletes) |
| `App\Prefecture\TypesSizes` | `v6/app/Http/Model/Prefecture/TypesSizes.php` | catálogo `types_sizes` (usado por outros módulos) |
| `App\Repositories\Eloquent\Prefecture\Archive\ArchiveRepository` | `v6/app/Repositories/Eloquent/Prefecture/Archive/ArchiveRepository.php` | repositório genérico de arquivos |
| `App\Http\Traits\FileTrait` | `v6/app/Http/Traits/FileTrait.php` | `saveUpload`, `compress`, `getFileName` |
| `App\Http\Model\Admin\Modulos` | `v6/app/Http/Model/Admin/Modulos.php` | registro do módulo `drive` |

## 4. Diagrama de fluxo

```mermaid
flowchart TD
    A[Operador: menu Drive] --> B[GET /cms/conteudos/cadastrar/midias]
    B --> C[ContentController@genericGenerate]
    C --> D[View prefecture.contents.midias.edit]
    D --> E[JS: chargeGallery + setupGallery]
    E --> F[GET /cms/galeria/]
    F --> G[ArchiveController@getArchivesFromGalleryOrDriver]
    G --> H[(archives)]
    D --> I[Upload multiplo]
    I --> J[POST /cms/galeria]
    J --> K[ArchiveController@saveArchivesFromGalleryOrDriver]
    K --> L[FileTrait::saveUpload]
    L --> M[(storage/content/midias)]
    K --> N[(archives)]
    D --> O[Excluir]
    O --> P[POST /cms/galeria/delete/{id}]
    P --> H
```

## 5. Dependências externas

| Pacote / biblioteca | Uso |
|---|---|
| `laravel/framework` 5.5 | rotas, Eloquent, storage |
| `intervention/image` | compressão e versões `_min`, `_med`, `_larg` (`FileTrait::compress`) |
| `jquery-upload-files` (`jquery.uploadfile.min.js`) | upload múltiplo com barra de progresso |
| `jquery` + `IntersectionObserver` | carregamento progressivo da grade |
| `toastr` | mensagens de sucesso/erro no upload, cópia e exclusão |
| `bootstrap` (AdminLTE 1.22) | layout do CMS |

## 6. Onde o módulo é registrado

| Camada | Arquivo | Trecho |
|---|---|---|
| Módulo do CMS | `v6/database/migrations/2024_11_01_150206_create_modulos_table.php` | `modulos` id 30, slug `drive`, `status = true` |
| Recurso/permissões | `v6/database/seeds/ResourcesTableSeeder.php:288` | `Resource::updateOrCreate(['slug' => 'drive'], ['name' => 'Drive', 'modulo_id' => 30])` |
| Renomeação de resource | `v6/database/seeds/AjustesMigracao.php:81-90` | `midias` -> `drive` |
| Ordem de menu | `v6/database/seeds/MenuOrderSeeder.php:174-180` | `menu_orders.slug = midias`, `modulo_id = 30` |
| Item de menu | `v6/app/Providers/MenuServiceProvider.php:287-289` | `case 'midias':` -> `/cms/conteudos/cadastrar/midias`, ícone `upload` |
| Categoria de conteúdo | `v6/database/seeds/CategoryContentTableSeeder.php:176-180` | `CategoryContent::updateOrCreate(['slug' => 'midias'], ['name' => 'Mídias', 'status_create' => 1])` |
| Papéis | `v6/database/seeds/RolesTableSeeder.php:114` | `midias.*` = `true` |

Trecho real do menu (`v6/app/Providers/MenuServiceProvider.php`):

```php
case 'midias':
    $event->menu->add(['text' => 'Drive', 'url' => '/cms/conteudos/cadastrar/midias', 'icon' => 'upload']);
    break;
```

Observação: o item de menu continua referenciado pelo slug da **categoria** (`midias`), enquanto o
módulo e o resource usam `drive` — três nomes para a mesma funcionalidade.

## 7. Permissões (guard)

O módulo reaproveita as permissões da categoria `midias` (`midias.index`, `midias.create`,
`midias.edit`, `midias.delete`, `midias.restore`, `midias.inactivate`, `midias.show`), conforme
`v6/database/seeds/RolesTableSeeder.php:114`. As rotas `galeria.*` ficam no grupo do CMS com
`check.logged`; `ArchiveController` **não** aplica `check.route.permission` (ao contrário de
`ContentController`), de modo que qualquer usuário logado com acesso ao `/cms` pode alterar os
arquivos.
