Which is correct: "usr.theme" or "cfg.defaulttheme" for use in Cotonti ?

This article systematises knowledge about Cotonti theming mechanisms and provides an unambiguous answer to the question posed. The material is intended both for beginner developers and for experienced specialists

0 Published Filed under: Cotonti Siena CMF > Cotonti - reading materials. Documentation.

Which is correct: Cot::$usr['theme'] or Cot::$cfg['defaulttheme']?

Table of Contents

  1. Introduction
  2. Purpose of the .rc.php file in the Cotonti architecture
    1. Definition
    2. Place in the CMF architecture
    3. How the engine includes the file
    4. Loading conditions
    5. Position in the execution sequence
  3. The $usr['theme'] and $cfg['defaulttheme'] variables
    1. The $cfg['defaulttheme'] variable
    2. The $usr['theme'] variable
    3. Possible values of $usr['theme']
    4. Relationship between the variables
  4. The mechanism of .rc.php inclusion by the engine
    1. Step-by-step breakdown
    2. What is available inside .rc.php
    3. What is guaranteed
  5. Relationship and priority of the variables
    1. Absence of priority
    2. Rule of choice
    3. Rationale
    4. Official Cotonti position
  6. Practical operational scenarios
    1. Scenario A. Single theme, forced mode enabled
    2. Scenario B. Single theme, forced mode disabled
    3. Scenario C. Multiple themes, user preferences
    4. Scenario D. Change of defaulttheme
    5. Scenario E. Fallback theme
    6. Summary table of scenarios
  7. Rules for structuring the .rc.php file
    1. General requirements
    2. Recommendations on structure
    3. Recommendations on resource order
    4. Recommendations on placement
    5. File template
  8. Reference of the Resources class
    1. Public methods
    2. Predefined aliases
    3. The scope mechanism
    4. The order mechanism
    5. Consolidation and minification
  9. Common errors and how to fix them
    1. Using $cfg['defaulttheme'] for theme resource paths
    2. Using the $theme variable
    3. Duplicate resources
    4. Placing CSS in the footer
    5. Placing all JS in the head
    6. Ignoring the addFile exception
    7. Modifying $theme_reload
    8. Using deprecated wrappers
    9. Incorrect order
    10. Database access
  10. Diagnostics and debugging
    1. Checking variable values
    2. Checking file inclusion
    3. Checking the resource registry
    4. Checking consolidation
    5. Checking exceptions
    6. Enabling the debug mode
  11. Conclusion

1. Introduction

When developing a theme for Cotonti CMF, a developer encounters the need to include CSS and JavaScript resources in the .rc.php file. A natural question arises: which variable should be used to build paths to the theme resources — Cot::$usr['theme'] or Cot::$cfg['defaulttheme']?

At first glance, the difference between these variables is minimal, and many ready-made themes use Cot::$cfg['defaulttheme']. However, this approach works only within a limited set of configurations. In the general case, it leads to broken paths, exceptions in Resources::addFile(), and a crash of the front-end part of the site.

This article systematises knowledge about Cotonti theming mechanisms and provides an unambiguous answer to the question posed. The material is intended both for beginner developers and for experienced specialists familiar with the internal structure of the CMF.

2. Purpose of the .rc.php file in the Cotonti architecture

2.1. Definition

The .rc.php file (from English resource control) is an auxiliary file of a Cotonti theme that registers CSS and JavaScript resources in the static registry of the Resources class. The engine then outputs these resources into the <head> of the page and into the footer.

The file is neither a plugin, nor a module, nor a standalone theme. It belongs to the category of auxiliary theme files alongside {theme}.php (the file that overrides language and resource strings) and {theme}.tpl (templates).

2.2. Place in the CMF architecture

Registration and output of resources are performed by the Resources class, which is located in the file system/resources.php. The class stores the following static structures:

  • $registry — registry of <head> resources when consolidation is enabled;
  • $headerRc — registry of <head> resources without consolidation;
  • $footerRc — registry of footer resources;
  • $addedFiles — map of already added files (for deduplication);
  • $alias — map of predefined aliases (@jQuery, @bootstrap, @select2, and others);
  • flags $cacheOn, $consolidate, $minify, $isAdmin, $headerComplete, $htmlCleanupEnabled.

Initialisation of the class is performed by the Resources::__init() method, which is called at the end of the file resources.php. The method reads settings from the $cfg array:

  • cache — global caching flag;
  • headrc_consolidate — resource consolidation flag;
  • headrc_minify — minification flag;
  • html_cleanup — flag for cleaning HTML from unnecessary whitespace;
  • cache_dir — cache directory;
  • dir_perms — permissions for created directories.

