Pular para conteúdo

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 de support ou infrastructure é 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.