You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							304 lines
						
					
					
						
							8.6 KiB
						
					
					
				
			
		
		
	
	
							304 lines
						
					
					
						
							8.6 KiB
						
					
					
				<?php | 
						|
namespace core\entities\user; | 
						|
 | 
						|
use core\entities\Session; | 
						|
use core\events\EventTrait; | 
						|
use lhs\Yii2SaveRelationsBehavior\SaveRelationsBehavior; | 
						|
use core\AggregateRoot; | 
						|
use core\events\user\UserSignUpConfirmed; | 
						|
use core\events\user\UserSignUpRequested; | 
						|
use Yii; | 
						|
use yii\behaviors\TimestampBehavior; | 
						|
use yii\db\ActiveQuery; | 
						|
use yii\db\ActiveRecord; | 
						|
use zertex\avatar_generator\AvatarGenerator; | 
						|
 | 
						|
/** | 
						|
 * User model | 
						|
 * | 
						|
 * @property integer $id | 
						|
 * @property string $username | 
						|
 * @property string $password_hash | 
						|
 * @property string $password_reset_token | 
						|
 * @property string $email | 
						|
 * @property string $email_confirm_token | 
						|
 * @property string $auth_key | 
						|
 * @property integer $status | 
						|
 * @property integer $created_at | 
						|
 * @property integer $updated_at | 
						|
 * @property string $user_pic | 
						|
 * @property string $backend_language | 
						|
 * @property string $frontend_language | 
						|
 * @property string $password write-only password | 
						|
 * | 
						|
 * @property Network[] $networks | 
						|
 */ | 
						|