The $isAdmin flag is set according to the value of the COT_ADMIN constant. For the front-end part of the site, $isAdmin === false, which permits consolidation and minification to operate provided they are enabled in the configuration.

2.3. How the engine includes the file

The .rc.php file is included by the engine in the Head Resources section of the file system/common.php:

if (!defined('COT_ADMIN')) {
    if (file_exists("{$cfg['themes_dir']}/{$usr['theme']}/{$usr['theme']}.rc.php")) {
        include "{$cfg['themes_dir']}/{$usr['theme']}/{$usr['theme']}.rc.php";
    }
}

Analysis of this fragment yields three key facts:

  1. The existence of the file at the path themes/{$usr['theme']}/{$usr['theme']}.rc.php is checked.
  2. If the file exists, it is included using the include operator.
  3. The theme name is taken from the $usr['theme'] variable, not from $cfg['defaulttheme'].

From this follows a fundamental conclusion: at the moment the .rc.php file is executed, the $usr['theme'] variable is guaranteed to be equal to the name of the current theme. If this were not the case, the file would not have been included.

2.4. Loading conditions

The .rc.php file is included when the following conditions are met:

  • the COT_ADMIN constant is not defined (front-end part of the site);
  • the file physically exists at the path themes/{$usr['theme']}/{$usr['theme']}.rc.php;
  • the Resources::__init() method has already been executed;
  • the cot_rc_add_standard() function has already included the standard resources (jQuery, js/base.js, js/ajax_on.js).

2.5. Position in the execution sequence

The .rc.php file is executed in the following sequence of common.php:

  1. Environment initialisation (configuration loading, database connection, Cot::init()).
  2. Configuration loading from the database.
  3. User determination and computation of $usr['theme'].
  4. Checking the existence of themes/{$usr['theme']}/header.tpl with fallback to $cfg['defaulttheme'].
  5. Calling cot_rc_add_standard().
  6. Execution of the rc hook.
  7. Inclusion of the theme's .rc.php.

3. The $usr['theme'] and $cfg['defaulttheme'] variables

3.1. The $cfg['defaulttheme'] variable

$cfg['defaulttheme'] is a global site setting that determines the default theme. The value is loaded from the configuration table of the database during engine initialisation and does not depend on which user accessed the site.

Characteristics of the variable:

  • Value type: a string containing the theme code (for example, index36).
  • Source: the cot_config table, the defaulttheme parameter.
  • Scope: global for the entire site.
  • Role in computation: input value.

3.2. The $usr['theme'] variable

$usr['theme'] is the theme applied to the current user. The value is computed in common.php based on several parameters.

For an authorised user:

$usr['theme'] = $cfg['forcedefaulttheme'] ? $cfg['defaulttheme'] : $row['user_theme'];

For a guest, the default value from the initialisation of the $usr array is used:

'theme' => $cfg['defaulttheme'],

After the computation, a check for the existence of the template is performed:

$mtheme = "{$cfg['themes_dir']}/{$usr['theme']}/header.tpl";
if (!file_exists($mtheme)) {
    $usr['theme'] = $cfg['defaulttheme'];
    $mtheme = "{$cfg['themes_dir']}/{$usr['theme']}/header.tpl";
    if (!file_exists($mtheme)) {
        cot_diefatal($L['com_defthemefail']);
    }
}

Characteristics of the variable:

  • Value type: a string containing the theme code.
  • Source: the result of computation based on $cfg['forcedefaulttheme'] and $row['user_theme'].
  • Scope: the current user (within the request).
  • Role in computation: result.

3.3. Possible values of $usr['theme']

The variable may take one of the following values:

  • $cfg['defaulttheme'] — if the forcedefaulttheme flag is enabled, or if the user has personally chosen the default theme;
  • $row['user_theme'] — if the forcedefaulttheme flag is disabled and the user has chosen their own theme;
  • $cfg['defaulttheme'] — as a fallback if the folder of the chosen theme is missing.

3.4. Relationship between the variables

The $usr['theme'] variable is computed based on $cfg['defaulttheme'], but no reverse dependency exists. This means:

  • $cfg['defaulttheme'] — input value;
  • $usr['theme'] — output (resulting) value.

For the .rc.php file, the correct value is the resulting one, since the file is physically included from the folder of that very theme.

4. The mechanism of .rc.php inclusion by the engine

4.1. Step-by-step breakdown

Let us examine the sequence of engine actions in more detail.

Step 1. Configuration initialisation.

The engine loads $cfg from the database and the file datas/config.php. At this stage the values defaulttheme, forcedefaulttheme, themes_dir, and others become available.

Step 2. User determination.

