Created
June 25, 2020 13:21
-
-
Save radzserg/79a2eaeacd247fec2c12128f60b9b4e3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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