CoolCMS API

DefaultThemeResolver
in package
implements ThemeResolverInterface

FinalYes

Table of Contents

Interfaces

ThemeResolverInterface

Constants

SKIN_COOKIE  : mixed = 'cms_skin_override'
Cookie remembering the color variant choice for later clicks.
SKIN_QUERY_PARAM  : mixed = '_skin'
Query parameter that switches the color variant: `?_skin=modra` (`?_skin=off` switches back).
SWITCH_COOKIE  : mixed = 'cms_theme_override'
Cookie remembering the switch for later clicks (session cookie, no expiry).
SWITCH_QUERY_PARAM  : mixed = '_theme'
Query parameter that switches the front theme: `?_theme=template3` (`?_theme=off` switches back).
SWITCH_RESET_VALUES  : mixed = ['off', 'reset', 'default', 'none']
`?_theme=...` values that cancel the switch and return to the theme from the settings.

Properties

$availableThemesCache  : array<string, array<int, string>>
Per-request memo of {@see availableThemes()}.
$deviceDetector  : DeviceDetector
$httpRequest  : Request
$httpResponse  : Response
$settingsSkinName  : string|null
Skin from the website settings, i.e. before the switch ({@see settingsSkinName()}).
$settingsThemeName  : string|null
Theme name from the website settings, i.e. before the switch ({@see settingsThemeName()}).
$theme  : Theme|null

Methods

__construct()  : mixed
activeSkinName()  : string|null
Returns the skin that is really rendered for this request; NULL is the base appearance.
availableThemes()  : array<int, string>
Returns the theme directories one can switch to: only those with a `desktop/` variant (without it `formatLayoutTemplateFiles()` would not find a layout and the page would fail).
formatTemplateFiles()  : array<int, string>
Returns the candidate action templates, in order of preference.
frontendThemesDir()  : string|null
Returns the root of the front themes (`.../www/themes/frontend/`), or NULL outside the front branch (the resolver also passes the admin theme through it, see {@see applyLocalOverride()}).
getTheme()  : Theme|null
isSkinSwitchingAllowed()  : bool
Returns whether URL/cookie may switch the skin.
isSwitchingAllowed()  : bool
Returns whether URL/cookie may switch the theme.
resolve()  : T
setTheme()  : void
settingsSkinName()  : string|null
Returns the skin set in the admin, i.e. what a visitor without their own choice sees.
settingsThemeName()  : string|null
Returns the theme set in the admin, i.e. what a visitor without their own choice sees.
applyLocalOverride()  : void
Switches the theme: the URL parameter `?_theme=<directory>` (remembered in a session cookie so the site can be browsed), or the environment variable `CMS_THEME_OVERRIDE` as the default theme of a server run.
applySkinOverride()  : void
Picks the skin for this request: the website setting, or `?_skin=...`/cookie/env.
formatTemplateFiles_inMainThemeFolder()  : array<int, string>
getNamePartsForThemePath()  : array<int, string>
isValidThemeName()  : bool
A directory name only: no `../`, no absolute path.
rememberChoice()  : void
Remembers (or forgets) the choice in a session cookie, for both theme and skin.
resolveOverride()  : string|null
Shared core of both switches; theme and skin are decided identically and differ only in the input names.
resolveOverrideName()  : string|null
Returns the theme directory name that overrides the DB setting, or NULL (leave unchanged).
resolveSkinOverrideName()  : string|null
Returns the skin name that overrides the setting, or NULL (keep the configured one).
themeTemplateCandidate()  : string|null
Returns the path the template should have in the theme, whether or not it exists. Used only to name the missing file in the 404 message ({@see self::formatTemplateFiles()}).

Constants

Cookie remembering the color variant choice for later clicks.

private mixed SKIN_COOKIE = 'cms_skin_override'

SKIN_QUERY_PARAM

Query parameter that switches the color variant: `?_skin=modra` (`?_skin=off` switches back).

private mixed SKIN_QUERY_PARAM = '_skin'

Cookie remembering the switch for later clicks (session cookie, no expiry).

private mixed SWITCH_COOKIE = 'cms_theme_override'

SWITCH_QUERY_PARAM

Query parameter that switches the front theme: `?_theme=template3` (`?_theme=off` switches back).

private mixed SWITCH_QUERY_PARAM = '_theme'

SWITCH_RESET_VALUES

`?_theme=...` values that cancel the switch and return to the theme from the settings.

private mixed SWITCH_RESET_VALUES = ['off', 'reset', 'default', 'none']

Properties

$availableThemesCache

Per-request memo of {@see availableThemes()}.

private array<string, array<int, string>> $availableThemesCache = []

The method runs scandir() and is_dir() per entry and the appearance switcher calls it on every rendered page (ThemeSwitcher). Theme directories do not change during a request, so a second disk read gains nothing.