A query to the cot_users table is executed to obtain the current user's data. If the user is authorised, the values from $row are placed into the $usr array.

Step 3. Computation of $usr['theme'].

Based on $cfg['forcedefaulttheme'] and $row['user_theme'], the value of $usr['theme'] is computed.

Step 4. Checking the existence of the template.

The engine checks for the presence of the file themes/{$usr['theme']}/header.tpl. If the file is missing, the value of $usr['theme'] is forcibly changed to $cfg['defaulttheme'].

Step 5. Resource initialisation.

cot_rc_add_standard() is called, which registers the standard resources: jQuery (if the option is enabled), js/jqModal.min.js, js/base.min.js, js/ajax_on.js (if AJAX is enabled).

Step 6. Execution of the rc hook.

Plugins registered on the rc hook have the opportunity to add their own resources.

Step 7. Inclusion of the theme's .rc.php.

Provided the conditions are met (see section 2.4), the engine executes:

include "{$cfg['themes_dir']}/{$usr['theme']}/{$usr['theme']}.rc.php";

4.2. What is available inside .rc.php

At the moment the .rc.php file is executed, the following variables and objects are available:

  • Cot::$cfg — the full configuration array;
  • Cot::$usr — the current user's data, including theme;
  • Cot::$sys — system variables (abs_url, site_uri, scheme, now);
  • Cot::$db — the database object;
  • $L — language strings;
  • $R — resource strings;
  • $theme — not defined (it is assigned later in the Theme / color scheme block).

4.3. What is guaranteed

At the moment .rc.php is executed, the following is guaranteed:

  • $usr['theme'] contains the name of the current theme;
  • the file themes/{$usr['theme']}/header.tpl exists;
  • Resources::__init() has been executed, and the Resources class is ready for use;
  • standard resources have already been registered.

5. Relationship and priority of the variables

5.1. Absence of priority

The phrasing "priority of variables" is incorrect. $usr['theme'] and $cfg['defaulttheme'] are quantities of a different nature that solve different tasks.

VariableRoleType
$cfg['defaulttheme']Default site themeInput
$usr['theme']Theme applied to the userResult

5.2. Rule of choice

For the .rc.php file, the correct value is the result ($usr['theme']), since the file is physically included from the folder of that theme.

5.3. Rationale

The .rc.php file is included by the engine at the path themes/{$usr['theme']}/{$usr['theme']}.rc.php. This means that all resources registered inside the file pertain precisely to that folder. Using $cfg['defaulttheme'] for assembling paths inside the file is permissible only in the case where $cfg['defaulttheme'] coincides with $usr['theme'], which is not a general case.

5.4. Official Cotonti position

In official Cotonti theme development guides and in discussions on the developer forum, it is recommended to use $usr['theme'] for links to theme resources. This is confirmed by the engine's architecture: .rc.php is included from the folder of the user's theme, and all resources inside the file must pertain to that very theme.

6. Practical operational scenarios

6.1. Scenario A. Single theme, forced mode enabled

Parameters:

  • defaulttheme = index36
  • forcedefaulttheme = true

Behaviour: $usr['theme'] is always equal to index36. Both variants ($usr['theme'] and $cfg['defaulttheme']) produce an identical path. The application works correctly.

Conclusion: the scenario is not indicative for analysis.

6.2. Scenario B. Single theme, forced mode disabled

Parameters:

  • defaulttheme = index36
  • forcedefaulttheme = false
  • All users have user_theme = index36

Behaviour: $usr['theme'] is equal to index36. Both variants produce an identical path. The application works correctly.

Conclusion: this scenario is also not indicative.

6.3. Scenario C. Multiple themes, user preferences

Parameters:

  • defaulttheme = index36
  • forcedefaulttheme = false
  • The user has user_theme = mytheme

Behaviour: the engine includes themes/mytheme/mytheme.rc.php. Inside the file:

  • when using $usr['theme'], the path is formed as themes/mytheme/assets/... — correct;
  • when using $cfg['defaulttheme'], the path is formed as themes/index36/assets/... — incorrect.

Files at the second path do not exist. Resources::addFile() throws an Exception. The front-end part of the site crashes.

Conclusion: using $cfg['defaulttheme'] leads to a critical error.

6.4. Scenario D. Change of defaulttheme

Parameters:

  • defaulttheme = newtheme (changed by the administrator)
  • forcedefaulttheme = false
  • The user has user_theme = index36

Behaviour: the engine includes themes/index36/index36.rc.php. Inside the file:

  • when using $usr['theme'], the path is formed as themes/index36/assets/... — correct;
  • when using $cfg['defaulttheme'], the path is formed as themes/newtheme/assets/... — incorrect.

