CoolCMS API

SkinCatalog
in package

FinalYes

Catalog of color variants (skins) of a front theme.

A skin is a directory <theme>/<variant>/assets/skins/<name>/ with skin.css, which contains only CSS variable overrides. It renders after style.css, so it changes colors, radii and shadows but leaves structure and layouts to the theme.

IMPORTANT: the service has no dependency on DefaultThemeResolver on purpose. The admin needs the skin list too, but there the resolver holds the admin branch theme and its availableSkins() would return nothing. The catalog works on the path the caller passes, whether that is the currently rendered theme or the front one from the website settings.

It is the single place that reads skin.json and decides what still counts as a skin; shared by ThemeSwitcher (visitor offer) and SiteIdentityPresenter (admin selection).

Table of Contents

Constants

DEFAULT_ORDER  : mixed = 1000
Skins without `order` go last, still sorted by name.
MANIFEST_FILE  : mixed = 'skin.json'
Optional descriptive file of a skin, with keys `label`, `description`, `color` and `order` (for example `label` "Brick", `color` "#ec3013", `order` 20).
SKIN_FILE  : mixed = 'skin.css'
File without which a directory is not a skin; the `<link>` points to it.
SKINS_DIR  : mixed = 'assets/skins/'
Directory with skins inside a theme variant.

Methods

exists()  : bool
Returns whether a skin of that name exists in the given theme.
listForThemePath()  : array<int, array{name: string, label: string, description: ?string, color: ?string, order: int}>
Returns the skins of the given theme, sorted by `order` and by label on a tie.
listForThemeSetting()  : array<int, array{name: string, label: string, description: ?string, order: int}>
Same, over the relative path from the website settings (`theme.frontend.path`, i.e.
selectItemsForThemePath()  : array<string, string>
Returns the options for `addSelect()`: directory name to label.
selectItemsForThemeSetting()  : array<string, string>
Returns the options for `addSelect()` over the relative path from the settings: directory name to label.
projectRoot()  : string
Project root (`cms/www`); `app/Core/Theme/` is three levels below it.
readManifest()  : array{label?: string, description?: string, color?: string, order?: int, hidden?: bool}
Reads `skin.json`. A broken or missing file is skipped silently: a typo in someone else's manifest must not break the offer; the skin is just offered under its directory name.
readPrimaryColor()  : string|null
Returns `--color-primary` from the skin file, or NULL when not found.
skinsDir()  : string

Constants

DEFAULT_ORDER

Skins without `order` go last, still sorted by name.

private mixed DEFAULT_ORDER = 1000

MANIFEST_FILE

Optional descriptive file of a skin, with keys `label`, `description`, `color` and `order` (for example `label` "Brick", `color` "#ec3013", `order` 20).

private mixed MANIFEST_FILE = 'skin.json'

color is the color the skin shows in the appearance switcher (the dot). When missing, --color-primary is read from skin.css itself, which is cheap because the file is a few kB. It cannot be read from style.css this way: it is over half a megabyte and --color-primary lies about 230 kB deep.

Without a manifest the skin is offered under its directory name. These are deliberately not translation keys: a missing translation takes down the whole page, while a missing manifest only loses a nice name. They are also texts of a concrete theme, not of the CMS, so they belong in its directory, not in app/Locale/. Same reasoning as for theme.json.

"hidden": true omits the skin from listForThemePath() and the offers but keeps it working: exists() and a direct ?_skin= link know nothing about it. For a skin that should stay on disk but not clutter the selection.

SKIN_FILE

File without which a directory is not a skin; the `<link>` points to it.

private mixed SKIN_FILE = 'skin.css'

SKINS_DIR

Directory with skins inside a theme variant.

private mixed SKINS_DIR = 'assets/skins/'

Methods

exists()

Returns whether a skin of that name exists in the given theme.

public exists(string $absThemePath, string $skin[, string $variant = 'desktop' ]) : bool
Parameters
$absThemePath : string
$skin : string
$variant : string = 'desktop'
Return values
bool

listForThemePath()

Returns the skins of the given theme, sorted by `order` and by label on a tie.

public listForThemePath(string $absThemePath[, string $variant = 'desktop' ]) : array<int, array{name: string, label: string, description: ?string, color: ?string, order: int}>

Only a directory with skin.css counts as a skin, so an empty folder or a stray .DS_Store is not offered. An empty array means the theme has no skins; the caller then renders neither the switcher nor the admin selection.

IMPORTANT: the default variant is desktop. Skins are not duplicated for tablet and mobile; ThemeHelper::getAssetPath() falls back to the desktop file, so mobile gets the same skin.

Parameters
$absThemePath : string

absolute path to the theme directory (.../themes/frontend/template1/)

$variant : string = 'desktop'
Return values
array<int, array{name: string, label: string, description: ?string, color: ?string, order: int}>

listForThemeSetting()

Same, over the relative path from the website settings (`theme.frontend.path`, i.e.

public listForThemeSetting(string $relThemePath[, string $variant = 'desktop' ]) : array<int, array{name: string, label: string, description: ?string, order: int}>

/www/themes/frontend/template1/).

The project root is derived from the location of this class, the same way as ThemeMapper::initalizeEntity(). It is deliberately not %wwwDir%, which is computed from the outermost stack frame and points elsewhere in CLI and harnesses.

Used by the admin, which has no absolute path to the front theme at hand (its resolver holds the admin branch theme).

Parameters
$relThemePath : string
$variant : string = 'desktop'
Return values
array<int, array{name: string, label: string, description: ?string, order: int}>

selectItemsForThemePath()

Returns the options for `addSelect()`: directory name to label.

public selectItemsForThemePath(string $absThemePath[, string $variant = 'desktop' ]) : array<string, string>
Parameters
$absThemePath : string
$variant : string = 'desktop'
Return values
array<string, string>

selectItemsForThemeSetting()

Returns the options for `addSelect()` over the relative path from the settings: directory name to label.

public selectItemsForThemeSetting(string $relThemePath[, string $variant = 'desktop' ]) : array<string, string>
Parameters
$relThemePath : string
$variant : string = 'desktop'
Return values
array<string, string>

projectRoot()

Project root (`cms/www`); `app/Core/Theme/` is three levels below it.

private projectRoot() : string
Return values
string

readManifest()

Reads `skin.json`. A broken or missing file is skipped silently: a typo in someone else's manifest must not break the offer; the skin is just offered under its directory name.

private readManifest(string $path) : array{label?: string, description?: string, color?: string, order?: int, hidden?: bool}
Parameters
$path : string
Return values
array{label?: string, description?: string, color?: string, order?: int, hidden?: bool}

readPrimaryColor()

Returns `--color-primary` from the skin file, or NULL when not found.

private readPrimaryColor(string $cssPath) : string|null

A safety net for a skin without color in its manifest, so the switcher need not draw an empty dot. The last occurrence is used: the CSS may declare it several times and the later one wins.

Parameters
$cssPath : string
Return values
string|null

skinsDir()

private skinsDir(string $absThemePath, string $variant) : string
Parameters
$absThemePath : string
$variant : string
Return values
string
On this page

Search results