> */ private $records = array(); /** * Which operations are configured to fail. * * @var array */ private $fail = array( 'get' => false, 'set' => false, 'delete' => false, 'list' => false, ); /** * Every record ever passed to set(), in call order. * * @var array> */ private $received_records = array(); public function get( string $name, bool $network = false ) { if ( $this->fail['get'] ) { return new WP_Error( WP_SECRETS_ERROR_STORE_UNAVAILABLE, 'Mock_Store: get() configured to fail.' ); } $key = $this->key( $name, $network ); return array_key_exists( $key, $this->records ) ? $this->records[ $key ] : null; } public function set( string $name, array $record, bool $network = false ) { $this->received_records[] = $record; if ( $this->fail['set'] ) { return new WP_Error( WP_SECRETS_ERROR_STORE_UNAVAILABLE, 'Mock_Store: set() configured to fail.' ); } $this->records[ $this->key( $name, $network ) ] = $record; return true; } public function delete( string $name, bool $network = false ) { if ( $this->fail['delete'] ) { return new WP_Error( WP_SECRETS_ERROR_STORE_UNAVAILABLE, 'Mock_Store: delete() configured to fail.' ); } unset( $this->records[ $this->key( $name, $network ) ] ); return true; } public function list_names( bool $network = false ) { if ( $this->fail['list'] ) { return new WP_Error( WP_SECRETS_ERROR_STORE_UNAVAILABLE, 'Mock_Store: list_names() configured to fail.' ); } $prefix = $network ? 'network:' : 'site:'; $names = array(); foreach ( array_keys( $this->records ) as $key ) { if ( str_starts_with( $key, $prefix ) ) { $names[] = substr( $key, strlen( $prefix ) ); } } return $names; } /** * @param string $operation One of 'get', 'set', 'delete', 'list'. * @param bool $fail Whether that operation should return WP_Error. * * @return $this */ public function configure_fail( string $operation, bool $fail = true ): self { $this->fail[ $operation ] = $fail; return $this; } /** * Every record ever passed to set(), in call order – including ones set() * went on to reject, since the assertion this exists for is "was this store * ever handed a plaintext," not "was a plaintext ever successfully stored." * * @return array> */ public function get_received_records(): array { return $this->received_records; } /** * @param string $name The secret's namespaced name. * @param bool $network Whether this is a network-scope secret. * @return string The key the record is held under. */ private function key( string $name, bool $network ): string { return ( $network ? 'network:' : 'site:' ) . $name; } }