Pular para conteúdo

Contracts

Contracts are interfaces you type-hint in your constructor. The DI container resolves the concrete implementation automatically.

use local_middag\framework\contract\command_bus_interface;

class my_service extends \local_middag\base\service
{
    public function __construct(
        private readonly command_bus_interface $bus,
    ) {}
}

All contracts listed on this page are classified Group A (@api) and follow SemVer evolution policy.


Cross-cutting contracts

Commonly injected by any extension:

Interface Purpose Example
command_bus_interface Dispatch commands (sync/async) $bus->handle(new my_command(...))
dispatcher_interface Publish typed signals $dispatcher->dispatch($signal)
item_service_interface CRUD operations on items $items->create($type, $data)
item_repository_interface Direct repository access $repo->find($id)
form_request_interface Declarative input validation Auto-injected before controller executes
job_service_interface Async job governance $jobs->create($command, $correlationId)
Psr\Log\LoggerInterface PSR-3 logging $logger->warning('msg', $context)

Core Capability contracts (ADR-607)

The framework exposes 6 Core Capabilities (CCs) as bounded contexts. Each CC provides one or more @api contracts that extensions consume via DI. CCs live in local_middag\framework\contract\.

Overview

CC Domain Primary contract(s) Extension point Facade
CC-02 core.connectors connector_interface, connector_registry_interface -- --
CC-03 core.workflow workflow_action_interface, workflow_registry_interface -- --
CC-06 core.instancegroup instancegroup_interface -- --
CC-07 core.segments segments_interface criteria_provider_interface --
CC-08 core.compliance compliance_interface -- --
CC-09 core.conditions conditions_interface condition_provider_interface --

CCs do not have dedicated facades. Consume them exclusively via constructor injection.

CC-02 -- Connectors

Catalog of external service connection types. Manages credentials, health checks, and per-extension binding. Extensions that integrate with third-party APIs (e.g. Twilio, BigQuery) implement connector_interface and register via connector_registry_interface during register().

CC-03 -- Workflow

Discrete work actions triggered by forms, events, or scheduled tasks. The workflow engine evaluates triggers and dispatches the matching action. Extensions implement workflow_action_interface and register via workflow_registry_interface during boot().

CC-06 -- Instance Group

Logical grouping and versioning of courses/resources. Extensions reference groups instead of individual courses, enabling course equivalence, re-enrolment, and progression logic. Consumed through instancegroup_interface.

CC-07 -- Segments

Rule-based audience segmentation engine. Segments return SQL subqueries (not materialized lists) for composability and performance at scale. Extensions add custom criteria types by implementing criteria_provider_interface and registering during boot().

CC-08 -- Compliance

Profile compliance verification against a Moodle context. Checks whether a user meets all mandatory profile requirements. When no provider is registered, consumers treat users as compliant (graceful degradation). Consumed through compliance_interface.

CC-09 -- Conditions

Inclusion/exclusion rule engine evaluated against Moodle contexts (categories, courses, activity types). Works like display conditions in page builders. Extensions add custom condition types by implementing condition_provider_interface and registering during boot().

How to consume

Type-hint the contract in your constructor. The container resolves it:

use local_middag\framework\contract\segments_interface;
use local_middag\framework\contract\compliance_interface;

class my_service extends \local_middag\base\service
{
    public function __construct(
        private readonly segments_interface $segments,
        private readonly compliance_interface $compliance,
    ) {}
}

When a CC provider may not be available, check before consuming:

if (!$this->container->has(compliance_interface::class)) {
    return true; // No provider -- treat as compliant.
}

For detailed method signatures, value objects, and code examples for each CC, see Core Capabilities.


Boundary contracts (Moodle)

Implemented by extensions to integrate with Moodle subsystems:

Interface When to implement
privacy_provider_interface Extension stores personal data (GDPR)
backup_steps_provider_interface Extension participates in backup/restore
file_area_handler_interface Extension manages files via Moodle File API

Attributes

Attribute Where to use
#[item_type('slug:type')] On an entity class to declare an item type
#[schedule('0 * * * *')] On an extension method to schedule periodic execution
#[on('middag/item/created')] On a subscriber method for auto-discovery of hooks

Moodle traditional vs MIDDAG

Aspect Moodle traditional MIDDAG
Dependency injection new my_class() or manual factory Type-hint in constructor, container resolves
Logging debugging('msg', DEBUG_DEVELOPER) LoggerInterface via DI
Backup/Restore Implement backup_*_stepslib.php by hand backup_steps_provider_interface with typed definitions
Privacy provider.php with static methods privacy_provider_interface with repository delegation

Cross-references

  • Core Capabilities -- full method signatures and code examples for each CC
  • API Classification -- Group A/B/C rules and inventory
  • Base Classes -- extension, service, controller base classes
  • ADR-607 -- Core subdomain model
  • ADR-601 -- Container and dependency injection
  • ADR-602 -- Extension lifecycle (register/boot/compile)