$wpcom_user_id, 'local_user_id' => $local_user_id, 'confirmed_at' => gmdate( 'Y-m-d\TH:i:s\Z' ), ); if ( Jetpack_Options::update_option( self::OPTION, $anchor ) ) { return true; } // `update_option()` reports false for an unchanged value as well as for a failed write. return Jetpack_Options::get_option( self::OPTION ) === $anchor; } /** * Point the anchor's cached local user ID at a different local user. * * The match key is `wpcom_user_id`; `local_user_id` is a cache of where that identity lives on * this site, and it legitimately moves when the owner reconnects under another local account. * Deliberately narrow: `confirmed_at` records when the owner was originally confirmed, and * re-pointing a cache is not a new confirmation. * * @since 9.5.0 * * @param int $local_user_id The local user the anchored identity now holds. * @return bool Whether the anchor now names that local user. */ public static function repoint( $local_user_id ) { $local_user_id = absint( $local_user_id ); $anchor = self::get(); if ( ! $anchor || ! $local_user_id ) { return false; } // Defaulted: `get()` only requires `wpcom_user_id`, so a partial anchor reaches here. if ( (int) ( $anchor['local_user_id'] ?? 0 ) === $local_user_id ) { return true; } $anchor['local_user_id'] = $local_user_id; if ( Jetpack_Options::update_option( self::OPTION, $anchor ) ) { return true; } return Jetpack_Options::get_option( self::OPTION ) === $anchor; } /** * Drop the anchor, unlocking ownership. * * Leaves `master_user` alone: clearing the lock does not change who the owner is. * * @internal Recovery and support flows only. Consumers must not call this. * @since 9.3.0 * * @return bool Whether the anchor was deleted. */ public static function clear() { return Jetpack_Options::delete_option( self::OPTION ); } /** * Get the anchor, but only while it protects somebody. * * The anchor is dropped the moment WordPress.com stops confirming it, so holding one and * being protected by it are the same thing. Kept as the name gates read by, which says what * the call site means rather than what the storage happens to be. * * @since 9.3.0 * * @return array|null The anchor, or null when there is none. */ public static function get_locked() { return self::get(); } /** * Whether an anchor is set and locked. * * Deliberately independent of whether the current owner matches it: a mismatch is when * ownership most needs to stay locked. * * @since 9.3.0 * * @return bool */ public static function is_locked() { return null !== self::get_locked(); } }