Skip to content

Import Repository Contract & Operational Detail

Reference for the repository that backup/restore uses to rehydrate persisted state on the Moodle adapter — direct, unvalidated insertion of historical data, deliberately bypassing the normal domain-creation path. Backs MDL-010.

Why restore does not use the normal creation path

Restoring a course reconstitutes historical state exactly as it existed on the source site — it is not a new business event. Routing restored rows through the ordinary domain-creation flow (item_repository::create() and friends) would generate new timestamps, fire domain events, and mint a new GUID on every row — exactly wrong when the goal is to reproduce history faithfully. The import repository exists to give restore a narrow, honest path that does none of that.

Contract

php
interface backup_steps_provider_interface {
    public function get_backup_steps(): array;   // backup_step instances
    public function get_restore_steps(): array;  // restore_step instances
}

interface import_repository_interface extends repository_interface {
    public function import_item(array $data): int;      // raw item insert
    public function import_itemmeta(array $data): int;   // raw metadata insert
}

backup_steps_provider_interface is how a plugin or integration with its own storage participates in backup/restore (Group A, stable public API). Integrations that only use the framework's central persistence (core EAV tables) need no provider of their own — the central handler covers them.

Tables involved

Core EAV tables: middag_items, middag_itemmeta.

What the import repository does on insert

StepBehaviorWhy
id fieldStripped before insertionMoodle Restore always remaps IDs on the target site — preserving the source id would either collide with auto-increment or be meaningless.
Insert pathDirect via db_support::insert_record()No domain events, no entity hydration, no validation — this is the deliberate bypass; spelled out here so it can't be "cleaned up" by someone unaware of the rationale.
timecreated, timemodified, guidPreserved exactly as read from the .mbz fileFaithful historical reproduction depends on not silently regenerating these.
ID remapping$this->get_mappingid('course'|'user', $old_id) inside the extension's own restore_stepThe source site's IDs do not exist on the destination — this is the only correct way to translate them.

Anti-patterns

Anti-patternWhy it's wrong
Using item_repository::create() during restoreGenerates new timestamps/events/GUID — exactly wrong for historical import.
Not remapping IDsThe source site's IDs do not exist on the destination site.
Inserting with the id field presentAuto-increment collision risk; the import repository already strips it — doing this means bypassing the import repository and inserting directly.
Validating data during restoreHistorical data may not satisfy today's domain rules. The bypass is deliberate, not a bug to fix.

Downstream consequence to track separately

Asynchronous jobs/work restored this way may need their own governance pass after import — tracked in the framework's own decisions record, out of scope for this adapter.

MIDDAG © 2015-2026