Skip to main content
OpenEyes provides a comprehensive settings system that allows administrators to customize behavior at multiple levels, from installation-wide defaults to user-specific preferences.

Settings Architecture

The settings system uses a hierarchical approach with multiple levels of specificity:
User Settings (highest priority)

Firm Settings

Institution + Subspecialty Settings

Subspecialty Settings

Specialty Settings

Site Settings

Institution Settings

Installation Settings (lowest priority, system defaults)
When retrieving a setting, the system checks each level in order (most specific first) until a value is found.

Settings Database Schema

The system uses 9 related tables:

Setting Metadata

Table: setting_metadata Defines available settings and their properties:
id
integer
Unique identifier
key
string
required
Unique setting key (used in code)
name
string
required
Display name for admin interface
field_type_id
integer
required
Type of input field (text, dropdown, checkbox, HTML, etc.)
data
text
Serialized data for field configuration (e.g., dropdown options)
default_value
text
required
Default value when no override exists
element_type_id
integer
Optional: Link to specific element type if setting is element-specific
description
text
Help text for administrators
group_id
integer
required
Setting group for organization in admin UI
lowest_setting_level
string
Minimum level at which this setting can be overridden

Setting Instance Tables

Each level has its own table for storing setting values:
  • setting_installation - System-wide defaults
  • setting_institution - Institution-specific values
  • setting_site - Site-specific values
  • setting_specialty - Specialty-specific values
  • setting_subspecialty - Subspecialty-specific values
  • setting_institution_subspecialty - Institution + subspecialty combination
  • setting_firm - Firm/context-specific values
  • setting_user - User-specific values
All instance tables share this structure:
CREATE TABLE setting_[level] (
    id INT PRIMARY KEY AUTO_INCREMENT,
    key VARCHAR(64) NOT NULL,
    value TEXT,
    element_type_id INT,
    [level]_id INT NOT NULL,
    last_modified_date DATETIME,
    created_date DATETIME,
    UNIQUE KEY (key, element_type_id, [level]_id)
);

Accessing Settings

In PHP Code

// Get a setting value
$value = SettingMetadata::model()->getSetting('setting_key');

// Get setting with element type context
$value = SettingMetadata::model()->getSetting(
    'examination_view_mode',
    ElementType::model()->findByAttributes(['class_name' => 'Element_OphCiExamination_History'])
);

// Get setting display name (applies data mapping)
$displayValue = SettingMetadata::model()->getSettingName('setting_key');

// Get setting for specific institution (e.g., in admin)
$value = SettingMetadata::model()->getSetting(
    'setting_key',
    $element_type = null,
    $return_object = false,
    $allowed_classes = ['SettingInstitution', 'SettingInstallation'],
    $institution_id = 123,
    $is_setting_page = true
);

// Check if setting has specific value
if (SettingMetadata::checkSetting('feature_enabled', 'on')) {
    // Feature is enabled
}

Setting Context

The system automatically determines context from the current session: File: protected/models/SettingMetadata.php:219
public function getSetting($key = null, $element_type = null, ...)
{
    // Gather context from session
    $user_id = Yii::app()->session['user']->id ?? null;
    $firm_id = $firm ? $firm->id : null;
    $subspecialty_id = /* from firm */;
    $specialty_id = /* from subspecialty */;
    $site_id = /* from session */;
    $institution_id = $site->institution_id ?? null;
    
    // Check each level in order
    foreach (self::$CONTEXT_CLASSES as $class => $field) {
        if ($setting = $this->getSettingValue($class, $key, ...)) {
            return $this->parseSetting($setting, $metadata);
        }
    }
    
    // Return default if no override found
    return $metadata->default_value;
}

Setting Field Types

Available Field Types

Table: setting_field_type
Simple text input field.
array(
    'field_type_id' => 1,  // Text
    'default_value' => 'Default text'
)

HTML Settings with Substitutions

HTML field types can include dynamic substitutions:

Available Substitutions

