*/ public static function all(): array { $state = get_option( self::OPTION, array() ); return is_array( $state ) ? $state : array(); } /** * One value. * * @param string $key Key. * @param mixed $fallback Returned when the key is missing. * @return mixed */ public static function get( string $key, $fallback = null ) { $state = self::all(); return array_key_exists( $key, $state ) ? $state[ $key ] : $fallback; } /** * Stores one value. * * @param string $key Key. * @param mixed $value Value. */ public static function set( string $key, $value ): void { // Built on what's stored now, so a key another request just stored stays. Option_Queue::change( self::OPTION, static function ( array $state ) use ( $key, $value ): array { $state[ $key ] = $value; return $state; } ); } /** * Changes one value from what's stored now, so what another request * changes in it meanwhile isn't lost. * * @param string $key Key. * @param callable $change Gets the stored value, null when there's none, * and returns the new one. It may run more than * once; its last run counts. */ public static function change( string $key, callable $change ): void { Option_Queue::change( self::OPTION, static function ( array $state ) use ( $key, $change ): array { $state[ $key ] = $change( $state[ $key ] ?? null ); return $state; } ); } /** * Removes values. * * @param string ...$keys Keys. */ public static function forget( string ...$keys ): void { Option_Queue::change( self::OPTION, static function ( array $state ) use ( $keys ): array { foreach ( $keys as $key ) { unset( $state[ $key ] ); } return $state; } ); } /** * Setup progress for the three-step checklist. * * @return array{account: bool, brief: bool, live: bool} */ public static function setup(): array { $setup = self::get( 'setup', array() ); $setup = is_array( $setup ) ? $setup : array(); return array( 'account' => ! empty( $setup['account'] ), 'brief' => ! empty( $setup['brief'] ), 'live' => ! empty( $setup['live'] ), ); } /** * Marks one setup step done (or not). * * @param string $step One of account, brief, live. * @param bool $done Done. */ public static function mark_setup( string $step, bool $done = true ): void { self::change( 'setup', static function ( $setup ) use ( $step, $done ): array { $setup = is_array( $setup ) ? $setup : array(); $setup[ $step ] = $done; return $setup; } ); } /** * Whether a notice is dismissed right now. * * @param string $notice Notice ID. */ public static function is_dismissed( string $notice ): bool { $dismissed = self::get( 'dismissed', array() ); if ( ! is_array( $dismissed ) || ! isset( $dismissed[ $notice ] ) ) { return false; } $until = (int) $dismissed[ $notice ]; return 0 === $until || $until > time(); } /** * Dismisses a notice, optionally until a time. * * @param string $notice Notice ID. * @param int $until Unix time; 0 means for good. */ public static function dismiss( string $notice, int $until = 0 ): void { self::change( 'dismissed', static function ( $dismissed ) use ( $notice, $until ): array { $dismissed = is_array( $dismissed ) ? $dismissed : array(); $dismissed[ $notice ] = $until; return $dismissed; } ); } }