Convert
in package
Turns what `Cooper` loaded into application configuration -- the counterpart of the Elixir `CooperConfig.Convert` and the Praxis `cooper.config/as-app-config`.
Typed literals arrive untagged
Application configuration is read by code that has never heard of Cooper -- a database client, an HTTP client, a framework option -- so Cooper's measurements lose their wrapper on the way in:
| CASC | Cooper | application configuration |
|---|---|---|
1GiB |
CooperBytes |
1073741824 (bytes; CooperInteger beyond 64 bits) |
14d |
CooperDuration |
1209600000 (milliseconds; CooperInteger beyond 64 bits) |
10.0.0.1 |
CooperIPv4 |
"10.0.0.1" |
10.0.0.0/8 |
CooperIPv4 with a prefix |
"10.0.0.0/8" |
(1, "a") |
CooperTuple |
[1, "a"] |
IPv6 follows IPv4. An address becomes its text where the
references give the BEAM's address tuple: text is what PHP's own
socket, stream, and filter functions take. A tuple becomes a list
array where the references keep a tuple: PHP has no tuple type, a
CooperTuple is Cooper's, and a list is the nearest value PHP code
already knows how to read. Its elements are converted too.
Durations become milliseconds, the unit most PHP timeouts and
TTLs take beside seconds (and the unit the references chose). One
that is not a whole number of milliseconds (1500us) is refused
rather than rounded: a silently shortened timeout is harder to find
than a failed boot.
Maps (associative arrays) and lists are walked at every depth; dates, times, atoms, big integers, and everything else pass through as Cooper returns them -- each is a value, not a tag on one.
Secrets: cooper-secrets
A top-level block is one application (or one part of one), and it
says how its own secrets arrive under the key cooper-secrets:
- absent, or
reveal-- revealed: configuration has always held raw values, and what reads it expects one; keep-- left as Cooper'sCooperSecret, untouched, for code that reveals at the point of use;- a string -- a module name, written as
!module("...")takes one (dot-separated PascalCase, mapped through themodulesoption or translated by convention,App.Secret->App\Secret): each secret is revealed, converted, and handed to that class's staticnew(), else its constructor -- for a codebase that owns a secret type.
The key is removed: it is this library's, not the application's. It governs every depth of its block and nothing else, and is refused at the document root (where it would name an application), nested deeper, with an unknown value, or naming a class that cannot wrap. It is a key in the document rather than an option because the document is the one place every way of loading it shares.
Table of Contents
Constants
- POLICY_KEY : mixed = 'cooper-secrets'
- The key an application states its secret handling under. Named for the library, so an application can still have a setting called `secrets` of its own.
- MODULE_VARIABLE : mixed = 'COOPER_CONFIG_SECRET_MODULE'
- Where `resolveModule()` passes the name to Cooper, so no CASC source is ever built from it.
Methods
- toAppConfig() : array<string|int, mixed>
- Converts a `Cooper::loadFile()`/`loadString()` result into application configuration (see the class documentation).
- __construct() : mixed
- converted() : mixed
- One value, as application configuration holds it.
- describe() : string
- A policy value as the document wrote it, for the refusal.
- milliseconds() : int|CooperInteger
- policyOf() : "reveal"|"keep"|array{0: class-string, 1: bool}
- How the application whose block is `$settings` wants its secrets: `'reveal'`, `'keep'`, or the class to wrap with and whether through `new()`.
- resolveModule() : string
- `$name` exactly as `!module("...")` would give it back: through the `modules` option, else Cooper's convention. Cooper itself is asked -- with the name passed in through the environment, never spliced into source -- so the two can never disagree about what a module name is.
- secret() : mixed
- One secret, as the policy asks for it. A revealed value is converted before it is wrapped: what the application's class receives is a value, not a Cooper measurement.
- takesOneArgument() : bool
- walk() : array<string|int, mixed>
- wrapperFor() : array{0: class-string, 1: bool}
- The class `$name` names, and whether it wraps through `new()` (preferred, as the references call it) or its constructor.
Constants
POLICY_KEY
The key an application states its secret handling under. Named for the library, so an application can still have a setting called `secrets` of its own.
public
mixed
POLICY_KEY
= 'cooper-secrets'
MODULE_VARIABLE
Where `resolveModule()` passes the name to Cooper, so no CASC source is ever built from it.
private
mixed
MODULE_VARIABLE
= 'COOPER_CONFIG_SECRET_MODULE'
Methods
toAppConfig()
Converts a `Cooper::loadFile()`/`loadString()` result into application configuration (see the class documentation).
public
static toAppConfig(array<string|int, mixed> $config[, array<string, mixed> $modules = [] ]) : array<string|int, mixed>
Parameters
- $config : array<string|int, mixed>
-
what Cooper loaded
- $modules : array<string, mixed> = []
-
the
modulesoption the document was loaded with, forcooper-secrets = "Name"
Tags
Return values
array<string|int, mixed> —the application configuration
__construct()
private
__construct() : mixed
converted()
One value, as application configuration holds it.
private
static converted(mixed $value, "reveal"|"keep"|array{0: class-string, 1: bool} $mode, array<int, string|int> $path) : mixed
Parameters
- $value : mixed
- $mode : "reveal"|"keep"|array{0: class-string, 1: bool}
- $path : array<int, string|int>
-
where
$valueis, for error messages
Tags
describe()
A policy value as the document wrote it, for the refusal.
private
static describe(mixed $value) : string
Parameters
- $value : mixed
Return values
stringmilliseconds()
private
static milliseconds(CooperDuration $duration, array<int, string|int> $path) : int|CooperInteger
Parameters
- $duration : CooperDuration
- $path : array<int, string|int>
Tags
Return values
int|CooperIntegerpolicyOf()
How the application whose block is `$settings` wants its secrets: `'reveal'`, `'keep'`, or the class to wrap with and whether through `new()`.
private
static policyOf(mixed $settings, array<string, mixed> $modules) : "reveal"|"keep"|array{0: class-string, 1: bool}
Parameters
- $settings : mixed
- $modules : array<string, mixed>
Tags
Return values
"reveal"|"keep"|array{0: class-string, 1: bool}resolveModule()
`$name` exactly as `!module("...")` would give it back: through the `modules` option, else Cooper's convention. Cooper itself is asked -- with the name passed in through the environment, never spliced into source -- so the two can never disagree about what a module name is.
private
static resolveModule(string $name, array<string, mixed> $modules) : string
Parameters
- $name : string
- $modules : array<string, mixed>
Tags
Return values
stringsecret()
One secret, as the policy asks for it. A revealed value is converted before it is wrapped: what the application's class receives is a value, not a Cooper measurement.
private
static secret(CooperSecret $secret, "reveal"|"keep"|array{0: class-string, 1: bool} $mode, array<int, string|int> $path) : mixed
Parameters
- $secret : CooperSecret
- $mode : "reveal"|"keep"|array{0: class-string, 1: bool}
- $path : array<int, string|int>
Tags
takesOneArgument()
private
static takesOneArgument(ReflectionFunctionAbstract $function) : bool
Parameters
- $function : ReflectionFunctionAbstract
Return values
boolwalk()
private
static walk(array<string|int, mixed> $items, "reveal"|"keep"|array{0: class-string, 1: bool} $mode, array<int, string|int> $path) : array<string|int, mixed>
Parameters
- $items : array<string|int, mixed>
- $mode : "reveal"|"keep"|array{0: class-string, 1: bool}
- $path : array<int, string|int>
Tags
Return values
array<string|int, mixed>wrapperFor()
The class `$name` names, and whether it wraps through `new()` (preferred, as the references call it) or its constructor.
private
static wrapperFor(string $name, array<string, mixed> $modules) : array{0: class-string, 1: bool}
Checked when the policy is read, not when the first secret meets it, so a typo is found the first time the document loads.
Parameters
- $name : string
- $modules : array<string, mixed>