User.php 10.3 KB
<?php
    namespace common\models;

    use Yii;
    use yii\base\NotSupportedException;
    use yii\behaviors\TimestampBehavior;
    use yii\db\ActiveRecord;
    use yii\web\IdentityInterface;
    use developeruz\db_rbac\interfaces\UserRbacInterface;

    /**
     * User model
     * @property integer $id
     * @property string  $username
     * @property string  $password_hash
     * @property string  $password_reset_token
     * @property string  $email
     * @property string  $auth_key
     * @property integer $status
     * @property integer $created_at
     * @property integer $updated_at
     * @property string  $password write-only password
     */
    class User extends ActiveRecord implements IdentityInterface, UserRbacInterface
    {

        /**
         * @var array EAuth attributes
         */

        const STATUS_DELETED = 0;
        const STATUS_ACTIVE = 10;

        public $profile;

        public $old_password;

        public $new_password;

        public $password_reply;

        /**
         * @inheritdoc
         */
        public static function tableName()
        {
            return '{{%user}}';
        }

        /**
         * @inheritdoc
         */
        public function behaviors()
        {
            return [
                TimestampBehavior::className(),
            ];
        }

        /**
         * @inheritdoc
         */
        public function rules()
        {
            return [
                [
                    'status',
                    'default',
                    'value' => self::STATUS_ACTIVE,
                ],
                [
                    'status',
                    'in',
                    'range' => [
                        self::STATUS_ACTIVE,
                        self::STATUS_DELETED,
                    ],
                ],
                [
                    [
                        'username',
                        'lastname',
                        'firstname',
                        'middlename',
                    ],
                    'string',
                    'max' => 255,
                ],
                [
                    [ 'firstname' ],
                    'required',
                ],
                [
                    [ 'type' ],
                    'in',
                    'range' => [
                        1,
                        2,
                    ],
                ],
                [
                    [ 'type' ],
                    'default',
                    'value' => '1',
                ],
                [
                    [
                        'specializationInput',
                        'paymentInput',
                    ],
                    'safe',
                ],
            ];
        }

        /**
         * @inheritdoc
         */
        public static function findIdentity($id)
        {
            if(Yii::$app->getSession()
                        ->has('user-' . $id)
            ) {
                if(Yii::$app->getSession()
                            ->has('user-' . $id)
                ) {
                    return new self(Yii::$app->getSession()
                                             ->get('user-' . $id));
                } else {
                    return isset( self::$users[ $id ] ) ? new self(self::$users[ $id ]) : NULL;
                }
            } else {
                return static::findOne([
                    'id'     => $id,
                    'status' => self::STATUS_ACTIVE,
                ]);
            }

        }

        /**
         * @param \nodge\eauth\ServiceBase $service
         *
         * @return User
         * @throws ErrorException
         */
        public static function findByEAuth($service)
        {
            if(!$service->getIsAuthenticated()) {
                throw new ErrorException('EAuth user should be authenticated before creating identity.');
            }
            $id = $service->getServiceName() . '-' . $service->getId();
            $attributes = [
                'id'       => $id,
                'username' => $service->getAttribute('name'),
                'authKey'  => md5($id),
                'profile'  => $service->getAttributes(),
            ];
            $attributes[ 'profile' ][ 'service' ] = $service->getServiceName();
            Yii::$app->getSession()
                     ->set('user-' . $id, $attributes);
            return new self($attributes);
        }

        public $authKey;

        /**
         * @inheritdoc
         */
        public static function findIdentityByAccessToken($token, $type = NULL)
        {
            throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
        }

        /**
         * 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 boolean
         */
        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();
        }

        /**
         * @inheritdoc
         */
        public function getId()
        {
            return $this->getPrimaryKey();
        }

        /**
         * @inheritdoc
         */
        public function getAuthKey()
        {
            return $this->auth_key;
        }

        /**
         * @inheritdoc
         */
        public function validateAuthKey($authKey)
        {
            return $this->getAuthKey() === $authKey;
        }

        /**
         * Validates password
         *
         * @param string $password password to validate
         *
         * @return boolean if password provided is valid for current user
         */
        public function validatePassword($password)
        {
            return Yii::$app->security->validatePassword($password, $this->password_hash);
        }

        /**
         * Generates password hash from password and sets it to the model
         *
         * @param string $password
         */
        public function setPassword($password)
        {
            $this->password_hash = Yii::$app->security->generatePasswordHash($password);
        }

        /**
         * Generates "remember me" authentication key
         */
        public function generateAuthKey()
        {
            $this->auth_key = Yii::$app->security->generateRandomString();
        }

        /**
         * Generates new password reset token
         */
        public function generatePasswordResetToken()
        {
            $this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
        }

        /**
         * Removes password reset token
         */
        public function removePasswordResetToken()
        {
            $this->password_reset_token = NULL;
        }

        public function getUserName()
        {
            return $this->username;
        }

        public function getRoles()
        {
            $auth = \Yii::$app->authManager;
            $roles = $this->getRoleChildrenRecursive($auth->getRolesByUser($this->id), $auth);
            return $roles;
        }

        protected function getRoleChildrenRecursive($roles, $auth, $result = [ ])
        {
            if(is_array($roles) && !empty( $roles )) {
                foreach($roles as $role => $item) {
                    if(!( $item instanceof \yii\rbac\Role )) {
                        continue;
                    }
                    $result[] = $role;
                    $result = self::getRoleChildrenRecursive($auth->getChildren($role), $auth, $result);
                }
                return $result;
            } else {
                return $result;
            }
        }

        //    public function afterSave ($insert, $changedAttributes)
        //    {
        //        parent::afterSave ($insert, $changedAttributes);
        //        \Yii::$app->options->createOptions($this->id);
        //    }

        public function getUserInfo()
        {
            return $this->hasOne(UserInfo::className(), [ 'user_id' => 'id' ]);
        }

        public function getIsPerformer()
        {
            return true;
        }

        public function getIsCustomer()
        {
            return true;
        }

        public function getPayments()
        {
            return $this->hasMany(Payment::className(), [ 'payment_id' => 'payment_id' ])
                        ->viaTable('user_payment', [ 'user_id' => 'id' ]);
        }

        public function getPaymentInput()
        {
            return $this->getPayments()
                        ->asArray()
                        ->column();
        }

        public function setPaymentInput($value)
        {
            $this->paymentInput = $value;
        }

        public function getSpecializations()
        {
            return $this->hasMany(Specialization::className(), [ 'specialization_id' => 'specialization_id' ])
                        ->viaTable('user_specialization', [ 'user_id' => 'id' ]);
        }

        public function getSpecializationInput()
        {
            return $this->getSpecializations()
                        ->asArray()
                        ->column();
        }

        public function setSpecializationInput($value)
        {
            $this->specializationInput = $value;
        }

    }