Paths value object
- Created
- Decided
- Versions
- History
Abstract
A single Paths value object holds every filesystem location the engine needs: configuration, data, modules, cache
and logs. Bootstrap constructs it once, from the arguments the panel is booted with, and it replaces the
configuration component's ConfigPaths.
Motivation
The configuration loader receives its locations through ConfigPaths, which holds configuration locations and
nothing else. More components need locations of their own: modules, the cache and logs. A single object holding
every location, constructed once during early bootstrap, is cleaner than a paths object for each component.
Proposal
Concepts
| Term | Meaning |
|---|---|
| Root | An absolute directory under which the engine keeps one type of file. |
| Relative path | A path beneath a root, joined onto it by Paths. |
Components
| Component | Responsibility |
|---|---|
Paths |
Final readonly value object holding every root, and joining relative paths onto them. |
Roots
| Property | Holds |
|---|---|
config |
The configuration directory, holding config.toml, config.d/ and modules-enabled/. |
data |
The application data directory. |
modules |
The Composer project that external modules are installed into, per ADR-0012. |
cache |
The cache directory. |
logs |
The log directory. |
Each root is an absolute path. Paths holds the roots and does nothing else with them: it does not work out where
they are, check that they exist, or create them.
$paths = new Paths(
config: '/etc/tgp',
data: '/var/lib/tgp',
modules: '/var/lib/tgp/modules',
cache: '/var/lib/tgp/cache',
logs: '/var/log/tgp',
);
Joining paths
Each root has a method of the same name that joins a relative path onto it:
| Method | Returns |
|---|---|
config(string $path): string |
The path beneath the configuration directory. |
data(string $path): string |
The path beneath the data directory. |
modules(string $path): string |
The path beneath the modules directory. |
cache(string $path): string |
The path beneath the cache directory. |
logs(string $path): string |
The path beneath the log directory. |
The root's trailing separator and the path's leading separator are removed, and the two are joined with a single
separator. A path passed to a method is always treated as relative to the root, so $paths->config('config.d') and
$paths->config('/config.d') both return /etc/tgp/config.d.
Construction
Bootstrap constructs Paths once, during early bootstrap, before configuration is loaded or modules are discovered.
Its roots come from arguments given when the panel is booted, which are passed in during bootstrapping.
Configuration loading
TomlLoader::load() takes Paths in place of ConfigPaths, and reads from the configuration directory:
config.toml, config.d/ and modules-enabled/ beneath $paths->config. ConfigPaths is removed.
$tree = new TomlLoader()->load($paths);
Out of scope
- Populating the roots. How bootstrap takes the roots from the arguments the panel is booted with, and resolves them, belongs to bootstrapping.
Alternatives considered
A paths object for each component, of which ConfigPaths is the existing one. Once modules, the cache and logs
need locations as well as configuration, a single object holding every root, constructed once during early
bootstrap, is cleaner.
No other alternatives were weighed.
Backwards compatibility
ConfigPathsis removed, andTomlLoader::load()takesPathsinstead.- The main configuration file is always
config.tomlin the configuration directory, and the drop-in and module configuration directories are alwaysconfig.d/andmodules-enabled/beside it.ConfigPathsheld each of the three as a path of its own.
Open questions
Changelog
Sources
- Issue #34, Engine - Paths Value Object, : the motivation, the single object and the per-component
objects it replaces, the five roots, construction during early bootstrap before configuration is loaded or modules
are discovered, and configuration loading reading from
$paths->config. This iscreated. Its tasks, ticked on , include resolving the roots in layers from compiled defaults, environment variables and command-line flags, and testing that resolution. Nothing at a50a9ab resolves the roots, and that resolution is left to bootstrapping. - PR #40, refactor(engine:config): Refactor ConfigPaths VO to Paths, merged and squashed as a50a9ab:
the implementation, whose merge is
decided.Paths, its methods andTomlLoader's use of it are described fromsrc/Config/Paths.phpat a50a9ab,src/Config/TomlLoader.phpat a50a9ab andtests/Unit/Config/ConfigPathsTest.phpat a50a9ab. - The roots coming from arguments given when the panel is booted, and populating and resolving them belonging to bootstrapping: first written down on .
Source rfc/0005-paths-value-object.md · commit 072385a · exported