Registries
Every extensible subsystem in Downloads Manager ships as a registry-and-adapter pair. Each registry holds a small interface, one or more built-in adapters, and a code event that lets third parties register their own. The shape matches MC\Quests.
Registries are bound on the container in Listener::appSetup(). The closure is lazy: the built-in adapters are registered and the *_handlers event is fired the first time the registry is resolved, not at boot.
$app->container()->set('mc_dm.{registry}_registry', function () {
$registry = new {Registry}Registry();
self::registerBuiltIn{Registry}($registry);
\XF::fire('mc_dm_{registry}_handlers', [$registry]);
return $registry;
});
The four registries
| # | Registry | Container key | Event | Built-ins | Third-party expected |
|---|---|---|---|---|---|
| 1 | Gate | mc_dm.gate_registry | mc_dm_gate_handlers | Permission, Criteria, Password, Hotlink, Captcha, RateLimit, Bandwidth | virus-scan gate, NSFW gate (ships as separate add-on) |
| 2 | Processor | mc_dm.processor_registry | mc_dm_processor_handlers | hash, size, mime, magic-byte, decompression-bomb | virus scan |
| 3 | Source | mc_dm.source_registry | mc_dm_source_handlers | DirectUrl, GitHubRelease, S3, Magnet | IPFS, GitLab/Gitea releases, tracker-only sources |
| 4 | Stats | mc_dm.stats_registry | mc_dm_stats_handlers | BuiltInAggregator | Plausible, Matomo |
Why only four
Fields, search, notifications, and storage use the existing core extension points instead of an add-on registry:
- Fields use the native
\XF\CustomField\Definitionsystem (8 native types plus thematch_typecolumn). - Search uses the native
Sourceinterface. This is the same swap point Enhanced Search uses for Elasticsearch. - Notifications use
XF\Notifier\AbstractNotifiersubclasses, the same pattern the Resource Manager uses. - Storage uses the Flysystem
MountManagerdirectly viainternal-data://mc-downloads/.... Admins reroute this add-on (and every other add-on) by editingconfig.php.
Adding a registry on top of any of these would just duplicate the existing swap points.
Building an adapter
Every registry exposes the same shape: a register($id, $adapter) method and a get($id) method. To add an adapter:
- Implement the registry's interface (e.g.
MC\DownloadsManager\Gate\Gate). - Subscribe to the registry's event in your add-on's
code_event_listeners.xml. - Call
$registry->register('your_id', new YourAdapter())from the listener.
See each registry page for the interface contract and concrete examples.