title: Integração: Fronteira com o Moodle description: Estratégias de isolamento, adapters e a ponte entre o framework e a plataforma hospedeira.
Fronteira com o Moodle¶
O local_middag foi projetado para ser um " framework de cidadão do mundo", capaz de rodar dentro do Moodle LMS sem se tornar refém de sua arquitetura procedural e suas mudanças de versão. A Fronteira com o Moodle é a camada que garante esse isolamento.
O que é¶
É a zona de contato oficial entre o código orientado a objetos do framework e as APIs globais da plataforma Moodle ($DB, $USER, $COURSE, $CFG).
Essa fronteira é composta por:
1. Support Layer (framework/support/moodle/): Onde vivem os adapters técnicos.
2. Adapters e Wrappers: Classes que escondem o acesso a funções globais do Moodle.
3. Observer Central: Um capturador de eventos nativos do Moodle que os traduz para a linguagem interna do framework.
Por que existe¶
O Moodle é uma plataforma imensa com décadas de legado. Depender diretamente dele em todo o código traria três grandes riscos:
* Fragilidade: Uma mudança na assinatura de uma função do Moodle (ex: entre a versão 3.9 e 4.4) quebraria o framework inteiro.
* Inviabilidade de Testes: Seria impossível testar uma regra de negócio sem subir todo o ambiente do Moodle (DB, Sessão, Cache).
* Contaminação: O código ficaria repleto de global $DB, $USER; e queries SQL "sujas" misturadas com lógica de domínio.
A fronteira garante que o framework fale a sua própria língua internamente, usando "tradutores" para conversar com o Moodle.
Componentes da Integração¶
1. Adapters de Infraestrutura¶
Em vez de chamar $DB->get_record(), o framework utiliza um Database Adapter. Isso permite que, durante um teste unitário, possamos trocar o banco real por um em memória (SQLite) sem alterar uma linha da lógica de negócio.
2. Observer Central e Signal Bridge¶
O Moodle dispara centenas de eventos (\core\event\*). O framework possui um Observer Central que ouve esses eventos e decide o que fazer:
* Tradução Oficial: Converte o evento Moodle em um Signal interno rico.
* Pass-through: Encaminha o objeto original do Moodle para o dispatcher interno se houver algum listener interessado.
* No-op Rápido: Ignora o evento instantaneamente se ele não for relevante para o MIDDAG, garantindo performance.
O framework fornece o moodle_transaction_manager para lidar com a forma peculiar como o Moodle trata transações e exceções (especialmente o conflito com Throwable nas versões modernas), garantindo que as tabelas do MIDDAG e do Moodle fiquem em sincronia.
Decisões de design¶
- Padrão Anti-Corrupção: A fronteira atua como uma Anti-Corruption Layer (ACL). O framework não aceita "vazamentos" de conceitos do Moodle (como o sistema de permissões
capabilities) para dentro do domínio sem uma abstração intermediária. - Isolamento de Versão: Se uma nova versão do Moodle muda a forma de acessar arquivos, o framework altera apenas o Adapter de Arquivos. Todo o restante do sistema permanece intocado.
- Desacoplamento de Eventos: O framework não depende dos eventos do Moodle para seu fluxo principal. Ele prefere seus próprios Signals, usando os eventos do Moodle apenas como gatilhos externos de entrada.
O que não é¶
- Não é um Fork do Moodle: O framework não tenta substituir o Moodle, apenas isolar a lógica de negócio Middag da plataforma.
- Não é Opcional: O uso de globais do Moodle (
$DB,$USER) fora da camada desupportouinfrastructureé considerado uma violação grave da arquitetura. - Não é um Abstração Total: Não tentamos esconder 100% que estamos no Moodle (seria um esforço infinito). Abstraímos apenas o que é recorrente, estrutural ou instável.
Perspectiva para builders de extensions¶
Ao desenvolver uma extension:
1. Use os Facades do Core: Em vez de acessar $DB, use as facades de persistência ou o moodle::db() adapter do framework.
2. Não use require_once do Moodle: Deixe que o framework e o autoloader do Moodle cuidem do carregamento das classes.
3. Acesse o Contexto via Service: Se precisar de informações do usuário atual ou do curso, peça o serviço moodle_context_provider via DI.
Exemplo ilustrativo¶
Evitando o acoplamento direto:
// ❌ INCORRETO: Acoplamento direto com o Moodle
global $DB;
$user = $DB->get_record('user', ['id' => 123]);
// ✅ CORRETO: Uso de adapter na fronteira
$user_adapter = middag::get(moodle_user_repository::class);
$user = $user_adapter->find_by_id(123);
No segundo exemplo, o código está protegido contra mudanças na tabela user ou na API global do Moodle.