Skip to content

Config Registry System

Flow ID: SY-19 | Module(s): core | Complexity: Medium Last Updated: 2026-04-04

Business Overview

The Registry is the platform's database-backed configuration system. It stores key-value pairs organized by group, with optional language scoping and encryption support. Nearly every aspect of the platform's runtime behavior is configured through the Registry -- from email subjects and payment provider credentials to feature flags and integration API keys.

What the Registry provides:

  • Hierarchical configuration: group -> key -> language -> value
  • Language-scoped settings for multilingual sites
  • Encrypted value support for sensitive data (API keys, secrets)
  • PSCache integration for read performance
  • Method chaining for fluent API usage
  • Array serialization (pipe-delimited) for list values

Why it matters: The Registry is referenced by virtually every module in the platform. Understanding its structure is essential for debugging, configuration, and client customization.


Architecture

Registry (Library)
  |
  +--> constructor:
  |      load Registry_model
  |      load PSCache
  |      load Encryption
  |      parseDb( pscache->model('registry_model', 'all', []) )
  |
  +--> value($group, $key, $lang, $encrypted)
  |      read from in-memory $data[$group][$key][$lang]
  |      optional decrypt via Encryption library
  |
  +--> setValue($group, $key, $val, $lang, $encrypted)
  |      update in-memory cache
  |      persist via Registry_model::set_regval()
  |
  +--> live()
         refresh PSCache + re-parse from DB
         (used by jobs that need latest config)

Core Classes

ClassFilePurpose
Registryapplication/libraries/Registry.phpMain library (loaded globally)
Registry_modelapplication/models/Registry_model.phpDatabase access layer

Access Pattern

The Registry is loaded as a CI library and available throughout the application:

php
// Read a value
$this->registry->value('EMAIL_SUBJECTS', 'ORDER_UPDATE', 'el');

// Read without language (BASE)
$this->registry->value('PAY_BY_BANK', 'API_KEY');

// Read encrypted value
$this->registry->value('PAY_BY_BANK', 'API_KEY', '', true);

// Read as array (pipe-delimited)
$this->registry->getArray('AVAILABLE_COUNTRIES', 'ESHOP');

// Read entire group as associative array
$this->registry->getGroupAsArray('COMPANY', '', ['API_SECRET']);

// Write a value
$this->registry->setValue('COMPANY', 'PHONE', '2101234567');

// Write array (pipe-delimited serialization)
$this->registry->setArray('AVAILABLE_COUNTRIES', 'ESHOP', '', ['GR', 'CY', 'DE']);

// Delete a value
$this->registry->delete('OLD_GROUP', 'DEPRECATED_KEY');

// Refresh from database (for jobs)
$this->registry->live();

Code Flow

1. Initialization (Constructor)

  1. Load Registry_model and pscache, encryption libraries
  2. Fetch all registry rows via PSCache: pscache->model('registry_model', 'all', [])
  3. Parse into a 3-level associative array: $data[group][key][lang] = value
  4. Empty lang values are stored under the BASE constant

2. Reading Values

value($regGroup, $regKey, $langAbbr, $encrypted):

  • If $langAbbr is empty, uses BASE (language-independent)
  • Looks up $data[$regGroup][$regKey][strtoupper($langAbbr)]
  • If $encrypted is true, decrypts the value via the Encryption library
  • Returns null if not found

3. Writing Values

setValue($regGroup, $regKey, $regVal, $langAbbr, $encrypted):

  • Updates the in-memory cache
  • Calls Registry_model::set_regval() which performs an upsert:
    • If a matching row exists (group + key + lang), updates regval
    • If not, inserts a new row
  • If $encrypted is true, the model encrypts the value before storage

4. Live Refresh

live():

  • Called by background jobs to ensure they have the latest config
  • Forces PSCache to refresh: pscache->updateCache('registry_model', 'all', [])
  • Re-parses the database data into memory
  • Returns $this for method chaining

5. Array Values

getArray($regKey, $regGroup, $langAbbr, $encrypted):

  • Reads the value and explodes by | delimiter
  • Returns an array of strings

setArray($regKey, $regGroup, $langAbbr, $regVal, $encrypted):

  • Implodes the array by | delimiter and stores as a single string

Data Model

Table: registry

ColumnTypeRole
reggroupvarcharConfiguration group (e.g., EMAIL_SUBJECTS, PAY_BY_BANK, ESHOP)
regkeyvarcharConfiguration key within the group
regvaltextConfiguration value (plain text or encrypted)
langvarcharLanguage code (empty string = language-independent)

Composite key behavior: The combination of reggroup + regkey + lang acts as a unique identifier. The set_regval() method performs an upsert on this combination.

Common Registry Groups

GroupPurposeExample Keys
EMAIL_SUBJECTSEmail subject templatesORDER_UPDATE, WAITING_LIST, CUSTOMER_INFORM_DELAY
EMAIL_SHOP_MAILERSMTP configurationSMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS
ESHOPGeneral e-shop settingsAVAILABLE_COUNTRIES, DEFAULT_CURRENCY
PAY_BY_BANKPayByBank configurationAPI_KEY, API_URL, EXPIRATION
COMPANYCompany informationPHONE, EMAIL, NAME
SEOSEO settingsMETA_TITLE, META_DESCRIPTION
SOCIALSocial media linksFACEBOOK, INSTAGRAM, TWITTER

Configuration

Loading

The Registry is auto-loaded as a CI library. It is available via:

  • $this->registry in controllers and models
  • registry() helper function (if the helper is loaded)

Caching

  • PSCache layer: Registry data is cached via PSCache (file or Redis-based). Cache is keyed on registry_model::all
  • In-memory: After loading, all values are held in the $data array for the duration of the request
  • Refresh: live() method forces a cache refresh -- used by cron jobs and long-running processes

Encryption

  • Uses CI's Encryption library for sensitive values
  • Encrypted values are stored as ciphertext in the database
  • Decryption happens at read time when $encrypted=true is passed
  • The getGroupAsArray() method accepts an $encryptedKeys array to decrypt specific keys within a group

Client Extension Points

  1. Add custom registry entries: Insert rows into the registry table directly or via the admin settings interface. No code changes needed for simple key-value configuration.

  2. Override the Registry library: Create application/libraries/Registry.php extending the base class to add custom methods (e.g., typed getters, validation).

  3. Override the Registry model: Create application/models/Registry_model.php to customize database queries (e.g., add audit logging on writes).

  4. Admin Settings UI: The admin settings page (AD-13) provides a UI for managing many registry groups. Client-specific settings can be added to the settings views.

  5. Patchers for data migration: Use the AbstractPatcher mechanism to create registry entries during deployment (e.g., set initial values for new features).


Business Rules

RuleDescription
Language fallbackNo automatic fallback -- if a language-specific value is not found, null is returned. Callers must handle fallback logic
BASE languageEmpty language string maps to BASE constant internally
Upsert semanticssetValue() creates or updates -- no separate create/update methods
Pipe-delimited arraysArray values are stored as pipe-delimited strings (e.g., GR|CY|DE)
Encryption at restSensitive values can be encrypted in the database; decrypted on read
Cache coherenceBackground jobs must call live() to get fresh values; web requests use PSCache TTL
Universal dependencyThe Registry is used by virtually every module -- changing its structure has platform-wide impact

Wiki Guide: Settings in Database -- developer guide for database-backed configuration