Overview

Packages

  • application
    • commands
    • components
      • actions
      • filters
      • leftWidget
      • permissions
      • sortableWidget
      • util
      • webupdater
      • x2flow
        • actions
        • triggers
      • X2GridView
      • X2Settings
    • controllers
    • models
      • embedded
    • modules
      • accounts
        • controllers
        • models
      • actions
        • controllers
        • models
      • calendar
        • controllers
        • models
      • charts
        • models
      • contacts
        • controllers
        • models
      • docs
        • components
        • controllers
        • models
      • groups
        • controllers
        • models
      • marketing
        • components
        • controllers
        • models
      • media
        • controllers
        • models
      • mobile
        • components
      • opportunities
        • controllers
        • models
      • products
        • controllers
        • models
      • quotes
        • controllers
        • models
      • services
        • controllers
        • models
      • template
        • models
      • users
        • controllers
        • models
      • workflow
        • controllers
        • models
      • x2Leads
        • controllers
        • models
  • None
  • system
    • base
    • caching
    • console
    • db
      • ar
      • schema
    • validators
    • web
      • actions
      • auth
      • helpers
      • widgets
        • captcha
        • pagers
  • zii
    • widgets
      • grid

Classes

  • AdminController
  • Api2Controller
  • ApiController
  • BugReportsController
  • CommonSiteControllerBehavior
  • ProfileController
  • RelationshipsController
  • SearchController
  • SiteController
  • StudioController
  • TemplatesController
  • TopicsController
  • x2base
  • X2Controller
  • Overview
  • Package
  • Class
  • Tree
   1: <?php
   2: /*****************************************************************************************
   3:  * X2Engine Open Source Edition is a customer relationship management program developed by
   4:  * X2Engine, Inc. Copyright (C) 2011-2016 X2Engine Inc.
   5:  * 
   6:  * This program is free software; you can redistribute it and/or modify it under
   7:  * the terms of the GNU Affero General Public License version 3 as published by the
   8:  * Free Software Foundation with the addition of the following permission added
   9:  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
  10:  * IN WHICH THE COPYRIGHT IS OWNED BY X2ENGINE, X2ENGINE DISCLAIMS THE WARRANTY
  11:  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
  12:  * 
  13:  * This program is distributed in the hope that it will be useful, but WITHOUT
  14:  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  15:  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
  16:  * details.
  17:  * 
  18:  * You should have received a copy of the GNU Affero General Public License along with
  19:  * this program; if not, see http://www.gnu.org/licenses or write to the Free
  20:  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  21:  * 02110-1301 USA.
  22:  * 
  23:  * You can contact X2Engine, Inc. P.O. Box 66752, Scotts Valley,
  24:  * California 95067, USA. or at email address contact@x2engine.com.
  25:  * 
  26:  * The interactive user interfaces in modified source and object code versions
  27:  * of this program must display Appropriate Legal Notices, as required under
  28:  * Section 5 of the GNU Affero General Public License version 3.
  29:  * 
  30:  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
  31:  * these Appropriate Legal Notices must retain the display of the "Powered by
  32:  * X2Engine" logo. If the display of the logo is not reasonably feasible for
  33:  * technical reasons, the Appropriate Legal Notices must display the words
  34:  * "Powered by X2Engine".
  35:  *****************************************************************************************/
  36: 
  37: /**
  38:  * User profiles controller
  39:  *
  40:  * @package application.controllers
  41:  */
  42: class ProfileController extends x2base {
  43: 
  44:     /**
  45:      * @var string The class of the model most often handled by this controller.
  46:      */
  47:     public $modelClass = 'Profile';
  48: 
  49:     /**
  50:      * Specifies the access control rules.
  51:      * This method is used by the 'accessControl' filter.
  52:      * @return array access control rules
  53:      */
  54:     public function accessRules() {
  55:         return array(
  56:             array('allow', // allow authenticated user to perform 'create' and 'update' actions
  57:                 'actions' => array(
  58:                     'index', 'view', 'update', 'search', 'addPost', 'deletePost', 'uploadPhoto',
  59:                     'getEvents', 'getEventsBetween', 'broadcastEvent', 'loadComments',
  60:                     'loadLikeHistory', 'likePost', 'flagPost', 'stickyPost', 'minimizePosts',
  61:                     'publishPost', 'createChartSetting', 'ajaxExportTheme',
  62:                     'deleteChartSetting', 'addComment',
  63:                     'toggleFeedControls', 'toggleFeedFilters', 'setWidgetSetting',
  64:                     'showWidgetContents', 'getWidgetContents',
  65:                     'setWidgetOrder', 'profiles', 'settings', 'deleteSound', 'deleteBackground',
  66:                     'changePassword', 'setResultsPerPage', 'hideTag', 'unhideTag', 'resetWidgets',
  67:                     'updatePost', 'loadTheme', 'createTheme', 'saveTheme', 'saveMiscLayoutSetting',
  68:                     'createUpdateCredentials', 'manageCredentials', 'deleteCredentials', 
  69:                     'verifyCredentials', 'ajaxGetModelAutoComplete',
  70:                     'setDefaultCredentials', 'activity', 'ajaxSaveDefaultEmailTemplate',
  71:                     'deleteActivityReport', 'createActivityReport', 'manageEmailReports',
  72:                     'toggleEmailReport', 'deleteEmailReport', 'sendTestActivityReport',
  73:                     'createProfileWidget','deleteSortableWidget','deleteTheme','previewTheme', 
  74:                     'resetTours', 'disableTours', 'mobileIndex', 'mobileView', 'mobileActivity', 
  75:                     'mobileViewEvent', 'mobilePublisher'),
  76:                 'users' => array('@'),
  77:             ),
  78:             array('deny', // deny all users
  79:                 'users' => array('*'),
  80:             ),
  81:         );
  82:     }
  83: 
  84:     public function behaviors() {
  85:         return array_merge(parent::behaviors(), array(
  86:             'X2MobileControllerBehavior' => array(
  87:                 'class' => 
  88:                     'application.modules.mobile.components.behaviors.'.
  89:                         'X2MobileProfileControllerBehavior'
  90:             ),
  91:             'ImportExportBehavior' => array('class' => 'ImportExportBehavior'),
  92:                 )
  93:         );
  94:     }
  95: 
  96:     public function filters() {
  97:         return array_merge(parent::filters(), array(
  98:             'accessControl',
  99:             'setPortlets',
 100:         ));
 101:     }
 102: 
 103:     public function actionHideTag($tag) {
 104:         $tag = "#" . $tag;
 105:         $profile = Yii::app()->params->profile;
 106:         if (isset($profile)) {
 107:             $hiddenTags = json_decode($profile->hiddenTags, true);
 108:             if (!is_array($hiddenTags))
 109:                 $hiddenTags = array();
 110:             if (!in_array($tag, $hiddenTags)) {
 111:                 array_push($hiddenTags, $tag);
 112:                 $profile->hiddenTags = json_encode($hiddenTags);
 113:                 $profile->save();
 114:             }
 115:         }
 116:     }
 117: 
 118:     public function actionUnhideTag($tag) {
 119:         $tag = "#" . $tag;
 120:         $profile = Yii::app()->params->profile;
 121:         if (isset($profile)) {
 122:             $hiddenTags = json_decode($profile->hiddenTags, true);
 123:             if (!is_array($hiddenTags))
 124:                 $hiddenTags = array();
 125:             if (in_array($tag, $hiddenTags)) {
 126:                 unset($hiddenTags[array_search($tag, $hiddenTags)]);
 127:                 $profile->hiddenTags = json_encode($hiddenTags);
 128:                 $profile->save();
 129:             }
 130:         }
 131:     }
 132: 
 133:     public function actionUpdatePost($id, $profileId) {
 134:         $post = Events::model()->findByPk($id);
 135:         if (isset($_POST['Events'])) {
 136:             $post->text = $_POST['Events']['text'];
 137:             $post->save();
 138:             $this->redirect(array('view', 'id' => $profileId));
 139:             //$this->redirect(array('/profile/profile'));
 140:         }
 141:         $commentDataProvider = new CActiveDataProvider('Events', array(
 142:             'criteria' => array(
 143:                 'order' => 'timestamp ASC',
 144:                 'condition' => "type='comment' AND associationType='Events' AND associationId=$id",
 145:         )));
 146:         $this->render('updatePost', array(
 147:             'id' => $id,
 148:             'model' => $post,
 149:             'commentDataProvider' => $commentDataProvider,
 150:             'profileId' => $profileId
 151:         ));
 152:     }
 153: 
 154:     /**
 155:      * Deletes a post in the public feed for the current user.
 156:      * @param integer $id
 157:      */
 158:     public function actionDeletePost($id, $profileId) {
 159:         $post = Events::model()->findByPk($id);
 160:         if (isset($post)) {
 161:             if ($post->type == 'comment') {
 162:                 $postParent = X2Model::model('Events')->findByPk($post->associationId);
 163:                 $user = Profile::model()->findByPk($postParent->associationId);
 164:             } else {
 165:                 $user = Profile::model()->findByPk($post->associationId);
 166:             }
 167:             if (isset($postParent) && $post->user != Yii::app()->user->getName()) {
 168:                 if ($postParent->associationId == Yii::app()->user->getId())
 169:                     $post->delete();
 170:             }
 171:             if ($post->user == Yii::app()->user->getName() || $post->associationId == Yii::app()->user->getId() || Yii::app()->params->isAdmin) {
 172:                 if ($post->delete()) {
 173:                     
 174:                 }
 175:             }
 176:         }
 177:         $this->redirect(array('view', 'id' => $profileId));
 178:     }
 179: 
 180:     /**
 181:      * Saves settings as a property of the miscLayoutSettings JSON field of the profile model. This 
 182:      * should be used to make miscellaneous layout settings persistent.
 183:      * POST Parameters:
 184:      *  settingName - string - must be an existing property name of the JSON field
 185:      *  settingVal - mixed - the value to which the JSON field property will get set
 186:      */
 187:     public function actionSaveMiscLayoutSetting() {
 188:         if (!isset($_POST['settingName']) || !isset($_POST['settingVal'])) {
 189:             echo 'failure';
 190:             return;
 191:         }
 192:         Profile::setMiscLayoutSetting($_POST['settingName'], $_POST['settingVal']);
 193:     }
 194: 
 195:     public function actionLoadTheme($themeId) {
 196:         $theme = Yii::app()->db->createCommand()
 197:                 ->select('description')
 198:                 ->from('x2_media')
 199:                 ->where('id=:id and associationType="theme"', array(':id' => $themeId))
 200:                 ->queryScalar();
 201:         echo $theme;
 202:     }
 203: 
 204:     public function canEditTheme($themeName) {
 205:         if ($themeName == 'Default') {
 206:             return false;
 207:         }
 208: 
 209: 
 210:         $themes = X2Model::model('Media')->findByAttributes(array(
 211:             'uploadedBy' => Yii::app()->user->id,
 212:             'fileName' => $themeName
 213:         ));
 214: 
 215:         if ( $themes ) {
 216:             return false;
 217:         } 
 218: 
 219:         return true;
 220:     }
 221: 
 222:     public function actionDeleteTheme($themeName) {
 223:         if( !$this->canEditTheme($themeName) ) {
 224:             echo 'error';
 225:             return;
 226:         }
 227: 
 228:         $theme = Media::model()->findByAttributes( 
 229:             array('associationType' => 'theme ',
 230:             'fileName' => $themeName)
 231:             );
 232:         if($theme){
 233:             $theme->delete();
 234:         }
 235:     }
 236: 
 237:     public function actionPreviewTheme($themeName) {
 238:         $theme = Media::model()->findByAttributes( 
 239:             array('associationType' => 'theme ',
 240:             'fileName' => $themeName)
 241:             );
 242: 
 243:         if($theme){
 244:             $settings = CJSON::decode($theme->description);
 245:             ThemeGenerator::previewTheme($settings);
 246:         }
 247:     }
 248: 
 249:     /**
 250:      * Overwrite an existing theme that the user uploaded.
 251:      */
 252:     public function actionSaveTheme() {
 253:         if (!isset ($_POST['themeAttributes'])) 
 254:             throw new CHttpException (400, Yii::t('app', 'Bad request.'));
 255:         $themeAttributes = $_POST['themeAttributes'];
 256:         $themeAttributesArr = CJSON::decode($themeAttributes);
 257:         if (!in_array('themeName', array_keys($themeAttributesArr)))
 258:             return;
 259: 
 260:         if( !$this->canEditTheme( $themeAttributesArr['themeName'] ) ) {
 261:             echo Yii::t('profile', 'Cannot edit theme');
 262:             return;
 263:         }
 264: 
 265:         $themeModel = X2Model::model('Media')->findByAttributes(array(
 266:             'uploadedBy' => Yii::app()->user->name,
 267:             'fileName' => $themeAttributesArr['themeName'],
 268:             'associationType' => 'theme'
 269:         ));
 270:         if ($themeModel !== null) {
 271:             $themeModel->fileName = $themeAttributesArr['themeName'];
 272:             $themeModel->description = $themeAttributes;
 273:             if ($themeModel->save()) {
 274:                 echo Yii::t('profile', 'Theme saved successfully.');
 275:             }
 276:         }
 277:     }
 278: 
 279:     private static function getThemeErrorMsg() {
 280:         $errorArr = array(
 281:             'success' => false,
 282:             'errorListHeader' => Yii::t('profile', 'Please fix the following errors:'),
 283:             'errorMsg' => Yii::t('profile', 'Theme name already exists or is invalid.'));
 284:         return CJSON::encode($errorArr);
 285:     }
 286: 
 287:     private static function getThemeSuccessMsg($data = array()) {
 288:         $successArr = array_merge(array(
 289:             'success' => true,
 290:             'msg' => Yii::t('profile', 'Theme created successfully.')), $data);
 291:         return CJSON::encode($successArr);
 292:     }
 293: 
 294:     /**
 295:      * Create a new theme record in the Media table, prevent duplicate filenames.
 296:      * If theme cannot be saved, error message object is returned.
 297:      */
 298:     public function actionCreateTheme($themeAttributes) {
 299:         $themeAttributesArr = CJSON::decode($themeAttributes);
 300:         if (!in_array('themeName', array_keys($themeAttributesArr)) ||
 301:                 !in_array('themeName', array_keys($themeAttributesArr))) {
 302:             echo self::getThemeErrorMsg();
 303:         }
 304:         $theme = new Media;
 305:         $theme->setScenario('themeCreate');
 306:         $theme->fileName = $themeAttributesArr['themeName'];
 307:         $theme->private = $themeAttributesArr['private'];
 308:         $theme->associationType = "theme";
 309:         $theme->uploadedBy = Yii::app()->user->name;
 310:         $theme->description = $themeAttributes;
 311:         if (!$theme->save()) {
 312:             echo self::getThemeErrorMsg();
 313:         } else {
 314:             echo self::getThemeSuccessMsg(array('id' => $theme->id));
 315:         }
 316:     }
 317: 
 318:     
 319: 
 320:     /**
 321:      * Display/set user profile settings.
 322:      */
 323:     public function actionSettings() {
 324:         $model = $this->loadModel(Yii::app()->user->getId());
 325: 
 326:         
 327: 
 328:         if (isset($_POST['Profile']) || isset($_POST['preferences'])) {
 329:             if (isset($_POST['Profile'])) {
 330:                 $model->attributes = $_POST['Profile'];
 331:                 if(isset($_POST['preferences']['loginSound'])){
 332:                     $pieces = explode(',',$_POST['preferences']['loginSound']);
 333:                     $model->loginSound = $pieces[0];
 334:                     unset ($_POST['preferences']['loginSound']);
 335:                 }
 336:                 if(isset($_POST['preferences']['notificationSound'])){
 337:                     $pieces = explode(',',$_POST['preferences']['notificationSound']);
 338:                     $model->notificationSound = $pieces[0];
 339:                     unset ($_POST['preferences']['notificationSound']);
 340:                 }
 341:                 $model->save();
 342:             }
 343:             
 344:             if (isset($_POST['preferences']['themeName'])) { 
 345:                 ThemeGenerator::clearCache();
 346:                 Yii::import('application.components.ThemeGenerator.LoginThemeHelper');
 347:                 LoginThemeHelper::saveProfileTheme($_POST['preferences']['themeName']);
 348:                 $model->theme = array_merge(
 349:                     array_diff_key (
 350:                         $model->theme, array_flip (ThemeGenerator::getProfileKeys ())),
 351:                     ThemeGenerator::loadDefault (
 352:                         $_POST['preferences']['themeName'], false), 
 353:                     array_diff_key (
 354:                         $_POST['preferences'], array_flip (ThemeGenerator::getProfileKeys ())));
 355:                 $model->save ();
 356:             }
 357:             $this->refresh();
 358:         }
 359: 
 360:         $modules = Modules::model()->findAllByAttributes(array('visible' => 1));
 361:         $menuItems = array();
 362:         foreach ($modules as $module) {
 363:             if ($module->name == 'document') {
 364:                 $menuItems[$module->title] = $module->title;
 365:             } else {
 366:                 $menuItems[$module->name] = Yii::t('app', $module->title);
 367:             }
 368:         }
 369:         $menuItems = array('' => Yii::t('app', 'Activity Feed')) + $menuItems;
 370: 
 371:         $languages = $model->getLanguageOptions ();
 372: 
 373:         $times = $this->getTimeZones();
 374: 
 375:         $myThemeProvider = new CActiveDataProvider('Media', array(
 376:             'criteria' => array(
 377:                 'condition' => "((private = 1 AND uploadedBy = '" . Yii::app()->user->name . "') OR private = 0) AND associationType = 'theme'",
 378:                 'order' => 'createDate DESC'
 379:             ),
 380:             'pagination' => false
 381:         ));
 382:         $myBackgroundProvider = new CActiveDataProvider('Media', array(
 383:             'criteria' => array(
 384:                 'condition' => "(associationType = 'bg-private' AND associationId = '" . Yii::app()->user->getId() . "') OR associationType = 'bg'",
 385:                 'order' => 'createDate DESC',
 386:             ),
 387:             'pagination' => false
 388:         ));
 389: 
 390:         $myLoginSoundProvider = new CActiveDataProvider('Media', array(
 391:             'criteria' => array(
 392:                 'condition' => "(associationType='loginSound' AND (private=0 OR private IS NULL OR uploadedBy='" . Yii::app()->user->getName() . "'))",
 393:                 'order' => 'createDate DESC'
 394:             ),
 395:             'pagination' => false
 396:         ));
 397:         $myNotificationSoundProvider = new CActiveDataProvider('Media', array(
 398:             'criteria' => array(
 399:                 'condition' => "(associationType='notificationSound' AND (private=0 OR private IS NULL OR uploadedBy='" . Yii::app()->user->getName() . "'))",
 400:                 'order' => 'createDate DESC'
 401:             ),
 402:             'pagination' => false
 403:         ));
 404:         $hiddenTags = json_decode(Yii::app()->params->profile->hiddenTags, true);
 405:         if (empty($hiddenTags))
 406:             $hiddenTags = array();
 407: 
 408:         if (sizeof($hiddenTags)) {
 409:             $tagParams = AuxLib::bindArray($hiddenTags);
 410:             $allTags = Yii::app()->db->createCommand()
 411:                     ->select('COUNT(*) AS count, tag')
 412:                     ->from('x2_tags')
 413:                     ->group('tag')
 414:                     ->where('tag IS NOT NULL AND tag IN (' .
 415:                             implode(',', array_keys($tagParams)) . ')', $tagParams)
 416:                     ->order('tag ASC')
 417:                     ->limit(20)
 418:                     ->queryAll();
 419:         } else {
 420:             $allTags = array();
 421:         }
 422: 
 423:         $admin = Yii::app()->settings;
 424: 
 425:         $this->render('settings', array(
 426:             'model' => $model,
 427:             'languages' => $languages,
 428:             'times' => $times,
 429:             'myThemes' => $myThemeProvider,
 430:             'myBackgrounds' => $myBackgroundProvider,
 431:             'myLoginSounds' => $myLoginSoundProvider,
 432:             'myNotificationSounds' => $myNotificationSoundProvider,
 433:             'menuItems' => $menuItems,
 434:             'allTags' => $allTags,
 435:             
 436:         ));
 437:     }
 438: 
 439:     public function actionManageCredentials() {
 440:         $this->pageTitle = Yii::t('app', 'Manage Credentials');
 441:         Yii::app()->clientScript->registerScriptFile(Yii::app()->getBaseUrl() . '/js/manageCredentials.js');
 442:         $this->render('manageCredentials', array('profile' => Yii::app()->params->profile));
 443:     }
 444: 
 445:     /**
 446:      * Basic CRUD for application credentials
 447:      * @param type $id
 448:      * @param type $class embedded model class name
 449:      * @throws CHttpException
 450:      */
 451:     public function actionCreateUpdateCredentials($id = null, $class = null) {
 452: 
 453:         $this->pageTitle = Yii::t('app', 'Edit Credentials');
 454:         $profile = Yii::app()->params->profile;
 455:         // Create or retrieve model:
 456:         if (empty($id)) {
 457:             if (empty($class))
 458:                 throw new CHttpException(
 459:                     400, 'Class must be specified when creating new credentials.');
 460:             $model = new Credentials();
 461:             $model->modelClass = $class;
 462:         } else {
 463:             $model = Credentials::model()->findByPk($id);
 464:             if (empty($model))
 465:                 throw new CHttpException(404);
 466:         }
 467:         if ($model->getAuthModel ()->getMetaData ()) {
 468:             $model->setAttributes ($model->getAuthModel ()->getMetaData (), false);
 469:             $disableMetaDataForm = true;
 470:         }
 471: 
 472:         if (in_array ($model->modelClass, array ('TwitterApp', 'GoogleProject'))) {
 473:             if (!Yii::app()->params->isAdmin) {
 474:                 $this->denied ();
 475:             }
 476:             if ($model->modelClass === 'GoogleProject') {
 477:                 if (isset ($_POST['Admin']['gaTracking_public'])) {
 478:                     Yii::app()->settings->gaTracking_public = $_POST['Admin']['gaTracking_public'];
 479:                 }
 480:                 if (isset ($_POST['Admin']['gaTracking_internal'])) {
 481:                     Yii::app()->settings->gaTracking_internal = 
 482:                         $_POST['Admin']['gaTracking_internal'];
 483:                 }
 484:                 if (isset ($_POST['Admin']['googleIntegration'])) {
 485:                     Yii::app()->settings->googleIntegration = 
 486:                         $_POST['Admin']['googleIntegration'];
 487:                 }
 488:             }
 489:             $this->layout = '//layouts/column1';
 490:         }
 491: 
 492:         $model->scenario = $model->isNewRecord ? 'create' : 'update';
 493: 
 494:         // Apply changes if any:
 495:         if (isset($_POST['Credentials'])) {
 496:             $model->attributes = $_POST['Credentials'];
 497:             // Check to see if user has permission:
 498:             if (!Yii::app()->user->checkAccess(
 499:                 'CredentialsCreateUpdate', array('model' => $model))) {
 500: 
 501:                 $this->denied();
 502:             }
 503:             // Save the model:
 504:             if ($model->validate()) {
 505:                 // Set timestamps
 506:                 $time = time();
 507:                 if ($model->isNewRecord)
 508:                     $model->createDate = $time;
 509:                 $model->lastUpdated = $time;
 510:                 if ($model->save()) {
 511:                     $message = Yii::t('app', 'Saved') . ' ' . Formatter::formatLongDateTime($time);
 512:                     Yii::app()->user->setFlash ('success', $message);
 513:                     if (in_array (
 514:                         $model->modelClass, array ('TwitterApp', 'GoogleProject'))) {
 515: 
 516:                         if ($model->modelClass === 'GoogleProject') {
 517:                             Yii::app()->settings->save ();
 518:                         }
 519:                     } else {
 520:                         $this->redirect (array('manageCredentials'));
 521:                     }
 522:                 }
 523:             } else {
 524:                 //AuxLib::debugLogR ($model->getErrors ());
 525:             }
 526:         }
 527:         $this->render(
 528:             'createUpdateCredentials', 
 529:             array(
 530:                 'model' => $model,
 531:                 'profile' => $profile,
 532:                 'disableMetaDataForm' => isset ($disableMetaDataForm) ? 
 533:                     $disableMetaDataForm : false,
 534:             ));
 535:     }
 536: 
 537:     /**
 538:      * Action to be called via ajax to verify authentication to the SMTP server
 539:      */
 540:     public function actionVerifyCredentials() {
 541:         $attributes = array('email', 'password', 'server', 'port', 'security');
 542:         foreach ($attributes as $attr)
 543:             ${$attr} = isset($_POST[$attr])? $_POST[$attr] : "";
 544:         $this->attachBehavior('EmailDeliveryBehavior', new EmailDeliveryBehavior);
 545:         $valid = $this->testUserCredentials($email, $password, $server, $port, $security);
 546:         if (!$valid) echo "Failed";
 547:     }
 548: 
 549:     /**
 550:      * Make a credentials record default for the active user.
 551:      * @param type $id
 552:      * @throws CHttpException
 553:      */
 554:     public function actionSetDefaultCredentials($id) {
 555:         $model = Credentials::model()->findByPk($id);
 556: 
 557:         if (!isset($_POST['userId']))
 558:             throw new Exception(400, 'Invalid request');
 559:         $userId = $_POST['userId'];
 560:         if (empty($model))
 561:             throw new CHttpException(404);
 562:         if (!Yii::app()->user->checkAccess('CredentialsSetDefault', array('model' => $model, 'userId' => $userId)))
 563:             $this->denied();
 564:         if (!is_array($_POST['default'])) { // It's a yes or no
 565:             if ($_POST['default']) {
 566:                 $defaults = $model->defaultSubstitutesInv[$model->modelClass];
 567:             }
 568:         } else { // It's a selector
 569:             $defaults = $_POST['default'];
 570:         }
 571: 
 572:         if (isset($defaults)) {
 573:             foreach ($defaults as $serviceType) {
 574:                 $model->makeDefault($userId, $serviceType);
 575:             }
 576:         }
 577:         $this->redirect(array('manageCredentials'));
 578:     }
 579: 
 580:     public function actionDeleteCredentials($id) {
 581:         $cred = Credentials::model()->findByPk($id);
 582:         if (empty($cred))
 583:             throw new CHttpException(404);
 584:         if (!Yii::app()->user->checkAccess('CredentialsDelete', array('model' => $cred)))
 585:             $this->denied();
 586:         
 587:         $cred->delete();
 588:         $this->redirect(array('/profile/manageCredentials'));
 589:     }
 590: 
 591:     /**
 592:      * Updates a particular model.
 593:      *
 594:      * If update is successful, the browser will be redirected to the 'view' page.
 595:      * @param integer $id the ID of the model to be updated
 596:      */
 597:     public function actionUpdate($id) {
 598:         if ($id == Yii::app()->user->getId() || Yii::app()->params->isAdmin) {
 599:             $model = $this->loadModel($id);
 600:             $users = User::getNames();
 601: 
 602:             if (isset($_POST['Profile'])) {
 603: 
 604:                 foreach ($_POST['Profile'] as $name => $value) {
 605:                     if ($value == $model->getAttributeLabel($name)) {
 606:                         $_POST['Profile'][$name] = '';
 607:                     }
 608:                     $model->$name = $value;
 609:                 }
 610:                 if ($model->save()) {
 611:                     $this->redirect(array('view', 'id' => $model->id));
 612:                 }
 613:             }
 614:             
 615:             $this->render('update', array(
 616:                 'model' => $model,
 617:                 'users' => $users,
 618:             ));
 619:         } else {
 620:             $this->redirect(array('/profile/view', 'id' => $id));
 621:         }
 622:     }
 623: 
 624:     /**
 625:      * Changes the password for the user given by its record ID number.
 626:      * @param integer $id ID of the user to be updated.
 627:      */
 628:     public function actionChangePassword($id) {
 629:         if ($id === Yii::app()->user->getId()) {
 630:             $user = User::model()->findByPk($id);
 631:             if (isset($_POST['oldPassword'], $_POST['newPassword'], $_POST['newPassword2'])) {
 632: 
 633:                 $oldPass = $_POST['oldPassword'];
 634:                 $newPass = $_POST['newPassword'];
 635:                 $newPass2 = $_POST['newPassword2'];
 636:                 if (PasswordUtil::validatePassword($oldPass, $user->password)) {
 637:                     if ($newPass === $newPass2) {
 638:                         $user->password = PasswordUtil::createHash($newPass);
 639:                         // Ensure an alias is set so that validation succeeds
 640:                         if (empty($user->userAlias)){
 641:                             $user->userAlias = $user->username;
 642:                         }
 643:                         $user->save();
 644: 
 645:                         $this->redirect($this->createUrl('/profile/view', array('id' => $id)));
 646:                     }
 647:                 } else {
 648:                     Yii::app()->clientScript->registerScript('alertPassWrong', "alert('Old password is incorrect.');");
 649:                 }
 650:             }
 651: 
 652:             $this->render('changePassword', array(
 653:                 'model' => $user,
 654:             ));
 655:         }
 656:     }
 657: 
 658:     /**
 659:      * Upload a profile photo.
 660:      * @param integer $id ID of the user in question.
 661:      */
 662:     public function actionUploadPhoto($id) {
 663:         if ($id == Yii::app()->user->getId()) {
 664:             $prof = Profile::model()->findByPk($id);
 665:             if (isset($_FILES['Profile'])) {
 666:                 $prof->photo = CUploadedFile::getInstance ($prof, 'photo'); 
 667:                 if ($prof->save ()) {
 668:                 } else {
 669:                     Yii::app()->user->setFlash(
 670:                         'error', Yii::t('app', "There was an error uploading the file."));
 671:                 }
 672:             } else if (isset($_GET['clear']) && $_GET['clear']) {
 673:                 $prof->avatar = null;
 674:                 $prof->save();
 675:             }
 676:         }
 677:         $this->redirect(Yii::app()->request->urlReferrer);
 678:         // $this->redirect(array('view', 'id' => $id));
 679:     }
 680: 
 681:     /**
 682:      * Delete a background image.
 683:      *
 684:      * @param type $id
 685:      */
 686:     public function actionDeleteBackground($id) {
 687: 
 688:         $image = X2Model::model('Media')->findByPk($id);
 689:         if ($image->associationId == Yii::app()->user->getId() && ($image->associationType == 'bg' || $image->associationType == 'bg-private')) {
 690: 
 691:             $profile = X2Model::model('Profile')->findByPk(Yii::app()->user->getId());
 692: 
 693:             if ($profile->backgroundImg == $image->fileName) { // if this BG is currently in use, clear user's background image setting
 694:                 $profile->backgroundImg = '';
 695:                 $profile->save();
 696:             }
 697: 
 698:             if ($image->delete()) {
 699:                 unlink('uploads/protected/' . $image->fileName); // delete file
 700:                 echo 'success';
 701:             }
 702:         }
 703:     }
 704: 
 705:     public function actionDeleteSound($id, $sound) {
 706:         $sound = X2Model::model('Media')->findByPk($id);
 707:         $profile = Yii::app()->params->profile;
 708:         $type = $sound->associationType;
 709:         if ($profile->$type == $sound->fileName) { // if this sound is currently in use, clear user's sound setting
 710:             $profile->$type = '';
 711:             $profile->update(array($sound->associationType));
 712:         }
 713:         if ($sound->delete()) {
 714:             unlink('uploads/protected/media/' . $sound->uploadedBy . '/' . $sound->fileName); // delete file
 715:             echo 'success';
 716:         }
 717:         return true;
 718:     }
 719: 
 720:     /**
 721:      * Generate a random filename for a picture.
 722:      *
 723:      * @return string
 724:      */
 725:     private function generatePictureName() {
 726: 
 727:         $time = time();
 728:         $rand = chr(rand(65, 90));
 729:         $salt = $time . $rand;
 730:         $name = md5($salt . md5($salt) . $salt);
 731:         return $name;
 732:     }
 733: 
 734:     /**
 735:      * Add a new post to the social feed.
 736:      *
 737:      * @param integer $id ID of the user.
 738:      */
 739:     public function actionAddPost($id, $redirect) {
 740:         $post = new Events;
 741:         // $user = $this->loadModel($id);
 742:         if (isset($_POST['Events']) && $_POST['Events']['text'] != Yii::t('app', 'Enter text here...')) {
 743:             $post->text = $_POST['Events']['text'];
 744:             $post->visibility = $_POST['Events']['visibility'];
 745:             if (isset($_POST['Events']['associationId'])) {
 746:                 $post->associationId = $_POST['Events']['associationId'];
 747:                 $post->associationType = 'User';
 748:             }
 749:             //$soc->attributes = $_POST['Social'];
 750:             //die(var_dump($_POST['Social']));
 751:             $post->user = Yii::app()->user->getName();
 752:             $post->type = 'feed';
 753:             $post->subtype = $_POST['Events']['subtype'];
 754:             $post->lastUpdated = time();
 755:             $post->timestamp = time();
 756:             if (!isset($post->associationId) || $post->associationId == 0)
 757:                 $post->associationId = $id;
 758:             if ($post->save()) {
 759:                 if ($post->associationId != Yii::app()->user->getId()) {
 760: 
 761:                     $notif = new Notification;
 762: 
 763:                     $notif->type = 'social_post';
 764:                     $notif->createdBy = $post->user;
 765:                     $notif->modelType = 'Profile';
 766:                     $notif->modelId = $post->associationId;
 767: 
 768:                     $notif->user = Yii::app()->db->createCommand()
 769:                             ->select('username')
 770:                             ->from('x2_users')
 771:                             ->where('id=:id', array(':id' => $post->associationId))
 772:                             ->queryScalar();
 773: 
 774:                     // $prof = X2Model::model('Profile')->findByAttributes(array('username'=>$post->user));
 775:                     // $notif->text = "$prof->fullName posted on your profile.";
 776:                     // $notif->record = "profile:$prof->id";
 777:                     // $notif->viewed = 0;
 778:                     $notif->createDate = time();
 779:                     // $subject=X2Model::model('Profile')->findByPk($id);
 780:                     // $notif->user = $subject->username;
 781:                     $notif->save();
 782:                 }
 783:             }
 784:         }
 785:         if ($redirect == "view")
 786:             $this->redirect(array('view', 'id' => $id));
 787:         else
 788:             $this->redirect(array('/profile/profile'));
 789:     }
 790: 
 791:     /**
 792:      * Redirect to current user's profile page
 793:      */
 794:     public function actionIndex() {
 795:         $this->redirect(array('view', 'id' => Yii::app()->user->getId()));
 796:     }
 797: 
 798:     /**
 799:      * Lists users profiles.
 800:      */
 801:     public function actionProfiles() {
 802:         $model = new Profile('search');
 803:         $this->render('profiles', array('model' => $model));
 804:     }
 805: 
 806:     /**
 807:      * Return a mapping of Olson TZ code names to timezone names.
 808:      * @return array
 809:      */
 810:     private function getTimeZones() {
 811:         return array(
 812:             'Pacific/Midway'       => "(GMT-11:00) Midway Island",
 813:             'US/Samoa'             => "(GMT-11:00) Samoa",
 814:             'US/Hawaii'            => "(GMT-10:00) Hawaii",
 815:             'US/Alaska'            => "(GMT-09:00) Alaska",
 816:             'US/Pacific'           => "(GMT-08:00) Pacific Time (US & Canada)",
 817:             'America/Tijuana'      => "(GMT-08:00) Tijuana",
 818:             'US/Arizona'           => "(GMT-07:00) Arizona",
 819:             'US/Mountain'          => "(GMT-07:00) Mountain Time (US & Canada)",
 820:             'America/Chihuahua'    => "(GMT-07:00) Chihuahua",
 821:             'America/Mazatlan'     => "(GMT-07:00) Mazatlan",
 822:             'America/Mexico_City'  => "(GMT-06:00) Mexico City",
 823:             'America/Monterrey'    => "(GMT-06:00) Monterrey",
 824:             'Canada/Saskatchewan'  => "(GMT-06:00) Saskatchewan",
 825:             'US/Central'           => "(GMT-06:00) Central Time (US & Canada)",
 826:             'US/Eastern'           => "(GMT-05:00) Eastern Time (US & Canada)",
 827:             'US/East-Indiana'      => "(GMT-05:00) Indiana (East)",
 828:             'America/Bogota'       => "(GMT-05:00) Bogota",
 829:             'America/Lima'         => "(GMT-05:00) Lima",
 830:             'America/Caracas'      => "(GMT-04:30) Caracas",
 831:             'Canada/Atlantic'      => "(GMT-04:00) Atlantic Time (Canada)",
 832:             'America/La_Paz'       => "(GMT-04:00) La Paz",
 833:             'America/Santiago'     => "(GMT-04:00) Santiago",
 834:             'Canada/Newfoundland'  => "(GMT-03:30) Newfoundland",
 835:             'America/Buenos_Aires' => "(GMT-03:00) Buenos Aires",
 836:             'Greenland'            => "(GMT-03:00) Greenland",
 837:             'Atlantic/Stanley'     => "(GMT-02:00) Stanley",
 838:             'Atlantic/Azores'      => "(GMT-01:00) Azores",
 839:             'Atlantic/Cape_Verde'  => "(GMT-01:00) Cape Verde Is.",
 840:             'Africa/Casablanca'    => "(GMT) Casablanca",
 841:             'Europe/Dublin'        => "(GMT) Dublin",
 842:             'Europe/Lisbon'        => "(GMT) Lisbon",
 843:             'Europe/London'        => "(GMT) London",
 844:             'Africa/Monrovia'      => "(GMT) Monrovia",
 845:             'UTC'                  => "(UTC)",
 846:             'Europe/Amsterdam'     => "(GMT+01:00) Amsterdam",
 847:             'Europe/Belgrade'      => "(GMT+01:00) Belgrade",
 848:             'Europe/Berlin'        => "(GMT+01:00) Berlin",
 849:             'Europe/Bratislava'    => "(GMT+01:00) Bratislava",
 850:             'Europe/Brussels'      => "(GMT+01:00) Brussels",
 851:             'Europe/Budapest'      => "(GMT+01:00) Budapest",
 852:             'Europe/Copenhagen'    => "(GMT+01:00) Copenhagen",
 853:             'Europe/Ljubljana'     => "(GMT+01:00) Ljubljana",
 854:             'Europe/Madrid'        => "(GMT+01:00) Madrid",
 855:             'Europe/Paris'         => "(GMT+01:00) Paris",
 856:             'Europe/Prague'        => "(GMT+01:00) Prague",
 857:             'Europe/Rome'          => "(GMT+01:00) Rome",
 858:             'Europe/Sarajevo'      => "(GMT+01:00) Sarajevo",
 859:             'Europe/Skopje'        => "(GMT+01:00) Skopje",
 860:             'Europe/Stockholm'     => "(GMT+01:00) Stockholm",
 861:             'Europe/Vienna'        => "(GMT+01:00) Vienna",
 862:             'Europe/Warsaw'        => "(GMT+01:00) Warsaw",
 863:             'Europe/Zagreb'        => "(GMT+01:00) Zagreb",
 864:             'Europe/Athens'        => "(GMT+02:00) Athens",
 865:             'Europe/Bucharest'     => "(GMT+02:00) Bucharest",
 866:             'Africa/Cairo'         => "(GMT+02:00) Cairo",
 867:             'Africa/Harare'        => "(GMT+02:00) Harare",
 868:             'Europe/Helsinki'      => "(GMT+02:00) Helsinki",
 869:             'Europe/Istanbul'      => "(GMT+02:00) Istanbul",
 870:             'Asia/Jerusalem'       => "(GMT+02:00) Jerusalem",
 871:             'Europe/Kiev'          => "(GMT+02:00) Kyiv",
 872:             'Europe/Minsk'         => "(GMT+02:00) Minsk",
 873:             'Europe/Riga'          => "(GMT+02:00) Riga",
 874:             'Europe/Sofia'         => "(GMT+02:00) Sofia",
 875:             'Europe/Tallinn'       => "(GMT+02:00) Tallinn",
 876:             'Europe/Vilnius'       => "(GMT+02:00) Vilnius",
 877:             'Asia/Baghdad'         => "(GMT+03:00) Baghdad",
 878:             'Asia/Kuwait'          => "(GMT+03:00) Kuwait",
 879:             'Europe/Moscow'        => "(GMT+03:00) Moscow",
 880:             'Africa/Nairobi'       => "(GMT+03:00) Nairobi",
 881:             'Asia/Riyadh'          => "(GMT+03:00) Riyadh",
 882:             'Europe/Volgograd'     => "(GMT+03:00) Volgograd",
 883:             'Asia/Tehran'          => "(GMT+03:30) Tehran",
 884:             'Asia/Baku'            => "(GMT+04:00) Baku",
 885:             'Asia/Muscat'          => "(GMT+04:00) Muscat",
 886:             'Asia/Tbilisi'         => "(GMT+04:00) Tbilisi",
 887:             'Asia/Yerevan'         => "(GMT+04:00) Yerevan",
 888:             'Asia/Kabul'           => "(GMT+04:30) Kabul",
 889:             'Asia/Yekaterinburg'   => "(GMT+05:00) Ekaterinburg",
 890:             'Asia/Karachi'         => "(GMT+05:00) Karachi",
 891:             'Asia/Tashkent'        => "(GMT+05:00) Tashkent",
 892:             'Asia/Kolkata'         => "(GMT+05:30) Kolkata",
 893:             'Asia/Kathmandu'       => "(GMT+05:45) Kathmandu",
 894:             'Asia/Almaty'          => "(GMT+06:00) Almaty",
 895:             'Asia/Dhaka'           => "(GMT+06:00) Dhaka",
 896:             'Asia/Novosibirsk'     => "(GMT+06:00) Novosibirsk",
 897:             'Asia/Bangkok'         => "(GMT+07:00) Bangkok",
 898:             'Asia/Jakarta'         => "(GMT+07:00) Jakarta",
 899:             'Asia/Krasnoyarsk'     => "(GMT+07:00) Krasnoyarsk",
 900:             'Asia/Chongqing'       => "(GMT+08:00) Chongqing",
 901:             'Asia/Hong_Kong'       => "(GMT+08:00) Hong Kong",
 902:             'Asia/Irkutsk'         => "(GMT+08:00) Irkutsk",
 903:             'Asia/Kuala_Lumpur'    => "(GMT+08:00) Kuala Lumpur",
 904:             'Australia/Perth'      => "(GMT+08:00) Perth",
 905:             'Asia/Singapore'       => "(GMT+08:00) Singapore",
 906:             'Asia/Taipei'          => "(GMT+08:00) Taipei",
 907:             'Asia/Ulaanbaatar'     => "(GMT+08:00) Ulaan Bataar",
 908:             'Asia/Urumqi'          => "(GMT+08:00) Urumqi",
 909:             'Asia/Seoul'           => "(GMT+09:00) Seoul",
 910:             'Asia/Tokyo'           => "(GMT+09:00) Tokyo",
 911:             'Asia/Yakutsk'         => "(GMT+09:00) Yakutsk",
 912:             'Australia/Adelaide'   => "(GMT+09:30) Adelaide",
 913:             'Australia/Darwin'     => "(GMT+09:30) Darwin",
 914:             'Australia/Brisbane'   => "(GMT+10:00) Brisbane",
 915:             'Australia/Canberra'   => "(GMT+10:00) Canberra",
 916:             'Pacific/Guam'         => "(GMT+10:00) Guam",
 917:             'Australia/Hobart'     => "(GMT+10:00) Hobart",
 918:             'Australia/Melbourne'  => "(GMT+10:00) Melbourne",
 919:             'Pacific/Port_Moresby' => "(GMT+10:00) Port Moresby",
 920:             'Australia/Sydney'     => "(GMT+10:00) Sydney",
 921:             'Asia/Vladivostok'     => "(GMT+10:00) Vladivostok",
 922:             'Asia/Magadan'         => "(GMT+11:00) Magadan",
 923:             'Pacific/Auckland'     => "(GMT+12:00) Auckland",
 924:             'Pacific/Fiji'         => "(GMT+12:00) Fiji",
 925:             'Asia/Kamchatka'       => "(GMT+12:00) Kamchatka",
 926:         );
 927:     }
 928: 
 929:     /**
 930:      * Sets the the option for the number of results per page.
 931:      * @param integer $results
 932:      */
 933:     public function actionSetResultsPerPage($results) {
 934:         Yii::app()->params->profile->resultsPerPage = $results;
 935:         Yii::app()->params->profile->save();
 936:     }
 937: 
 938:     public function actionResetWidgets($id) {
 939:         $model = $this->loadModel($id);
 940: 
 941:         $model->layout = json_encode($model->initLayout());
 942:         $model->update();
 943: 
 944:         $this->redirect(array('view', 'id' => $id));
 945:     }
 946: 
 947:     /***********************************************************************
 948:      * Profile Page Methods
 949:      ***********************************************************************/
 950: 
 951:     public function actionCreateProfileWidget () {
 952:         if (!isset ($_POST['widgetLayoutName']) || !isset ($_POST['widgetType'])) {
 953:             throw new CHttpException (400, 'Bad Request');
 954:         }
 955:         $widgetClass = $_POST['widgetType'];
 956:         $widgetSettings = array ();
 957:         if (preg_match ('/::/', $widgetClass)) {
 958:             // Custom module summary widget. extract model name
 959:             $widgetSettings['modelType'] = preg_replace ('/::.*$/', '', $widgetClass);
 960:             $widgetSettings['label'] = Modules::displayName(true,$widgetSettings['modelType']) . ' Summary';
 961:             $widgetClass = preg_replace ('/^.*::/', '', $widgetClass);
 962:             if (!class_exists ($widgetSettings['modelType'])) {
 963:                 echo 'false';
 964:             }
 965:         }
 966: 
 967:         $widgetLayoutName = $_POST['widgetLayoutName'];
 968:         list ($success, $uid) = SortableWidget::createSortableWidget (
 969:             Yii::app()->params->profile, $widgetClass, $widgetLayoutName, $widgetSettings);
 970:         if ($success) {
 971:             echo $widgetClass::getWidgetContents(
 972:                 $this, Yii::app()->params->profile, $widgetLayoutName, $uid);
 973:         } else {
 974:             echo 'false';
 975:         }
 976: 
 977:     }
 978: 
 979:     /***********************************************************************
 980:      * Profile Page Methods
 981:      ***********************************************************************/
 982: 
 983:     public function actionCreateChartingWidget () {
 984:         if (!isset ($_POST['widgetLayoutName']) || !isset ($_POST['chartId'])) {
 985:             throw new CHttpException (400, 'Bad Request');
 986:         }
 987: 
 988:         $chartId = $_POST['chartId'];
 989:         $widgetSettings = array ();
 990: 
 991:         $chart = Charts::findByPk($chartId);
 992: 
 993: 
 994:         if (preg_match ('/::/', $widgetClass)) {
 995:             // Custom module summary widget. extract model name
 996:             $widgetSettings['modelType'] = preg_replace ('/::.*$/', '', $widgetClass);
 997:             $widgetSettings['label'] = $widgetSettings['modelType'] . ' Summary';
 998:             $widgetClass = preg_replace ('/^.*::/', '', $widgetClass);
 999:             if (!class_exists ($widgetSettings['modelType'])) {
1000:                 echo 'false';
1001:             }
1002:         }
1003: 
1004:         $widgetLayoutName = $_POST['widgetLayoutName'];
1005:         list ($success, $uid) = SortableWidget::createSortableWidget (
1006:             Yii::app()->params->profile, $widgetClass, $widgetLayoutName, $widgetSettings);
1007:         if ($success) {
1008:             echo $widgetClass::getWidgetContents(
1009:                 $this, Yii::app()->params->profile, $widgetLayoutName, $uid);
1010:         } else {
1011:             echo 'false';
1012:         }
1013: 
1014:     }
1015: 
1016:     public function actionDeleteSortableWidget () {
1017:         if (!isset ($_POST['widgetLayoutName']) || !isset ($_POST['widgetKey'])) {
1018:             throw new CHttpException (400, 'Bad Request');
1019:         }
1020:         $widgetKey = $_POST['widgetKey'];
1021: 
1022:         $profile = self::getModelFromPost();
1023: 
1024:         list($widgetClass, $widgetUID) = SortableWidget::parseWidgetLayoutKey ($widgetKey);
1025:             $widgetLayoutName = $_POST['widgetLayoutName'];
1026:         if (SortableWidget::subtypeIsValid ($widgetLayoutName, $widgetClass)) {
1027:             if (SortableWidget::deleteSortableWidget (
1028:                 $profile, $widgetClass, $widgetUID, $widgetLayoutName)) {
1029: 
1030:                 echo 'success';
1031:                 return;
1032:             }
1033:         }
1034:         echo 'failure';
1035:     }
1036: 
1037:     public static function getModelFromPost() {
1038:         if (isset($_POST['settingsModelName']) && isset($_POST['settingsModelId'])) {
1039:             if ($_POST['settingsModelName'] && $_POST['settingsModelId']) {
1040:                 return X2Model::model($_POST['settingsModelName'])
1041:                     ->findByPk($_POST['settingsModelId']);
1042:             }
1043:         } 
1044: 
1045:         return $profile = Yii::app()->params->profile;
1046:     }
1047: 
1048: 
1049: 
1050:     /**
1051:      * Called to save profile widget sort order
1052:      * Expected POST data:
1053:      *  widgetOrder - an array of strings, each corresponding to a widget class name
1054:      * Echoes:
1055:      *  'failure' if the request action fails, 'success' otherwise
1056:      */
1057:     public function actionSetWidgetOrder() {
1058:         if (!isset($_POST['widgetOrder']) ||
1059:                 !is_array($_POST['widgetOrder']) || !isset($_POST['widgetType'])) {
1060: 
1061:             echo 'Failure: invalid post params';
1062:             return;
1063:         }
1064:         $profile = self::getModelFromPost();
1065:         $widgetOrder = $_POST['widgetOrder'];
1066:         $widgetType = $_POST['widgetType'];
1067: 
1068:         if (SortableWidget::setSortOrder($profile, $widgetOrder, $widgetType)) {
1069:             echo 'success';
1070:             return;
1071:         }
1072:         echo 'Failure: failed to set sort order';
1073:     }
1074: 
1075:     /**
1076:      * Called to retieve widget contents
1077:      * Expected POST data:
1078:      *  widgetClass - the name of the widget class
1079:      * Echoes:
1080:      *  'failure' if the request action fails, an HTML string containing the widget contents 
1081:      *      otherwise
1082:      */
1083:     public function actionShowWidgetContents() {
1084:         if (!isset($_POST['widgetClass']) || !isset($_POST['widgetType'])) {
1085: 
1086:             echo 'failure';
1087:             return;
1088:         }
1089:         if (isset($_POST['widgetType']) && 
1090:             SortableWidget::getParentType ($_POST['widgetType']) === 'recordView' && 
1091:             (!isset ($_POST['modelId']) || !isset ($_POST['modelType']))) {
1092: 
1093:             echo 'failure';
1094:             return;
1095:         }
1096:         $profile = self::getModelFromPost();
1097:         $widgetKey = $_POST['widgetClass'];
1098:         $widgetType = $_POST['widgetType'];
1099:         list($widgetClass, $widgetUID) = SortableWidget::parseWidgetLayoutKey ($widgetKey);
1100: 
1101:         if ($profile && class_exists($widgetClass)) {
1102:             if ($widgetClass::setJSONProperty($profile, 'hidden', 0, $widgetType, $widgetUID)) {
1103:                 if (SortableWidget::getParentType ($widgetType) === 'recordView') {
1104:                     $model = X2Model::getModelOfTypeWithId (
1105:                         $_POST['modelType'], $_POST['modelId']);
1106:                     if ($model !== null && $model instanceof X2Model) {
1107:                         echo $widgetClass::getWidgetContents(
1108:                             $this, $profile, $widgetType, $widgetUID, 
1109:                             array (
1110:                                 'model' => $model,
1111:                             ));
1112:                     }
1113:                 } else {
1114:                     echo $widgetClass::getWidgetContents($this, $profile, $widgetType, $widgetUID);
1115:                 }
1116:                 return;
1117:             }
1118:         }
1119:         echo 'failure';
1120:         return;
1121:     }
1122: 
1123:     /**
1124:      * A wrapper around actionShowWidgetContents () which allows widget contents to be requested
1125:      * with a GET request. This is used for gridview widgets.
1126:      */
1127:     public function actionGetWidgetContents() {
1128:         if (!isset($_GET['widgetClass']) ||
1129:                 !isset($_GET['widgetType'])) {
1130: 
1131:             echo 'failure';
1132:             return;
1133:         }
1134:         $_POST['widgetClass'] = $_GET['widgetClass'];
1135:         $_POST['widgetType'] = $_GET['widgetType'];
1136: 
1137:         if (isset($_GET['settingsModelName'])) {
1138:             $_POST['settingsModelName'] = $_GET['settingsModelName'];
1139:         }
1140: 
1141:         if (isset($_GET['settingsModelId'])) {
1142:             $_POST['settingsModelId'] = $_GET['settingsModelId'];
1143:         }
1144: 
1145: 
1146:         $this->actionShowWidgetContents();
1147:         return;
1148:     }
1149: 
1150:     /**
1151:      * Called to save settings for a particular profile widget
1152:      * Expected POST data:
1153:      *  widgetClass - the name of the widget class
1154:      *  key - the widget settings JSON property 
1155:      *  value - the value which the JSON property will be set to 
1156:      * Echoes:
1157:      *  'failure' if the request action fails, 'success' otherwise
1158:      */
1159:     public function actionSetWidgetSetting() {
1160:         if (!isset($_POST['widgetClass']) || 
1161:             ((!isset ($_POST['props']) || !is_array ($_POST['props'])) && 
1162:              (!isset($_POST['key']) || !isset($_POST['value']))) ||
1163:             !isset($_POST['widgetType']) || !isset($_POST['widgetUID'])) {
1164: 
1165:             throw new CHttpException (404, 'Bad Request');
1166:         }
1167: 
1168:         $profile = self::getModelFromPost();
1169:         $widgetClass = $_POST['widgetClass'];
1170:         $widgetType = $_POST['widgetType'];
1171:         $widgetUID = $_POST['widgetUID'];
1172:         $failed = false;
1173:         if (class_exists($widgetClass) &&
1174:             method_exists($widgetClass, 'setJSONProperty')) {
1175: 
1176:             if (isset ($_POST['props'])) {
1177:                 foreach ($_POST['props'] as $key => $value) {
1178:                     if (!$widgetClass::setJSONProperty(
1179:                         $profile, $key, $value, $widgetType, $widgetUID)) {
1180:                         
1181:                         $failed = true;
1182:                         break;
1183:                     }
1184:                 }
1185:             } else {
1186:                 $key = $_POST['key'];
1187:                 $value = $_POST['value'];
1188: 
1189:                 if (!$widgetClass::setJSONProperty(
1190:                     $profile, $key, $value, $widgetType, $widgetUID)) {
1191: 
1192:                     $failed = true;
1193:                 }
1194:             }
1195:         } else {
1196:             $failed = true;
1197:         }
1198:         echo $failed ? 'failure' : 'success';
1199:     }
1200: 
1201:     public function getActivityFeedViewParams($id, $publicProfile) {
1202:         Events::deleteOldEvents();
1203: 
1204:         $isMyProfile = !$publicProfile && $id === Yii::app()->params->profile->id;
1205:         $profile = $this->loadModel($id);
1206: 
1207:         if (!Yii::app()->request->isAjaxRequest || Yii::app()->params->isMobileApp) {
1208:             $_SESSION['lastDate'] = 0;
1209:             unset($_SESSION['lastEventId']);
1210:         }
1211: 
1212:         unset($_SESSION['feed-condition']);
1213:         unset($_SESSION['feed-condition-params']);
1214:         if (!isset($_GET['filters'])) {
1215:             unset($_SESSION['filters']);
1216:         }
1217:         if (isset(Yii::app()->params->profile->defaultFeedFilters)) {
1218:             $_SESSION['filters'] = json_decode(
1219:                 Yii::app()->params->profile->defaultFeedFilters, true);
1220:         }
1221: 
1222:         $filters = null;
1223:         $filtersOn = false;
1224:         if (isset($_GET['filters'])) {
1225:             $filters = $_GET;
1226:             if ($_GET['filters']) {
1227:                 $filtersOn = true;
1228:             }
1229:         }
1230: 
1231:         $retVal = Events::getFilteredEventsDataProvider(
1232:             $profile, $isMyProfile, $filters, $filtersOn);
1233:         $dataProvider = $retVal['dataProvider'];
1234:         $lastTimestamp = $retVal['lastTimestamp'];
1235:         $lastId = $retVal['lastId'];
1236: 
1237:         $data = $dataProvider->getData();
1238:         if (isset($data[count($data) - 1]))
1239:             $firstId = $data[count($data) - 1]->id;
1240:         else
1241:             $firstId = 0;
1242: 
1243:         if ($isMyProfile) {
1244:             $users = User::getUserIds();
1245:         } else {
1246:             $users = array($profile->id => $profile->fullName);
1247:         }
1248: 
1249:         $_SESSION['firstFlag'] = true;
1250:         $stickyDataProvider = new CActiveDataProvider('Events', array(
1251:             'criteria' => array(
1252:                 'condition' => 'sticky=1',
1253:                 'order' => 'timestamp DESC, id DESC',
1254:             ),
1255:             'pagination' => array(
1256:                 'pageSize' => 20
1257:             ),
1258:         ));
1259:         $_SESSION['stickyFlag'] = false;
1260: 
1261:         $userModels = User::model ()->active ()->findAll ();
1262:         return array(
1263:             'model' => $profile,
1264:             'profileId' => $profile->id,
1265:             'isMyProfile' => $isMyProfile,
1266:             'dataProvider' => $dataProvider,
1267:             'users' => $users,
1268:             'lastEventId' => !empty($lastId) ? $lastId : 0,
1269:             'firstEventId' => !empty($firstId) ? $firstId : 0,
1270:             'lastTimestamp' => $lastTimestamp,
1271:             'stickyDataProvider' => $stickyDataProvider,
1272:             'userModels' => $userModels
1273:         );
1274:     }
1275: 
1276:     
1277: 
1278:     public function actionActivity() {
1279:         $id = Yii::app()->params->profile->id;
1280:         $params = $this->getActivityFeedViewParams($id, false);
1281:         $this->render('activity', $params);
1282:     }
1283: 
1284:     /**
1285:      * Default landing page action for the web application.
1286:      *
1287:      * Displays a feed of new records that have been created since the last
1288:      * login of the current web user.
1289:      */
1290:     public function actionView($id, $publicProfile = false) {
1291:         if (isset($_GET['ajax'])) { // ajax request from grid view widget
1292:             if (!isset ($_POST['widgetClass']) && !isset ($_POST['widgetType'])) {
1293:                 $_POST['widgetClass'] = $_GET['ajax'];
1294:                 $_POST['widgetType'] = $_GET['widgetType'];
1295:             }
1296:             if (SortableWidget::getParentType ($_POST['widgetType']) === 'recordView') {
1297:                 $_POST['modelId'] = $_GET['modelId'];
1298:                 $_POST['modelType'] = $_GET['modelType'];
1299:             }
1300:             $this->actionShowWidgetContents();
1301:             return;
1302:         }
1303:         if (isset($_GET['widgetClass']) && // record view widget update request
1304:             isset($_GET['widgetType']) &&
1305:             SortableWidget::getParentType ($_GET['widgetType']) === 'recordView' &&
1306:             isset ($_GET['modelId']) &&
1307:             isset ($_GET['modelType'])) {
1308: 
1309:             $_POST['widgetClass'] = $_GET['widgetClass'];
1310:             $_POST['widgetType'] = $_GET['widgetType'];
1311:             $_POST['modelId'] = $_GET['modelId'];
1312:             $_POST['modelType'] = $_GET['modelType'];
1313:             $this->actionShowWidgetContents();
1314:             return;
1315:         }
1316:         if (isset($_GET['widgetClass']) && // widget update request
1317:             isset($_GET['widgetType'])) {
1318: 
1319:             $_POST['widgetClass'] = $_GET['widgetClass'];
1320:             $_POST['widgetType'] = $_GET['widgetType'];
1321:             $this->actionShowWidgetContents();
1322:             return;
1323:         }
1324: 
1325:         if (!Yii::app()->user->isGuest) {
1326:             $activityFeedParams = $this->getActivityFeedViewParams($id, $publicProfile);
1327: 
1328:             $params = array(
1329:                 'activityFeedParams' => $activityFeedParams,
1330:                 'isMyProfile' => $activityFeedParams['isMyProfile'],
1331:                 'model' => $activityFeedParams['model']
1332:             );
1333: 
1334:             $this->render('profile', $params);
1335:         } else {
1336:             $this->redirectToLogin ();
1337:         }
1338: 
1339:     }
1340: 
1341:     public function actionGetEvents($lastEventId, $lastTimestamp, $myProfileId, $profileId) {
1342:         // validate params
1343:         if (!ctype_digit ($lastEventId) ||
1344:             !ctype_digit ($lastTimestamp) ||
1345:             !ctype_digit ($myProfileId) ||
1346:             !ctype_digit ($profileId)) {
1347: 
1348:             throw new CHttpException (400, Yii::t('app', 'Invalid parameter'));
1349:         }
1350: 
1351:         $myProfile = Profile::model()->findByPk($myProfileId);
1352:         $profile = Profile::model()->findByPk($profileId);
1353:         if (!isset($myProfile) || !isset($profile))
1354:             return false;
1355: 
1356: 
1357:         $result = Events::getEvents(
1358:             $lastEventId, $lastTimestamp, null, $profile, $myProfile->id === $profile->id);
1359: 
1360:         $events = $result['events'];
1361:         $eventData = "";
1362:         $newLastEventId = $lastEventId;
1363:         $newLastTimestamp = $lastTimestamp;
1364:         foreach ($events as $event) {
1365:             if ($event instanceof Events) {
1366:                 if ($event->id > $newLastEventId) {
1367:                     $newLastEventId = $event->id;
1368:                 }
1369:                 if ($event->timestamp > $newLastTimestamp) {
1370:                     $newLastTimestamp = $event->timestamp;
1371:                 }
1372:                 $eventData.=$this->renderPartial(
1373:                         'application.views.profile._viewEvent', array(
1374:                     'data' => $event,
1375:                     'noDateBreak' => true,
1376:                     'profileId' => $profileId,
1377:                         ), true
1378:                 );
1379:             }
1380:         }
1381:         $commentCriteria = new CDbCriteria();
1382:         $sqlParams = array(
1383:             ':lastEventId' => $lastEventId
1384:         );
1385:         $condition = "associationType='Events' AND 
1386:             timestamp <=" . time() . " AND id > :lastEventId";
1387:         $parameters = array('order' => 'id ASC');
1388:         $parameters['condition'] = $condition;
1389:         $parameters['params'] = $sqlParams;
1390:         $commentCriteria->scopes = array('findAll' => array($parameters));
1391:         $comments = X2Model::model('Events')->findAll($commentCriteria);
1392:         $commentCounts = array();
1393:         $lastCommentId = $lastEventId;
1394:         foreach ($comments as $comment) {
1395:             $parentPost = X2Model::model('Events')->findByPk($comment->associationId);
1396:             if (isset($parentPost) && !isset($commentCounts[$parentPost->id])) {
1397:                 $commentCounts[$parentPost->id] = count($parentPost->children);
1398:             }
1399:             $lastCommentId = $comment->id;
1400:         }
1401: 
1402:         echo CJSON::encode(array(
1403:             $newLastEventId,
1404:             $newLastEventId != $lastEventId ? $eventData : '',
1405:             $commentCounts,
1406:             $lastCommentId,
1407:             $newLastTimestamp,
1408:         ));
1409:     }
1410: 
1411:     public function actionGetEventsBetween ($startTimestamp, $endTimestamp, $widgetType) {
1412:         if (class_exists ($widgetType) && is_subclass_of ($widgetType, 'SortableWidget')) {
1413:             echo CJSON::encode($widgetType::getChartData($startTimestamp, $endTimestamp));
1414:         } else {
1415:             throw new CHttpException (404, 'Bad Request.');
1416:         }
1417:     }
1418: 
1419:     public function actionLoadComments($id, $profileId) {
1420:         $commentDataProvider = new CActiveDataProvider('Events', array(
1421:             'criteria' => array(
1422:                 'order' => 'timestamp ASC',
1423:                 'condition' => "type in ('comment', 'structured-feed') AND associationType='Events' AND associationId=$id",
1424:         )));
1425:         $this->widget('zii.widgets.CListView', array(
1426:             'dataProvider' => $commentDataProvider,
1427:             'viewData' => array(
1428:                 'profileId' => $profileId
1429:             ),
1430:             'itemView' => '../social/_view',
1431:             'template' => '&nbsp;{items}',
1432:             'id' => $id . '-comments',
1433:         ));
1434:     }
1435: 
1436:     /*
1437:       Used for both like and unlike buttons. If the user has alread liked the
1438:       post, the post will be unliked and visa versa. The function returns a string
1439:       indicating whether the post was liked or unliked.
1440:       Parameter:
1441:       $id - the user's id
1442:      */
1443: 
1444:     public function actionLikePost($id) {
1445:         $userId = Yii::app()->user->id;
1446: 
1447:         $likedPost = Yii::app()->db->createCommand()
1448:                 ->select('count(userId)')
1449:                 ->from('x2_like_to_post')
1450:                 ->where('userId=:userId and postId=:postId', array(':userId' => Yii::app()->user->id, ':postId' => $id))
1451:                 ->queryScalar();
1452: 
1453:         if (!$likedPost) {
1454:             Yii::app()->db->createCommand()
1455:                     ->insert('x2_like_to_post', array('userId' => $userId, 'postId' => $id));
1456:             echo 'liked post';
1457:         } else {
1458:             Yii::app()->db->createCommand()
1459:                     ->delete('x2_like_to_post', 'userId=:userId and postId=:postId', array('userId' => $userId, 'postId' => $id));
1460:             echo 'unliked post';
1461:         }
1462:     }
1463: 
1464:     /*
1465:       Returns an array of links to the user profiles of users who have liked the
1466:       post.
1467:       Parameter:
1468:       $id - the id of the post
1469:      */
1470: 
1471:     public function actionLoadLikeHistory($id) {
1472:         $likeHistory = Yii::app()->db->createCommand()
1473:                 ->select('concat (firstName, " ", lastName), usrs.id')
1474:                 ->from('x2_like_to_post as likes, x2_users as usrs')
1475:                 ->where('likes.userId=usrs.id and likes.postId=:postId', array('postId' => $id))
1476:                 ->queryAll();
1477: 
1478:         $likeHistoryLinks = array();
1479:         foreach ($likeHistory as $like) {
1480:             $likeHistoryLinks[] = CHtml::link($like['concat (firstName, " ", lastName)'], array('/profile/view', 'id' => $like['id']));
1481:         }
1482: 
1483:         echo CJSON::encode($likeHistoryLinks);
1484:     }
1485: 
1486:     /*
1487:       Indicates that a post is important by changing it's css properties.
1488:       Called via ajax from the make important dialog.
1489:      */
1490: 
1491:     public function actionFlagPost() {
1492:         if (isset($_GET['id']) && isset($_GET['attr'])) {
1493:             $id = $_GET['id'];
1494:             $important = $_GET['attr'];
1495:             $event = X2Model::model('Events')->findByPk($id);
1496:             if (isset($event)) {
1497:                 if (isset($_GET['color']) && !empty($_GET['color'])) {
1498:                     $event->color = $_GET['color'];
1499:                 } else {
1500:                     $event->color = null;
1501:                 }
1502:                 if (isset($_GET['fontColor']) && !empty($_GET['fontColor'])) {
1503:                     $event->fontColor = $_GET['fontColor'];
1504:                 } else {
1505:                     $event->fontColor = null;
1506:                 }
1507:                 if (isset($_GET['linkColor']) && !empty($_GET['linkColor'])) {
1508:                     $event->linkColor = $_GET['linkColor'];
1509:                 } else {
1510:                     $event->linkColor = null;
1511:                 }
1512:                 if ($important == 'important') {
1513:                     $event->important = 1;
1514:                 } else {
1515:                     $event->important = 0;
1516:                 }
1517:                 if( $event->save() ) {
1518:                     echo 'success';
1519:                     return;
1520:                 }
1521:             }
1522:         }
1523: 
1524:         echo 'failure';
1525: 
1526:     }
1527: 
1528:     /*
1529:       Broadcasts an event via email or notification to a list of users.
1530:       Called via ajax from the broadcast event dialog.
1531:      */
1532: 
1533:     public function actionBroadcastEvent($id, $email, $notify, $users) {
1534:         $event = X2Model::model('Events')->findByPk($id);
1535:         if (isset($event)) {
1536:             $users = Profile::model()->findAllByPk(CJSON::decode($users));
1537:             if ($email === 'true') { // broadcast via email
1538:                 // Check if user has set a default account for email delivery
1539:                 $subject = "Event Broadcast";
1540:                 $fromName = Yii::app()->params->profile->fullName;
1541:                 $body = "$fromName has broadcast an event on your X2Engine Activity Feed:<br><br>" .
1542:                         $event->getText(array('requireAbsoluteUrl' => true));
1543:                 $recipients = array('to' => array());
1544:                 foreach ($users as $user)
1545:                     $recipients['to'][] = array($user->fullName, $user->emailAddress);
1546:                 //$this->sendUserEmail($recipients, $subject, $body, null, Credentials::$sysUseId['systemNotificationEmail']);
1547:                 $this->sendUserEmail($recipients, $subject, $body);
1548:             }
1549:             if ($notify === 'true') { // broadcast via notifation
1550:                 $time = time();
1551:                 foreach ($users as $user) {
1552:                     $notif = new Notification;
1553:                     $notif->modelType = 'Events';
1554:                     $notif->createdBy = Yii::app()->user->getName();
1555:                     $notif->modelId = $event->id;
1556:                     $notif->user = $user->username;
1557:                     $notif->createDate = $time;
1558:                     $notif->type = 'event_broadcast';
1559:                     $notif->save();
1560:                 }
1561:             }
1562:         }
1563:     }
1564: 
1565:     public function actionStickyPost($id) {
1566:         if (Yii::app()->params->isAdmin) {
1567:             $event = X2Model::model('Events')->findByPk($id);
1568:             if (isset($event)) {
1569:                 $event->sticky = !$event->sticky;
1570:                 $event->update(array('sticky'));
1571:             }
1572:             echo (date("M j", time()) == date("M j", $event->timestamp) ? Yii::t('app', "Today") : Yii::app()->locale->dateFormatter->formatDateTime($event->timestamp, 'long', null));
1573:         }
1574:     }
1575: 
1576:     public function actionMinimizePosts() {
1577:         if (isset($_GET['minimize'])) {
1578:             $profile = Yii::app()->params->profile;
1579:             if ($_GET['minimize'] == 'minimize') {
1580:                 $profile->minimizeFeed = 1;
1581:             } else {
1582:                 $profile->minimizeFeed = 0;
1583:             }
1584:             echo $_GET['minimize'] == true;
1585:             $profile->save();
1586:         }
1587:     }
1588: 
1589:     /**
1590:      * Create a new chart setting record in the chart settings table.
1591:      * Called via ajax from the chart setting creation dialog.
1592:      */
1593:     function actionCreateChartSetting() {
1594:         if (isset($_POST['chartSettingAttributes'])) {
1595:             $chartSettingAttributes = $_POST['chartSettingAttributes'];
1596:             $chartSetting = new ChartSetting;
1597:             if (is_array($chartSettingAttributes) &&
1598:                     array_key_exists('settings', $chartSettingAttributes) &&
1599:                     array_key_exists('chartType', $chartSettingAttributes) &&
1600:                     array_key_exists('name', $chartSettingAttributes)) {
1601: 
1602:                 $chartSetting->settings = $chartSettingAttributes['settings'];
1603:                 $chartSetting->name = $chartSettingAttributes['name'];
1604:                 $chartSetting->chartType = $chartSettingAttributes['chartType'];
1605:                 $chartSetting->userId = Yii::app()->user->id;
1606:                 if ($chartSetting->validate()) {
1607:                     if ($chartSetting->save()) {
1608:                         return;
1609:                     }
1610:                 }
1611:                 echo CJSON::encode($chartSetting->getErrors());
1612:                 return;
1613:             }
1614:         }
1615:         echo CJSON::encode(array('failure'));
1616:     }
1617: 
1618:     /**
1619:      * Delete a chart setting record from the chart settings table.
1620:      * Called via ajax from the feed chart UI.
1621:      */
1622:     function actionDeleteChartSetting($chartSettingName) {
1623:         $chartSetting = ChartSetting::model()->findByAttributes(array(
1624:             'userId' => Yii::app()->user->id,
1625:             'name' => $chartSettingName
1626:         ));
1627:         if (!empty($chartSetting) && $chartSetting->delete()) {
1628:             echo 'success';
1629:         } else {
1630:             echo 'failure';
1631:         }
1632:     }
1633: 
1634:     public function actionPublishPost() {
1635:         $post = new Events;
1636:         // $user = $this->loadModel($id);
1637:         if (isset($_POST['text']) && $_POST['text'] != "") {
1638:             $post->text = $_POST['text'];
1639:             $post->visibility = $_POST['visibility'];
1640:             if (isset($_POST['associationId'])) {
1641:                 $post->associationId = $_POST['associationId'];
1642:                 $post->associationType = 'User';
1643:             }
1644:             //$soc->attributes = $_POST['Social'];
1645:             //die(var_dump($_POST['Social']));
1646:             $post->user = Yii::app()->user->getName();
1647:             $post->type = 'feed';
1648:             $post->subtype = $_POST['subtype'];
1649:             $post->lastUpdated = time();
1650:             $post->timestamp = time();
1651:             if ($post->save()) {
1652:                 if (!empty($post->associationId) && 
1653:                     $post->associationId != Yii::app()->user->getId() &&
1654:                     $post->isVisibleTo (User::model ()->findByPk ($post->associationId))) {
1655: 
1656:                     $notif = new Notification;
1657: 
1658:                     $notif->type = 'social_post';
1659:                     $notif->createdBy = $post->user;
1660:                     $notif->modelType = 'Profile';
1661:                     $notif->modelId = $post->associationId;
1662: 
1663:                     $notif->user = Yii::app()->db->createCommand()
1664:                             ->select('username')
1665:                             ->from('x2_users')
1666:                             ->where('id=:id', array(':id' => $post->associationId))
1667:                             ->queryScalar();
1668: 
1669:                     // $prof = X2Model::model('Profile')->findByAttributes(array('username'=>$post->user));
1670:                     // $notif->text = "$prof->fullName posted on your profile.";
1671:                     // $notif->record = "profile:$prof->id";
1672:                     // $notif->viewed = 0;
1673:                     $notif->createDate = time();
1674:                     // $subject=X2Model::model('Profile')->findByPk($id);
1675:                     // $notif->user = $subject->username;
1676:                     $notif->save();
1677:                 }
1678:             }
1679:         }
1680:     }
1681: 
1682:     public function actionAddComment() {
1683:         if (isset($_POST['id']) && isset($_POST['text']) && $_POST['text'] != '') {
1684:             $id = $_POST['id'];
1685:             $comment = $_POST['text'];
1686:             $postModel = Events::model()->findByPk($id);
1687: 
1688:             if ($postModel === null)
1689:                 throw new CHttpException(404, Yii::t('app', 'The requested post does not exist.'));
1690: 
1691:             $commentModel = new Events;
1692:             $commentModel->text = $comment;
1693:             $commentModel->user = Yii::app()->user->name;
1694:             $commentModel->type = 'comment';
1695:             $commentModel->associationId = $postModel->id;
1696:             $commentModel->associationType = 'Events';
1697:             $commentModel->timestamp = time();
1698: 
1699:             if ($commentModel->save()) {
1700:                 $commentCount = X2Model::model('Events')->countByAttributes(array(
1701:                     'type' => 'comment',
1702:                     'associationType' => 'Events',
1703:                     'associationId' => $postModel->id,
1704:                 ));
1705:                 $postModel->lastUpdated = time();
1706:                 $postModel->save();
1707: 
1708:                 $profileUser = Yii::app()->db->createCommand()
1709:                         ->select('username')
1710:                         ->from('x2_users')
1711:                         ->where('id=:id', array(':id' => $postModel->associationId))
1712:                         ->queryScalar();
1713: 
1714: 
1715:                 // notify the owner of the feed containing the post you commented on (unless that person is you)
1716:                 if ($postModel->associationId != Yii::app()->user->getId()) {
1717:                     $postNotif = new Notification;
1718:                     $postNotif->type = 'social_comment';
1719:                     $postNotif->createdBy = $commentModel->user;
1720:                     $postNotif->modelType = 'Profile';
1721:                     $postNotif->modelId = $postModel->associationId;
1722: 
1723:                     // look up the username of the owner of the feed
1724:                     $postNotif->user = $profileUser;
1725: 
1726:                     $postNotif->createDate = time();
1727:                     $postNotif->save();
1728:                 }
1729:                 // now notify the person whose post you commented on (unless they're the same person as the first notification)
1730:                 if ($profileUser != $postModel->user && $postModel->user != Yii::app()->user->name) {
1731:                     $commentNotif = new Notification;
1732:                     $commentNotif->type = 'social_comment';
1733:                     $commentNotif->createdBy = $commentModel->user;
1734:                     $commentNotif->modelType = 'Profile';
1735:                     $commentNotif->modelId = $postModel->associationId;
1736: 
1737:                     $commentNotif->user = $postModel->user;
1738: 
1739:                     $commentNotif->createDate = time();
1740:                     $commentNotif->save();
1741:                 }
1742:             }
1743:             echo $commentCount;
1744:         } else {
1745:             echo "";
1746:         }
1747:     }
1748: 
1749:     public function actionToggleFeedFilters($filter) {
1750:         $profile = Yii::app()->params->profile;
1751:         if (isset($profile)) {
1752:             $filters = json_decode($profile->feedFilters, true);
1753:             if (isset($filters[$filter])) {
1754:                 $filters[$filter] = $filters[$filter] == 1 ? 0 : 1;
1755:             } else {
1756:                 $filters[$filter] = 0;
1757:             }
1758:             $flag = $filters[$filter];
1759:             $profile->feedFilters = json_encode($filters);
1760:             $profile->update(array('feedFilters'));
1761:             echo $flag;
1762:         }
1763:     }
1764: 
1765:     public function actionToggleFeedControls() {
1766:         $profile = Yii::app()->params->profile;
1767:         if (isset($profile)) {
1768:             $profile->fullFeedControls = !$profile->fullFeedControls;
1769:             $profile->update(array('fullFeedControls'));
1770:         }
1771:     }
1772: 
1773:     /**
1774:      * Saves a default template for the specified module into the users profile settings
1775:      * @param string $moduleName
1776:      * @param int $templateId
1777:      */
1778:     public function actionAjaxSaveDefaultEmailTemplate($moduleName, $templateId) {
1779:         $profile = Yii::app()->params->profile;
1780:         $errors = false;
1781:         $message = '';
1782:         if (isset($profile)) {
1783:             $defaultEmailTemplates = CJSON::decode($profile->defaultEmailTemplates);
1784: 
1785:             if ($templateId !== '') {
1786:                 $template = Docs::model()->findByPk($templateId);
1787:                 if (!$this->checkPermissions($template, 'view')) {
1788:                     $errors = true;
1789:                     $message = Yii::t(
1790:                                     'profile', 'You do not have permission to view that template');
1791:                 } else {
1792:                     // check that template exists, that it's of the correct doc type, and is 
1793:                     // associated with the correct model type
1794:                     if ($template && 
1795:                         (($template->type === 'email' &&
1796:                          $template->associationType === X2Model::getModelName($moduleName)) ||
1797:                          ($template->type === 'quote' && $moduleName === 'quotes'))) {
1798: 
1799:                         $defaultEmailTemplates[$moduleName] = $templateId;
1800:                         $profile->defaultEmailTemplates = CJSON::encode($defaultEmailTemplates);
1801:                         $profile->save();
1802:                     } else {
1803:                         $errors = true;
1804:                         $message = Yii::t('profile', 'Invalid template');
1805:                     }
1806:                 }
1807:             } else { // remove default
1808:                 if (isset($defaultEmailTemplates[$moduleName]))
1809:                     unset($defaultEmailTemplates[$moduleName]);
1810:                 $profile->defaultEmailTemplates = CJSON::encode($defaultEmailTemplates);
1811:                 $profile->save();
1812:             }
1813:         } else {
1814:             $message = Yii::t('profile', 'Profile not found');
1815:         }
1816:         echo CJSON::encode(array(
1817:             'success' => !$errors,
1818:             'message' => $message,
1819:         ));
1820:     }
1821: 
1822:     public function insertActionMenu () {
1823:         $model = Yii::app()->user;
1824: 
1825:         $this->actionMenu = array(
1826:             array(
1827:                 'name' => 'view', 
1828:                 'label' => Yii::t('profile', 'Profile Dashboard'), 
1829:                 'url' => array('view', 'id' => $model->id)
1830:             ),
1831:             array(
1832:                 'name' => 'profiles', 
1833:                 'label' => Yii::t('profile', 'All Profiles'), 
1834:                 'url' => array('profiles')
1835:             ),
1836:             array(
1837:                 'name' => 'viewPublic', 
1838:                 'label' => Yii::t('profile', 'View Profile'), 
1839:                 'url' => array('view', 'id' => $model->id, 'publicProfile' => 1)
1840:             ),
1841:             array(
1842:                 'name' => 'edit', 
1843:                 'label' => Yii::t('profile', 'Edit Profile'),
1844:                 'url' => array('update', 'id' => $model->id)
1845:             ),
1846:             array(
1847:                 'name' => 'settings', 
1848:                 'label' => Yii::t('profile', 'Change Settings'), 
1849:                 'url' => array('settings', 'id' => $model->id), 'visible' => ($model->id == Yii::app()->user->id)
1850:             ),
1851:             array(
1852:                 'name' => 'changePassword', 
1853:                 'label' => Yii::t('profile', 'Change Password'), 
1854:                 'url' => array('changePassword', 'id' => $model->id), 'visible' => ($model->id == Yii::app()->user->id)
1855:             ),
1856:             array(
1857:                 'name' => 'manageCredentials', 
1858:                 'label' => Yii::t('profile', 'Manage Apps'), 
1859:                 'url' => array('manageCredentials')
1860:                 ),
1861:             
1862:         );
1863: 
1864:         if ($this->action->id == 'view') {
1865:             if (isset($_GET['publicProfile']) && $_GET['publicProfile']) {
1866:                 unset($this->actionMenu[2]['url']);
1867:             } 
1868:             return;
1869:         }
1870:         
1871:         $this->prepareMenu ($this->actionMenu, true);
1872:     }
1873: 
1874:     /**
1875:      * Action to reset all tip and show them again
1876:      */
1877:     public function actionResetTours() {
1878:         Tours::model()->updateAll (array(
1879:             'seen' => null,
1880:         ), 'profileId=:profileId', array(
1881:             'profileId' => Yii::app()->params->profile->id
1882:         ));
1883: 
1884:         echo 'success';
1885:     }
1886: 
1887: 
1888:     /**
1889:      * Action to reset all tip and show them again
1890:      */
1891:     public function actionDisableTours () {
1892:         $profile = Yii::app()->params->profile;
1893:         $profile->showTours = false;
1894:         $profile->save();
1895:         echo 'success';
1896:     }
1897: 
1898: 
1899: }
1900: 
X2CRM Documentation API documentation generated by ApiGen 2.8.0