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

  • ActionsController
  • Overview
  • Package
  • Class
  • Tree
   1: <?php
   2: 
   3: /*****************************************************************************************
   4:  * X2Engine Open Source Edition is a customer relationship management program developed by
   5:  * X2Engine, Inc. Copyright (C) 2011-2016 X2Engine Inc.
   6:  * 
   7:  * This program is free software; you can redistribute it and/or modify it under
   8:  * the terms of the GNU Affero General Public License version 3 as published by the
   9:  * Free Software Foundation with the addition of the following permission added
  10:  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
  11:  * IN WHICH THE COPYRIGHT IS OWNED BY X2ENGINE, X2ENGINE DISCLAIMS THE WARRANTY
  12:  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
  13:  * 
  14:  * This program is distributed in the hope that it will be useful, but WITHOUT
  15:  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  16:  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
  17:  * details.
  18:  * 
  19:  * You should have received a copy of the GNU Affero General Public License along with
  20:  * this program; if not, see http://www.gnu.org/licenses or write to the Free
  21:  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  22:  * 02110-1301 USA.
  23:  * 
  24:  * You can contact X2Engine, Inc. P.O. Box 66752, Scotts Valley,
  25:  * California 95067, USA. or at email address contact@x2engine.com.
  26:  * 
  27:  * The interactive user interfaces in modified source and object code versions
  28:  * of this program must display Appropriate Legal Notices, as required under
  29:  * Section 5 of the GNU Affero General Public License version 3.
  30:  * 
  31:  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
  32:  * these Appropriate Legal Notices must retain the display of the "Powered by
  33:  * X2Engine" logo. If the display of the logo is not reasonably feasible for
  34:  * technical reasons, the Appropriate Legal Notices must display the words
  35:  * "Powered by X2Engine".
  36:  *****************************************************************************************/
  37: 
  38: /**
  39:  * @package application.modules.actions.controllers
  40:  */
  41: class ActionsController extends x2base {
  42: 
  43:     public $modelClass = 'Actions';
  44:     public $showActions = null;
  45: 
  46:     public function behaviors() {
  47:         return array_merge(parent::behaviors(), array(
  48:             'ActionsQuickCreateRelationshipBehavior' => array(
  49:                 'class' => 'ActionsQuickCreateRelationshipBehavior',
  50:                 'attributesOfNewRecordToUpdate' => array(
  51:                 )
  52:             ),
  53:         ));
  54:     }
  55: 
  56:     /**
  57:      * Specifies the access control rules.
  58:      * This method is used by the 'accessControl' filter.
  59:      * @return array access control rules
  60:      */
  61:     public function accessRules(){
  62:         return array(
  63:             array('allow', // allow all users to perform 'index' and 'view' actions
  64:                 'actions' => array('invalid', 'sendReminder', 'emailOpened'),
  65:                 'users' => array('*'),
  66:             ),
  67:             array('allow', // allow authenticated user to perform 'create' and 'update' actions
  68:                 'actions' => array('index', 'view', 'create', 'createSplash', 'createInline', 'viewGroup', 'complete', //quickCreate
  69:                     'completeRedirect', 'update', 'quickUpdate', 'saveShowActions', 'viewAll', 'search', 'completeNew', 'parseType', 'uncomplete', 'uncompleteRedirect', 'delete', 'shareAction', 'inlineEmail', 'publisherCreate','saveShowActions', 'copyEvent'),
  70:                 'users' => array('@'),
  71:             ),
  72:             array('allow', // allow admin user to perform 'admin' and 'delete' actions
  73:                 'actions' => array('admin', 'testScalability'),
  74:                 'users' => array('admin'),
  75:             ),
  76:             array('deny', // deny all users
  77:                 'users' => array('*'),
  78:             ),
  79:         );
  80:     }
  81: 
  82:     public function actions(){
  83:         return array_merge(parent::actions(), array(
  84:             'captcha' => array(
  85:                 'class' => 'CCaptchaAction',
  86:                 'backColor' => 0xeeeeee,
  87:             ),
  88:             'timerControl' => array(
  89:                 'class' => 'application.modules.actions.components.TimerControlAction',
  90:             ),
  91:         ));
  92:     }
  93:     public function actionSaveShowActions(){
  94:         if(isset($_POST['ShowActions'])){
  95:             $profile = Profile::model()->findByPk(Yii::app()->user->id);
  96:             $profile->showActions = $_POST['ShowActions'];
  97:             $profile->update();
  98:         }
  99:     }
 100: 
 101:     /**
 102:      * Displays a particular model.
 103:      * @param integer $id the ID of the model to be displayed
 104:      */
 105:     public function actionView($id){
 106:         $action = CActiveRecord::model('Actions')->findByPk($id);
 107: 
 108:         if($action === null)
 109:             $this->redirect('index');
 110: 
 111:         $users = User::getNames();
 112:         $association = $this->getAssociation($action->associationType, $action->associationId);
 113: 
 114:         if($this->checkPermissions($action, 'view')){
 115: 
 116:             X2Flow::trigger('RecordViewTrigger', array('model' => $action));
 117: 
 118:             User::addRecentItem('t', $id, Yii::app()->user->getId()); //add action to user's recent item list
 119:             $this->render('view', array(
 120:                 'model' => $this->loadModel($id),
 121:                 'associationModel' => $association,
 122:                 'users' => $users,
 123:             ));
 124:         } else
 125:             $this->redirect('index');
 126:     }
 127: 
 128:     public function actionViewEmail($id){
 129:         $this->redirectOnNullModel = false;
 130:         $action = $this->loadModel($id);
 131:         if(!Yii::app()->user->isGuest || 
 132:             Yii::app()->user->checkAccess(ucfirst($action->associationType).'View')){
 133: 
 134:             header('Content-Type: text/html; charset=utf-8');
 135:             if(!Yii::app()->user->isGuest){
 136:                 echo preg_replace(
 137:                     '/<\!--BeginOpenedEmail-->(.*?)<\!--EndOpenedEmail-->/s', '', 
 138:                     $action->actionDescription);
 139:             }else{
 140:                 // Strip out the action header since it's being viewed directly:
 141:                 $actionHeaderPattern = InlineEmail::insertedPattern('ah', '(.*)', 1, 'mis');
 142:                 if(!preg_match($actionHeaderPattern, $action->actionDescription, $matches)){
 143:                     // Legacy action header
 144:                     echo preg_replace('/<b>(.*?)<\/b>(.*)/mis', '', $action->actionDescription); 
 145:                 }else{
 146:                     // Current action header
 147:                     echo preg_replace($actionHeaderPattern, '', $action->actionDescription); 
 148:                 }
 149:             }
 150:         }
 151:     }
 152: 
 153:     public function actionViewAction($id, $publisher = false){
 154:         $this->redirectOnNullModel = false;
 155:         $this->throwOnNullModel = false;
 156:         $model = $this->loadModel($id);
 157:         if(isset($model)){
 158:             if(in_array($model->type, Actions::$emailTypes)){
 159:                 $this->actionViewEmail($id);
 160:                 return;
 161:             }
 162:             X2Flow::trigger('RecordViewTrigger', array('model' => $model));
 163:             $this->renderPartial('_viewFrame', array(
 164:                 'model' => $model,
 165:                 'publisher' => $publisher,
 166:             ));
 167:         }else{
 168:             echo "<b>Error: 404</b><br><br>Unable to find the requested action.";
 169:         }
 170:     }
 171: 
 172:     public function actionShareAction($id){
 173: 
 174:         $model = $this->loadModel($id);
 175:         $body = "\n\n\n\n".Yii::t('actions', "Reminder, the following action is due")." ".Formatter::formatLongDateTime($model->dueDate).":<br />
 176: <br />".Yii::t('actions', 'Description').": $model->actionDescription
 177: <br />".Yii::t('actions', 'Type').": $model->type
 178: <br />".Yii::t('actions', 'Associations').": ".$model->associationName."
 179: <br />".Yii::t('actions', 'Link to the action').": ".CHtml::link('Link', 'http://'.Yii::app()->request->getServerName().$this->createUrl('/actions/'.$model->id));
 180:         $body = trim($body);
 181: 
 182:         $errors = array();
 183:         $status = array();
 184:         $email = array();
 185:         if(isset($_POST['email'], $_POST['body'])){
 186: 
 187:             $subject = Yii::t('actions', "Reminder, the following action is due")." ".date("Y-m-d", $model->dueDate);
 188:             $email['to'] = $this->parseEmailTo($this->decodeQuotes($_POST['email']));
 189:             $body = $_POST['body'];
 190:             // if(empty($email) || !preg_match("/[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}/",$email))
 191:             if($email['to'] === false)
 192:                 $errors[] = 'email';
 193:             if(empty($body))
 194:                 $errors[] = 'body';
 195: 
 196:             if(empty($errors))
 197:                 $status = $this->sendUserEmail($email, $subject, $body);
 198: 
 199:             if(array_search('200', $status)){
 200:                 $this->redirect(array('view', 'id' => $model->id));
 201:                 return;
 202:             }
 203:             if($email['to'] === false)
 204:                 $email = $_POST['email'];
 205:             else
 206:                 $email = $this->mailingListToString($email['to']);
 207:         }
 208:         $this->render('shareAction', array(
 209:             'model' => $model,
 210:             'body' => $body,
 211:             'email' => $email,
 212:             'status' => $status,
 213:             'errors' => $errors
 214:         ));
 215:     }
 216: 
 217:     /*public function actionSendReminder(){
 218: 
 219:         $dataProvider = new CActiveDataProvider('Actions', array(
 220:                     'criteria' => array(
 221:                         'condition' => '(dueDate<"'.mktime(23, 59, 59).'" AND dueDate>"'.mktime(0, 0, 0).'" AND complete="No")',
 222:                         )));
 223: 
 224:         $actionArray = $dataProvider->getData();
 225: 
 226:         foreach($actionArray as $action){
 227:             if($action->reminder == 1){
 228:                 $action->sendEmailRemindersToAssignees ();
 229:             }
 230:         }
 231:     }*/
 232: 
 233:     public function create($model, $oldAttributes, $api){
 234:         if($api == 0){
 235:             parent::create($model, $oldAttributes, $api);
 236:         }else
 237:             return parent::create($model, $oldAttributes, $api);
 238:     }
 239: 
 240:     /**
 241:      * Creates a new model.
 242:      * If creation is successful, the browser will be redirected to the 'view' page.
 243:      */
 244:     public function actionCreate(){
 245:         if ((Yii::app()->user->isGuest && 
 246:             !Yii::app()->user->checkAccess($_POST['Actions']['associationType'].'View'))) {
 247: 
 248:             $this->denied ();
 249:         }
 250: 
 251:         $formTypes = Actions::getFormTypes ();
 252:         foreach ($formTypes as $type) { // determine which kind of action we're creating
 253:             if (isset ($_POST[$type])) {
 254:                 $post = $_POST[$type];
 255:                 $modelType = $type;
 256:                 break;
 257:             }
 258:         }
 259:         if (!isset ($modelType) && isset ($_POST['actionType']) && 
 260:             in_array ($_POST['actionType'], $formTypes)) {
 261: 
 262:             $modelType = $_POST['actionType'];
 263:         } elseif (!isset ($modelType)) {
 264:             $modelType = 'Actions';
 265:         }
 266:         $model = new $modelType;
 267: 
 268:         if (isset ($post)){
 269:             if ($model instanceof ActionFormModelBase) {
 270:                 $model->setAttributes ($post);
 271: 
 272:                 if ($model->validate ()) {
 273:                     $model = $model->getAction (); // convert to active record
 274:                 }
 275:             } else { // ($model instanceof Actions)
 276:                 $model->setX2Fields ($post);
 277:             }
 278: 
 279:             if (!$model->hasErrors () && isset($_POST['x2ajax'])) {
 280:                 $this->quickCreate($model);
 281:                 $model->syncGoogleCalendar('create');
 282:             } elseif(!$model->hasErrors () && $model->save()){
 283:                 $model->syncGoogleCalendar('create');
 284:                 $this->redirect(array('index'));
 285:             }
 286:         }
 287:         if(empty($model->assignedTo)){
 288:             $model->assignedTo = Yii::app()->user->getName();
 289:         }
 290: 
 291:         if (isset($_POST['x2ajax'])) {
 292:             // allows form to be refreshed
 293:             if (!$model->hasErrors ()) $model = new $modelType;
 294:             $this->renderInlineForm ($model);
 295:         } else {
 296:             $this->render('create', array(
 297:                 'model' => $model,
 298:             ));
 299:         }
 300:     }
 301: 
 302:     public function actionPublisherCreate(){
 303:         if(isset($_POST['SelectedTab'], $_POST['Actions']) && 
 304:            (!Yii::app()->user->isGuest || 
 305:             Yii::app()->user->checkAccess($_POST['Actions']['associationType'].'View'))) {
 306: 
 307:             Yii::app()->clientScript->scriptMap['*.css'] = false;
 308: 
 309: //            // if association name is sent without id, try to lookup the record by name and type
 310: //            if (isset ($_POST['calendarEventTab']) && $_POST['calendarEventTab'] &&
 311: //                isset ($_POST['Actions']['associationName']) && 
 312: //                empty ($_POST['Actions']['associationId'])) {
 313: //
 314: //                $associatedModel = X2Model::getModelOfTypeWithName (
 315: //                    $_POST['Actions']['associationType'], $_POST['Actions']['associationName']);
 316: //                if ($associatedModel) {
 317: //                    $_POST['Actions']['associationId'] = $associatedModel->id;
 318: //                } else {
 319: //                    echo CJSON::encode (
 320: //                        array ('error' => Yii::t('actions', 'Invalid association name')));
 321: //                    Yii::app()->end ();
 322: //                }
 323: //            }
 324: //
 325: //            if(!Yii::app()->user->isGuest){
 326: //                $model = new Actions;
 327: //            }else{
 328: //                $model = new Actions('guestCreate');
 329: //                $model->verifyCode = $_POST['Actions']['verifyCode'];
 330: //            }
 331: //            $model->setX2Fields($_POST['Actions']);
 332: //            // format dates,
 333: //            if (isset ($_POST[get_class($model)]['dueDate'])) {
 334: //                $model->dueDate = Formatter::parseDateTime($_POST[get_class($model)]['dueDate']);
 335: //            }
 336: 
 337:             if($_POST['SelectedTab'] == 'new-event' || 
 338:                 $_POST['SelectedTab'] == 'new-small-calendar-event'){
 339: 
 340:                 $model->disableBehavior('changelog');
 341:                 $event = new Events;
 342:                 $event->type = 'calendar_event';
 343:                 $event->visibility = $model->visibility;
 344:                 $event->associationType = 'Actions';
 345:                 $event->timestamp = $model->dueDate;
 346:                 $model->type = 'event';
 347:                 if($model->completeDate){
 348:                     $model->completeDate = Formatter::parseDateTime($model->completeDate);
 349:                 }else{
 350:                     $model->completeDate = $model->dueDate;
 351:                 }
 352:             } 
 353: 
 354:             // format association
 355:             if($model->associationId == '')
 356:                 $model->associationId = 0;
 357: 
 358:             //$association = $this->getAssociation($model->associationType, $model->associationId);
 359: 
 360: //            if($association){
 361: //                
 362: //                $model->associationName = $association->name;
 363: //                if($association->hasAttribute('lastActivity')){
 364: //                    $association->lastActivity = time();
 365: //                    $association->update(array('lastActivity'));
 366: //                    X2Flow::trigger('RecordUpdateTrigger', array(
 367: //                        'model' => $association,
 368: //                    ));
 369: //                }
 370: //            } else
 371: //                $model->associationName = 'none';
 372: //
 373: //            if($model->associationName == 'None' && $model->associationType != 'none')
 374: //                $model->associationName = ucfirst($model->associationType);
 375: 
 376: //            if(in_array($_POST['SelectedTab'],array('log-a-call','new-comment','log-time-spent'))){
 377: //                // Set the complete date accordingly:
 378: //                if(!empty($_POST[get_class($model)]['completeDate'])) {
 379: //                    $model->completeDate = Formatter::parseDateTime(
 380: //                        $_POST[get_class($model)]['completeDate']);
 381: //                }
 382: //                foreach(array('dueDate','completeDate') as $attr)
 383: //                    if(empty($model->$attr))
 384: //                        $model->$attr = time();
 385: //                if($model->dueDate > $model->completeDate) {
 386: //                    // User specified a negative time range! Let's say that the
 387: //                    // starting time is equal to when it ended (which is earlier)
 388: //                    $model->dueDate = $model->completeDate;
 389: //                }
 390: //                $model->complete = 'Yes';
 391: //                $model->visibility = '1';
 392: //                $model->assignedTo = Yii::app()->user->getName();
 393: //                $model->completedBy = Yii::app()->user->getName();
 394: ////                if($_POST['SelectedTab'] == 'log-a-call') {
 395: ////                    $model->type = 'call';
 396: ////                } elseif($_POST['SelectedTab'] == 'log-time-spent') {
 397: ////                    $model->type = 'time';
 398: ////                 
 399: ////                } else {
 400: ////                    $model->type = 'note';
 401: ////                }
 402: //            }
 403: //            if(in_array($model->type, array('call','time','note'))){
 404: //                $event = new Events;
 405: //                $event->associationType = 'Actions';
 406: //                $event->type = 'record_create';
 407: //                $event->user = Yii::app()->user->getName();
 408: //                $event->visibility = $model->visibility;
 409: //                $event->subtype = $model->type;
 410: //            }
 411: //            // save model
 412: //            $model->createDate = time();
 413: //
 414: //            if(!empty($model->type))
 415: //                $model->disableBehavior('changelog');
 416: //
 417: //            
 418:             if($model->save()){ // action saved to database *
 419: //                if(isset($_POST['Actions']['reminder']) && $_POST['Actions']['reminder']){
 420: //                    $model->createNotifications(
 421: //                            $_POST['notificationUsers'], 
 422: //                            $model->dueDate - ($_POST['notificationTime'] * 60),
 423: //                            'action_reminder');
 424: //                }
 425:                 
 426: //                X2Model::updateTimerTotals(
 427: //                    $model->associationId,X2Model::getModelName($model->associationType));
 428: 
 429:                 if(isset($event)){
 430:                     $event->associationId = $model->id;
 431:                     $event->save();
 432:                 }
 433:                 //$model->syncGoogleCalendar('create', true);
 434:             }else{
 435:                 if($model->hasErrors('verifyCode')){
 436:                     echo CJSON::encode (array ('error' => $model->getError('verifyCode')));
 437:                     Yii::app()->end ();
 438:                 }
 439:             }
 440:             echo CJSON::encode (array ('success'));
 441:             Yii::app()->end ();
 442:         } else {
 443:             throw new CHttpException (400, Yii::t('app', 'Bad request'));
 444:         }
 445:     }
 446: 
 447:     /**
 448:      * Create a menu for Actions
 449:      * @param array Menu options to remove
 450:      * @param X2Model Model object passed to the view
 451:      * @param array Additional menu parameters
 452:      */
 453:     public function insertMenu($selectOptions = array(), $model = null, $menuParams = null) {
 454:         $Action = Modules::displayName(false);
 455:         $Actions = Modules::displayName();
 456:         $modelId = isset($model) ? $model->id : 0;
 457: 
 458:         /**
 459:          * To show all options:
 460:          * $menuOptions = array(
 461:          *     'list', 'todays', 'my', 'everyones', 'create', 'view', 'edit', 'share',
 462:          *     'delete', 'import', 'export',
 463:          * );
 464:          */
 465: 
 466:         $menuItems = array(
 467:             array(
 468:                 'name'=>'list',
 469:                 'label'=>Yii::t('actions','{module} List', array(
 470:                     '{module}' => Modules::displayName(false),
 471:                 )),
 472:                 'url'=>array('index'),
 473:             ),
 474:             array(
 475:                 'name'=>'todays',
 476:                 'label'=>Yii::t('actions','Today\'s {module}', array(
 477:                     '{module}' => $Actions,
 478:                 )),
 479:                 'url'=>array('index'),
 480:             ),
 481:             array(
 482:                 'name'=>'my',
 483:                 'label'=>Yii::t('actions','All My {module}', array(
 484:                     '{module}' => $Actions,
 485:                 )),
 486:                 'url'=>array('viewAll')
 487:             ),
 488:             array(
 489:                 'name'=>'everyones',
 490:                 'label'=>Yii::t('actions','Everyone\'s {module}', array(
 491:                     '{module}' => $Actions,
 492:                 )),
 493:                 'url'=>array('viewGroup')
 494:             ),
 495:             array(
 496:                 'name'=>'create',
 497:                 'label'=>Yii::t('actions','Create {module}', array(
 498:                     '{module}' => $Action,
 499:                 )),
 500:                 'url'=>array('create','param'=>Yii::app()->user->getName().";none:0")
 501:             ),
 502:             array(
 503:                 'name'=>'view',
 504:                 'label'=>Yii::t('actions','View'),
 505:                 'url'=>array('view', 'id'=>$modelId),
 506:             ),
 507:             array(
 508:                 'name'=>'edit',
 509:                 'label'=>Yii::t('actions','Edit {module}', array(
 510:                     '{module}' => $Action,
 511:                 )),
 512:                 'url'=>array('update', 'id'=>$modelId)
 513:             ),
 514:             array(
 515:                 'name'=>'share',
 516:                 'label'=>Yii::t('contacts','Share {module}', array(
 517:                     '{module}' => $Action,
 518:                 )),
 519:                 'url'=>array('shareAction','id'=>$modelId)
 520:             ),
 521:             array(
 522:                 'name'=>'delete',
 523:                 'label'=>Yii::t('actions','Delete {module}', array(
 524:                     '{module}' => $Action,
 525:                 )),
 526:                 'url'=>'#',
 527:                 'linkOptions'=>array(
 528:                     'submit'=>array('delete','id'=>$modelId),
 529:                     'confirm'=>'Are you sure you want to delete this item?')
 530:             ),
 531:             array(
 532:                 'name'=>'import',
 533:                 'label'=>Yii::t('actions', 'Import {module}', array(
 534:                     '{module}' => $Actions,
 535:                 )),
 536:                 'url'=>array('admin/importModels', 'model'=>'Actions'),
 537:             ),
 538:             array(
 539:                 'name'=>'export',
 540:                 'label'=>Yii::t('actions', 'Export {module}', array(
 541:                     '{module}' => $Actions,
 542:                 )),
 543:                 'url'=>array('admin/exportModels', 'model'=>'Actions'),
 544:             ),
 545:         );
 546: 
 547:         $this->prepareMenu($menuItems, $selectOptions);
 548:         $this->actionMenu = $this->formatMenu($menuItems, $menuParams);
 549:     }
 550: 
 551:     public function update($model, $oldAttributes, $api){
 552: 
 553:         // now in Actions::beforeSave()
 554:         /* $model->dueDate = Formatter::parseDateTime($model->dueDate);
 555: 
 556:           if($model->completeDate)
 557:           $model->completeDate = Formatter::parseDateTime($model->completeDate);
 558: 
 559:           $association = $this->getAssociation($model->associationType,$model->associationId);
 560: 
 561:           if($association != null) {
 562:           $model->associationName = $association->name;
 563:           } else {
 564:           $model->associationName = 'None';
 565:           $model->associationId = 0;
 566:           } */
 567: 
 568:         // now in Actions::synchGoogleCalendar()
 569:         /* if( !is_numeric($model->assignedTo)) { // assigned to user
 570:           $profile = Profile::model()->findByAttributes(array('username'=>$model->assignedTo));
 571:           if(isset($profile)) // prevent error for actions assigned to 'Anyone'
 572:           $profile->updateGoogleCalendarEvent($model); // update action in Google Calendar if user has a Google Calendar
 573:           } else { // Assigned to group
 574:           $groups = Yii::app()->db->createCommand()->select('userId')->from('x2_group_to_user')->where("groupId={$model->assignedTo}")->queryAll();
 575:           foreach($groups as $group) {
 576:           $profile = Profile::model()->findByPk($group['userId']);
 577:           if(isset($profile)) // prevent error for actions assigned to 'Anyone'
 578:           $profile->updateGoogleCalendarEvent($model);
 579:           }
 580:           } */
 581: 
 582:         if($api == 0)
 583:             parent::update($model, $oldAttributes, $api);
 584:         else
 585:             return parent::update($model, $oldAttributes, $api);
 586:     }
 587: 
 588:     /**
 589:      * Updates a particular model.
 590:      * If update is successful, the browser will be redirected to the 'view' page.
 591:      * @param integer $id the ID of the model to be updated
 592:      */
 593:     public function actionUpdate($id){
 594:         $model = $this->loadModel($id);
 595:         $users = User::getNames();
 596:         $notifications = X2Model::model('Notification')->findAllByAttributes(array(
 597:             'modelType' => 'Actions',
 598:             'modelId' => $model->id,
 599:             'type' => 'action_reminder'
 600:         ));
 601:         // Uncomment the following line if AJAX validation is needed
 602:         // $this->performAjaxValidation($model);
 603: 
 604:         if(isset($_POST['Actions'])){
 605:             $oldAttributes = $model->attributes;
 606:             $model->setX2Fields($_POST['Actions']);
 607:             if($model->lastUpdated != $oldAttributes['lastUpdated']){
 608:                 $model->disableBehavior('X2TimestampBehavior');
 609:             }
 610:             if($model->dueDate != $oldAttributes['dueDate']){
 611:                 $event = CActiveRecord::model('Events')
 612:                     ->findByAttributes(
 613:                         array(
 614:                             'type' => 'action_reminder',
 615:                             'associationType' => 'Actions',
 616:                             'associationId' => $model->id));
 617:                 if(isset($event)){
 618:                     $event->timestamp = $model->dueDate;
 619:                     $event->update(array('timestamp'));
 620:                 }
 621:             }
 622: 
 623:             
 624: 
 625:             // $this->update($model,$oldAttributes,'0');
 626:             if($model->save()){
 627:                 if(Yii::app()->user->checkAccess('ActionsAdmin') || 
 628:                     Yii::app()->settings->userActionBackdating){
 629: 
 630:                     $events = X2Model::model('Events')->findAllByAttributes(array(
 631:                         'associationType' => 'Actions',
 632:                         'associationId' => $model->id,
 633:                     ));
 634:                     foreach($events as $event) {
 635:                         $event->timestamp = $model->getRelevantTimestamp();
 636:                         $event->update(array('timestamp'));
 637:                     }
 638:                 }
 639:                 $model->syncGoogleCalendar('update');
 640:                 // if the action has an association
 641:                 if(isset($_GET['redirect']) && $model->associationType != 'none'){ 
 642:                     if($model->associationType == 'product' || 
 643:                         $model->associationType == 'products') {
 644:                         $this->redirect(
 645:                             array('/products/products/view', 'id' => $model->associationId));
 646:                     //TODO: avoid such hackery
 647:                     } elseif($model->associationType == 'Campaign') {
 648:                         $this->redirect(
 649:                             array('/marketing/marketing/view', 'id' => $model->associationId));
 650:                     } else {
 651:                         $this->redirect(
 652:                             array(
 653:                                 '/'.$model->associationType.'/'.$model->associationType.'/view',
 654:                                 'id' => $model->associationId)); // go back to the association
 655:                     }
 656:                 } elseif(!Yii::app()->request->isAjaxRequest){ // no association
 657:                     $this->redirect(array('index')); // view the action
 658:                 }else{
 659:                     echo $this->renderPartial('_viewIndex', array('data' => $model), true);
 660:                     return;
 661:                 }
 662:             }
 663:         } else {
 664: 
 665:             /* Set assignedTo back into an array only before re-rendering the input box with 
 666:                assignees selected */
 667:             $model->assignedTo = array_map(function($n){
 668:                 return trim($n,',');
 669:             },explode(' ',$model->assignedTo));
 670: 
 671:             $this->render('update', array(
 672:                 'model' => $model,
 673:                 'users' => $users,
 674:             ));
 675:         }
 676:     }
 677: 
 678:     public function actionCopyEvent ($id) {
 679:         $modelClass = $this->modelClass;
 680:         $model = $this->loadModel ($id);
 681:         $model->setX2Fields ($_POST[$modelClass]);
 682:         $model->id = null;
 683:         $copy = new $modelClass;
 684:         $copy->setAttributes ($model->getAttributes (), false);
 685:         if ($copy->save ()) {
 686:             $copy->syncGoogleCalendar('create');
 687:             echo $this->ajaxResponse ('success');
 688:         } else {
 689:             echo $this->ajaxResponse ('failure');
 690:         }
 691:     }
 692: 
 693:     public function actionQuickUpdate($id){
 694:         $model = $this->loadModel($id);
 695:         if(isset($_POST['Actions'])){
 696:             $model->setX2Fields($_POST['Actions']);
 697: 
 698:             $model->dueDate = Formatter::parseDateTime($model->dueDate);
 699:             if($model->completeDate){
 700:                 $model->completeDate = Formatter::parseDateTime($model->completeDate);
 701:             }elseif(empty($model->completeDate)){
 702:                 $model->completeDate = $model->dueDate;
 703:             }
 704:             if($model->save()){
 705:                 $model->syncGoogleCalendar('update');
 706:             }
 707:             if (isset($_POST['isEvent']) && $_POST['isEvent']) {
 708:                 // Update calendar event
 709:                 $event = X2Model::model('Events')->findByAttributes(array(
 710:                     'associationType' => 'Actions',
 711:                     'associationId' => $model->id,
 712:                 ));
 713:                 if ($event !== null) {
 714:                     $event->timestamp = $model->dueDate;
 715:                     $event->update(array('timestamp'));
 716:                 }
 717:             }
 718:         }
 719:     }
 720: 
 721:     public function actionToggleSticky($id){
 722:         $action = X2Model::model('Actions')->findByPk($id);
 723:         if(isset($action)){
 724:             $action->sticky = !$action->sticky;
 725:             $action->update(array('sticky'));
 726:             echo $action->sticky;
 727:         }
 728:     }
 729: 
 730:     // Postpones due date (and sets action to incomplete)
 731:     /* public function actionTomorrow($id) {
 732:       $model = $this->loadModel($id);
 733:       $model->complete='No';
 734:       $model->dueDate=time()+86400; //set to tomorrow
 735:       if($model->save()){
 736:       if($model->associationType!='none')
 737:       $this->redirect(array($model->associationType.'/'.$model->associationId));
 738:       else
 739:       $this->redirect(array('view','id'=>$id));
 740:       }
 741:       } */
 742: 
 743:     /**
 744:      * API method to delete an action
 745:      * @param integer $id The id of the action
 746:      */
 747:     public function delete($id){
 748:         $model = $this->loadModel($id);
 749:         $this->cleanUpTags($model);
 750:         $model->delete();
 751:     }
 752: 
 753:     /**
 754:      * Deletes an action
 755:      * @param integer $id The id of the action
 756:      */
 757:     public function actionDelete($id){
 758: 
 759:         $model = $this->loadModel($id);
 760:         if(Yii::app()->request->isPostRequest){
 761:             // $this->cleanUpTags($model);  // now in TagBehavior
 762:             $event = new Events;
 763:             $event->type = 'record_deleted';
 764:             $event->associationType = $this->modelClass;
 765:             $event->associationId = $model->id;
 766:             $event->text = $model->name;
 767:             $event->visibility = $model->visibility;
 768:             $event->user = Yii::app()->user->getName();
 769:             $event->save();
 770:             Events::model()->deleteAllByAttributes(array('associationType' => 'Actions', 'associationId' => $id, 'type' => 'action_reminder'));
 771: 
 772:             $model->syncGoogleCalendar('delete');
 773: 
 774:             /* if(!is_numeric($model->assignedTo)) { // assigned to user
 775:               $profile = Profile::model()->findByAttributes(array('username'=>$model->assignedTo));
 776:               if(isset($profile))
 777:               $profile->deleteGoogleCalendarEvent($model); // update action in Google Calendar if user has a Google Calendar
 778:               } else { // Assigned to group
 779:               $groups = Yii::app()->db->createCommand()->select('userId')->from('x2_group_to_user')->where("groupId={$model->assignedTo}")->queryAll();
 780:               foreach($groups as $group) {
 781:               $profile = Profile::model()->findByPk($group['userId']);
 782:               if(isset($profile))
 783:               $profile->deleteGoogleCalendarEvent($model);
 784:               } */
 785: 
 786:             $model->delete();
 787:         }else{
 788:             throw new CHttpException(400, 'Invalid request. Please do not repeat this request again.');
 789:         }
 790:         // if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
 791:         if(!isset($_GET['ajax']) && !Yii::app()->request->isAjaxRequest)
 792:             $this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('index'));
 793:         // Only report the success of a deleted record if this request wasn't made via mass actions
 794:         else if (!isset($_POST['gvSelection']))
 795:             echo 'success';
 796:     }
 797: 
 798:     /**
 799:      * Marks an action as complete and redirects back to the page it was completed on.
 800:      * @param integer $id The id of the action
 801:      */
 802:     public function actionComplete($id){
 803:         $model = $this->loadModel($id);
 804:         if(isset($_GET['notes'])){
 805:             $notes = $_GET['notes'];
 806:         }else{
 807:             $notes = null;
 808:         }
 809: 
 810:         if($model->isAssignedTo (Yii::app()->user->getName ()) ||
 811:            Yii::app()->params->isAdmin){ // make sure current user can edit this action
 812: 
 813:             if(isset($_POST['note']) && !empty($_POST['note']))
 814:                 $model->actionDescription = $model->actionDescription."\n\n".$_POST['note'];
 815: 
 816:             // $model = $this->updateChangelog($model,'Completed');
 817:             $model->complete(null, $notes);
 818: 
 819:             // Actions::completeAction($id);
 820:             // $this->completeNotification('admin',$model->id);
 821: 
 822:             $createNew = isset($_GET['createNew']) || ((isset($_POST['submit']) && ($_POST['submit'] == 'completeNew')));
 823:             $redirect = isset($_GET['redirect']) || $createNew;
 824: 
 825:             if($redirect){
 826:                 if($model->associationType != 'none' && !$createNew){ // if the action has an association
 827:                     $this->redirect(array('/'.$model->associationType.'/'.$model->associationType.'/view', 'id' => $model->associationId)); // go back to the association
 828:                 }else{ // no association
 829:                     if($createNew)
 830:                         $this->redirect(array('/actions/actions/create'));  // go to blank 'create action' page
 831:                     else
 832:                         $this->redirect(array('index')); // view the action
 833:                 }
 834:             } elseif(Yii::app()->request->isAjaxRequest){
 835:                 echo "Success";
 836:             }else{
 837:                 $this->redirect(array('index'));
 838:             }
 839:         }elseif(Yii::app()->request->isAjaxRequest){
 840:             echo "Failure";
 841:         }else{
 842:             $this->redirect(array('/actions/actions/invalid'));
 843:         }
 844:     }
 845: 
 846:     /**
 847:      * Marks an action as incomplete and clears the completedBy field.
 848:      * @param integer $id The id of the action
 849:      */
 850:     public function actionUncomplete($id){
 851:         $model = $this->loadModel($id);
 852:         if($model->uncomplete()){
 853:             if(Yii::app()->request->isAjaxRequest) {
 854:                 echo 'success';
 855:             }else{
 856:                 $this->redirect(array('/actions/'.$id));
 857:             }
 858:         }
 859:     }
 860: 
 861:     /**
 862:      * Called when a Contact opens an email sent from Inline Email Form. Inline Email Form
 863:      * appends an image to the email with src pointing to this function. This function
 864:      * creates an action associated with the Contact indicating that the email was opened.
 865:      *
 866:      * @param integer $uid The unique id of the recipient
 867:      * @param string $type 'open', 'click', or 'unsub'
 868:      *
 869:      */
 870:     public function actionEmailOpened($uid, $type){
 871:         // If the request is coming from within the web application, ignore it.
 872:         $referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
 873:         $baseUrl = Yii::app()->request->getBaseUrl(true);
 874:         $fromApp = strpos($referrer, $baseUrl) === 0;
 875: 
 876:         if($type == 'open' && !$fromApp){
 877:             $track = TrackEmail::model()->findByAttributes(array('uniqueId' => $uid));
 878:             $track->recordEmailOpen();
 879:         }
 880:         //return a one pixel transparent png
 881:         header('Content-Type: image/png');
 882:         echo base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAAXNSR0IArs4c6QAAAAJiS0dEAP+Hj8y/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAC0lEQVQI12NgYAAAAAMAASDVlMcAAAAASUVORK5CYII=');
 883:     }
 884: 
 885:     // Lists all actions assigned to this user
 886:     public function actionIndex(){
 887:         if(isset($_GET['toggleView']) && $_GET['toggleView']){
 888:             if(Yii::app()->params->profile->oldActions){
 889:                 Yii::app()->params->profile->oldActions = 0;
 890:             }else{
 891:                 Yii::app()->params->profile->oldActions = 1;
 892:             }
 893:             Yii::app()->params->profile->update(array('oldActions'));
 894:             $this->redirect(array('index'));
 895:         }
 896: 
 897:         $model = new Actions('search');
 898:         if(!isset(Yii::app()->params->profile->oldActions) || 
 899:            !Yii::app()->params->profile->oldActions){
 900: 
 901:             if(!empty($_POST) || !empty(Yii::app()->params->profile->actionFilters)){
 902:                 if(isset($_POST['complete'], $_POST['assignedTo'], $_POST['dateType'],
 903:                     $_POST['dateRange'], $_POST['orderType'], $_POST['order'], $_POST['start'],
 904:                     $_POST['end'])){
 905: 
 906:                     $complete = $_POST['complete'];
 907:                     $assignedTo = $_POST['assignedTo'];
 908:                     $dateType = $_POST['dateType'];
 909:                     $dateRange = $_POST['dateRange'];
 910:                     $orderType = $_POST['orderType'];
 911:                     $order = $_POST['order'];
 912:                     $start = $_POST['start'];
 913:                     $end = $_POST['end'];
 914:                     if($dateRange != 'range'){
 915:                         $start = null;
 916:                         $end = null;
 917:                     }
 918:                     $filters = array(
 919:                         'complete' => $complete, 'assignedTo' => $assignedTo,
 920:                         'dateType' => $dateType, 'dateRange' => $dateRange,
 921:                         'orderType' => $orderType, 'order' => $order, 'start' => $start,
 922:                         'end' => $end);
 923:                 }elseif(!empty(Yii::app()->params->profile->actionFilters)){
 924:                     $filters = json_decode(Yii::app()->params->profile->actionFilters, true);
 925:                 }
 926:                 $condition = Actions::createCondition($filters);
 927:                 $dataProvider = $model->search($condition, Actions::ACTION_INDEX_PAGE_SIZE);
 928:                 $params = $filters;
 929:             }else{
 930:                 $dataProvider = $model->search(null, Actions::ACTION_INDEX_PAGE_SIZE);
 931:                 $params = array();
 932:             }
 933:             $this->render('index', array(
 934:                 'model' => $model,
 935:                 'dataProvider' => $dataProvider,
 936:                 'params' => $params,
 937:             ));
 938:         }else{
 939:             $this->render('oldIndex', array('model' => $model));
 940:         }
 941:     }
 942: 
 943:     /**
 944:      * List all public actions
 945:      */
 946:     public function actionViewAll(){
 947:         $model = new Actions('search');
 948:         $profile = Profile::model()->findByPk(Yii::app()->user->id);
 949: 
 950:         $this->render(
 951:             'oldIndex',
 952:             array(
 953:                 'model' => $model,
 954:                 'showActions' => $profile->showActions,
 955:             )
 956:         );
 957:     }
 958: 
 959:     public function actionViewGroup(){
 960:         $model = new Actions('search');
 961:         $this->render('oldIndex', array('model' => $model));
 962:     }
 963: 
 964:     // display error page
 965:     public function actionInvalid(){
 966:         $this->render('invalid');
 967:     }
 968: 
 969:     public function actionParseType(){
 970:         if(isset($_POST['Actions']['associationType'])){
 971:             $type = $_POST['Actions']['associationType'];
 972:             if($modelName = X2Model::getModelName($type)){
 973:                 $linkModel = $modelName;
 974:                 if(class_exists($linkModel)){
 975:                     if($linkModel == "X2Calendar")
 976:                         $linkSource = ''; // Return no data to disable autocomplete on actions/update
 977:                     else
 978:                         $linkSource = $this->createUrl(X2Model::model($linkModel)->autoCompleteSource);
 979:                 }else{
 980:                     $linkSource = "";
 981:                 }
 982:                 echo $linkSource;
 983:             }else{
 984:                 echo '';
 985:             }
 986:         }else{
 987:             echo '';
 988:         }
 989:     }
 990: 
 991:     public function getAssociation($type, $id){
 992:         return X2Model::getAssociationModel($type, $id);
 993:     }
 994: 
 995:     /**
 996:      * Returns the data model based on the primary key given in the GET variable.
 997:      * If the data model is not found, an HTTP exception will be raised.
 998:      * @param integer the ID of the model to be loaded
 999:      */
1000:     public function loadModel($id){
1001:         $model = CActiveRecord::model('Actions')->findByPk((int) $id);
1002:         //$dueDate=$model->dueDate;
1003:         //$model=Actions::changeDates($model);
1004:         // if($model->associationId!=0) {
1005:         // $model->associationName = $this->parseName(array($model->associationType,$model->associationId));
1006:         // } else
1007:         // $model->associationName = 'None';
1008: 
1009:         if($model === null)
1010:             throw new CHttpException(404, 'The requested page does not exist.');
1011:         return $model;
1012:     }
1013: 
1014: 
1015:     public function actionGetItems($term){
1016:         X2LinkableBehavior::getItems ($term, 'subject');
1017:     }
1018: 
1019:     /**
1020:      * Performs AJAX validation.
1021:      * @param CModel the model to be validated
1022:      */
1023:     protected function performAjaxValidation($model){
1024:         if(isset($_POST['ajax']) && $_POST['ajax'] === 'actions-form'){
1025:             echo CActiveForm::validate($model);
1026:             Yii::app()->end();
1027:         }
1028:     }
1029: 
1030: }
1031: 
X2CRM Documentation API documentation generated by ApiGen 2.8.0