*/ public function __invoke( ?string $email = null, ?string $username = null ): array { $check = $this->guard( 'manage_pointics', 'manage_options' ); if ( $check ) { return $check; } $check = $this->pointics_tables_ready(); if ( $check ) { return $check; } try { $email = trim( (string) $email ); $username = trim( (string) $username ); if ( '' === $email && '' === $username ) { return $this->steer( [ 'error' => __( 'Provide an email or username to find a WordPress member.', 'aisentic' ), 'code' => 'invalid_argument', 'status' => 422, ] ); } $user = null; if ( '' !== $email ) { $matches = array_values( array_filter( (array) get_users( [ 'search' => $email, 'search_columns' => [ 'user_email' ], 'fields' => 'all', 'number' => 50, ] ), static fn ( $candidate ): bool => is_object( $candidate ) && strtolower( $email ) === strtolower( (string) ( $candidate->user_email ?? '' ) ) ) ); if ( count( $matches ) > 1 ) { return $this->steer( [ 'error' => __( 'Multiple members match this email. Choose one member from the matches using its user_id.', 'aisentic' ), 'code' => 'invalid_argument', 'status' => 422, 'matches' => array_map( [ $this, 'identity' ], $matches ), ] ); } $user = $matches[0] ?? get_user_by( 'email', $email ); } else { $user = get_user_by( 'login', $username ); } if ( ! is_object( $user ) || empty( $user->ID ) ) { return $this->steer( [ 'error' => sprintf( /* translators: %s: member email or username. */ __( 'No WordPress member matched "%s". Provide an exact email or username and try again.', 'aisentic' ), '' !== $email ? $email : $username ), 'code' => 'not_found', 'status' => 404, ] ); } $result = $this->identity( $user ); try { $balance = pointics_container()->make( \Pointics\Points\Balance_Service::class )->snapshot( (int) $user->ID ); $result['points_available'] = (int) ( $balance['available'] ?? 0 ); $result['points_lifetime'] = (int) ( $balance['lifetime'] ?? 0 ); } catch ( \Throwable $e ) { Log::warning( 'Pointics member balance service unavailable', [ 'error' => $e->getMessage() ] ); $result['note'] = __( 'The Pointics balance service is unavailable, so identity details were returned without point balances.', 'aisentic' ); } return $result; } catch ( \Throwable $e ) { Log::error( 'Pointics_Find_Member_Tool error', [ 'error' => $e->getMessage() ] ); return $this->steer( [ 'error' => __( 'Failed to find the WordPress member.', 'aisentic' ), 'code' => 'internal', 'status' => 500, ] ); } } /** * Shape the WordPress identity fields shared by the result and disambiguation list. * * @param object $user WordPress user object. * @return array */ protected function identity( object $user ): array { return [ 'user_id' => (int) $user->ID, 'display_name' => (string) ( $user->display_name ?? '' ), 'email' => (string) ( $user->user_email ?? '' ), ]; } }