1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
36:
37:
38:
39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49:
50: class User extends CActiveRecord {
51:
52: const STATUS_ACTIVE = 1;
53: const STATUS_INACTIVE = 0;
54:
55: public static $recentItemTypes = array(
56: 'a' => 'Accounts',
57: 'b' => 'BugReports',
58: 'c' => 'Contacts',
59: 'd' => 'Docs',
60:
61: 'g' => 'Groups',
62: 'l' => 'X2Leads',
63: 'm' => 'Media',
64: 'o' => 'Opportunity',
65: 'p' => 'Campaign',
66: 'q' => 'Quote',
67: 'r' => 'Product',
68: 's' => 'Services',
69: 't' => 'Actions',
70:
71: 'w' => 'Workflow',
72: );
73:
74: 75: 76: 77:
78: private $_fullName;
79:
80: 81: 82: 83:
84: public $dbPersistentGridSettings = false;
85:
86: 87: 88: 89:
90: public static function model($className = __CLASS__){
91: return parent::model($className);
92: }
93:
94: 95: 96:
97: public function tableName(){
98: return 'x2_users';
99: }
100:
101: public function behaviors(){
102: $viewRoute = '/profile';
103: if (!Yii::app()->params->isMobileApp) {
104: $viewRoute = '/profile/view';
105: }
106: return array_merge(parent::behaviors(), array(
107: 'X2LinkableBehavior' => array(
108: 'class' => 'X2LinkableBehavior',
109: 'module' => 'users',
110: 'viewRoute' => $viewRoute,
111: ),
112: 'ERememberFiltersBehavior' => array(
113: 'class' => 'application.components.ERememberFiltersBehavior',
114: 'defaults' => array(),
115: 'defaultStickOnClear' => false
116: )
117: ));
118: }
119:
120: 121: 122:
123: public function beforeValidate () {
124: if ($this->scenario === 'insert') {
125: if ($this->userAlias === null)
126: $this->userAlias = $this->username;
127: }
128: return parent::beforeValidate ();
129: }
130:
131: 132: 133:
134: public function rules(){
135:
136:
137: $userRules = array(
138: array('status', 'required'),
139: array('password', 'required', 'on' => 'insert'),
140: array('firstName, lastName, username', 'required', 'except' => 'invite'),
141: array('userAlias', 'required', 'except' => 'invite'),
142: array('status, lastLogin, login', 'numerical', 'integerOnly' => true),
143: array('firstName, username, userAlias, title, updatedBy', 'length', 'max' => 20),
144: array('lastName, department, officePhone, cellPhone, homePhone', 'length', 'max' => 40),
145: array('password, address, emailAddress, recentItems, topContacts', 'length', 'max' => 100),
146: array('lastUpdated', 'length', 'max' => 30),
147: array('userKey', 'length', 'max' => 32, 'min' => 3),
148: array('backgroundInfo', 'safe'),
149: array('status', 'validateUserDisable'),
150: array('username','in','not'=>true,'range'=>array('Guest','Anyone',Profile::GUEST_PROFILE_USERNAME),'message'=>Yii::t('users','The specified username is reserved for system usage.')),
151: array('username', 'unique', 'allowEmpty' => false),
152: array('userAlias', 'unique', 'allowEmpty' => false),
153: array('userAlias', 'match', 'pattern' => '/^\s+$/', 'not' => true),
154: array(
155: 'userAlias',
156: 'match',
157: 'pattern' => '/^((\s+\S+\s+)|(\s+\S+)|(\S+\s+))$/',
158: 'not' => true,
159: 'message' => Yii::t(
160: 'users', 'Username cannot contain trailing or leading whitespace.'),
161: ),
162: array('username,userAlias','userAliasUnique'),
163: array('username', 'match', 'pattern' => '/^\d+$/', 'not' => true),
164: array('username','match','pattern'=>'/^\w+$/'),
165:
166:
167: array('id, firstName, lastName, username, password, title, department, officePhone, cellPhone, homePhone, address, backgroundInfo, emailAddress, status, lastUpdated, updatedBy, recentItems, topContacts, lastLogin, login', 'safe', 'on' => 'search'),
168: );
169:
170: return $userRules;
171: }
172:
173: 174: 175:
176: public function relations(){
177:
178:
179: return array(
180: 'profile' => array(self::HAS_ONE, 'Profile', 'id'),
181: );
182: }
183:
184: public function scopes () {
185: return array (
186: 'active' => array (
187: 'condition' => 'status=1',
188: 'order' => 'lastName ASC',
189: ),
190: );
191: }
192:
193:
194: 195: 196:
197: public function beforeDelete () {
198: $adminUser = User::model()->findByPk(1);
199: if (!$adminUser) {
200: throw new CException (Yii::t('app', 'admin user could not be found'));
201: }
202:
203: $params = array (
204: ':username' => $this->username,
205: ':adminUsername' => $adminUser->username
206: );
207:
208:
209: Yii::app()->db->createCommand("
210: UPDATE x2_actions
211: SET updatedBy=:adminUsername
212: WHERE assignedTo=:username AND updatedBy=:username
213: ")->execute ($params);
214: Yii::app()->db->createCommand("
215: UPDATE x2_actions
216: SET completedBy=:adminUsername
217: WHERE assignedTo=:username AND completedBy=:username
218: ")->execute ($params);
219: Yii::app()->db->createCommand("
220: UPDATE x2_actions
221: SET assignedTo='Anyone'
222: WHERE assignedTo=:username
223: ")->execute (array (
224: ':username' => $this->username
225: ));
226:
227:
228: Yii::app()->db->createCommand("
229: UPDATE x2_contacts
230: SET updatedBy=:adminUsername
231: WHERE assignedTo=:username AND updatedBy=:username
232: ")->execute ($params);
233: Yii::app()->db->createCommand("
234: UPDATE x2_contacts
235: SET assignedTo='Anyone'
236: WHERE assignedTo=:username
237: ")->execute (array (
238: ':username' => $this->username
239: ));
240:
241: return parent::beforeDelete ();
242: }
243:
244: public function afterDelete () {
245:
246: $social=Social::model()->findAllByAttributes(array('user'=>$this->username));
247: foreach($social as $socialItem){
248: $socialItem->delete();
249: }
250: $social=Social::model()->findAllByAttributes(array('associationId'=>$this->id));
251: foreach($social as $socialItem){
252: $socialItem->delete();
253: }
254:
255: X2CalendarPermissions::model()->deleteAllByAttributes (
256: array(), 'user_id=:userId OR other_user_id=:userId', array (':userId' => $this->id)
257: );
258:
259:
260: $prof=Profile::model()->findByAttributes(array('username'=>$this->username));
261: if ($prof) $prof->delete();
262:
263:
264: Yii::app()->db->createCommand()
265: ->delete ('x2_events',
266: "user=:username OR (type='feed' AND associationId=".$this->id.")",
267: array (':username' => $this->username));
268:
269:
270: GroupToUser::model ()->deleteAll (array (
271: 'condition' => 'userId='.$this->id
272: ));
273: parent::afterDelete ();
274: }
275:
276:
277: public static function hasRole($user, $role){
278: if(is_numeric($role)){
279: $lookup = RoleToUser::model()->findByAttributes(array('userId' => $user, 'roleId' => $role));
280: return isset($lookup);
281: }else{
282: $roleRecord = Roles::model()->findByAttributes(array('name' => $role));
283: if(isset($roleRecord)){
284: $lookup = RoleToUser::model()->findByAttributes(array('userId' => $user, 'roleId' => $roleRecord->id));
285: return isset($lookup);
286: }else{
287: return false;
288: }
289: }
290: }
291:
292: 293: 294: 295:
296: public function getGroupIds () {
297: $results = Yii::app()->db->createCommand ()
298: ->select ('groupId')
299: ->from ('x2_group_to_user')
300: ->where ('userId=:id', array (':id' => $this->id))
301: ->queryAll ();
302: return array_map (function ($a) {
303: return $a['groupId'];
304: }, $results);
305: }
306:
307: 308: 309: 310:
311: public static function getMe () {
312: return User::model()->findByPk (Yii::app()->getSuId());
313: }
314:
315: public static function getUsersDataProvider () {
316: $usersDataProvider = new CActiveDataProvider('User', array(
317: 'criteria' => array(
318: 'condition' => 'status=1',
319: 'order' => 'lastName ASC'
320: )
321: ));
322: return $usersDataProvider;
323: }
324:
325: 326: 327:
328: public static function getUserOptions () {
329: $userOptions = Yii::app()->db->createCommand ("
330: select username, concat(firstName, ' ', lastName) as fullName
331: from x2_users
332: where status=1
333: order by lastName asc
334: ")->queryAll ();
335: return array_combine (
336: array_map (function ($row) {
337: return $row['username'];
338: }, $userOptions),
339: array_map (function ($row) {
340: return $row['fullName'];
341: }, $userOptions)
342: );
343: }
344:
345:
346: 347: 348: 349:
350: public static function getNames(){
351:
352: $userNames = array();
353: $userModels = self::model()->findAllByAttributes(array('status' => 1));
354: $userNames = array_combine(
355: array_map(function($u){return $u->username;},$userModels),
356: array_map(function($u){return $u->getFullName();},$userModels)
357: );
358:
359: natcasesort($userNames);
360:
361: return array('Anyone' => Yii::t('app', 'Anyone')) + $userNames;
362: }
363:
364: public static function getUserIds(){
365: $userNames = array();
366: $query = Yii::app()->db->createCommand()
367: ->select('id, CONCAT(firstName," ",lastName) AS name')
368: ->from('x2_users')
369: ->where('status=1')
370: ->order('name ASC')
371: ->query();
372:
373: while(($row = $query->read()) !== false)
374: $userNames[$row['id']] = $row['name'];
375: natcasesort($userNames);
376:
377: return array('' => Yii::t('app', 'Anyone')) + $userNames;
378: }
379:
380: public static function getUserId ($username) {
381: static $cache = array ();
382: if (!$cache) {
383: $records = Yii::app()->db->createCommand()
384: ->select('id, username')
385: ->from('x2_users')
386: ->where('status=1')
387: ->query();
388: foreach ($records as $record) {
389: $cache[$record['username']] = $record['id'];
390: }
391: }
392: if (isset ($cache[$username])) return $cache[$username];
393: }
394:
395: public function getName(){
396: return $this->firstName.' '.$this->lastName;
397: }
398:
399: public static function getProfiles(){
400: $arr = X2Model::model('User')->findAll('status="1"');
401: $names = array('0' => Yii::t('app', 'All'));
402: foreach($arr as $user){
403: $names[$user->id] = $user->firstName." ".$user->lastName;
404: }
405: return $names;
406: }
407:
408: 409: 410:
411: public static function getTopContacts(){
412: Yii::import('application.components.leftWidget.TopContacts');
413: return TopContacts::getBookmarkedRecords ();
414: }
415:
416: public static function getRecentItems($filter=null){
417: $userRecord = X2Model::model('User')->findByPk(Yii::app()->user->getId());
418:
419:
420: $recentItemsTemp = empty($userRecord->recentItems) ?
421: array() : explode(',', $userRecord->recentItems);
422: $recentItems = array();
423:
424:
425: $validAbbreviations = array_keys (self::$recentItemTypes);
426: foreach($recentItemsTemp as $item){
427: $itemType = strtok($item, '-');
428: $itemId = strtok('-');
429: if (in_array ($itemType, $validAbbreviations)) {
430: $recordType = self::$recentItemTypes[$itemType];
431: $record = $recordType::model ()->findByPk ($itemId);
432:
433: if(!is_null($record))
434: array_push($recentItems, array('type' => $itemType, 'model' => $record));
435: }
436:
437: }
438: if (is_callable ($filter)) {
439: $recentItems = array_filter ($recentItems, $filter);
440: }
441: return $recentItems;
442: }
443:
444: 445: 446: 447: 448:
449: public static function addRecentItem($type, $itemId, $userId=null){
450: if ($userId === null) $userId = Yii::app()->user->getId ();
451: if (in_array ($type, self::$recentItemTypes)) {
452: $validRecordTypes = array_flip (self::$recentItemTypes);
453: $type = $validRecordTypes[$type];
454: }
455:
456: if(in_array($type, array_keys (self::$recentItemTypes))){
457: $newItem = $type.'-'.$itemId;
458: $userRecord = X2Model::model('User')->findByPk($userId);
459:
460: $recentItems = ($userRecord->recentItems == '') ?
461: array() : explode(',', $userRecord->recentItems);
462: $existingEntry = array_search($newItem, $recentItems);
463: if($existingEntry !== false)
464: unset($recentItems[$existingEntry]);
465: array_unshift($recentItems, $newItem);
466:
467: while(count($recentItems) > 10){
468: array_pop($recentItems);
469: }
470: $userRecord->setAttribute('recentItems', implode(',', $recentItems));
471: $userRecord->update(array('recentItems'));
472: }
473: }
474:
475: 476: 477: 478: 479: 480: 481: 482: 483:
484: public static function getUserLinks(
485: $users, $makeLinks = true, $useFullName = true){
486:
487: if (Yii::app()->params->isMobileApp) {
488: $makeGroupLinks = false;
489: } else {
490: $makeGroupLinks = $makeLinks;
491: }
492:
493: if(!is_array($users)){
494:
495: if(preg_match('/^\d+$/',$users)){
496: $group = Groups::model()->findByPk($users);
497: if(isset($group))
498:
499: $link = $makeGroupLinks ?
500: CHtml::link(
501: $group->name,
502: Yii::app()->controller->createAbsoluteUrl(
503: '/groups/groups/view', array('id' => $group->id)),array('style'=>'text-decoration:none;')) :
504: $group->name;
505: else
506: $link = '';
507: return $link;
508: }
509:
510: if($users == '' || $users == 'Anyone')
511: return Yii::t('app', 'Anyone');
512:
513: $users = explode(', ', $users);
514: }
515: $links = array();
516: $userCache = Yii::app()->params->userCache;
517:
518: foreach($users as $user){
519: if($user == 'Email'){
520: continue;
521: }elseif($user == 'Anyone'){
522: $links[] = Yii::t('app', 'Anyone');
523: }else if(is_numeric($user)){
524: if(isset($userCache[$user])){
525: $group = $userCache[$user];
526:
527: $links[] = $makeGroupLinks ? CHtml::link($group->name, Yii::app()->controller->createAbsoluteUrl('/groups/groups/view', array('id' => $group->id)), array('style'=>'text-decoration:none;')) : $group->name;
528: }else{
529: $group = Groups::model()->findByPk($user);
530:
531: if(isset($group)){
532:
533: $groupLink = $makeGroupLinks ? CHtml::link($group->name, Yii::app()->controller->createAbsoluteUrl('/groups/groups/view', array('id' => $group->id)),array('style'=>'text-decoration:none;')) : $group->name;
534: $userCache[$user] = $group;
535: $links[] = $groupLink;
536: }
537: }
538: }else{
539: if(isset($userCache[$user])){
540: $model = $userCache[$user];
541: $linkText = $useFullName ? $model->fullName : $model->getAlias ();
542:
543: $userLink = $makeLinks ? $model->getLink (array('style'=>'text-decoration:none;')) : $linkText;
544: $links[] = $userLink;
545: }else{
546: $model = X2Model::model('User')->findByAttributes(array('username' => $user));
547: if(isset($model)){
548: $linkText = $useFullName ? $model->fullName : $model->getAlias ();
549:
550: $userLink = $makeLinks ? $model->getLink (array('style'=>'text-decoration:none;')) : $linkText;
551: $userCache[$user] = $model;
552: $links[] = $userLink;
553: }
554: }
555: }
556: }
557: Yii::app()->params->userCache = $userCache;
558: return implode(', ', $links);
559: }
560:
561: public static function getEmails(){
562: $userArray = User::model()->findAllByAttributes(array('status' => 1));
563: $emails = array('Anyone' => Yii::app()->params['adminEmail']);
564: foreach($userArray as $user){
565: $emails[$user->username] = $user->emailAddress;
566: }
567: return $emails;
568: }
569:
570: 571: 572: 573:
574: public function attributeLabels(){
575: return array(
576: 'id' => Yii::t('users', 'ID'),
577: 'firstName' => Yii::t('users', 'First Name'),
578: 'lastName' => Yii::t('users', 'Last Name'),
579: 'username' => Yii::t('users', 'Username'),
580: 'userAlias' => Yii::t('users', 'Username'),
581: 'password' => Yii::t('users', 'Password'),
582: 'title' => Yii::t('users', 'Title'),
583: 'department' => Yii::t('users', 'Department'),
584: 'officePhone' => Yii::t('users', 'Office Phone'),
585: 'cellPhone' => Yii::t('users', 'Cell Phone'),
586: 'homePhone' => Yii::t('users', 'Home Phone'),
587: 'address' => Yii::t('users', 'Address'),
588: 'backgroundInfo' => Yii::t('users', 'Background Info'),
589: 'emailAddress' => Yii::t('users', 'Email'),
590: 'status' => Yii::t('users', 'Status'),
591: 'updatePassword' => Yii::t('users', 'Update Password'),
592: 'lastUpdated' => Yii::t('users', 'Last Updated'),
593: 'updatedBy' => Yii::t('users', 'Updated By'),
594: 'recentItems' => Yii::t('users', 'Recent Items'),
595: 'topContacts' => Yii::t('users', 'Top Contacts'),
596: 'userKey' => Yii::t('users', 'API Key'),
597: );
598: }
599:
600: 601: 602: 603:
604: public function search(){
605:
606: $criteria = new CDbCriteria;
607:
608: $criteria->compare('id', $this->id);
609: $criteria->compare('firstName', $this->firstName, true);
610: $criteria->compare('lastName', $this->lastName, true);
611: $criteria->compare('username', $this->username, true);
612: $criteria->compare('password', $this->password, true);
613: $criteria->compare('title', $this->title, true);
614: $criteria->compare('department', $this->department, true);
615: $criteria->compare('officePhone', $this->officePhone, true);
616: $criteria->compare('cellPhone', $this->cellPhone, true);
617: $criteria->compare('homePhone', $this->homePhone, true);
618: $criteria->compare('address', $this->address, true);
619: $criteria->compare('backgroundInfo', $this->backgroundInfo, true);
620: $criteria->compare('emailAddress', $this->emailAddress, true);
621: $criteria->compare('status', $this->status);
622: $criteria->compare('lastUpdated', $this->lastUpdated, true);
623: $criteria->compare('updatedBy', $this->updatedBy, true);
624: $criteria->compare('recentItems', $this->recentItems, true);
625: $criteria->compare('topContacts', $this->topContacts, true);
626: $criteria->compare('lastLogin', $this->lastLogin);
627: $criteria->compare('login', $this->login);
628: $criteria->addCondition('(temporary=0 OR temporary IS NULL)');
629:
630: return new SmartActiveDataProvider(get_class($this), array(
631: 'criteria' => $criteria,
632: 'pagination'=>array(
633: 'pageSize'=>Profile::getResultsPerPage(),
634: ),
635: ));
636: }
637:
638: 639: 640: 641: 642: 643: 644:
645: public function userAliasUnique($attribute,$params=array()) {
646: $otherAttribute = $attribute=='username'?'userAlias':'username';
647: if(!empty($this->$attribute) &&
648: self::model()->exists(
649: (isset ($this->id) ? "id != $this->id AND " : '') . "`$otherAttribute` = BINARY :u",
650: array(':u'=>$this->$attribute))) {
651:
652: $this->addError($attribute,Yii::t('users','That name is already taken.'));
653: }
654: }
655:
656: 657: 658: 659: 660:
661: public function findByAlias($name) {
662: if(empty($name))
663: return null;
664: return self::model()->findBySql('SELECT * FROM `'.$this->tableName().'` '
665: . 'WHERE `username` = BINARY :n1 OR `userAlias` = BINARY :n2',array(
666: ':n1' => $name,
667: ':n2' => $name
668: ));
669: }
670:
671: 672: 673: 674: 675:
676: public function getAlias() {
677: if(empty($this->userAlias))
678: return $this->username;
679: else
680: return $this->userAlias;
681: }
682:
683: 684: 685:
686: public function getFullName(){
687: if(!isset($this->_fullName)){
688: $this->_fullName = Formatter::fullName($this->firstName, $this->lastName);
689: }
690: return $this->_fullName;
691: }
692:
693: public function getDisplayName ($plural=true, $ofModule=true) {
694: return Yii::t('users', '{user}', array(
695: '{user}' => Modules::displayName($plural, 'Users'),
696: ));
697: }
698:
699:
700:
701: public function initCheckedCalendars() {
702:
703: if (is_null($this->showCalendars)) {
704: $showCalendars = array(
705: 'userCalendars' => array('Anyone', $this->username),
706: 'groupCalendars' => array(),
707: 'sharedCalendars' => array(),
708: 'googleCalendars' => array()
709: );
710: $this->showCalendars = CJSON::encode($showCalendars);
711:
712: $this->update();
713: }
714: }
715:
716: 717: 718:
719: public function validateUserDisable() {
720: if ($this->status === '0' && $this->id == X2_PRIMARY_ADMIN_ID) {
721: $this->addError ('status', Yii::t('users',
722: 'The primary admin account cannot be disabled'));
723: }
724: }
725: }
726: