57 lines
		
	
	
		
			1.3 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			57 lines
		
	
	
		
			1.3 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| # This class extracts all users found in a piece of text by the username or the
 | |
| # email address
 | |
| 
 | |
| module Gitlab
 | |
|   class UserExtractor
 | |
|     # Not using `Devise.email_regexp` to filter out any chars that an email
 | |
|     # does not end with and not pinning the email to a start of end of a string.
 | |
|     EMAIL_REGEXP = /(?<email>([^@\s]+@[^@\s]+(?<!\W)))/.freeze
 | |
|     USERNAME_REGEXP = User.reference_pattern
 | |
| 
 | |
|     def initialize(text)
 | |
|       # EE passes an Array to `text` in a few places, so we want to support both
 | |
|       # here.
 | |
|       @text = Array(text).join(' ')
 | |
|     end
 | |
| 
 | |
|     def users
 | |
|       return User.none unless @text.present?
 | |
|       return User.none if references.empty?
 | |
| 
 | |
|       @users ||= User.from_union(union_relations)
 | |
|     end
 | |
| 
 | |
|     def usernames
 | |
|       matches[:usernames]
 | |
|     end
 | |
| 
 | |
|     def emails
 | |
|       matches[:emails]
 | |
|     end
 | |
| 
 | |
|     def references
 | |
|       @references ||= matches.values.flatten
 | |
|     end
 | |
| 
 | |
|     def matches
 | |
|       @matches ||= {
 | |
|         emails: @text.scan(EMAIL_REGEXP).flatten.uniq,
 | |
|         usernames: @text.scan(USERNAME_REGEXP).flatten.uniq
 | |
|       }
 | |
|     end
 | |
| 
 | |
|     private
 | |
| 
 | |
|     def union_relations
 | |
|       relations = []
 | |
| 
 | |
|       relations << User.by_any_email(emails) if emails.any?
 | |
|       relations << User.by_username(usernames) if usernames.any?
 | |
| 
 | |
|       relations
 | |
|     end
 | |
|   end
 | |
| end
 |