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: * Track service/support cases among contacts.
40: *
41: * Every Service Case must be associated with a contact. It's possible to
42: * create a service case from a contacts view via ajax by clicking the
43: * "Create Case" button. (the new case is associated with the contact).
44: *
45: * @package application.modules.services.controllers
46: */
47: class ServicesController extends x2base {
48:
49: public $modelClass = 'Services';
50: public $serviceCaseStatuses = null;
51:
52: public function accessRules(){
53: return array(
54: array('allow',
55: 'actions' => array('getItems', 'webForm'),
56: 'users' => array('*'),
57: ),
58: array('allow', // allow authenticated user to perform 'create' and 'update' actions
59: 'actions' => array('index', 'view', 'create', 'update', 'search', 'saveChanges', 'delete', 'inlineEmail', 'createWebForm', 'statusFilter'),
60: 'users' => array('@'),
61: ),
62: array('allow', // allow admin user to perform 'admin' and 'delete' actions
63: 'actions' => array('admin', 'testScalability'),
64: 'users' => array('admin'),
65: ),
66: array('deny', // deny all users
67: 'users' => array('*'),
68: ),
69: );
70: }
71:
72: public function actions(){
73: return array_merge(parent::actions(), array(
74: 'webForm' => array(
75: 'class' => 'WebFormAction',
76: ),
77: 'createWebForm' => array(
78: 'class' => 'CreateWebFormAction',
79: ),
80: 'inlineEmail' => array(
81: 'class' => 'InlineEmailAction',
82: ),
83: ));
84: }
85:
86: public function behaviors(){
87: return array_merge(parent::behaviors(), array(
88: 'X2MobileControllerBehavior' => array(
89: 'class' =>
90: 'application.modules.mobile.components.behaviors.X2MobileControllerBehavior'
91: ),
92: 'ServiceRoutingBehavior' => array(
93: 'class' => 'ServiceRoutingBehavior'
94: ),
95: 'QuickCreateRelationshipBehavior' => array(
96: 'class' => 'QuickCreateRelationshipBehavior',
97: ),
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: $model = $this->loadModel($id);
107: if (!$this->checkPermissions($model, 'view')) $this->denied ();
108:
109: // add service case to user's recent item list
110: User::addRecentItem('s', $id, Yii::app()->user->getId());
111:
112: parent::view($model, 'services');
113: }
114:
115: /**
116: * Creates a new model.
117: * If creation is successful, the browser will be redirected to the 'view' page.
118: */
119: /* public function create($model,$oldAttributes, $api){
120: // $model->annualRevenue = Formatter::parseCurrency($model->annualRevenue,false);
121: $model->createDate=time();
122: $model->lastUpdated=time();
123: $model->updatedBy = Yii::app()->user->name;
124: if($api==0) {
125: parent::create($model,$oldAttributes,'1');
126: if( !$model->isNewRecord ) {
127: $model->name = $model->id;
128: $model->update();
129: if($model->escalatedTo != '') {
130: $event=new Events;
131: $event->type='case_escalated';
132: $event->user=Yii::app()->user->getName();
133: $event->associationType=$this->modelClass;
134: $event->associationId=$model->id;
135: if($event->save()){
136: $notif = new Notification;
137: $notif->user = $model->escalatedTo;
138: $notif->createDate = time();
139: $notif->createdBy = Yii::app()->user->name;
140: $notif->type = 'escalateCase';
141: $notif->modelType = $this->modelClass;
142: $notif->modelId = $model->id;
143: $notif->save();
144: }
145: }
146:
147: $this->redirect(array('view', 'id' => $model->id));
148: }
149: } else {
150: return parent::create($model,$oldAttributes,$api);
151: }
152: } */
153:
154: /**
155: * Create a new Service Case
156: *
157: * This action can be called normally (by clicking the Create button in Service module)
158: * or it can be called via ajax by clicking the "Create Case" button in a contact view.
159: *
160: */
161: public function actionCreate(){
162: $model = new Services;
163: $users = User::getNames();
164: unset($users['admin']);
165: unset($users['']);
166: foreach(Groups::model()->findAll() as $group){
167: $users[$group->id] = $group->name;
168: }
169:
170: if(isset($_POST['Services'])){
171: $temp = $model->attributes;
172: foreach($_POST['Services'] as $name => &$value){
173: if($value == $model->getAttributeLabel($name))
174: $value = '';
175: }
176: $model->setX2Fields($_POST['Services']);
177:
178: if(isset($_POST['x2ajax'])){ // we're creating a case with "Create Case" button in contacts view
179: /* every model needs a name field to work with X2GridView and a few other places,
180: for service cases the id of the case is the name */
181: $model->name = $model->id;
182: $ajaxErrors = $this->quickCreate ($model);
183:
184: }elseif($model->save()){
185: $this->redirect(array('view', 'id' => $model->id));
186: // $this->create($model,$temp, '0');
187: }
188: }
189:
190: // we're creating a case with "Create Case" button in contacts view
191: if(isset($_POST['x2ajax'])){
192: $this->renderInlineCreateForm ($model, isset ($ajaxErrors) ? $ajaxErrors : false);
193: }else{
194: $this->render('create', array(// normal (non-ajax) create
195: 'model' => $model,
196: 'users' => $users,
197: ));
198: }
199: }
200:
201: /* public function update($model, $oldAttributes,$api){
202:
203: $ret = parent::update($model,$oldAttributes,'1');
204:
205: if($model->escalatedTo != '' && $model->escalatedTo != $oldAttributes['escalatedTo']) {
206: $event=new Events;
207: $event->type='case_escalated';
208: $event->user=Yii::app()->user->getName();
209: $event->associationType=$this->modelClass;
210: $event->associationId=$model->id;
211: if($event->save()){
212: $notif = new Notification;
213: $notif->user = $model->escalatedTo;
214: $notif->createDate = time();
215: $notif->createdBy = Yii::app()->user->name;
216: $notif->type = 'escalateCase';
217: $notif->modelType = $this->modelClass;
218: $notif->modelId = $model->id;
219: $notif->save();
220: }
221: }
222:
223: if($api==0)
224: $this->redirect(array('view', 'id' => $model->id));
225: else
226: return $ret;
227: } */
228:
229: /**
230: * Updates a particular model.
231: * If update is successful, the browser will be redirected to the 'view' page.
232: * @param integer $id the ID of the model to be updated
233: */
234: public function actionUpdate($id){
235: $model = $this->loadModel($id);
236: $users = User::getNames();
237: unset($users['admin']);
238: unset($users['']);
239: foreach(Groups::model()->findAll() as $group){
240: $users[$group->id] = $group->name;
241: }
242:
243: if(isset($_POST['Services'])){
244: $temp = $model->attributes;
245: foreach($_POST['Services'] as $name => &$value){
246: if($value == $model->getAttributeLabel($name))
247: $value = null;
248: }
249: $model->setX2Fields($_POST['Services']);
250:
251: if($model->contactId != '' && !is_numeric($model->contactId)) // make sure an existing contact is associated with this case, otherwise don't create it
252: $model->addError('contactId', Yii::t('services', 'Contact does not exist'));
253:
254: // $this->update($model,$temp,'0');
255: if($model->save()){
256: $this->redirect(array('view', 'id' => $model->id));
257: }
258: }
259:
260: $this->render('update', array(
261: 'model' => $model,
262: 'users' => $users,
263: ));
264: }
265:
266: public function delete($id){
267:
268: $model = $this->loadModel($id);
269: $dataProvider = new CActiveDataProvider('Actions', array(
270: 'criteria' => array(
271: 'condition' => 'associationId='.$id.' AND associationType=\'services\'',
272: )));
273:
274: $actions = $dataProvider->getData();
275: foreach($actions as $action){
276: $action->delete();
277: }
278: $this->cleanUpTags($model);
279: $model->delete();
280: }
281:
282: /**
283: * Deletes a particular model.
284: * If deletion is successful, the browser will be redirected to the 'admin' page.
285: * @param integer $id the ID of the model to be deleted
286: */
287: public function actionDelete($id){
288: $model = $this->loadModel($id);
289: if(Yii::app()->request->isPostRequest){
290: $event = new Events;
291: $event->type = 'record_deleted';
292: $event->associationType = $this->modelClass;
293: $event->associationId = $model->id;
294: $event->text = $model->name;
295: $event->user = Yii::app()->user->getName();
296: $event->save();
297: Actions::model()->deleteAll('associationId='.$id.' AND associationType=\'services\'');
298: $this->cleanUpTags($model);
299: $model->delete();
300: } else
301: throw new CHttpException(400, 'Invalid request. Please do not repeat this request again.');
302: // if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
303: if(!isset($_GET['ajax']))
304: $this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('index'));
305: }
306:
307: /**
308: * Lists all models.
309: */
310: public function actionIndex(){
311:
312: $model = new Services('search');
313: $this->render('index', array('model' => $model));
314: }
315:
316: public function actionGetItems($term){
317: X2LinkableBehavior::getItems ($term, 'id', 'id');
318: }
319:
320: /**
321: * Show or hide a certain status in the gridview
322: *
323: * Called through ajax with a status and if that status should be shown or hidden.
324: * Saves the result in the user's profile.
325: *
326: */
327: public function actionStatusFilter(){
328:
329: if(isset($_POST['all'])){ // show all the things!!
330: Yii::app()->params->profile->hideCasesWithStatus = CJSON::encode(array()); // hide none
331: Yii::app()->params->profile->update(array('hideCasesWithStatus'));
332: }elseif(isset($_POST['none'])){ // hide all the things!!!!11
333: $statuses = array();
334:
335: $dropdownId = Yii::app()->db->createCommand() // get the ID of the statuses dropdown via fields table
336: ->select('linkType')
337: ->from('x2_fields')
338: ->where('modelName="Services" AND fieldName="status" AND type="dropdown"')
339: ->queryScalar();
340: if($dropdownId !== null)
341: $statuses = Dropdowns::getItems($dropdownId); // get the actual statuses
342:
343: Yii::app()->params->profile->hideCasesWithStatus = CJSON::encode($statuses);
344: Yii::app()->params->profile->update(array('hideCasesWithStatus'));
345: } elseif(isset($_POST['checked'])){
346:
347: $checked = CJSON::decode($_POST['checked']);
348: $status = isset($_POST['status']) ? $_POST['status'] : false;
349:
350: // var_dump($checked);
351: // var_dump($status);
352:
353: $hideStatuses = CJSON::decode(Yii::app()->params->profile->hideCasesWithStatus); // get a list of statuses the user wants to hide
354: if($hideStatuses === null || !is_array($hideStatuses))
355: $hideStatuses = array();
356:
357: // var_dump($checked);
358: // var_dump(in_array($status, $hideStatuses));
359: if($checked && ($key = array_search($status, $hideStatuses)) !== false){ // if we want to show the status, and it's not being shown
360: unset($hideStatuses[$key]); // show status
361: }else if(!$checked && !in_array($status, $hideStatuses)){ // if we want to hide the status, and it's not being hidden
362: $hideStatuses[] = $status;
363: }
364:
365: Yii::app()->params->profile->hideCasesWithStatus = CJSON::encode($hideStatuses);
366: Yii::app()->params->profile->update(array('hideCasesWithStatus'));
367: }
368: }
369:
370: /**
371: * Create a menu for Services
372: * @param array Menu options to remove
373: * @param X2Model Model object passed to the view
374: * @param array Additional menu parameters
375: */
376: public function insertMenu($selectOptions = array(), $model = null, $menuParams = null) {
377: $Services = Modules::displayName();
378: $Service = Modules::displayName(false);
379: $modelId = isset($model) ? $model->id : 0;
380:
381: /**
382: * To show all options:
383: * $menuOptions = array(
384: * 'index', 'create', 'view', 'edit', 'delete', 'email', 'attach', 'quotes',
385: * 'createWebForm', 'print', 'import', 'export',
386: * );
387: */
388:
389: $menuItems = array(
390: array(
391: 'name'=>'index',
392: 'label'=>Yii::t('services','All Cases'),
393: 'url'=>array('index')
394: ),
395: array(
396: 'name'=>'create',
397: 'label'=>Yii::t('services','Create Case'),
398: 'url'=>array('create')
399: ),
400: RecordViewLayoutManager::getViewActionMenuListItem ($modelId),
401: array(
402: 'name'=>'edit',
403: 'label'=>Yii::t('services','Edit Case'),
404: 'url'=>array('update', 'id'=>$modelId)
405: ),
406: array(
407: 'name'=>'delete',
408: 'label'=>Yii::t('services','Delete Case'),
409: 'url'=>'#',
410: 'linkOptions'=>array(
411: 'submit'=>array('delete','id'=>$modelId),
412: 'confirm'=>'Are you sure you want to delete this item?')
413: ),
414: array(
415: 'name'=>'email',
416: 'label'=>Yii::t('app','Send Email'),
417: 'url'=>'#',
418: 'linkOptions'=>array('onclick'=>'toggleEmailForm(); return false;')
419: ),
420: ModelFileUploader::menuLink(),
421: array(
422: 'name'=>'quotes',
423: 'label' => Yii::t('quotes', '{quotes}/Invoices', array(
424: '{quotes}' => Modules::displayName(true, "Quotes"),
425: )),
426: 'url' => 'javascript:void(0)',
427: 'linkOptions' => array('onclick' => 'x2.inlineQuotes.toggle(); return false;')
428: ),
429: array(
430: 'name'=>'createWebForm',
431: 'label'=>Yii::t('services','Create Web Form'),
432: 'url'=>array('createWebForm')
433: ),
434: array(
435: 'name'=>'print',
436: 'label' => Yii::t('app', 'Print Record'),
437: 'url' => '#',
438: 'linkOptions' => array (
439: 'onClick'=>"window.open('".
440: Yii::app()->createUrl('/site/printRecord', array (
441: 'modelClass' => 'Services',
442: 'id' => $modelId,
443: 'pageTitle' => Yii::t('app', '{service} Case', array(
444: '{service}' => $Service,
445: )).': '.(isset($model) ? $model->name : "")
446: ))."');"
447: )
448: ),
449: array(
450: 'name'=>'import',
451: 'label'=>Yii::t('services', 'Import {services}', array(
452: '{services}' => $Services,
453: )),
454: 'url'=>array('admin/importModels', 'model'=>'Services'),
455: ),
456: array(
457: 'name'=>'export',
458: 'label'=>Yii::t('services', 'Export {services}', array(
459: '{services}' => $Services,
460: )),
461: 'url'=>array('admin/exportModels', 'model'=>'Services'),
462: ),
463: RecordViewLayoutManager::getEditLayoutActionMenuListItem (),
464: );
465:
466: $this->prepareMenu($menuItems, $selectOptions);
467: $this->actionMenu = $this->formatMenu($menuItems, $menuParams);
468: }
469: }
470: