/**
  * Generates a new login hash associated with a device
  * The device is assigned a globally unique device ID
  * The returned login hash stores the hashed token in the
  * database, for this device and this member
  * @param Member $member The logged in user
  * @return RememberLoginHash The generated login hash
  */
 public static function generate(Member $member)
 {
     if (!$member->exists()) {
         return null;
     }
     if (static::config()->force_single_token) {
         RememberLoginHash::get()->filter('MemberID', $member->ID)->removeAll();
     }
     /** @var RememberLoginHash $rememberLoginHash */
     $rememberLoginHash = RememberLoginHash::create();
     do {
         $deviceID = $rememberLoginHash->getNewDeviceID();
     } while (RememberLoginHash::get()->filter('DeviceID', $deviceID)->count());
     $rememberLoginHash->DeviceID = $deviceID;
     $rememberLoginHash->Hash = $rememberLoginHash->getNewHash($member);
     $rememberLoginHash->MemberID = $member->ID;
     $now = DBDatetime::now();
     $expiryDate = new DateTime($now->Rfc2822());
     $tokenExpiryDays = static::config()->token_expiry_days;
     $expiryDate->add(new DateInterval('P' . $tokenExpiryDays . 'D'));
     $rememberLoginHash->ExpiryDate = $expiryDate->format('Y-m-d H:i:s');
     $rememberLoginHash->extend('onAfterGenerateToken');
     $rememberLoginHash->write();
     return $rememberLoginHash;
 }