IMPORTANT: the key is the root of the front branch, not just NULL/array: frontendThemesDir() derives from the active theme, which changes during resolve() (override). Without the key the memo could return the list of another root.

$settingsSkinName

Skin from the website settings, i.e. before the switch ({@see settingsSkinName()}).

private string|null $settingsSkinName = NULL

$settingsThemeName

Theme name from the website settings, i.e. before the switch ({@see settingsThemeName()}).

private string|null $settingsThemeName = NULL

Methods

activeSkinName()

Returns the skin that is really rendered for this request; NULL is the base appearance.

public activeSkinName() : string|null
Return values
string|null

availableThemes()

Returns the theme directories one can switch to: only those with a `desktop/` variant (without it `formatLayoutTemplateFiles()` would not find a layout and the page would fail).

public availableThemes() : array<int, string>

Plain directory names sorted alphabetically; the active theme is among them. An empty array means nothing to switch to, and the caller then does not render the switcher.

IMPORTANT: it reads from the front branch by the active theme, not from %wwwDir%, which is computed from the outermost stack frame and points elsewhere in CLI and harnesses.

Return values
array<int, string>

formatTemplateFiles()

Returns the candidate action templates, in order of preference.

public formatTemplateFiles(Presenter $presenter) : array<int, string>

IMPORTANT: it must never return an empty array. After a failed search Nette's Presenter::findTemplateFile() reaches for $files[0] to name the missing template in the message and send a nice 404. Over an empty array that is a TypeError in strtr(), i.e. HTTP 500 instead of 404 for every missing front template.

So the result is only preferred by existence, not filtered: when nothing exists, the candidates are returned anyway. On the happy path nothing changes: an existing file is still first and findTemplateFile() takes it before it gets to the candidates.

Parameters
$presenter : Presenter
Return values
array<int, string>

frontendThemesDir()

Returns the root of the front themes (`.../www/themes/frontend/`), or NULL outside the front branch (the resolver also passes the admin theme through it, see {@see applyLocalOverride()}).

public frontendThemesDir() : string|null
Return values
string|null

isSkinSwitchingAllowed()

Returns whether URL/cookie may switch the skin.

public isSkinSwitchingAllowed() : bool

It has its own switch CMS_SKIN_SWITCH, separate from the theme switch CMS_THEME_SWITCH. Both are on until someone turns them off explicitly.

NOTE: turning the theme switch off does not turn skins off, on purpose: CMS_THEME_SWITCH=0 means "this installation has one theme", which says nothing about its color variants. To lock the appearance completely, set both variables to 0.

Return values
bool

isSwitchingAllowed()

Returns whether URL/cookie may switch the theme.

public isSwitchingAllowed() : bool

Always on, for every visitor: the switcher is part of the CMS showcase (ThemeSwitcher), not only a developer aid. It is turned off only by env CMS_THEME_SWITCH=0, for an installation that should not have the switcher. A visitor can switch the appearance, but only through their own session cookie; everyone else sees the site as set in the admin.

NOTE: only directories that really exist in www/themes/frontend/ are offered (availableThemes()), so with a single theme there is nothing to switch.

Return values
bool

settingsSkinName()

Returns the skin set in the admin, i.e. what a visitor without their own choice sees.

public settingsSkinName() : string|null

The switcher uses it to know that "back to default" must delete the cookie instead of setting it to the same value (same reasoning as settingsThemeName()).

NOTE: after switching the theme it is meaningless, since the configured skin belongs to the theme from the settings, not the switched one. It then returns NULL so that the switcher offers "base appearance" as the default choice.

Return values
string|null

settingsThemeName()

Returns the theme set in the admin, i.e. what a visitor without their own choice sees.

public settingsThemeName() : string|null

The switcher uses it to know that "back to default" must delete the cookie (?_theme=off) instead of setting it to the same value; otherwise clicking the default appearance would pin a state that survives a later theme change in the admin.

NOTE: precisely it is what a visitor without their own choice sees, so on a server started with CMS_THEME_OVERRIDE it is that variable, not the DB row. Without this exception the switcher would offer to cancel the choice for a theme that cannot be reached there anyway.

Return values
string|null

applyLocalOverride()

Switches the theme: the URL parameter `?_theme=<directory>` (remembered in a session cookie so the site can be browsed), or the environment variable `CMS_THEME_OVERRIDE` as the default theme of a server run.

private applyLocalOverride(Theme|null $theme) : void

The switch is not a setting because theme.frontend.path is one row in cms_system_settings and the table has no environment column. The database is shared by dev and production, so overwriting it would change the theme on the live site too, and since production lacks the files of a new theme, all its front pages would fail on missing layouts. This switch leaves the database alone and acts only where the variable is set:

