|null */ #[\Override] public function readAtomic( string $key ): ?array { if ( ! function_exists( 'maybe_unserialize' ) ) { throw new \RuntimeException( 'WordPress serialization is unavailable.' ); } global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- CAS reads must bypass the WordPress option cache. $raw = $wpdb->get_var( $wpdb->prepare( "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s", $key ) ); if ( $wpdb->last_error !== '' ) { throw new \RuntimeException( 'Could not read the atomic option.' ); } if ( $raw === null ) { return null; } $value = maybe_unserialize( $raw ); if ( ! is_array( $value ) ) { throw new \RuntimeException( 'Atomic option value must be an array.' ); } return $value; } /** * @param string $key Option key. * @param array|null $expected Expected value. * @param array $value Replacement value. */ #[\Override] public function compareAndSwap( string $key, ?array $expected, array $value ): bool { if ( ! function_exists( 'maybe_serialize' ) || ! function_exists( 'wp_cache_delete' ) ) { throw new \RuntimeException( 'WordPress atomic option persistence is unavailable.' ); } global $wpdb; $encoded = maybe_serialize( $value ); if ( $expected === null ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- The unique option_name index arbitrates concurrent initializers. $changed = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->options} (option_name, option_value, autoload) VALUES (%s, %s, 'no')", $key, $encoded ) ); } else { // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- Compare the complete serialized value atomically, not a cached snapshot. $changed = $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->options} SET option_value = %s, autoload = 'no' WHERE option_name = %s AND BINARY option_value = %s", $encoded, $key, maybe_serialize( $expected ) ) ); } if ( $changed === false ) { throw new \RuntimeException( 'Could not update the atomic option.' ); } if ( $changed === 1 ) { wp_cache_delete( $key, 'options' ); wp_cache_delete( 'alloptions', 'options' ); wp_cache_delete( 'notoptions', 'options' ); return true; } return false; } }