Pular para conteúdo

Kernel e Ciclo de Vida

O Kernel (local_middag\core\kernel\kernel) é o componente central de orquestração do plugin. Ele atua como a ponte entre o ambiente procedural do Moodle e a arquitetura orientada a objetos do MIDDAG.

Sua responsabilidade é única e crítica: Inicializar o Container de Injeção de Dependência (DI) e garantir que todos os componentes (Core e Extensões) estejam prontos para uso.


O Processo de Boot (Bootstrapping)

O MIDDAG utiliza um processo de inicialização "Lazy" (preguiçoso). O Kernel só é instanciado quando o primeiro recurso do plugin é solicitado.

O diagrama abaixo detalha a sequência exata de eventos quando middag::init() é chamado:

sequenceDiagram
    participant Moodle as Moodle / Lib.php
    participant Facade as Facade (middag)
    participant Kernel as Kernel
    participant Container as ContainerBuilder
    participant Loaders as Loaders (Ext/Svc/Type)

    Moodle->>Facade: Chama middag::init()
    Facade->>Kernel: init() (Singleton Check)

    alt Já inicializado
        Kernel-->>Facade: Retorna instância existente
    else Primeira execução
        Kernel->>Container: new ContainerBuilder()

        note right of Kernel: Fase 1: Descoberta
        Kernel->>Loaders: Executa Loaders
        Loaders-->>Container: Registra Definições (autowire)

        note right of Kernel: Fase 2: Compilação
        Kernel->>Container: compile() (Congela configuração)

        note right of Kernel: Fase 3: Injeção Sintética
        Kernel->>Container: set(serviços_vivos)

        Kernel-->>Facade: Boot Concluído
    end

Fases do Boot

  1. Descoberta (Discovery): O Kernel aciona os Loaders que varrem os diretórios do projeto para encontrar classes, serviços e configurações de extensões. Nenhuma classe é instanciada aqui, apenas suas definições são registradas.
  2. Compilação (Compilation): O ContainerBuilder do Symfony processa todas as definições, resolve dependências e otimiza o grafo de objetos. Após este ponto, a configuração do container torna-se imutável (frozen) para garantir performance.
  3. Injeção Sintética (Synthetic Injection): Objetos que já existem em tempo de execução (como o próprio Kernel ou instâncias de Loaders) são injetados manualmente no container compilado.

Container de Injeção de Dependência

O MIDDAG utiliza o componente symfony/dependency-injection. Isso elimina a necessidade de new Class() espalhados pelo código e permite testes unitários fáceis via Mocking.

Autowiring

A maioria dos serviços é configurada com autowire: true. Isso significa que você não precisa configurar dependências manualmente. Basta declarar o tipo no construtor.

Exemplo:

<?php

// O Kernel lerá o tipo 'item_repository' e injetará a instância correta automaticamente.
public function __construct(private item_repository $repository) {}

Serviços Sintéticos (Synthetic Services)

Alguns serviços são marcados como sintéticos no Kernel. Isso significa: "Container, não tente criar isso. Eu vou te entregar a instância pronta depois de compilar". Isso é usado para evitar referências circulares durante o boot do próprio Kernel.


Loaders: O Sistema de Descoberta

Para evitar arquivos de configuração XML ou YAML gigantescos, o Kernel delega a descoberta de recursos para classes especializadas chamadas Loaders. Elas operam sob o princípio de Convention over Configuration (Convenção sobre Configuração).

1. Service Loader (service_loader.php)

Varre diretórios padrão (classes/core/service, classes/core/repository, etc.) e registra automaticamente qualquer classe encontrada como um serviço público no container.

  • Cache: Em produção, o mapa de arquivos é cacheado para evitar acesso lento ao disco.

2. Extension Loader (extension_loader.php)

Varre a pasta classes/extensions/.

  • Identifica classes que estendem base_extension.
  • Lê metadados como GROUP e PRIORITY.
  • Executa arquivos bootstrap.php de cada extensão de forma isolada (try/catch), garantindo que uma extensão quebrada não derrube o sistema.

3. Type Loader (type_loader.php)

Responsável pelo DDD. Varre as pastas domain/entity procurando classes que definem constantes TYPE.

  • Popula o item_types registry.
  • Permite que o repositório saiba qual classe instanciar baseada em uma string (ex: 'course' -> course_item::class).

HttpKernel e Roteamento

Embora o Kernel principal cuide dos objetos, o http_kernel cuida da Web. Ele é anexado ao Kernel principal após o boot.

Responsabilidades:

  • Request Lifecycle: Captura a Request global do PHP/Moodle.
  • Routing: Usa o route_manager para mapear URLs para Controllers.
  • Response Handling: Garante que se o Controller retornar um Array, ele seja convertido para JsonResponse automaticamente.
  • Error Handling: Intercepta exceções e as transforma em respostas JSON padronizadas (evitando a "Tela Branca da Morte" ou vazamento de HTML em chamadas AJAX).

Atributos PHP 8

O roteamento usa reflexão para ler atributos nativos. Não há arquivo de rotas central.

<?php

#[Route('/api/v1/courses', name: 'api.courses', methods: ['GET'])]
public function index(): Response { ... }

Como acessar o Kernel

Em desenvolvimento de extensões ou scripts de manutenção, você raramente acessará a classe kernel diretamente. Utilize sempre a Facade:

<?php

use local_middag\core\middag;

// 1. Inicializar (seguro chamar múltiplas vezes)
middag::init();

// 2. Pegar um serviço
$service = middag::get(meu_servico::class);

// 3. Gerar uma URL
$url = middag::url_generator('minha_rota', ['id' => 1]);