CMS_THEME_OVERRIDE=template2 php -S 127.0.0.1:8099 -t www

Without the variable the method is a no-op; production never sets it. A nonexistent directory is ignored so that a typo cannot take the site down.

IMPORTANT: it acts only on the front theme. The resolver is one shared service and resolve() also passes the admin theme through it (ThemeMapper). Without the branch check the admin theme would be overridden too and the admin would look for layouts in /www/themes/frontend/<override>/desktop/layouts/, where @layout.latte and @login.latte do not exist. Presenter::findLayoutTemplateFile() then silently returns null, so the whole admin renders as a bare {block content} without <html>, CSS and JS, with nothing in the log.

Parameters
$theme : Theme|null

applySkinOverride()

Picks the skin for this request: the website setting, or `?_skin=...`/cookie/env.

private applySkinOverride(Theme|null $theme) : void

IMPORTANT: the skin is checked against the resulting theme, i.e. after applyLocalOverride(). Skins belong to a concrete theme; after switching to another one the configured name would point into a directory that does not exist there. A nonexistent skin therefore falls back to NULL (base appearance) instead of rendering a link to a 404.

IMPORTANT: the admin branch respects the skin from the settings (theme.admin.skin) but has no ?_skin=/cookie/env switching, on purpose. The visitor switcher is an offer for anonymous front visitors; the admin looks the same for everyone per one setting, so a URL parameter would let anybody override the appearance the administrator chose.

Parameters
$theme : Theme|null

formatTemplateFiles_inMainThemeFolder()

private formatTemplateFiles_inMainThemeFolder(Presenter $presenter) : array<int, string>
Parameters
$presenter : Presenter
Return values
array<int, string>

getNamePartsForThemePath()

private getNamePartsForThemePath(Presenter $presenter) : array<int, string>
Parameters
$presenter : Presenter
Return values
array<int, string>

isValidThemeName()

A directory name only: no `../`, no absolute path.

private isValidThemeName(string $name) : bool
Parameters
$name : string
Return values
bool

rememberChoice()

Remembers (or forgets) the choice in a session cookie, for both theme and skin.

private rememberChoice(string $cookieName, string|null $name) : void

expire NULL makes a session cookie: the choice disappears when the browser closes, so the appearance is not fixed for a visitor forever.

Parameters
$cookieName : string
$name : string|null

resolveOverride()

Shared core of both switches; theme and skin are decided identically and differ only in the input names.

private resolveOverride(string $envName, string $queryParam, string $cookieName, bool $switchingAllowed) : string|null

Priority: ?<param>=..., then cookie, then env. A reset (off/reset/default/none or an empty value) forgets the choice and returns env, not the DB value; see resolveOverrideName().

Parameters
$envName : string
$queryParam : string
$cookieName : string
$switchingAllowed : bool

whether URL/cookie may switch; passed in because theme and skin have separate switches, see isSkinSwitchingAllowed()

Return values
string|null

resolveOverrideName()

Returns the theme directory name that overrides the DB setting, or NULL (leave unchanged).

private resolveOverrideName() : string|null

Priority, strongest first:

  1. ?_theme=<directory> in the URL: the freshest and most explicit intent, stored in the cookie. ?_theme=off (and reset/default/none) deletes the cookie.
  2. The cookie from an earlier ?_theme=...: keeps the switch across clicks.
  3. Env CMS_THEME_OVERRIDE: the default theme of that server run.

The URL ranks above env on purpose: CMS_THEME_OVERRIDE=template2 php -S ... configures the whole server run, not one window. If env won, ?_theme=template3 would silently do nothing on such a server. So ?_theme=off means "back to the default theme of the run", i.e. env when set, not the DB theme.

Points 1 and 2 work only where isSwitchingAllowed() permits.

Return values
string|null

resolveSkinOverrideName()

Returns the skin name that overrides the setting, or NULL (keep the configured one).

private resolveSkinOverrideName() : string|null

Same priority as for the theme: ?_skin=..., then cookie, then env CMS_SKIN_OVERRIDE. ?_skin=off (and reset/default/none) cancels the choice and returns to the website setting.

IMPORTANT: it is gated by isSkinSwitchingAllowed(), not isSwitchingAllowed(). Otherwise CMS_THEME_SWITCH=0 would silence skins too, and on an installation with a single theme and several color variants the only switchable thing would be turned off.

Return values
string|null

themeTemplateCandidate()

Returns the path the template should have in the theme, whether or not it exists. Used only to name the missing file in the 404 message ({@see self::formatTemplateFiles()}).

private themeTemplateCandidate(Presenter $presenter) : string|null
Parameters
$presenter : Presenter
Return values
string|null
On this page

Search results