class User extends ActiveRecord implements AggregateRoot | 
						|
{ | 
						|
    use EventTrait; | 
						|
 | 
						|
    const STATUS_WAIT = 0; | 
						|
    const STATUS_ACTIVE = 10; | 
						|
 | 
						|
    public static function create(string $username, string $email, string $password): self | 
						|
    { | 
						|
        $user = new User(); | 
						|
        $user->username = $username; | 
						|
        $user->email = $email; | 
						|
        $user->setPassword(!empty($password) ? $password : Yii::$app->security->generateRandomString()); | 
						|
        $user->created_at = time(); | 
						|
        $user->status = self::STATUS_ACTIVE; | 
						|
        $user->auth_key = Yii::$app->security->generateRandomString(); | 
						|
 | 
						|
	    if ($user->user_pic) | 
						|
	    { | 
						|
		    $fileName = md5('avatar-' . $user->user_pic->baseName . time()) . '.' . $user->user_pic->extension; | 
						|
		    if ($user->user_pic->saveAs((new AvatarGenerator())->getPath('avatar') . '/' . $fileName)) | 
						|
		    { | 
						|
			    $user->user_pic = $fileName; | 
						|
		    } | 
						|
	    } | 
						|
 | 
						|
        return $user; | 
						|
    } | 
						|
 | 
						|
    public function edit(string $username, string $email, string $password, $user_pic = null): void | 
						|
    { | 
						|
        $this->username = $username; | 
						|
        $this->email = $email; | 
						|
        $this->updated_at = time(); | 
						|
 | 
						|
	    if ($user_pic) | 
						|
	    { | 
						|
		    $fileName = md5('avatar-' . $user_pic->baseName . time()) . '.' . $user_pic->extension; | 
						|
		    if ($user_pic->saveAs((new AvatarGenerator())->getPath('avatar') . '/' . $fileName)) | 
						|
		    { | 
						|
			    (new AvatarGenerator())->remove('avatar', $this->user_pic); | 
						|
			    $this->user_pic = $fileName; | 
						|
		    } | 
						|
	    } | 
						|
 | 
						|
	    if ($password) { | 
						|
		    $this->setPassword(!empty($password) ? $password : Yii::$app->security->generateRandomString()); | 
						|
		    $this->generateAuthKey(); | 
						|
		    Session::deleteAll(['user_id' => $this->id]); | 
						|
	    } | 
						|
    } | 
						|
 | 
						|
    public function editProfile(string $email, string $username, string $password = null, $user_pic = null, $language): void | 
						|
    { | 
						|
        $this->email = $email; | 
						|
        $this->username = $username; | 
						|
        if ($password && !empty($password)) { | 
						|
	        $this->setPassword( $password ); | 
						|
        } | 
						|
        $this->updated_at = time(); | 
						|
        $this->backend_language = $language; | 
						|
 | 
						|
        /* @var $user_pic \yii\web\UploadedFile */ | 
						|
	    if ($user_pic) | 
						|
	    { | 
						|
		    $fileName = md5('avatar-' . $user_pic->baseName . time()) . '.' . $user_pic->extension; | 
						|
		    $path = Yii::getAlias( '@runtime/' . $fileName); | 
						|
		    $user_pic->saveAs($path); | 
						|
		    $this->user_pic = basename(Yii::$app->avatar->update($username, null, $path)); | 
						|
		    if (file_exists($path)) { | 
						|
		    	unlink($path); | 
						|
		    } | 
						|
	    } | 
						|
    } | 
						|
 | 
						|
    public static function requestSignup(string $username, string $email, string $password): self | 
						|
    { | 
						|
        $user = new User(); | 
						|
        $user->username = $username; | 
						|
        $user->email = $email; | 
						|
        $user->setPassword($password); | 
						|
        $user->created_at = time(); | 
						|
        $user->status = self::STATUS_WAIT; | 
						|
        $user->email_confirm_token = Yii::$app->security->generateRandomString(); | 
						|
        $user->generateAuthKey(); | 
						|
        $user->recordEvent(new UserSignUpRequested($user)); | 
						|
        return $user; | 
						|
    } | 
						|
 | 
						|
    public function confirmSignup(): void | 
						|
    { | 
						|
        if (!$this->isWait()) { | 
						|
            throw new \DomainException('User is already active.'); | 
						|
        } | 
						|
        $this->status = self::STATUS_ACTIVE; | 
						|
        $this->email_confirm_token = null; | 
						|
        $this->recordEvent(new UserSignUpConfirmed($this)); | 
						|
    } | 
						|
 | 
						|
    public static function signupByNetwork($network, $identity): self | 
						|
    { | 
						|
        $user = new User(); | 
						|
        $user->created_at = time(); | 
						|
        $user->status = self::STATUS_ACTIVE; | 
						|
        $user->generateAuthKey(); | 
						|
        $user->networks = [Network::create($network, $identity)]; | 
						|
        return $user; | 
						|
    } | 
						|
 | 
						|
    public function attachNetwork($network, $identity): void | 
						|
    { | 
						|
        $networks = $this->networks; | 
						|
        foreach ($networks as $current) { | 
						|
            if ($current->isFor($network, $identity)) { | 
						|
                throw new \DomainException('Network is already attached.'); | 
						|
            } | 
						|
        } | 
						|
        $networks[] = Network::create($network, $identity); | 
						|
        $this->networks = $networks; | 
						|
    } | 
						|
 | 
						|
 | 
						|
    public function requestPasswordReset(): void | 
						|
    { | 
						|
        if (!empty($this->password_reset_token) && self::isPasswordResetTokenValid($this->password_reset_token)) { | 
						|
            throw new \DomainException(Yii::t('auth', 'Password resetting is already requested.')); | 
						|
        } | 
						|
        $this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time(); | 
						|
    } | 
						|
 | 
						|
    public function resetPassword($password): void | 
						|
    { | 
						|
        if (empty($this->password_reset_token)) { | 
						|
            throw new \DomainException(Yii::t('auth', 'Password resetting is not requested.')); | 
						|
        } | 
						|
        $this->setPassword($password); | 
						|
        $this->password_reset_token = null; | 
						|
    } | 
						|
 | 
						|
    public function isWait(): bool | 
						|
    { | 
						|
        return $this->status === self::STATUS_WAIT; | 
						|
    } | 
						|
 | 
						|
    public function isActive(): bool | 
						|
    { | 
						|
        return $this->status === self::STATUS_ACTIVE; | 
						|
    } | 
						|
 | 
						|
    public function getNetworks(): ActiveQuery | 
						|
    { | 
						|
        return $this->hasMany(Network::class, ['user_id' => 'id']); | 
						|
    } | 
						|
 | 
						|
    /** | 
						|
     * @inheritdoc | 
						|
     */ | 
						|
    public static function tableName() | 
						|
    { | 
						|
        return '{{%users}}'; | 
						|
    } | 
						|
 | 
						|
    /** | 
						|
     * @inheritdoc | 
						|
     */ | 
						|
    public function behaviors() | 
						|
    { | 
						|
        return [ | 
						|
            TimestampBehavior::class, | 
						|
            [ | 
						|
                'class' => SaveRelationsBehavior::class, | 
						|
                'relations' => ['networks'], | 
						|
            ], | 
						|
        ]; | 
						|
    } | 
						|
 | 
						|
    public function transactions() | 
						|
    { | 
						|
        return [ | 
						|
            self::SCENARIO_DEFAULT => self::OP_ALL, | 
						|
        ]; | 
						|
    } | 
						|
 | 
						|
    /** | 
						|
     * Finds user by username | 
						|
     * | 
						|
     * @param string $username | 
						|
     * @return static|null | 
						|
     */ | 
						|
    public static function findByUsername($username) | 
						|
    { | 
						|
        return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]); | 
						|
    } | 
						|
 | 
						|
    /** | 
						|
     * Finds user by password reset token | 
						|
     * | 
						|
     * @param string $token password reset token | 
						|
     * @return static|null | 
						|
     */ | 
						|
    public static function findByPasswordResetToken($token) | 
						|
    { | 
						|
        if (!static::isPasswordResetTokenValid($token)) { | 
						|
            return null; | 
						|
        } | 
						|
 | 
						|
        return static::findOne([ | 
						|
            'password_reset_token' => $token, | 
						|
            'status' => self::STATUS_ACTIVE, | 
						|
        ]); | 
						|
    } | 
						|
 | 
						|
    /** | 
						|
     * Finds out if password reset token is valid | 
						|
     * | 
						|
     * @param string $token password reset token | 
						|
     * @return bool | 
						|
     */ | 
						|
    public static function isPasswordResetTokenValid($token) | 
						|
    { | 
						|
        if (empty($token)) { | 
						|
            return false; | 
						|
        } | 
						|
 | 
						|
        $timestamp = (int) substr($token, strrpos($token, '_') + 1); | 
						|
        $expire = Yii::$app->params['user.passwordResetTokenExpire']; | 
						|
        return $timestamp + $expire >= time(); | 
						|
    } | 
						|
 | 
						|
    /** | 
						|
     * Validates password | 
						|
     * | 
						|
     * @param string $password password to validate | 
						|
     * @return bool if password provided is valid for current user | 
						|
     */ | 
						|
    public function validatePassword($password) | 
						|
    { | 
						|
        return Yii::$app->security->validatePassword($password, $this->password_hash); | 
						|
    } | 
						|
 | 
						|
	/** | 
						|
	 * @param $password | 
						|
	 * | 
						|
	 * @throws \yii\base\Exception | 
						|
	 */ | 
						|
    private function setPassword($password) | 
						|
    { | 
						|
        $this->password_hash = Yii::$app->security->generatePasswordHash($password); | 
						|
    } | 
						|
 | 
						|
    /** | 
						|
     * Generates "remember me" authentication key | 
						|
     */ | 
						|
    private function generateAuthKey() | 
						|
    { | 
						|
        $this->auth_key = Yii::$app->security->generateRandomString(); | 
						|
    } | 
						|
 | 
						|
    public function attributeLabels() { | 
						|
	    return [ | 
						|
		    'id' => Yii::t('user', 'ID'), | 
						|
	        'username' => Yii::t('user', 'Username'), | 
						|
	        'email' => Yii::t('user', 'E-mail'), | 
						|
	        'status' => Yii::t('user', 'Status'), | 
						|
	        'created_at' => Yii::t('user', 'Created At'), | 
						|
		    'updated_at' => Yii::t('user', 'Updated At'), | 
						|
	    ]; | 
						|
    } | 
						|
}
 | 
						|
 |