Skip to main content

RegisterResolverService

OCA\OpenRegister\Service\RegisterResolverService is a small, DI-friendly public service that consumer apps use to resolve <context>_register and <context>_schema IAppConfig keys into either bare slug/UUID strings or hydrated Register / Schema entities. It replaces the duplicated getValueString(...) + manual mapper-lookup pattern observed across opencatalogi (5 controllers), pipelinq (8 services / jobs), and docudesk (OpenRegisterResolver helper).

The service is multi-tenant aware — it goes through the same RegisterMapper / SchemaMapper find() calls every other OR code path takes, so MultiTenancyTrait::applyOrganisationFilter is honoured for free. An explicit $organisationUuid override on every resolve method is available for cross-tenant admin tooling. Resolved entities are cached at the request scope so a single PHP request only pays one mapper hit per (appId, configKey, organisationUuid) tuple.

Naming convention

FormWhen to useExample
<context>_registerPreferred. New code MUST use this shape.theme_register
<context>_schemaPreferred. New code MUST use this shape.listing_schema
Bare register / schemaGrandfathered for legacy consumers (pipelinq).register

enumerateAppConfigs() surfaces the bare keys as default_register / default_schema so admin UIs can flag them as legacy convention.

Consuming-app migration

Before — every consumer ships some variant of this:

$registerSlug = $this->appConfig->getValueString(
Application::APP_ID,
'theme_register',
''
);
if ($registerSlug === '') {
return new JSONResponse(['error' => 'Theme register not configured'], 500);
}
$register = $this->registerMapper->findBySlug($registerSlug);

After — the resolver returns a hydrated entity or throws a typed exception:

use OCA\OpenRegister\Service\RegisterResolverService;
use OCA\OpenRegister\Service\Resolver\Exception\MissingConfigException;
use OCA\OpenRegister\Service\Resolver\Exception\RegisterNotFoundException;

public function __construct(private readonly RegisterResolverService $resolver) {}

public function showTheme(): JSONResponse {
try {
$register = $this->resolver->resolveRegister(
Application::APP_ID,
'theme_register'
);
} catch (MissingConfigException $e) {
return new JSONResponse([
'error' => 'Theme register not configured',
'configKey' => $e->getConfigKey(),
], 500);
} catch (RegisterNotFoundException $e) {
return new JSONResponse([
'error' => 'Theme register not found',
'resolvedValue' => $e->getResolvedValue(),
], 500);
}

return new JSONResponse($register->jsonSerialize());
}

Diagnostic CLI

A new console command lists every resolver-shaped config key currently set for an app, mirroring enumerateAppConfigs():

$ occ openregister:resolver:list opencatalogi
Resolver keys for app "opencatalogi":
listing_register = cms
listing_schema = listing-v2
theme_register = theme-2026
theme_schema = theme-v1

Public API

MethodReturnsThrows
resolveRegisterId(appId, configKey, default?, organisationUuid?)stringMissingConfigException
resolveSchemaId(appId, configKey, default?, organisationUuid?)stringMissingConfigException
resolveRegister(appId, configKey, default?, organisationUuid?)RegisterMissingConfigException, RegisterNotFoundException
resolveSchema(appId, configKey, default?, organisationUuid?)SchemaMissingConfigException, SchemaNotFoundException
resolvePair(appId, registerKey, schemaKey, organisationUuid?)RegisterSchemaPairMissingConfigException, RegisterNotFoundException, SchemaNotFoundException
enumerateAppConfigs(appId)array<string,string>-
clearCache()void-

Exceptions live under OCA\OpenRegister\Service\Resolver\Exception\ to avoid name collision with the generic OCA\OpenRegister\Exception\RegisterNotFoundException / SchemaNotFoundException used by the entity layer.