Skip to content

Instantly share code, notes, and snippets.

@radzserg
Created June 25, 2020 13:21
Show Gist options
  • Save radzserg/79a2eaeacd247fec2c12128f60b9b4e3 to your computer and use it in GitHub Desktop.
Save radzserg/79a2eaeacd247fec2c12128f60b9b4e3 to your computer and use it in GitHub Desktop.
<?php
// be sure to change BaseUser to inherit from Permitable
Yii::import('application.components.behaviors.ActiveRecordOriginalAttributeValuesBehavior');
Yii::import('application.components.behaviors.VendoriTimestampBehavior');
use vendori\components\clearbit\RequestQueuedException;
use Phpass\Hash as PhpassHash;
use vendori\components\ClearbitSalesReps;
use vendori\emails\RegistrationConfirmation;
use vendori\helpers\EmailAddressHelper;
use vendori\emails\users\PasswordReset;
use vendori\tasks\BackgroundTaskHelper;
use vendori\user\UserDiscoverer;
/**
* Class User
*
* @property string $id
* @property string $work_email
* @property string $image_url
* @property string $password
* @property string $first_name
* @property string $title_id
* @property string $department_id
* @property string $address
* @property integer $timezone_id
* @property integer $role
* @property integer $status
* @property integer $verified_work_email
* @property integer $verified_mobile_phone
* @property string $zip
* @property string $last_name
* @property string $personal_email
* @property string $work_phone
* @property string $mobile_phone
* @property integer $preferred_phone
* @property string $current_company_id
* @property integer $is_sales
* @property integer $plan_id
* @property integer $image_id
* @property string $stripe_id
* @property string $clearbit_user_id
* @property string $profile_filled_at
* @property string $updated_at
* @property string $created_at
* @property integer $parent_id
* @property string $created_by
* @property string $deactivated_at
* @property string $deactivation_message
*
* @property string $name
*
* @property Company[] $companies
* @property CompanyFlag[] $companyFlags
* @property CompanyReview[] $companyReviews
* @property CompanyHasContact[] $companyHasContacts
* @property Document[] $documents
* @property DocumentHasUser[] $fileUsers
* @property ForgotPassword[] $forgotPasswords
* @property ReviewFlag[] $reviewFlags
* @property ReviewHelpful[] $reviewHelpfuls
* @property Company $currentCompany
* @property Plan $plan
* @property UserTitle $title
* @property UserDepartment $department
* @property UserBrand[] $userBrands
* @property UserHasChannel[] $userChannels
* @property Tag[] $channels
* @property Tag[] $tags
* @property Office[] $offices
* @property Region[] $regions
* @property UserSocial[] $userSocials
* @property UserHasTag[] $userSolutions
* @property Tag[] $solutions
* @property User[] $acquaints
* @property UserSalesRep $salesRepInfo
*
* @property UnverifiedUser $unverifiedUser
* @property Brand[] $brands
* @property Collection[] $collectionsPersonal
* @property Collection[] $collectionsCurrentCompany
* @property Collection[] $collections
* @property UserTrial $trialPeriod
* @property BrandIndustry[] $industries
* @property Timezone $timezone
* @property User $parentUser
* @property Image $image
*
* @property UserCurrentCompany $userCurrentCompany
*
* @method syncElastic($attributes = [])
* @method string getImage($attribute, $options = [])
* @method string getImageUrl($attribute, $options = [])
* @method array getChangedAttributes()
* @method array getOldAttributes()
* @method getOldAttribute($key)
*/
class User extends VendoriActiveRecord
{
const ROLE_GUEST = -2;
const ROLE_USER_NOT_VERIFIED = -1;
const ROLE_ADMIN = 1;
const ROLE_USER = 5;
const STATUS_INACTIVE = 0;
const STATUS_ACTIVE = 1;
const STATUS_BLOCKED = 2;
const SCENARIO_VERIFY_EMAIL = 'verifyEmail';
const SCENARIO_FILL_PROFILE = 'fillProfile';
const SCENARIO_EDIT = 'edit';
// user register
const SCENARIO_REGISTER = 'register';
const SCENARIO_CREATE_DISCOVERED_REP = 'create_discovered_rep';
// user register with google mail. We automatically verify him email and assign ROLE_USER
const SCENARIO_REGISTER_WITH_GOOGLE = 'register_with_google';
// user clicks on the link in invitation email. We automatically verify him email and assign ROLE_USER
const SCENARIO_REGISTER_WITH_INVITE = 'register_with_invite';
// another user adds contact info for user
const SCENARIO_INVITE_CONTACT = 'invite_contact';
const SCENARIO_INVITE_CONTACT_BY_SHARE = 'invite_contact_by_share';
const SCENARIO_INVITE_CONTACT_SILENT = 'invite_contact_silent';
const SCENARIO_RESET_PASSWORD = 'reset_pass';
const SCENARIO_ADMIN_EDIT = 'admin_edit';
const SCENARIO_DEACTIVATION = 'deactivation';
const IS_WORK_PHONE_PREFERRED = 0;
const IS_MOBILE_PHONE_PREFERRED = 1;
public $source;
public $userInvite;
/**
* Use separate property to update password
* @var - string
*/
public $new_password;
protected $safeFields = [
'id', 'work_email', 'first_name', 'last_name', 'current_company_id', 'work_phone', 'user_phone', 'status'
];
public function tableName()
{
return 'user';
}
public function rules()
{
return [
['role, status, verified_work_email, verified_mobile_phone, preferred_phone, is_sales, plan_id', 'numerical', 'integerOnly' => true],
['work_email, personal_email', 'length', 'max' => 128],
['personal_email', 'email', 'on' => static::SCENARIO_EDIT],
['image_url', 'length', 'max' => 250],
['password, work_phone, mobile_phone', 'length', 'max' => 64],
['first_name, last_name', 'length', 'max' => 50],
['title_id, department_id', 'length', 'max' => 11],
['zip, current_company_id', 'length', 'max' => 10],
['parent_id', 'safe', 'on' => static::SCENARIO_INVITE_CONTACT],
['address', 'safe'],
['work_email, image_url, password, first_name, title_id, department_id, address, timezone_id, role, status,
verified_work_email, verified_mobile_phone, zip, last_name, personal_email, work_phone, mobile_phone,
preferred_phone, current_company_id, is_sales, plan_id',
'default', 'setOnEmpty' => true, 'value' => null
],
['id, work_email, image_url, password, first_name, title_id, department_id, address, timezone_id, role,
status, verified_work_email, verified_mobile_phone, zip, last_name, personal_email, work_phone,
mobile_phone, preferred_phone, current_company_id, is_sales, plan_id, image_id, stripe_id, status,
clearbit_user_id, profile_filled_at, updated_at, created_at, parent_id, created_by, deactivated_at,
deactivation_message', 'safe', 'on' => 'search'
],
['work_email', 'required'],
['work_email', 'email'],
['work_email', 'unsafe', 'on' => static::SCENARIO_EDIT],
['work_email', 'notBlacklistDomain'],
['work_email', 'unique', 'message' => '{attribute} "{value}" previously registered. If you forgot your password, '
. CHtml::link('click here', ['/site/forgot']) . '.', 'on' => static::SCENARIO_REGISTER, 'criteria' => [
'condition' => 'status <> :status',
'params' => [
':status' => static::STATUS_INACTIVE
]
]
],
['work_email', 'unique', 'except' => [static::SCENARIO_INVITE_CONTACT, static::SCENARIO_INVITE_CONTACT_SILENT, static::SCENARIO_REGISTER]],
['work_email', 'unique', 'on' => [static::SCENARIO_INVITE_CONTACT, static::SCENARIO_INVITE_CONTACT_SILENT], 'message' => 'This user is already a member of MRKTNG'],
['status', 'default', 'value' => static::STATUS_ACTIVE],
['status', 'unsafe', 'except' => [static::SCENARIO_DEACTIVATION, 'search']],
['deactivation_message', 'unsafe', 'except' => [static::SCENARIO_ADMIN_EDIT, static::SCENARIO_DEACTIVATION]],
['deactivated_at', 'unsafe', 'except' => [static::SCENARIO_ADMIN_EDIT]],
['new_password', 'passwordNotEmpty', 'on' => [
static::SCENARIO_FILL_PROFILE,
static::SCENARIO_RESET_PASSWORD,
static::SCENARIO_REGISTER
]],
['is_sales', 'required', 'on' => static::SCENARIO_FILL_PROFILE],
['clearbit_user_id', 'safe', 'on' => static::SCENARIO_REGISTER_WITH_INVITE],
['verified_work_email', 'safe', 'on' => static::SCENARIO_VERIFY_EMAIL],
['personal_email', 'unique'],
['personal_email', 'compare', 'compareAttribute' => 'work_email', 'operator' => '!=', 'allowEmpty' => true,
'message' => '{attribute} is previously registered as Work Email.'],
['first_name', 'required', 'on' => static::SCENARIO_EDIT],
['image_id', 'file', 'types' => 'jpg, png, jpeg, png, gif', 'allowEmpty' => true, 'safe' => false],
['title_id, department_id', 'numerical', 'integerOnly' => true, 'min' => 1],
['department_id', 'exist', 'className' => 'UserDepartment', 'attributeName' => 'id'],
['profile_filled_at', 'required', 'on' => static::SCENARIO_FILL_PROFILE],
['timezone_id', 'required', 'on' => static::SCENARIO_FILL_PROFILE],
['timezone_id', 'required', 'on' => static::SCENARIO_EDIT],
['created_by', 'numerical', 'integerOnly' => true, 'on' => [
static::SCENARIO_INVITE_CONTACT_BY_SHARE,
static::SCENARIO_INVITE_CONTACT,
static::SCENARIO_INVITE_CONTACT_SILENT
]
]
];
}
public function relations()
{
return [
'companyFlags' => [self::HAS_MANY, 'CompanyFlag', 'user_id'],
'companyReviews' => [self::HAS_MANY, 'CompanyReview', 'user_id'],
'companyHasContacts' => array(self::HAS_MANY, 'CompanyHasContact', 'user_id'),
'documents' => [self::HAS_MANY, 'Document', 'user_id'],
'forgotPasswords' => [self::HAS_MANY, 'ForgotPassword', 'user_id'],
'notes' => [self::HAS_MANY, 'Note', 'user_id'],
'reviewFlags' => [self::HAS_MANY, 'ReviewFlag', 'user_id'],
'currentCompany' => [self::BELONGS_TO, 'Company', 'current_company_id'],
'plan' => [self::BELONGS_TO, 'Plan', 'plan_id'],
'salesRepInfo' => [self::HAS_ONE, 'UserSalesRep', 'user_id'],
'userCurrentCompany' => [self::HAS_ONE, 'UserCurrentCompany', 'user_id'],
'title' => [self::BELONGS_TO, 'UserTitle', 'title_id'],
'department' => [self::BELONGS_TO, 'UserDepartment', 'department_id'],
'offices' => [self::MANY_MANY, 'Office', 'user_office(user_id, office_id)'],
'acquaints' => [self::HAS_MANY, 'User', 'user_people(owner_id, acquaint_id)'],
'regions' => [self::MANY_MANY, 'Region', 'user_region(user_id,region_id)'],
'userSocials' => [self::HAS_MANY, 'UserSocial', 'user_id'],
'userWorkExperiences' => [self::HAS_MANY, 'UserWorkExperience', 'user_id'],
'brands' => [self::MANY_MANY, 'Brand', 'user_brand(user_id, brand_id)'],
'channels' => [self::MANY_MANY, 'Tag', 'user_has_tag(user_id, tag_id)', 'condition' => 'type = :type', 'params' => [':type' => Tag::TYPE_CHANNEL]],
'reviewHelpful' => [self::HAS_ONE, 'ReviewHelpful', 'user_id'],
'solutions' => [self::MANY_MANY, 'Tag', 'user_has_tag(user_id, tag_id)', 'condition' => 'type = :type', 'params' => [':type' => Tag::TYPE_SOLUTION]],
'parentUser' => [self::BELONGS_TO, 'User', 'parent_id'],
'unverifiedUser' => [self::HAS_ONE, 'UnverifiedUser', 'user_id'],
'tags' => [self::MANY_MANY, 'Tag', 'user_has_tag(user_id, tag_id)'],
'casestudies' => [self::HAS_MANY, 'Casestudy', 'company_id'],
'decks' => [self::HAS_MANY, 'Deck', 'company_id'],
'videos' => [self::HAS_MANY, 'Video', 'company_id'],
'whitepapers' => [self::HAS_MANY, 'Whitepaper', 'company_id'],
'trialPeriod' => [self::HAS_ONE, 'UserTrial', 'user_id'],
'timezone' => [self::BELONGS_TO, 'Timezone', 'timezone_id'],
'image' => [self::BELONGS_TO, 'Image', 'image_id'],
];
}
public function behaviors()
{
return CMap::mergeArray(parent::behaviors(), [
'ActiveRecordOriginalAttributeValuesBehavior' => 'ActiveRecordOriginalAttributeValuesBehavior',
'hasElasticIndex' => [
'class' => '\vendori\behaviors\HasElasticIndexBehavior',
],
'VTimestampBehavior' => [
'class' => 'VendoriTimestampBehavior',
'createAttribute' => 'created_at',
'updateAttribute' => 'updated_at',
'setUpdateOnCreate' => true,
],
'hasImage' => [
'class' => '\vendori\behaviors\HasImageBehavior',
'attributes' => [
'image_id' => [
'basePath' => 'user',
'defaultImage' => 'images/defaults/svg/user.svg',
'defaultPngImage' => 'images/defaults/user.png',
]
]
],
'changedAttributes' => [
'class' => '\vendori\behaviors\ChangedAttributesBehavior',
],
]);
}
public function pivotModels()
{
return [
'companyReviews' => 'ReviewHelpful',
'brands' => 'UserBrand',
'channels' => 'UserHasTag',
'solutions' => 'UserHasTag',
];
}
/**
* Return role labels
* @param string
* @return array
*/
public static function getRoleLabels($key = null)
{
$labels = [
// static::ROLE_GUEST => 'Guest',
static::ROLE_USER_NOT_VERIFIED => 'Guest',
static::ROLE_ADMIN => 'Admin',
static::ROLE_USER => 'User',
];
if (is_null($key)) {
return $labels;
} else {
return isset($labels[$key]) ? $labels[$key] : null;
}
}
public static function getStatusLabels($key = null)
{
$statuses = [
self::STATUS_INACTIVE => 'Inactive',
self::STATUS_ACTIVE => 'Active',
self::STATUS_BLOCKED => 'Blocked'
];
if (is_null($key)) {
return $statuses;
} else {
return isset($statuses[$key]) ? $statuses[$key] : null;
}
}
/**
* Block user
* @param null $deactivationMessage
*/
public function deactivate($deactivationMessage = null)
{
$this->scenario = static::SCENARIO_DEACTIVATION;
$this->status = static::STATUS_INACTIVE;
$this->deactivation_message = $deactivationMessage;
$this->deactivated_at = date('Y-m-d H:i:s');
$this->save(false);
}
/**
* Block user
* @param null $deactivationMessage
* @throws CDbException
*/
public function block($deactivationMessage = null)
{
$this->scenario = static::SCENARIO_DEACTIVATION;
$this->status = static::STATUS_BLOCKED;
$this->deactivation_message = $deactivationMessage;
$this->deactivated_at = date('Y-m-d H:i:s');
// Remove all user data when user is blocked
UserBrand::model()->deleteAllByAttributes(['user_id' => $this->id]);
UserSalesRep::model()->deleteAllByAttributes(['user_id' => $this->id]);
UserHasTag::model()->deleteAllByAttributes(['user_id' => $this->id]);
DocumentHasUser::model()->deleteAllByAttributes(['user_id' => $this->id]);
DocumentLog::model()->deleteAllByAttributes(['user_id' => $this->id]);
Comment::model()->deleteAllByAttributes(['user_id' => $this->id]);
CommentMention::model()->deleteAllByAttributes(['user_id' => $this->id]);
CollectionEntry::model()->deleteAllByAttributes(['content_type' => CollectionEntry::CONTENT_TYPE_USER, 'content_id' => $this->id]);
$documents = Document::model()->findAllByAttributes(['user_id' => $this->id]);
foreach ($documents as $document) {
$document->deactivate("Deactivated after author block");
}
$collections = Collection::model()->findAllByAttributes(['user_id' => $this->id]);
foreach ($collections as $collection) {
$collection->delete();
}
$this->save(false);
}
/**
* Check is user active
* @access public
* @return bool
*/
public function isActive()
{
return $this->status == self::STATUS_ACTIVE;
}
/**
* @inheritdoc
*/
protected function beforeDelete()
{
throw new Exception("User deletion is not allowed. Inactivate user instead");
}
/**
* @inheritdoc
*/
protected function beforeValidate()
{
if (!empty($this->new_password)) {
$this->password = static::encryptPassword($this->new_password);
}
return parent::beforeValidate();
}
/**
* @inheritdoc
*/
protected function afterSave()
{
if ($this->isNewRecord || !$this->isVerified()) {
if (in_array($this->scenario, [
static::SCENARIO_REGISTER,
static::SCENARIO_CREATE_DISCOVERED_REP,
static::SCENARIO_INVITE_CONTACT,
static::SCENARIO_INVITE_CONTACT_SILENT,
static::SCENARIO_INVITE_CONTACT_BY_SHARE
])) {
$this->sendVerificationEmail();
}
}
if ($this->isNewRecord) {
$this->isNewRecord = false;
BackgroundTaskHelper::addTask(BackgroundTaskHelper::DISCOVER_USER, ['user_id' => $this->id]);
}
if ($this->current_company_id) {
UserCurrentCompany::setUserCompany($this->id, $this->current_company_id);
$emailDomain = CompanyEmailDomain::getDomainFromEmail($this->work_email);
if (!CompanyEmailDomain::isVerifiedDomain($emailDomain, $this->current_company_id)) {
$this->current_company_id = null;
$this->save(false);
}
}
parent::afterSave();
}
/**
* @inheritdoc
*/
protected function beforeSave()
{
if ($this->isNewRecord) {
if (in_array($this->scenario, [static::SCENARIO_REGISTER_WITH_GOOGLE, static::SCENARIO_REGISTER_WITH_INVITE])) {
$this->role = User::ROLE_USER;
$this->verified_work_email = true;
}
if (!$this->timezone_id && $this->role !== self::ROLE_ADMIN) {
//$ip = Yii::app()->request->getUserHostAddress();
//$this->timezone_id = Timezone::getByIp($ip);
}
} else { //existing ActiveRecord
$changedAttributes = $this->getChangedAttributes();
if (!empty($changedAttributes['mobile_phone'])) {
$this->verified_mobile_phone = PhoneVerification::isNumberVerified($this, $this->mobile_phone);
}
if (!empty($changedAttributes['work_email'])) {
$this->verified_work_email = null;
}
}
return parent::beforeSave();
}
protected function extraFields($field)
{
if (preg_match('~avatar_(\d+)_(\d+)~', $field, $m)) {
$width = $m[1];
$height = $m[2];
return $this->getImage('image_id', ['width' => $width, 'height' => $height]);
}
$currentUser = Yii::app()->user->getModel();
switch ($field) {
case 'display_name': // @deprecated use "name" instead
case 'name':
return $this->getDisplayName();
case 'title_name' :
return $this->title ? $this->title->name : null;
case 'department_name' :
return $this->department ? $this->department->name : null;
case 'company_name':
return $this->currentCompany ? $this->currentCompany->name : null;
case 'company':
return $this->currentCompany ? $this->currentCompany->toArray() : null;
case 'md5_email':
return md5($this->work_email);
case 'office_city_name' :
$office = $this->getCurrentOffice();
return $office && $office->city ? $office->city->name : null;
case 'contact_type':
return CompanyHasContact::getContactType($currentUser->current_company_id, $this->id);
case 'partner_type':
return CompanyHasPartner::getPartnerType($currentUser->current_company_id, $this->current_company_id);
case 'is_coworker':
return $this->current_company_id == $currentUser->current_company_id;
}
return null;
}
/**
* Return display name for user
* @access public
* @param bool $prepareEmail
* @return string
*/
public function getDisplayName($prepareEmail = true)
{
$name = trim("{$this->first_name} {$this->last_name}");
if (empty($name)) {
$name = $prepareEmail ? User::guestNameByEmail($this->work_email) : $this->work_email;
}
return $name;
}
/**
* Return user name
* @deprecated - use getDisplayName
* @return string
*/
public function getName()
{
$name = $this->getDisplayName() ? $this->getDisplayName() :
($this->work_email ? $this->work_email : '');
return $name;
}
public function passwordNotEmpty($attribute)
{
$googleSocial = $this->getSocialConnection('google');
if (empty($this->password) && empty($googleSocial)) {
$this->addError($attribute, ApplicationMessage::getMessage(ApplicationMessageCode::PASSWORD_CAN_NOT_BE_EMPTY));
}
}
public function notBlacklistDomain()
{
$domain = EmailAddressHelper::getEmailDomain($this->work_email);
if (!$domain || BlacklistDomain::isInList($domain)) {
$this->addError('work_email', ApplicationMessage::getMessage(ApplicationMessageCode::INCORRECT_OR_BLACKLISTED_WORK_EMAIL));
}
}
public function sendVerificationEmail()
{
$this->userInvite = new UnverifiedUser();
$this->userInvite->createInvite($this);
}
protected function generateVerificationCode($emailAttributeName)
{
$verificationArray = [
'id' => $this->id,
'attributeName' => $emailAttributeName,
'email' => $this->$emailAttributeName,
'verifiedAttributeName' => 'verified_' . $emailAttributeName,
'random' => Util::getUniqueStr(),
];
$jsonEncodedVerificationArray = CJSON::encode($verificationArray);
$encryptedVerificationCode = Util::hashString($jsonEncodedVerificationArray);
return $encryptedVerificationCode;
}
/**
* Set current company for user
* @param $currentCompanyId
*/
public function setCurrentCompany($currentCompanyId)
{
$this->current_company_id = $currentCompanyId;
$this->save();
}
/**
* Check user password
* @param $password
* @return bool
*/
public function checkPassword($password)
{
if (!$this->password) {
return false;
}
$phpassHashObject = new PhpassHash();
$databaseHash = $this->password;
return $phpassHashObject->checkPassword($password, $databaseHash);
}
public static function encryptPassword($password)
{
$phpassHashObject = new PhpassHash();
$passwordHash = $phpassHashObject->hashPassword($password);
return $passwordHash;
}
/**
* Set user brands
* @param $brandNames
*/
public function setBrands($brandNames)
{
UserBrand::model()->deleteAllByAttributes(['user_id' => $this->id]);
foreach ($brandNames as $name) {
$userBrand = null;
$brand = Brand::findByNameOrCreateByNameAndIsPublic($name, true);
if ($brand) {
$userBrand = new UserBrand();
$userBrand->user_id = $this->id;
$userBrand->brand_id = $brand->id;
$userBrand->is_verified = 0;
$userBrand->save();
}
}
}
/**
* Set user relationships with tags
* @param $tagIds
* @throws Exception
*/
public function setTagsByIds($tagIds)
{
UserHasTag::setByIds(['user_id' => $this->id], $tagIds);
$this->syncElastic(['tags']);
}
/**
* Set relationships with tags
* @param $tags
* @throws Exception
*/
public function setTags($tags)
{
UserHasTag::setByType(['user_id' => $this->id], $tags);
$this->syncElastic(['tags']);
}
/**
* Verify user email
*/
public function verifyEmail()
{
$this->setScenario(User::SCENARIO_VERIFY_EMAIL);
$this->verified_work_email = 1;
if ($this->role == User::ROLE_USER_NOT_VERIFIED) {
$this->role = User::ROLE_USER;
}
return $this->save(true, ['verified_work_email', 'role']);
}
/**
* Set user department
* @param $name
* @return bool
* @throws Exception
*/
public function setDepartment($name)
{
$department = UserDepartment::findByName($name);
if (!$department) {
$department = new UserDepartment();
$department->name = $name;
$department->save();
}
$this->department_id = $department->id;
return $this->save();
}
/**
* Set user job title, i.e. SEO, WPP, Manager etc
* @param $name
* @return bool
* @throws Exception
*/
public function setTitle($name)
{
$title = UserTitle::findByName($name);
if (!$title) {
$title = new UserTitle();
$title->name = $name;
$title->save();
}
$this->title_id = $title->id;
return $this->save(false);
}
/**
* Return title name
* @return null|string
*/
public function getTitleName()
{
return $this->title ? $this->title->name : null;
}
public function forgotPassword()
{
$forgotPassword = ForgotPassword::model()->findByAttributes(['user_id' => $this->id]);
if (!$forgotPassword) {
$forgotPassword = new ForgotPassword();
$forgotPassword->user_id = $this->id;
}
$forgotPassword->code = $this->generateVerificationCode('work_email');
if ($forgotPassword->save()) {
$email = new PasswordReset([
'to' => $this,
'code' => $forgotPassword->code
]);
return $email->send();
} else {
throw new CHttpException(405, "Cannot sent reset password request");
}
}
public function changePassword($password)
{
if (!$password) {
throw new Exception('Password can not be empty');
}
$this->scenario = self::SCENARIO_RESET_PASSWORD;
$this->password = static::encryptPassword($password);
return $this->save();
}
public function setVerified()
{
if ($this->role == User::ROLE_USER_NOT_VERIFIED) {
$this->role = User::ROLE_USER;
return $this->save();
} else {
$this->addError('role', ApplicationMessage::getMessage(ApplicationMessageCode::USER_IS_ALREADY_VERIFIED));
return false;
}
}
public function getSocialConnection($serviceName)
{
return UserSocial::model()->findByAttributes(["user_id" => $this->id, "oauth_provider" => $serviceName]);
}
public function getEmailDomain()
{
return EmailAddressHelper::getEmailDomain($this->work_email);
}
public function setOffice($officeId)
{
UserOffice::model()->deleteAllByAttributes(['user_id' => $this->id]);
$userOffice = new UserOffice();
$userOffice->user_id = $this->id;
$userOffice->office_id = $officeId;
$userOffice->save();
}
/**
* Return current user office
* @return Office
*/
public function getCurrentOffice()
{
$userOffice = UserOffice::model()->findByAttributes(['user_id' => $this->id]);
$office = null;
if ($userOffice) {
$office = Office::model()->findByPk($userOffice->office_id);
}
return $office;
}
/**
* Return current user office
* @return integer
*/
public function getCurrentOfficeId()
{
$userOffice = UserOffice::model()->findByAttributes(['user_id' => $this->id]);
return CHtml::value($userOffice, 'office_id');
}
/**
* Find user by primary email
* @param $email
* @return User
*/
public static function findByEmail($email)
{
return static::model()->findByAttributes(['work_email' => $email]);
}
public function attributeLabels()
{
return [
'id' => Yii::t('app', 'ID'),
'work_email' => Yii::t('app', 'Work Email'),
'image_id' => Yii::t('app', 'Image'),
'image_url' => Yii::t('app', 'Image Url'),
'password' => Yii::t('app', 'Password'),
'first_name' => Yii::t('app', 'First Name'),
'title_id' => null,
'department_id' => null,
'address' => Yii::t('app', 'Address'),
'timezone_id' => Yii::t('app', 'Timezone'),
'role' => Yii::t('app', 'Role'),
'status' => Yii::t('app', 'Status'),
'verified_work_email' => Yii::t('app', 'Verified Work Email'),
'zip' => Yii::t('app', 'Zip'),
'last_name' => Yii::t('app', 'Last Name'),
'personal_email' => Yii::t('app', 'Personal Email'),
'work_phone' => Yii::t('app', 'Work Phone'),
'mobile_phone' => Yii::t('app', 'Mobile Phone'),
'preferred_phone' => Yii::t('app', 'Preferred Phone'),
'current_company_id' => null,
'is_sales' => Yii::t('app', 'Is Sales'),
'plan_id' => null,
'companies' => null,
'companyFlags' => null,
'companyReviews' => null,
'documents' => null,
'fileUsers' => null,
'forgotPasswords' => null,
'notes' => null,
'reviewFlags' => null,
'reviewHelpfuls' => null,
'currentCompany' => null,
'plan' => null,
'title' => 'Title',
'department' => null,
'userBrands' => null,
'userChannels' => null,
'userInfo' => null,
'offices' => null,
'userRegions' => null,
'userSocials' => null,
'userSolutions' => null,
'userWorkExperiences' => null,
];
}
public function search()
{
$criteria = new CDbCriteria;
$criteria->compare('id', $this->id);
$criteria->compare('work_email', $this->work_email, true);
$criteria->compare('image_id', $this->image_id);
$criteria->compare('image_url', $this->image_url, true);
$criteria->compare('password', $this->password, true);
$criteria->compare('first_name', $this->first_name, true);
$criteria->compare('title_id', $this->title_id);
$criteria->compare('department_id', $this->department_id);
$criteria->compare('address', $this->address, true);
$criteria->compare('timezone_id', $this->timezone_id);
$criteria->compare('role', $this->role);
$criteria->compare('status', $this->status);
$criteria->compare('verified_work_email', $this->verified_work_email);
$criteria->compare('zip', $this->zip, true);
$criteria->compare('last_name', $this->last_name, true);
$criteria->compare('personal_email', $this->personal_email, true);
$criteria->compare('work_phone', $this->work_phone, true);
$criteria->compare('mobile_phone', $this->mobile_phone, true);
$criteria->compare('preferred_phone', $this->preferred_phone);
$criteria->compare('current_company_id', $this->current_company_id);
$criteria->compare('is_sales', $this->is_sales);
$criteria->compare('plan_id', $this->plan_id);
if (isset($this->profile_filled_at) && $this->profile_filled_at !== "") {
if ($this->profile_filled_at == 1) {
$criteria->addCondition('profile_filled_at IS NOT NULL');
} else {
$criteria->addCondition('profile_filled_at IS NULL');
}
}
return new CActiveDataProvider($this, [
'criteria' => $criteria,
'sort' => [
'defaultOrder' => 't.id DESC'
],
'pagination' => [
'pageSize' => Yii::app()->params['rows_per_page_on_grid'],
]
]);
}
/**
* @return Collection[]
*/
public function getCollections()
{
$model = new Collection();
$model->user_id = $this->id;
$model->company_id = $this->current_company_id;
$dp = $model->search();
$dp->setPagination(false);
$dp->setSort(false);
$dp->getCriteria()->mergeWith(['index' => 'id']);
return $dp->getData();
}
/**
* Return sales rep
* @param $id
* @return static
*/
public static function findSalesRep($id)
{
return User::model()->findByAttributes([
'id' => $id,
'is_sales' => 1,
'status' => User::STATUS_ACTIVE
]);
}
/**
* Check if payment info for user is set
* @return bool
*/
public function hasPaymentInfo()
{
return $this->stripe_id ? true : false;
}
/**
* Check is profile filled
* @return bool
*/
public function isProfileFilled()
{
return !empty($this->current_company_id);
}
public function isTrialActive()
{
if (!$this->trialPeriod) {
return false;
}
return strtotime($this->trialPeriod->end_date) < time();
}
public function setRegions(array $regionShortNames)
{
if (empty($regionShortNames)) {
return;
}
UserRegion::model()->deleteAllByAttributes(['user_id' => $this->id]);
foreach ($regionShortNames as $regionName) {
$regionName = strtoupper(trim($regionName));
if ($region = Region::model()->findByAttributes(['short_name' => $regionName])) {
$userRegion = new UserRegion();
$userRegion->user_id = $this->id;
$userRegion->region_id = $region->id;
if (!$userRegion->save()) {
Yii::log("UserRegion saving failed: " . print_r($userRegion->errors, true), CLogger::LEVEL_ERROR);
};
}
}
}
/**
* @return array
*/
public function getAssignedRegionsShortNames()
{
$regionShortNames = [];
foreach ($this->regions as $region) {
$regionShortNames[] = $region->short_name;
}
return $regionShortNames;
}
/**
* @param $regionShortName
* @return bool
*/
public function hasAssignedRegion($regionShortName)
{
if (!$regionShortName) {
return false;
}
return in_array($regionShortName, $this->getAssignedRegionsShortNames());
}
public function getOfficeRegionShortName()
{
$office = $this->getCurrentOffice();
if (!$office || !$office->state || !$office->state->region) {
return null;
}
return $office->state->region->short_name;
}
/**
* Checks if user are in $this user area
* @param User|null $user
* @return bool
*/
public function isUserInRepArea(User $user = null)
{
if (!$user) {
return false;
}
if (!$this->hasAssignedRegion($user->getOfficeRegionShortName())) {
return false;
}
return true;
}
/**
* Format time to user timezone
* @param $timestamp
* @param string $format
* @return string
*/
public function formatLocalTime($timestamp, $format = 'F j, Y, g:i a')
{
$timezone = $this->timezone ? $this->timezone->name : Timezone::DEFAULT_TIMEZONE;
$date = new DateTime();
$date->setTimestamp($timestamp);
$date->setTimezone(new DateTimeZone($timezone));
return $date->format($format);
}
/**
* Transform local time to unix timestamp
* @param $localTime
* @return int
*/
public function localTimeToTimestamp($localTime)
{
$timezone = $this->timezone ? $this->timezone->name : Timezone::DEFAULT_TIMEZONE;
$date = new DateTime($localTime, new DateTimeZone($timezone));
return $date->getTimestamp();
}
/**
* Save mobile phone
* @param $phone
* @return bool
*/
public function saveMobilePhone($phone)
{
$this->mobile_phone = $phone;
$this->verified_mobile_phone = 1;
if (!$this->save(true, ['mobile_phone', 'verified_mobile_phone'])) {
Yii::log('Unable to save User, details: ' . print_r($this->getErrors(), true), CLogger::LEVEL_ERROR);
return false;
}
return true;
}
/**
* Check if user save CC details
* @return bool
*/
public function isCreditCardSet()
{
if (!$this->stripe_id) {
return false;
}
return Yii::app()->stripe->hasCard($this->stripe_id);
}
public function getBalance()
{
if (!$this->stripe_id) {
return false;
}
return Yii::app()->stripe->getBalance($this->stripe_id);
}
/**
* Get tagged docs
* @access public
* @param User $user
* @param string $type - document type [Document::TYPE_SIMPLE_DOCUMENT, Document::TYPE_VIDEO, Document::TYPE_PRESENTATION]
* @return int
*/
public function countTaggedDocs($user, $type = null)
{
return Yii::app()->elastic->searchDocuments($user, [
'tagged_user_id' => $this->id,
'document_type' => $type,
'pageSize' => 0
], [])['total'];
}
/**
* Get referring company
* @access public
* @return mixed
*/
public function getReferringCompany()
{
$unverifiedUser = UnverifiedUser::model()->with(['createdBy'])->findByAttributes([
'user_id' => $this->id
]);
if (!$unverifiedUser || !$unverifiedUser->createdBy) {
return null;
}
return $this->current_company_id != $unverifiedUser->createdBy->current_company_id ?
$unverifiedUser->createdBy->currentCompany : null;
}
/**
* Generate guest name by email
* @todo - remove Yii::app()->user to higher level
* @access public
* @param string $email
* @return string
*/
public static function guestNameByEmail($email)
{
if (Yii::app() instanceof CWebApplication && YII_ENV != 'test' && Yii::app()->user->isGuest) {
return 'Guest at ' . explode('@', $email)[1];
} else {
return $email;
}
}
/**
* User invites his co-worker
* @param User $invitingUser
* @param $data
* @return bool
*/
public function inviteCoworker(User $invitingUser, $data)
{
$this->setScenario(User::SCENARIO_INVITE_CONTACT);
$this->role = User::ROLE_USER_NOT_VERIFIED;
$this->attributes = $data;
$this->created_by = $invitingUser->id;
$this->current_company_id = $invitingUser->current_company_id;
if (!CompanyEmailDomain::getCompanyIdForEmail($this->work_email)) {
$emailDomain = CompanyEmailDomain::getDomainFromEmail($this->work_email);
CompanyEmailDomain::addDomain($this->currentCompany, $emailDomain, $invitingUser->current_company_id, false);
}
return $this->optimisticSave();
}
/**
* Create user if it exists in clearbit data
* @param $companyId
* @param $email
* @param $requestedUserId
* @return bool
*/
public function createFromClearbit($companyId, $email, $requestedUserId = null)
{
$clearbitData = ClearbitSalesReps::getEmployeeInfo($email);
if (!$clearbitData) {
$this->addError('error', "Cannot get info from clearbit");
return false;
}
$this->setScenario(User::SCENARIO_CREATE_DISCOVERED_REP);
$this->work_email = $email;
$this->current_company_id = $companyId;
$this->is_sales = 1;
$this->status = User::STATUS_ACTIVE;
$this->role = User::ROLE_USER_NOT_VERIFIED;
$this->created_by = $requestedUserId;
return $this->optimisticSave();
}
/**
* Check if user is verified or not
* @return bool
*/
public function isVerified()
{
return $this->verified_work_email != 0 ||
$this->role != User::ROLE_USER_NOT_VERIFIED ||
($this->unverifiedUser && !empty($this->unverifiedUser->activated_at)) ? true : false;
}
/**
* Get available statuses
* @access public
* @return array
*/
public static function getActiveStatuses()
{
return [
0 => 'Guest',
1 => 'Active',
2 => 'Inactive'
];
}
/**
* Get current user status
* @access public
* @return int
*/
public function getActiveStatus()
{
if (self::STATUS_ACTIVE == $this->status) {
// Guest
if (!$this->isVerified()) {
return 0;
}
// Active - default
return 1;
}
return 2;
}
/**
* Automatically sign up user when someone share document with this user
* @param $email
* @param $name
* @param User $invitedUser
* @param $contactType
* @return bool
*/
public function signUpViaDocumentShare($email, $name, User $invitedUser, $contactType)
{
$this->setScenario(User::SCENARIO_INVITE_CONTACT_BY_SHARE);
$this->work_email = $email;
$this->first_name = $name;
$this->created_by = $invitedUser->id;
$this->role = User::ROLE_USER_NOT_VERIFIED;
$this->current_company_id = CompanyEmailDomain::getCompanyIdForEmail($this->work_email);
$this->is_sales = CompanyHasContact::TYPE_SALES == $contactType ? 1 : 0;
return $this->optimisticSave();
}
/**
* Get current company from different sources
* @return Company|null
*/
public function getCurrentCompany()
{
$company = null;
if ($this->current_company_id) {
$company = $this->currentCompany;
} else {
$company = UserCurrentCompany::getUserCompany($this->id);
}
return $company;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment