keyHandle ) // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase || ! property_exists( $register, 'publicKey' ) || empty( $register->publicKey ) // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase || ! property_exists( $register, 'certificate' ) || empty( $register->certificate ) || ! property_exists( $register, 'counter' ) || ( -1 > $register->counter ) ) { return false; } $register = array( 'keyHandle' => $register->keyHandle, // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase 'publicKey' => $register->publicKey, // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase 'certificate' => $register->certificate, 'counter' => $register->counter, ); $register['name'] = __( 'New Security Key', 'two-factor' ); $register['added'] = time(); $register['last_used'] = $register['added']; return add_user_meta( $user_id, self::REGISTERED_KEY_USER_META_KEY, $register ); } /** * Retrieve registered security keys for a user. * * @since 0.1-dev * * @param int $user_id User ID. * @return array|bool Array of keys on success, false on failure. */ public static function get_security_keys( $user_id ) { if ( ! is_numeric( $user_id ) ) { return false; } $keys = get_user_meta( $user_id, self::REGISTERED_KEY_USER_META_KEY ); if ( $keys ) { foreach ( $keys as &$key ) { $key = (object) $key; } unset( $key ); } return $keys; } /** * Update registered security key. * * Use the $prev_value parameter to differentiate between meta fields with the * same key and user ID. * * If the meta field for the user does not exist, it will be added. * * @since 0.1-dev * * @param int $user_id User ID. * @param object $data The data of registered security key. * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure. */ public static function update_security_key( $user_id, $data ) { if ( ! is_numeric( $user_id ) ) { return false; } if ( ! is_object( $data ) || ! property_exists( $data, 'keyHandle' ) || empty( $data->keyHandle ) // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase || ! property_exists( $data, 'publicKey' ) || empty( $data->publicKey ) // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase || ! property_exists( $data, 'certificate' ) || empty( $data->certificate ) || ! property_exists( $data, 'counter' ) || ( -1 > $data->counter ) ) { return false; } $keys = self::get_security_keys( $user_id ); if ( $keys ) { foreach ( $keys as $key ) { if ( $key->keyHandle === $data->keyHandle ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase return update_user_meta( $user_id, self::REGISTERED_KEY_USER_META_KEY, (array) $data, (array) $key ); } } } return self::add_security_key( $user_id, $data ); } /** * Remove registered security key matching criteria from a user. * * @since 0.1-dev * * @param int $user_id User ID. * @param string $keyHandle Optional. Key handle. * @return bool True on success, false on failure. */ public static function delete_security_key( $user_id, $keyHandle = null ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase global $wpdb; if ( ! is_numeric( $user_id ) ) { return false; } $user_id = absint( $user_id ); if ( ! $user_id ) { return false; } $keyHandle = wp_unslash( $keyHandle ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase $keyHandle = maybe_serialize( $keyHandle ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase $query = $wpdb->prepare( "SELECT umeta_id FROM {$wpdb->usermeta} WHERE meta_key = %s AND user_id = %d", self::REGISTERED_KEY_USER_META_KEY, $user_id ); if ( $keyHandle ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase $key_handle_lookup = sprintf( ':"%s";s:', $keyHandle ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase $query .= $wpdb->prepare( ' AND meta_value LIKE %s', '%' . $wpdb->esc_like( $key_handle_lookup ) . '%' ); } $meta_ids = $wpdb->get_col( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared if ( ! count( $meta_ids ) ) { return false; } foreach ( $meta_ids as $meta_id ) { delete_metadata_by_mid( 'user', $meta_id ); } return true; } }