Session Substitutions (user/firm/site context):
  • [user_name] - Current user’s full name
  • [user_title] - User’s professional title
  • [firm_name] - Current firm name
  • [site_name] - Current site name
  • [site_address] - Site address
  • [site_phone] - Site phone number
  • [site_fax] - Site fax number
  • [site_email] - Site email
  • [current_date] - Today’s date
  • [primary_logo] - Institution primary logo
  • [secondary_logo] - Institution secondary logo
Patient Substitutions:
  • [patient_full_name]
  • [patient_first_name]
  • [patient_last_name]
  • [patient_date_of_birth]
  • [patient_gender]
  • [patient_nhs_num]
  • [patient_hos_num]
  • [patient_last_exam_date]

Using Substitutions

// In setting metadata
array(
    'key' => 'correspondence_footer',
    'field_type_id' => 6,  // HTML
    'data' => serialize(array(
        'substitutions' => array(
            'site_name',
            'site_address',
            'site_phone'
        )
    )),
    'default_value' => '<p><span data-substitution="site_name">[site_name]</span><br>
                        <span data-substitution="site_address">[site_address]</span><br>
                        Tel: <span data-substitution="site_phone">[site_phone]</span></p>'
)

// Performing substitutions at runtime
$html = SettingMetadata::model()->getSetting('correspondence_footer');
// Substitutions are automatically applied when retrieved
Substitutions are processed automatically by the parseSetting() method in SettingMetadata.php:384.

Managing Settings in Admin Interface

Accessing System Settings

Navigate to: Admin → System Settings Settings are organized into groups:
  • Core - Essential system settings
  • User Interface - Display and behavior settings
  • Clinical - Clinical workflow settings
  • Correspondence - Letter and document settings
  • Examination - Examination module settings
  • Module-specific - Settings for each active module

Setting Groups

Table: setting_group
class SettingGroup extends BaseActiveRecord
{
    public $id;
    public $name;           // Display name
    public $description;    // Help text
    public $display_order;  // Sort order
}

Editing Settings

1

Select Setting Group

Choose the group containing the setting to edit
2

Choose Setting Level

Select whether to edit at:
  • Installation (system default)
  • Institution
  • Site
  • Subspecialty
  • etc.
3

Modify Value

Change the setting value using the appropriate input field
4

Save Changes

Click “Save” to apply the new value
Changing installation-level settings affects all institutions and users unless overridden at a more specific level.

Common System Settings

Core Settings

hos_num_label
string
default:"Hospital Number"
Label for hospital number field
nhs_num_label
string
default:"NHS Number"
Label for NHS number field
show_version
boolean
default:"on"
Display version number in footer
helpdesk_email
string
Email address for helpdesk/support
helpdesk_phone
string
Phone number for helpdesk/support

User Interface Settings

recent_context_firm_limit
integer
default:"6"
Number of recent firms to show in context menu
default_rows_per_page
integer
default:"30"
Default pagination size for lists
patient_summary_id_widgets
text
Configure which ID numbers to display in patient summary

Clinical Settings

default_site_id
integer
Default site for new events
auto_generate_event_name
boolean
Automatically generate event descriptions
event_print_method
string
default:"pdf"
Method for printing events: pdf or html

Correspondence Settings

correspondence_sort_order
string
Default sort order for correspondence list
default_letter_address
string
Default address type for letters
Default letter footer content (supports substitutions)

Custom Text Settings

OpenEyes allows customizing display text for event types and element types:

Event Type Custom Text

// protected/controllers/AdminController.php:307
public function actionEditEventTypeCustomText()
{
    foreach ($_POST['EventType'] as $event_type_form) {
        $event_type = EventType::model()->findByPk($event_type_form['id']);
        $event_type->custom_event_name = $form['custom_event_name'];
        $event_type->save();
    }
}

Element Type Custom Text

// protected/controllers/AdminController.php:334  
public function actionEditElementTypeCustomText()
{
    foreach ($_POST['ElementType'] as $element_type_form) {
        $element_type = ElementType::model()->findByPk(
            $element_type_form['id']
        );
        $element_type->custom_hint_text = $form['custom_hint_text'];
        $element_type->save();
    }
}

Caching

