Estilo arquitetural
Clean Architecture (adaptada)
Sem framework, sem container de injeção de dependência — as camadas são separadas por pasta em vez de por pacote/módulo.
PHP 8.2 sem framework, dividido em quatro camadas. A dependência flui numa direção só: View chama Domain, Domain chama Infrastructure. Core é transversal e pode ser usado por qualquer camada.
Camadas e fluxo de dependência
flowchart TD
V["View — Pages & Components"] --> D["Domain — Importers · Reports · Security · Services · Validation"]
D --> I["Infrastructure — Database · Elasticsearch · External · Storage"]
C["Core — HookManager · PluginLoader · Anonymizer"] -.-> V
C -.-> D
C -.-> I
| Camada | Pasta | Responsabilidade |
|---|---|---|
| Core | src/Core/ | Infraestrutura transversal: Anonymizer, HookManager, PluginLoader |
| Domain | src/Domain/ | Regras de negócio: Importers (Lattes), Reports (CAPES), Security (Auth, LGPD), Services, Validation |
| Infrastructure | src/Infrastructure/ | Adaptadores externos: Database, Elasticsearch, External (ORCID/OpenAlex/BrCris), Storage |
| View | src/View/ | Componentes (Navbar, Footer, HeroSection) e páginas (Auth, Dashboard, Search, Static) |
Classes críticas
| Classe | Caminho | Papel |
|---|---|---|
AuthManager | Domain/Security/ | Login, BCrypt, brute-force, sessão segura |
LattesImporter | Domain/Importers/ | Importação de XML do Lattes, com validação anti-XXE |
ElasticsearchService | Infrastructure/Elasticsearch/ | Cliente ES 8.x, com fallback automático para MySQL |
LgpdComplianceService | Domain/Security/ | DPIA, status de conformidade — exposto em admin.php |
ExportService | Domain/Services/ | BibTeX, RIS, CSV, JSON, XML |
Fluxo de autenticação
flowchart TD
L["LoginPage: usuário + senha"] --> AM["AuthManager::login()"]
AM --> CHK{"Senha confere e conta não bloqueada?"}
CHK -- sim --> SESS["iniciarSessaoSegura(): regenera ID, timeout 2h"]
SESS --> OK["Redireciona ao painel"]
CHK -- não --> CNT["Incrementa tentativas em log_login"]
CNT --> BLK{"5 tentativas?"}
BLK -- sim --> LOCK["Bloqueio de 15min"]
BLK -- não --> RETRY["Retorna erro, permite nova tentativa"]
Convenção obrigatória: todo método de serviço retorna
['sucesso' => bool, 'mensagem' => string, 'dados' => mixed]. Prepared statements sempre; nunca concatenar SQL. filter_input() em toda entrada externa.