Files are missing. Exception. The front-end crashes.

Conclusion: changing defaulttheme without disabling user themes breaks themes that use $cfg['defaulttheme'] in .rc.php.

6.5. Scenario E. Fallback theme

Parameters:

  • defaulttheme = broken
  • The folder themes/broken/ is missing
  • forcedefaulttheme = true

Behaviour: the engine detects the absence of themes/broken/header.tpl and performs a fallback check. If the folder is missing and the fallback does not help, cot_diefatal($L['com_defthemefail']) is called. The .rc.php file is not included.

Conclusion: the scenario is an emergency one; .rc.php is not executed.

6.6. Summary table of scenarios

Scenariodefaultthemeforcedefaultthemeuser_themeResult
Aindex36true—Works
Bindex36falseindex36Works
Cindex36falsemythemeBreaks
Dnewthemefalseindex36Breaks
Ebrokentrue—Emergency

7. Rules for structuring the .rc.php file

7.1. General requirements

  1. The file begins with the mandatory construct:

    <?php
    defined('COT_CODE') or die('Wrong URL.');
  2. Any output to the standard output stream (echo, print, var_dump) is prohibited. The file is included at the moment when some of the headers have already been sent.
  3. Use exclusively the public static methods of the Resources class. Direct access to the protected and private fields of the class is not allowed.
  4. Local files are specified as a path from the site root without a leading slash. The Resources class performs a file_exists() check and throws an Exception if the file is missing.
  5. External resources are specified with a full URL (http://, https://, //). For them, the file_exists() check is not performed.
  6. CSS files are placed in <head> via Resources::addFile() or Resources::linkFile().
  7. JavaScript files are placed in the footer via Resources::linkFileFooter(), with the exception of scripts critical for rendering.
  8. The $order is set explicitly for all files except for the default value of 50.
  9. Manual invocation of Resources::render() and Resources::renderFooter() is prohibited. These methods are called by the engine.
  10. The use of deprecated wrappers cot_rc_add_file(), cot_rc_add_embed(), cot_rc_link_file() is prohibited. They are marked as deprecated.
  11. The file must be idempotent: repeated execution must not change the registry configuration.
  12. Database access is not allowed: .rc.php is executed on every request.
  13. Overriding $L and $R is prohibited — the file {theme}.php is intended for that.

7.2. Recommendations on structure

It is recommended to define a variable for the theme's root path:

$themeDir = Cot::$cfg['themes_dir'] . '/' . Cot::$usr['theme'];

This ensures uniformity and reduces the risk of typos.

7.3. Recommendations on resource order

The order of resource inclusion (the $order values):

  • 10–20 — base libraries (jQuery);
  • 20–40 — frameworks (Bootstrap);
  • 40–70 — plugins (Select2, Fancybox, Perfect Scrollbar);
  • 100–150 — theme scripts;
  • 800–900 — theme overrides.

7.4. Recommendations on placement

CSS resources:

  • base libraries — in <head>;
  • plugins — in <head>;
  • theme styles — in <head>;
  • overrides — in <head> with a high $order.

JavaScript resources:

  • jQuery — in <head>;
  • Bootstrap bundle — in <head> (with consolidation) or in the footer;
  • plugins — in the footer;
  • theme scripts — in the footer;
  • initialisation scripts — in the footer with the maximum $order.

7.5. File template

<?php
/**
 * Theme resource loader
 *
 * @package    {theme}
 * @version    {version}
 * @author     {author}
 * @copyright  {copyright}
 * @license    {license}
 */

defined('COT_CODE') or die('Wrong URL.');

$themeDir = Cot::$cfg['themes_dir'] . '/' . Cot::$usr['theme'];

// CSS — <head>
Resources::addFile('lib/bootstrap/css/bootstrap.min.css', 'css', 10);
Resources::addFile($themeDir . '/css/theme.css', 'css', 800);

// JS — <head> (critical)
Resources::addFile($themeDir . '/js/header.first.js', 'js', 40);

// JS — footer
Resources::linkFileFooter('lib/bootstrap/js/bootstrap.bundle.min.js', 'js', 30);
Resources::linkFileFooter($themeDir . '/js/theme.js', 'js', 100);

8. Reference of the Resources class

8.1. Public methods

Resources::addFile($path, $type = '', $order = 50, $scope = 'global')

Registers a file in the <head> registry. When consolidation is enabled, the file may be concatenated with others into a single asset.

Parameters:

  • $path — path to the file, full URL, or alias;
  • $type — 'js' or 'css'; if empty, it is determined by extension;
  • $order — output order (default 50);
  • $scope — visibility scope (global, guest, user, group_{id}).

Returns true on success, false on duplicate file. Throws an Exception if the local file is not found.

Resources::linkFile($path, $type = '', $order = 50)

Adds a file to <head> without consolidation. The HTML is generated immediately.

Resources::linkFileFooter($path, $type = '', $order = 50)

Adds a file to the footer. The HTML is generated immediately.

Resources::addEmbed($code, $type = 'js', $order = 50, $scope = 'global', $identifier = '')

Registers embedded code in <head>. When consolidation and minification are enabled, the code is saved to a file in the cache_dir/assets/ directory.

Resources::embed($code, $type = 'js', $order = 50, $attr = '')

Immediate insertion of code into <head>.

Resources::embedFooter($code, $type = 'js', $order = 50, $attr = '')

Immediate insertion of code into the footer.

Resources::setAlias($alias, $path, $canReWrite = false)

Registers or overrides an alias. By default, rewriting is prohibited.

Resources::getAlias($alias)

Returns the path for the alias, or null.

Resources::isFileAdded($fileName)

Checks whether the specified file or alias has been previously added.

Resources::minify($code, $type)

Performs minification of JavaScript (via lib/jsmin.php) or CSS (via lib/cssmin.php).

8.2. Predefined aliases

The Resources class contains the following predefined aliases:

  • @jQuery → js/jquery.min.js
  • @ckeditor → plugins/ckeditor/lib/ckeditor.js
  • @ckeditorPreset.js → plugins/ckeditor/presets/ckeditor.default.set.js
  • @bootstrap → lib/bootstrap/js/bootstrap.bundle.min.js
  • @bootstrap.css → lib/bootstrap/css/bootstrap.min.css
  • @select2 → lib/select2/js/select2.full.min.js
  • @select2.css → lib/select2/css/select2.min.css

Class constants:

  • Resources::JQUERY
  • Resources::BOOTSTRAP
  • Resources::CKEDITOR
  • Resources::SELECT2

8.3. The scope mechanism

The $scope parameter determines the resource's visibility scope:

  • global — the resource is always included;
  • guest — only for guests ($usr['id'] === 0);
  • user — only for authorised users ($usr['id'] > 0);
  • group_{id} — only for users whose maingrp equals {id}.

The visibility scope is applied during output in Resources::render().

8.4. The order mechanism

The $order parameter determines the output order. A smaller value corresponds to earlier output. The default is 50.

8.5. Consolidation and minification

Under the condition $cfg['cache'] && $cfg['headrc_consolidate'] && !$isAdmin, the Resources class performs consolidation of resources of the same type and visibility scope into a single file:

  • cache_dir/assets/{scope}.{theme}.{type} — the resulting file;
  • cache_dir/assets/{scope}.{theme}.{type}.idx — the file index;
  • cache_dir/assets/{scope}.{theme}.{type}.gz — the gzip version.

The consolidated file is served via the URL rc.php?rc={scope}.{theme}.{type}&nc={mtime}.

9. Common errors and how to fix them

9.1. Using $cfg['defaulttheme'] for theme resource paths

Symptom: when the default theme is changed or multiple themes are present, the front-end part crashes with an Exception error.

Cause: inside .rc.php, a path is formed via Cot::$cfg['themes_dir'] . '/' . Cot::$cfg['defaulttheme'], which does not correspond to the folder from which the file was included.

Solution: use Cot::$usr['theme'].

9.2. Using the $theme variable

Symptom: the warning Undefined variable $theme or an incorrect path.

Cause: the $theme variable is assigned in common.php later, in the Theme / color scheme block.

Solution: use Cot::$usr['theme'].

9.3. Duplicate resources

Symptom: the source HTML contains duplicate <script> and <link> tags for jQuery, Bootstrap, or other libraries.

Cause: re-registration of resources already included via cot_rc_add_standard().

Solution: do not add jQuery, jqModal, base.js, ajax_on.js again.

Symptom: the <link rel="stylesheet"> tag is located at the end of <body>.

Cause: using Resources::linkFileFooter() for CSS files.

Solution: place CSS files in <head> via Resources::addFile() or Resources::linkFile().

9.5. Placing all JS in the head

Symptom: slow page loading, blocking of HTML parsing.

Cause: all JS files are registered via Resources::addFile() in <head>.

Solution: place non-critical JS in the footer via Resources::linkFileFooter(). In <head>, leave only jQuery and scripts critical for the initial render.

9.6. Ignoring the addFile exception

Symptom: the front-end part crashes when a file is missing.

Cause: Resources::addFile() throws an Exception if the local file is not found.

Solution: check the file's existence via file_exists() before registration if the file may be missing.

9.7. Modifying $theme_reload

Symptom: overrides of $L and $R do not work or work incorrectly.

Cause: manual interference with the $theme_reload array.

Solution: do not modify $theme_reload manually. Overrides are performed via $L and $R in the file {theme}.php.

9.8. Using deprecated wrappers

Symptom: the deprecated warning appears in the logs.

Cause: using cot_rc_add_file(), cot_rc_add_embed(), cot_rc_link_file().

Solution: use the methods of the Resources class.

9.9. Incorrect order

Symptom: theme styles are overridden by plugin or library styles.

Cause: insufficiently high $order value for theme styles.

Solution: set the $order for theme styles in the range 800–900.

9.10. Database access

Symptom: slowdown of page loading.

Cause: execution of SQL queries inside .rc.php.

Solution: move the logic to the controller or module.

10. Diagnostics and debugging

10.1. Checking variable values

For diagnostics, you may temporarily add the following to the top of .rc.php:

error_log('usr theme: ' . Cot::$usr['theme']);
error_log('default theme: ' . Cot::$cfg['defaulttheme']);
error_log('themes dir: ' . Cot::$cfg['themes_dir']);

The records will go to the web server's error log.

10.2. Checking file inclusion

To verify that .rc.php is actually included:

error_log('rc.php loaded from: ' . __FILE__);

10.3. Checking the resource registry

To view the registered resources:

error_log('headerRc: ' . print_r(Resources::$headerRc ?? null, true));

Accessing the protected fields of the class requires caution and is used only for debugging purposes.

10.4. Checking consolidation

To verify the consolidation status:

error_log('consolidate: ' . (int) Cot::$cfg['headrc_consolidate']);
error_log('cache: ' . (int) Cot::$cfg['cache']);

10.5. Checking exceptions

Wrapping Resources::addFile() calls in try/catch:

try {
    Resources::addFile($themeDir . '/css/theme.css', 'css', 800);
} catch (Exception $e) {
    error_log('Resource error: ' . $e->getMessage());
}

This approach allows isolating the problem without crashing the page.

10.6. Enabling the debug mode

When Cot::$cfg['debug_mode'] === true, the engine outputs additional information. The check can be performed via:

error_log('debug_mode: ' . (int) Cot::$cfg['debug_mode']);

11. Conclusion

The choice between Cot::$usr['theme'] and Cot::$cfg['defaulttheme'] in the .rc.php file is determined by the architecture of the Cotonti engine.

The .rc.php file is included by the engine from the folder themes/{$usr['theme']}/. This means that the $usr['theme'] variable at the moment of file execution is guaranteed to contain the name of the current theme. All resources registered inside the file pertain precisely to that folder.

The $cfg['defaulttheme'] variable contains the default site setting. It coincides with $usr['theme'] only when a number of conditions are met:

  • the forcedefaulttheme flag is enabled;
  • all users' user_theme coincides with defaulttheme;
  • defaulttheme has not been changed.

In the general case there is no coincidence, and using $cfg['defaulttheme'] leads to the formation of incorrect paths. The Resources class throws an Exception, and the front-end part of the site crashes.

Rule: to build paths to theme resources inside .rc.php, use Cot::$usr['theme'].

Rationale: the file is included from the folder themes/{$usr['theme']}/, therefore the resources belong to that very theme. Using $cfg['defaulttheme'] violates this correspondence.

This rule applies to all theme resources: CSS, JavaScript, images, fonts, and any other files located inside the theme folder.


Reference table: when to use $cfg['defaulttheme'] and when to use Cot::$usr['theme']

Below is a table constructed exclusively on the basis of an analysis of the Cotonti source code (system/common.php, system/functions.php, system/resources.php, system/admin/admin.functions.php). Each row is a real usage case taken from the engine.


Table 1. Legitimate cases of using $cfg['defaulttheme']

No.File / place in codeTaskWhy specifically $cfg['defaulttheme']Example from the source
1system/common.php, initialisation of the $usr arraySet a default value before the user is determinedAt the moment the user data array is created, the user does not yet exist. Some starting value is needed. For a guest, this is the default site theme'theme' => $cfg['defaulttheme'],
2system/common.php, computation of $usr['theme'] for an authorised userForce the theme for all usersIf the administrator has enabled forcedefaulttheme, the engine is obliged to take the global theme rather than the user's personal preferences$usr['theme'] = $cfg['forcedefaulttheme'] ? $cfg['defaulttheme'] : $row['user_theme'];
3system/common.php, checking the existence of the headerSubstitute the missing theme with the default oneThe user's theme is physically missing. The only reasonable fallback is the default site theme$usr['theme'] = $cfg['defaulttheme']; (after if (!file_exists($mtheme)))
4system/common.php, final fallback errorAcknowledge a complete failure of themingEven the default theme is unavailable. Only an emergency termination remainsif (!file_exists($mtheme)) { cot_diefatal($L['com_defthemefail']); }
5system/functions.php, the cot_schemeFile() functionReturn the path to the CSS file of the colour schemeThe function may be called before $usr is initialised. If $usr['theme'] has not yet been set, the default value is taken$theme = isset($usr['theme']) ? $usr['theme'] : $cfg['defaulttheme'];

Conclusion on Table 1: $cfg['defaulttheme'] is used only in three roles:

  • starting value (initialisation);
  • forced value (forcedefaulttheme = true);
  • emergency fallback (theme unavailable).

In all other cases, it is not the right source.


Table 2. Places where $cfg['defaulttheme'] must not be used, and where Cot::$usr['theme'] is required

No.File / place in codeTaskWhy Cot::$usr['theme']Example from the source
1system/common.php, inclusion of the theme's .rc.phpLocate the resource file of the current themeThe file is physically included from the folder {$usr['theme']}. Hence, inside the file as well, $usr['theme'] = the name of this themeinclude "{$cfg['themes_dir']}/{$usr['theme']}/{$usr['theme']}.rc.php";
2system/common.php, inclusion of {theme}.phpThe file that overrides $L/$RIt is tied to the folder of the current theme, not to the global setting$sys['theme_resources'] = "{$cfg['themes_dir']}/{$usr['theme']}/{$usr['theme']}.php";
3system/common.php, the theme's language fileLoad translations of the current themeThe user's theme may differ from defaulttheme$usr['theme_lang'] = "{$cfg['themes_dir']}/{$usr['theme']}/{$usr['theme']}.{$usr['lang']}.lang.php";
4system/common.php, the header templateLocate header.tplIt is tied to the folder of the current theme$mtheme = "{$cfg['themes_dir']}/{$usr['theme']}/header.tpl";
5system/functions.php, cot_tplfile()Locate any .tpl of the current themeAll front-end templates are located in the folder $usr['theme']$theme = !empty($usr['theme']) ? $usr['theme'] : '';
6system/common.php, the theme's .rc.php (internal logic)Paths to the theme's assetsThe file is included from the folder of that very theme$themeDir = Cot::$cfg['themes_dir'] . '/' . Cot::$usr['theme'];
7system/resources.php, additionalFiles() for @select2Searching for the Select2 i18n file for the user's languageIt is tied to the language, and the theme is irrelevant here — but the example shows that theme resources are tied to the user's context$select2i18n = 'lib/select2/js/i18n/' . Cot::$usr['lang'] . '.js';

Conclusion on Table 2: everything related to files inside the theme folder (CSS, JS, templates, languages, .rc.php, .php) must use Cot::$usr['theme'].


Table 3. Admin context: where $cfg['defaulttheme'] and $usr['theme'] do not work, and a third source is needed

No.File / place in codeTaskWhich variable to useExample from the source
1system/common.php, the admin theme's language fileLoad translations of the admin theme$cfg['admintheme']$usr['def_theme_lang'] = "{$cfg['themes_dir']}/admin/{$cfg['admintheme']}/{$cfg['admintheme']}.en.lang.php";
2system/common.php, the admin theme's resource fileInclude {admintheme}.php$cfg['admintheme']$sys['theme_resources'] = "{$cfg['themes_dir']}/admin/{$cfg['admintheme']}/{$cfg['admintheme']}.php";
3system/common.php, the path to the admin templatesLocate the admin theme's .tpl$cfg['admintheme']Used in cot_tplfile() via the variable $adminTheme
4system/admin/admin.functions.phpResource inclusionCot::$cfg['admintheme']Resources::addFile(Cot::$cfg['themes_dir'] . '/admin/' . Cot::$cfg['admintheme'] . '/assets/...');
5system/common.php, the icon packIcons for the interface$cfg['defaulticons'] (fallback), $usr['icons'] (primary)if (empty($usr['icons'])) { $usr['icons'] = $cfg['defaulticons']; }

Conclusion on Table 3: in the admin context, a third variable is used — $cfg['admintheme']. Neither defaulttheme nor usr['theme'] is suitable for admin templates.


Table 4. Summary matrix: which variable to use in which context

ContextCorrect variableRationale
Paths to the front-end theme's CSS/JSCot::$usr['theme']The files are physically located in themes/{usr['theme']}/
Paths to the front-end theme's .tplCot::$usr['theme']All front-end templates are tied to the user's theme folder
Paths to the front-end theme's .php (.rc.php, {theme}.php, {theme}.lang.php)Cot::$usr['theme']These files are included precisely from the usr['theme'] folder
Emergency fallback when the theme is missing$cfg['defaulttheme']The only reasonable source in case of failure
Initialisation of the $usr array before the user is determined$cfg['defaulttheme']Starting value
Forced theme (forcedefaulttheme = true)$cfg['defaulttheme']Direct purpose of the flag
Paths to the admin theme's CSS/JS$cfg['admintheme']The admin panel uses a separate theme
Paths to the admin theme's .tpl$cfg['admintheme']Similarly
Language files of the admin theme$cfg['admintheme']Similarly
Emergency termination when the default theme is missing$cfg['defaulttheme']Only for the cot_diefatal() check

Table 5. Practical substitutions: what to write in a specific file

FileWhat to writeWhy
themes/{theme}/{theme}.rc.phpCot::$cfg['themes_dir'] . '/' . Cot::$usr['theme'] . '/...'The file is included by the engine from the current theme's folder
themes/{theme}/{theme}.php$L[...], $R[...] (without paths)String overrides; they are not tied to a folder
themes/admin/{admintheme}/{admintheme}.rc.phpCot::$cfg['themes_dir'] . '/admin/' . Cot::$cfg['admintheme'] . '/...'The admin theme is set separately
themes/admin/{admintheme}/{admintheme}.php$L[...], $R[...] (without paths)Admin string overrides
system/functions.php, helpers$usr['theme'] ?? $cfg['defaulttheme']Fallback in case $usr['theme'] is missing
system/common.php, initial initialisation$cfg['defaulttheme']The user is not yet determined
system/common.php, computation of $usr['theme']$cfg['forcedefaulttheme'] ? $cfg['defaulttheme'] : $row['user_theme']Forcing or personal choice
system/common.php, fallback$cfg['defaulttheme']The only reasonable source in case of failure

Table 6. Antipatterns: where $cfg['defaulttheme'] must not be used and why

No.What is written incorrectlyWhy this is an errorWhat it should be
1Inside {theme}.rc.php: Cot::$cfg['themes_dir'] . '/' . Cot::$cfg['defaulttheme'] . '/assets/...'The file is included from the usr['theme'] folder. The path leads to another folder when they divergeCot::$cfg['themes_dir'] . '/' . Cot::$usr['theme'] . '/assets/...'
2Inside {theme}.rc.php: Cot::$cfg['themes_dir'] . '/' . Cot::$cfg['defaulttheme'] . '/js/...'SimilarlyCot::$cfg['themes_dir'] . '/' . Cot::$usr['theme'] . '/js/...'
3Inside {theme}.php: links to theme files via defaultthemeThe file pertains to the current theme, not to the global setting$usr['theme']
4In theme templates: {PHP.cfg.defaulttheme} for asset pathsIn a template, one can use {PHP.usr.theme} — then the path is always correct{PHP.usr.theme}
5In the admin theme: Cot::$cfg['defaulttheme'] for admin asset pathsThe admin panel uses a separate theme set in $cfg['admintheme']Cot::$cfg['admintheme']
6In the admin theme: Cot::$usr['theme'] for admin asset pathsThe front-end user theme has no relation to the admin interfaceCot::$cfg['admintheme']

Table 7. Quick cheat sheet "what to take in a given situation"

SituationSource
The front-end theme's .rc.php file is included by the engineCot::$usr['theme']
The front-end theme's .php file (overrides of $L/$R)No paths — only $L/$R
The admin theme's .rc.php file is included by the engineCot::$cfg['admintheme']
The admin theme's .php file (overrides of $L/$R)No paths — only $L/$R
A global function that may be called before $usr$usr['theme'] ?? $cfg['defaulttheme']
Initialisation of $usr for a guest$cfg['defaulttheme']
Forcing the theme for all users$cfg['defaulttheme']
Emergency fallback when the theme is missing$cfg['defaulttheme']
Paths to front-end templates (cot_tplfile())Cot::$usr['theme']
Paths to admin templates (cot_tplfile())Cot::$cfg['admintheme']

Key rules based on the results of the tables

  1. $cfg['defaulttheme'] — only three roles: initialisation, forcing, emergency fallback.
  2. Cot::$usr['theme'] — all paths to files inside the current front-end theme folder.
  3. $cfg['admintheme'] — all paths to files inside the admin theme folder.
  4. $usr['theme'] ?? $cfg['defaulttheme'] — a compromise for global functions with an undefined context.
  5. Neither in .rc.php, nor in {theme}.php, nor in front-end templates may one substitute $cfg['defaulttheme'] for paths to the current theme's assets.
No comments yet
Only registered users can post new comments