<commit_before>class User < ActiveRecord::Base

  ##
  ## CORE EXTENSIONS
  ##

  include UserExtension::Cache      # cached user data (should come first)
  include UserExtension::Users      # user <--> user
  include UserExtension::Groups     # user <--> groups
  include UserExtension::Pages      # user <--> pages
  include UserExtension::Tags       # user <--> tags
  include UserExtension::ChatChannels # user <--> chat channels
  include UserExtension::AuthenticatedUser

  ##
  ## VALIDATIONS
  ##

  include CrabgrassDispatcher::Validations
  validates_handle :login

  validates_presence_of :email, :if => :should_validate_email

  before_validation :validates_receive_notifications

  def validates_receive_notifications
    self.receive_notifications = nil if ! ['Single', 'Digest'].include?(self.receive_notifications)
  end

  validates_as_email :email
  before_validation 'self.email = nil if email.empty?'
  # ^^ makes the validation succeed if email == ''

  def should_validate_email
    should_validate = if Site.current
      Site.current.require_user_email
    else
      Conf.require_user_email
    end
    should_validate
  end

  ##
  ## NAMED SCOPES
  ##

  named_scope :recent, :order => 'users.created_at DESC', :conditions => ["users.created_at > ?", RECENT_SINCE_TIME]

  named_scope :active_since, lambda{ |since|
    {:order => 'users.last_seen_at DESC', :conditions => ["users.last_seen_at > ?", since]} 
  }

  named_scope :inactive_since, lambda{ |since|
    {:order => 'users.last_seen_at ASC', :conditions => ["users.last_seen_at < ?", since]}
  }

  # alphabetized and (optional) limited to +letter+
  named_scope :alphabetized, lambda {|letter|
    opts = {
      :order => 'login ASC'
    }
    if letter == '#'
      opts[:conditions] = ['login REGEXP ?', "^[^a-z]"]
    elsif not letter.blank?
      opts[:conditions] = ['login LIKE ?', "#{letter}%"]
    end

    opts
  }

  # select only logins
  named_scope :logins_only, :select => 'login'


  ##
  ## USER IDENTITY
  ##

  belongs_to :avatar, :dependent => :destroy

  validates_format_of :login, :with => /^[a-z0-9]+([-_\.]?[a-z0-9]+){1,17}$/
  before_validation :clean_names

  def clean_names
    write_attribute(:login, (read_attribute(:login)||'').downcase)

    t_name = read_attribute(:display_name)
    if t_name
      write_attribute(:display_name, t_name.gsub(/[&<>]/,''))
    end
  end

  after_save :update_name
  def update_name
    if login_changed? and !login_was.nil?
      Page.update_owner_name(self)
      Wiki.clear_all_html(self)
    end
  end

  after_destroy :kill_avatar
  def kill_avatar
    avatar.destroy if avatar
  end

  # the user's custom display name, could be anything.
  def display_name
    read_attribute('display_name').any? ? read_attribute('display_name') : login
  end

  # the user's handle, in same namespace as group name,
  # must be url safe.
  def name; login; end

  # displays both display_name and name
  def both_names
    if read_attribute('display_name').any? and read_attribute('display_name') != name
      '%s (%s)' % [display_name,name]
    else
      name
    end
  end
  alias :to_s :both_names   # used for indexing

  def cut_name
    name[0..20]
  end

  def to_param
    return login
  end

  def banner_style<commit_msg>fixes #2426 - change order of names when displaying both names<commit_after>class User < ActiveRecord::Base

  ##
  ## CORE EXTENSIONS
  ##

  include UserExtension::Cache      # cached user data (should come first)
  include UserExtension::Users      # user <--> user
  include UserExtension::Groups     # user <--> groups
  include UserExtension::Pages      # user <--> pages
  include UserExtension::Tags       # user <--> tags
  include UserExtension::ChatChannels # user <--> chat channels
  include UserExtension::AuthenticatedUser

  ##
  ## VALIDATIONS
  ##

  include CrabgrassDispatcher::Validations
  validates_handle :login

  validates_presence_of :email, :if => :should_validate_email

  before_validation :validates_receive_notifications

  def validates_receive_notifications
    self.receive_notifications = nil if ! ['Single', 'Digest'].include?(self.receive_notifications)
  end

  validates_as_email :email
  before_validation 'self.email = nil if email.empty?'
  # ^^ makes the validation succeed if email == ''

  def should_validate_email
    should_validate = if Site.current
      Site.current.require_user_email
    else
      Conf.require_user_email
    end
    should_validate
  end

  ##
  ## NAMED SCOPES
  ##

  named_scope :recent, :order => 'users.created_at DESC', :conditions => ["users.created_at > ?", RECENT_SINCE_TIME]

  named_scope :active_since, lambda{ |since|
    {:order => 'users.last_seen_at DESC', :conditions => ["users.last_seen_at > ?", since]} 
  }

  named_scope :inactive_since, lambda{ |since|
    {:order => 'users.last_seen_at ASC', :conditions => ["users.last_seen_at < ?", since]}
  }

  # alphabetized and (optional) limited to +letter+
  named_scope :alphabetized, lambda {|letter|
    opts = {
      :order => 'login ASC'
    }
    if letter == '#'
      opts[:conditions] = ['login REGEXP ?', "^[^a-z]"]
    elsif not letter.blank?
      opts[:conditions] = ['login LIKE ?', "#{letter}%"]
    end

    opts
  }

  # select only logins
  named_scope :logins_only, :select => 'login'


  ##
  ## USER IDENTITY
  ##

  belongs_to :avatar, :dependent => :destroy

  validates_format_of :login, :with => /^[a-z0-9]+([-_\.]?[a-z0-9]+){1,17}$/
  before_validation :clean_names

  def clean_names
    write_attribute(:login, (read_attribute(:login)||'').downcase)

    t_name = read_attribute(:display_name)
    if t_name
      write_attribute(:display_name, t_name.gsub(/[&<>]/,''))
    end
  end

  after_save :update_name
  def update_name
    if login_changed? and !login_was.nil?
      Page.update_owner_name(self)
      Wiki.clear_all_html(self)
    end
  end

  after_destroy :kill_avatar
  def kill_avatar
    avatar.destroy if avatar
  end

  # the user's custom display name, could be anything.
  def display_name
    read_attribute('display_name').any? ? read_attribute('display_name') : login
  end

  # the user's handle, in same namespace as group name,
  # must be url safe.
  def name; login; end

  # displays both display_name and name
  def both_names
    if read_attribute('display_name').any? and read_attribute('display_name') != name
      '%s (%s)' % [name, display_name]
    else
      name
    end
  end
  alias :to_s :both_names   # used for indexing

  def cut_name
    name[0..20]
  end

  def to_param
    return login
  end

  def banner_style
{'fraction_non_alphanumeric': 0.11955205811138014, 'fraction_numerical': 0.0036319612590799033, 'mean_word_length': 3.4746106973595126, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6466381', 'n_tokens_mistral': 2231, 'n_tokens_neox': 2119, 'n_words': 521}