The settings system implements aggressive caching for performance: File: protected/models/SettingMetadata.php:250-270
// Check for settings table updates
$debounce_val = Yii::app()->settingCache->get('SettingMetaDebounce');
if ($debounce_val === false) {
    // Query last update time of all setting tables
    $dependency_sql = "SELECT sha1(GROUP_CONCAT(UPDATE_TIME))
                       FROM information_schema.tables
                       WHERE TABLE_NAME IN (
                           'setting_metadata',
                           'setting_installation',
                           'setting_institution',
                           ...
                       )";
    $debounce_val = Yii::app()->db->createCommand($dependency_sql)
                                   ->queryScalar();
    // Cache for 5 seconds to prevent excessive queries
    Yii::app()->settingCache->set('SettingMetaDebounce', $debounce_val, 5);
}

Cache Management

// Clear settings cache
SettingMetadata::resetCache();
// or via CLI
./yiic cache flush settingCache

// Clear all caches
./yiic cache flush all
Settings are cached with a dependency on the last update time of setting tables. The cache automatically invalidates when settings are modified.

Creating New Settings

Via Database Migration

class m240101_120000_add_new_setting extends OEMigration
{
    public function up()
    {
        // Get or create setting group
        $group_id = $this->getIdOfSettingGroupByName('Core');
        
        // Get field type
        $field_type_id = $this->getIdOfSettingFieldTypeByName('Checkbox');
        
        // Insert setting metadata
        $this->insert('setting_metadata', [
            'element_type_id' => null,
            'display_order' => 10,
            'field_type_id' => $field_type_id,
            'key' => 'my_new_setting',
            'name' => 'My New Setting',
            'data' => null,
            'default_value' => 'off',
            'description' => 'Description of what this setting does',
            'group_id' => $group_id,
            'lowest_setting_level' => 'INSTALLATION',
        ]);
        
        // Optionally set installation-level value
        $this->insert('setting_installation', [
            'key' => 'my_new_setting',
            'value' => 'on',
        ]);
    }
    
    public function down()
    {
        $this->delete('setting_installation', 
                     "`key` = 'my_new_setting'");
        $this->delete('setting_metadata', 
                     "`key` = 'my_new_setting'");
    }
}

Via Admin SQL

-- Insert setting metadata
INSERT INTO setting_metadata (
    element_type_id,
    display_order,
    field_type_id,
    `key`,
    name,
    data,
    default_value,
    description,
    group_id
) VALUES (
    NULL,
    10,
    (SELECT id FROM setting_field_type WHERE name = 'Checkbox'),
    'feature_enabled',
    'Enable Feature',
    NULL,
    'off',
    'Enable the new feature functionality',
    (SELECT id FROM setting_group WHERE name = 'Core')
);

-- Set installation default
INSERT INTO setting_installation (`key`, value) 
VALUES ('feature_enabled', 'on');

API Reference

SettingMetadata Methods

File: protected/models/SettingMetadata.php
  • getSetting($key, $element_type, $return_object, $allowed_classes, $institution_id, $is_setting_page) - Retrieve setting value
  • getSettingName($key, $allowed_classes, $institution_id, $is_setting_page) - Get display name with data mapping
  • checkSetting($key, $value) - Check if setting has specific value
  • parseSetting($setting, $metadata) - Process setting value (apply substitutions, etc.)
  • performSubstitutions($html, $substitutions, $preserve_empty) - Apply substitutions to HTML
  • getSessionSubstitutions() - Get available session-based substitutions
  • getPatientSubstitutions($patient, $event) - Get patient-specific substitutions
  • resetCache() - Clear settings cache

AdminController Settings Methods

File: protected/controllers/AdminController.php
  • actionEditEventTypeCustomText() - Line 307
  • actionEditElementTypeCustomText() - Line 334

Best Practices

Use Appropriate Levels

Set settings at the most appropriate level for your use case

Document Custom Settings

Add clear descriptions to help future administrators

Test Before Production

Test setting changes in a development environment first

Version Control Migrations

Use database migrations for new settings in code

Build docs developers (and LLMs) love