""" Het plugin-register: het hart van de modulaire architectuur. Elke module (een Django-app) maakt zichzelf bij opstarten bekend door een `ModuleSpec` te registreren. Het register houdt bij wélke modules er bestaan, wat ze aanbieden (menu-items / uitbreidpunten) en hoe ze van elkaar afhangen. Of een module daadwerkelijk AAN staat, wordt per school bewaard in de database (zie models.ModuleState) en is via het beheerscherm in te stellen. Zo is modulariteit een echt verkoopargument: de kern is overal gelijk, en een school schakelt naar wens modules bij. """ from __future__ import annotations from dataclasses import dataclass, field @dataclass(frozen=True) class MenuItem: """Een navigatie-item dat een module toevoegt aan de app. `group` plaatst het item onder een (inklapbaar) submenu in de zijbalk. Leeg = een item op het hoofdniveau. """ label: str path: str icon: str = "puzzle" order: int = 100 group: str = "" @dataclass(frozen=True) class ModuleSpec: """Beschrijving waarmee een module zich aanmeldt bij het register.""" key: str # unieke sleutel, bv. "printing" name: str # leesbare naam description: str = "" version: str = "0.1.0" category: str = "Overig" core: bool = False # kern-module: altijd aan, niet uitschakelbaar default_enabled: bool = False # standaard aan na installatie? depends_on: tuple[str, ...] = field(default_factory=tuple) menu_items: tuple[MenuItem, ...] = field(default_factory=tuple) class ModuleRegistry: """Centrale verzameling van alle bekende modules (in-memory).""" def __init__(self) -> None: self._specs: dict[str, ModuleSpec] = {} def register(self, spec: ModuleSpec) -> None: if spec.key in self._specs: raise ValueError(f"Module '{spec.key}' is al geregistreerd.") self._specs[spec.key] = spec def all(self) -> list[ModuleSpec]: return sorted(self._specs.values(), key=lambda s: (s.category, s.name)) def get(self, key: str) -> ModuleSpec | None: return self._specs.get(key) def dependents_of(self, key: str) -> list[ModuleSpec]: """Modules die deze module nodig hebben.""" return [s for s in self._specs.values() if key in s.depends_on] # Eén gedeeld register voor de hele applicatie. registry = ModuleRegistry()