'constant', 'value' => $value, 'name' => $constant, ]; } } $hook = self::filter_name( $option_name ); /** * Filters the value in force for one Albert setting. * * The hook name carries the option name, so * `albert/settings/value/albert_privacy_mode` overrides the privacy * mode. Return null (the default) to defer to the stored value. * * A setting under an active override renders read-only on the Settings * screen, with a note saying where the value comes from: an owner is * never shown a control that would not actually change anything. * * @since 1.4.0 * * @param mixed $value The overriding value, or null to defer. */ $filtered = apply_filters( $hook, null ); if ( $filtered !== null && ( $validator === null || (bool) $validator( $filtered ) ) ) { /** * Filters the name reported as the source of an override. * * Only useful to something that answers the value filter on another * hook's behalf. `albert/privacy/mode` is bridged onto this chain by * {@see Overrides}, so without this the screen would tell an owner * their value came from `albert/settings/value/albert_privacy_mode` * — a hook nobody wrote, and one they would not find by grepping * their own code. Return null to report the hook that answered. * * @since 1.4.0 * * @param string|null $name The hook or constant to name, or null. */ $reported = apply_filters( 'albert/settings/value_source/' . $option_name, null ); return [ 'source' => 'filter', 'value' => $filtered, 'name' => is_string( $reported ) && $reported !== '' ? $reported : $hook, ]; } return null; } /** * Whether code, rather than the stored option, decides this setting. * * @since 1.4.0 * * @param string $option_name The option name. * @param callable|null $validator Optional `fn( $value ): bool`. * * @return bool */ public static function is_overridden( string $option_name, ?callable $validator = null ): bool { return self::override( $option_name, $validator ) !== null; } /** * Where an override comes from: `constant`, `filter`, or null for neither. * * @since 1.4.0 * * @param string $option_name The option name. * @param callable|null $validator Optional `fn( $value ): bool`. * * @return string|null */ public static function override_source( string $option_name, ?callable $validator = null ): ?string { $override = self::override( $option_name, $validator ); return $override === null ? null : $override['source']; } /** * The option's own validator, if it has declared one. * * @since 1.4.0 * * @param string $option_name The option name. * * @return callable|null `fn( $value ): bool`, or null when the option * accepts anything. */ public static function validator( string $option_name ): ?callable { /** * Filters the validator that decides whether an override is usable. * * Return `fn( $value ): bool`. An override it rejects is skipped and * resolution continues to the next layer, so a malformed constant falls * through to the stored value instead of pinning the site to nonsense. * * Declare one for any setting with a closed vocabulary or a range. It is * what stops the Settings screen reporting an override that the code * reading the setting would refuse: both ask this same question. * * @since 1.4.0 * * @param callable|null $validator The validator, or null to accept anything. */ $validator = apply_filters( self::validator_name( $option_name ), null ); if ( is_callable( $validator ) ) { return $validator; } // Free's own, which are a plain static map rather than something // published on a hook: this has to answer correctly on the very first // request, before anything has had a chance to register. return Validators::for_option( $option_name ); } /** * The filter that overrides one setting. * * @since 1.4.0 * * @param string $option_name The option name. * * @return non-empty-string Always: the prefix alone guarantees it. */ public static function filter_name( string $option_name ): string { return 'albert/settings/value/' . $option_name; } /** * The filter that declares one setting's validator. * * @since 1.4.0 * * @param string $option_name The option name. * * @return non-empty-string Always: the prefix alone guarantees it. */ public static function validator_name( string $option_name ): string { return 'albert/settings/validator/' . $option_name; } /** * The constant that overrides one setting, or '' when the option name * cannot spell a legal constant. * * Option names are lower case by convention and already namespaced, so * upper-casing is the whole rule: `albert_privacy_mode` → * `ALBERT_PRIVACY_MODE`. Guarded because an option name is not required to * be a legal PHP identifier, and `defined()` on a malformed name is a * question worth not asking. * * @since 1.4.0 * * @param string $option_name The option name. * * @return string */ public static function constant_name( string $option_name ): string { if ( preg_match( '/^[A-Za-z_][A-Za-z0-9_]*$/', $option_name ) !== 1 ) { return ''; } return strtoupper( $option_name ); } }