1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
36:
37: Yii::import('application.modules.users.models.*');
38:
39: 40: 41: 42: 43:
44: class ApiController extends x2base {
45:
46: 47: 48:
49: public $modelClass;
50: public $user;
51:
52: private $_model;
53:
54: 55: 56: 57:
58: public $actionAuthItemMap = array(
59: 'lookUp' => 'View',
60: );
61:
62: public function behaviors() {
63: return array_merge(parent::behaviors(),array(
64: 'LeadRoutingBehavior' => array(
65: 'class' => 'LeadRoutingBehavior'
66: ),
67: 'responds' => array(
68: 'class' => 'application.components.ResponseBehavior',
69: 'isConsole' => false,
70: 'exitNonFatal' => false,
71: 'longErrorTrace' => false,
72: ),
73: 'CommonControllerBehavior' => array(
74: 'class' => 'application.components.CommonControllerBehavior',
75: 'redirectOnNullModel' => false,
76: 'throwOnNullModel' => false
77: ),
78: ));
79: }
80:
81: 82: 83:
84: public function filters() {
85: return array(
86: 'noSession',
87: 'available',
88: 'authenticate - voip,webListener,targetedContent,x2cron',
89: 'validModel + create,view,lookup,update,delete,relationships,tags',
90: 'checkCRUDPermissions + create,view,lookup,update,delete',
91: );
92: }
93:
94: public function actions() {
95: $actions = array();
96: if(class_exists('WebListenerAction'))
97: $actions['webListener'] = array('class' => 'WebListenerAction');
98: if(class_exists('TargetedContentAction'))
99: $actions['targetedContent'] = array('class' => 'TargetedContentAction');
100: if(class_exists('X2CronAction'))
101: $actions['x2cron'] = array('class' => 'X2CronAction');
102: if(class_exists('EmailImportAction'))
103: $actions['dropbox'] = array('class'=>'EmailImportAction');
104: return $actions;
105: }
106:
107: 108: 109: 110: 111: 112: 113: 114: 115:
116: public function actionCheckPermissions($action, $username = null, $api = 0) {
117: $access = true;
118: $this->log("Checking user permissions for API transaction.");
119: $auth = Yii::app()->authManager;
120: $item = $auth->getAuthItem($action);
121: $authenticated = $auth->getAuthItem('DefaultRole');
122: if (isset($item)) {
123: $access = false;
124: $userId = null;
125: $access = Yii::app()->params->isAdmin;
126: $access = $authenticated->checkAccess($action);
127:
128: if (!$access) {
129: if ($username != null) {
130: $userId = User::model()->findByAttributes(array('username' => $username))->id;
131: } elseif (isset($this->user)) {
132: $userId = $this->user->id;
133: }
134: }
135:
136: if ($userId != null && !$access) {
137: $access = $access || $auth->checkAccess($action,$userId);
138: }
139: } elseif($this->action->id != 'checkPermissions')
140: $this->log(sprintf("Auth item %s not found. Permitting action %s.",$action,$this->action->id));
141:
142: if ($api == 1) {
143:
144: $access = $access ? "true" : "false";
145: header('Content-type: text/plain');
146: echo $access;
147: Yii::app()->end();
148: } else {
149:
150:
151: return $access;
152: }
153: }
154:
155: 156: 157: 158: 159: 160: 161: 162: 163: 164:
165: public function actionCreate(){
166:
167: $model = $this->getModel(true);
168: $model->setX2Fields($_POST);
169:
170: if($this->modelClass === 'Contacts') {
171: if (isset($_POST['trackingKey'])){
172:
173: $model->trackingKey = $_POST['trackingKey'];
174: }
175: if (isset($_POST['_leadRouting']) && $_POST['_leadRouting']) {
176: $model->assignedTo = $this->getNextAssignee ();
177: }
178: }
179:
180: $setUserFields = false;
181:
182: if(!empty($_POST['createDate'])){
183: $model->disableBehavior('changelog');
184: $setUserFields = true;
185:
186: }
187: try{
188: $editingUsername = $model->editingUsername;
189:
190: }catch(Exception $e){
191: $setUserFields = true;
192:
193: }
194:
195: if($setUserFields)
196: $this->modelSetUsernameFields($model);
197:
198:
199: if($model->save()){
200: $this->response['model'] = $model->attributes;
201: $message = "A {$this->modelClass} type record was created";
202: switch($this->modelClass){
203:
204: case 'Actions':
205:
206:
207: if(isset($_POST['actionDescription'])){
208: $model->actionDescription = $_POST['actionDescription'];
209: }
210: $message .= " with description {$model->actionDescription}";
211: $model->syncGoogleCalendar('create');
212: break;
213: case 'Contacts':
214: $message .= " with name {$model->name}";
215: break;
216: }
217: $this->_sendResponse(200, $message);
218: }else{
219: $this->response['modelErrors'] = $model->errors;
220: switch($this->modelClass){
221: case 'Contacts':
222: $this->log(sprintf('Failed to save record of type %s due to errors: %s', $this->modelClass, CJSON::encode($model->errors)));
223: $msg = $this->validationMsg('create', $model);
224:
225:
226: $notif = new Notification;
227: $notif->user = 'admin';
228: $notif->type = 'lead_failure';
229: $notif->createdBy = $this->user->username;
230: $notif->createDate = time();
231: $notif->save();
232:
233: $to = Yii::app()->settings->webLeadEmail;
234: $subject = "Web Lead Failure";
235: if(!Yii::app()->params->automatedTesting){
236:
237: $responderId = Credentials::model()->getDefaultUserAccount(Credentials::$sysUseId['systemNotificationEmail'], 'email');
238: if($responderId != Credentials::LEGACY_ID){
239: $this->sendUserEmail(array('to' => array(array($to, 'X2Engine Administrator'))), $subject, $msg, null, $responderId);
240: }else{
241: $phpMail = $this->getPhpMailer();
242: $fromEmail = Yii::app()->settings->emailFromAddr;
243: $fromName = Yii::app()->settings->emailFromName;
244: $phpMail->AddReplyTo($fromEmail, $fromName);
245: $phpMail->SetFrom($fromEmail, $fromName);
246: $phpMail->Subject = $subject;
247: $phpMail->AddAddress($to, 'X2Engine Administrator');
248: $phpMail->MsgHTML($msg."<br />JSON Encoded Attributes:<br /><br />".json_encode($model->attributes));
249: $phpMail->Send();
250: }
251: }
252:
253: $attributes = $model->attributes;
254: ksort($attributes);
255:
256: if(file_exists($flCsv = implode(DIRECTORY_SEPARATOR, array(Yii::app()->basePath, 'data', 'failed_leads.csv')))){
257: $fp = fopen($flCsv,'a+');
258: fputcsv($fp, $attributes);
259: }else{
260: $fp = fopen($flCsv,'w+');
261: fputcsv($fp, array_keys($attributes));
262: fputcsv($fp, $attributes);
263: }
264: $this->_sendResponse(500, $msg);
265: break;
266: default:
267: $this->log(sprintf('Failed to save record of type %s due to errors: %s', $this->modelClass, CJSON::encode($model->errors)));
268:
269: $msg = "<h1>Error</h1>";
270: $msg .= sprintf("Couldn't create model <b>%s</b> due to errors:", $this->modelClass);
271: $msg .= "<ul>";
272: foreach($model->errors as $attribute => $attr_errors){
273: $msg .= "<li>Attribute: $attribute</li>";
274: $msg .= "<ul>";
275: foreach($attr_errors as $attr_error)
276: $msg .= "<li>$attr_error</li>";
277: $msg .= "</ul>";
278: }
279: $msg .= "</ul>";
280: $this->_sendResponse(500, $msg);
281: }
282: }
283: }
284:
285: 286: 287:
288: public function actionDelete() {
289: $model = $this->model;
290: if ($this->modelClass === 'Actions')
291: $model->syncGoogleCalendar('delete');
292:
293: $num = $model->delete();
294: if ($num > 0) {
295: $this->_sendResponse(200, 1);
296: } else
297: $this->_sendResponse(500, sprintf("Error: Couldn't delete model <b>%s</b> with ID <b>%s</b>.", $_GET['model'], $_POST['id']));
298: }
299:
300: 301: 302:
303: public function actionList() {
304: $listId = $_POST['id'];
305: $list = X2List::model()->findByPk($listId);
306: if (isset($list)) {
307:
308: } else {
309: $list = X2List::model()->findByAttributes(array('name' => $listId));
310: if (isset($list)) {
311: $listId = $list->id;
312:
313: } else {
314: $this->_sendResponse(404, 'No list found with id: ' . $_POST['id']);
315: }
316: }
317: $model = new Contacts('search');
318: $dataProvider = $model->searchList($listId, 10);
319: $data = $dataProvider->getData();
320: $this->_sendResponse(200, json_encode($data),true);
321: }
322:
323: 324: 325:
326: public function actionListUsers() {
327: $access = $this->actionCheckPermissions('UsersAccess');
328: $fullAccess = false;
329: if($access)
330: $fullAccess = $this->actionCheckPermissions('UsersFullAccess');
331: if(!$access)
332: $this->sendResponse(403,"User {$this->user} does not have permission to run UsersIndex");
333: $users = User::model()->findAll();
334: $userAttr = User::model()->attributes;
335: if(!$fullAccess) {
336: unset($userAttr['password']);
337: unset($userAttr['userKey']);
338: }
339: $userAttr = array_keys($userAttr);
340: $userList = array();
341: foreach($users as $user) {
342: $userList[] = $user->getAttributes($userAttr);
343: }
344: $this->_sendResponse(200,$userList,true);
345: }
346:
347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357:
358: public function actionLookup() {
359: $attrs = $_POST;
360: unset($attrs['user']);
361: unset($attrs['userKey']);
362: $tempModel = new $this->modelClass('search');
363:
364:
365: $attrs = array_intersect_key($attrs,$tempModel->attributes);
366: $model = X2Model::model($this->modelClass)->findByAttributes($attrs);
367:
368:
369: if (is_null($model)) {
370: $this->_sendResponse(404, 'No Item found with specified attributes.');
371: } else {
372: $this->_sendResponse(200, $model->attributes,true);
373: }
374: }
375:
376: 377: 378:
379: public function actionRelationship(){
380: $rType = Yii::app()->request->requestType;
381: switch($rType){
382: case 'GET':
383: $attr = array('firstType'=>$_GET['model']);
384: $relationships = Relationships::model()->findAllByAttributes(array_merge(array_intersect_key($_GET,array_flip(Relationships::model()->safeAttributeNames)),$attr));
385: if(empty($relationships))
386: $this->_sendResponse(404,Yii::t('api','No relationships found.'));
387: else
388: $this->_sendResponse(200,array_map(function($r){return $r->attributes;},$relationships),1);
389: case 'POST':
390: $relationship = new Relationships('api');
391: $relationship->attributes = $_POST;
392: $relationship->firstType = $_GET['model'];
393: if($relationship->validate()){
394: $existingRelationship = Relationships::model()->findByAttributes(array_intersect_key($relationship->attributes,array_flip(array('firstType','secondType','firstId','secondId'))));
395: if($existingRelationship)
396: $this->_sendResponse(200,Yii::t('api','Such a relationship already exists.'));
397: if($relationship->save()){
398: $this->_sendResponse(200,Yii::t('api','Successfully saved a relationship.'));
399: } else {
400: $this->_sendResponse(500,Yii::t('api','Failed to save relationship record for unknown reason.'));
401: }
402: } else {
403: $this->response['modelErrors'] = $relationship->errors;
404: $this->_sendResponse(400,$this->validationMsg('create', $relationship));
405: }
406: break;
407: case 'DELETE':
408: if(!isset($_GET['secondType'],$_GET['firstId'],$_GET['secondId']))
409: $this->_sendResponse(400,Yii::t('api','Cannot delete; no parameters specified for finding a relationship record to delete.'));
410: $relationships = Relationships::model()->findAllByAttributes(array_merge(array('firstType'=>$_GET['model']),array_intersect_key($_GET,array_flip(Relationships::model()->attributeNames()))));
411: if(empty($relationships))
412: $this->_sendResponse(404,Yii::t('api','No relationships deleted; none were found matching specfied parameters.'));
413: $n_d = 0;
414: $n_d_t = count($relationships);
415: foreach($relationships as $model) {
416: $n_d += $model->delete() ? 1 : 0;
417: }
418: if($n_d == $n_d_t)
419: $this->_sendResponse(200,Yii::t('api','{n} relationships deleted.',array('{n}'=>$n_d)));
420: else
421: $this->_sendResponse(500,Yii::t('api','One or more relationships could not be deleted.'));
422: break;
423: default:
424: $this->_sendResponse(400,Yii::t('api','Request type not supported for this action.'));
425: break;;
426: }
427: }
428:
429: 430: 431: 432: 433: 434: 435: 436:
437: public function actionTags() {
438: $model = $this->model;
439: $rType = Yii::app()->request->requestType;
440: switch($rType){
441: case 'GET':
442:
443: $this->_sendResponse(200, $model->getTags(),true);
444: case 'POST':
445:
446: if(array_key_exists('tags', $_POST))
447: $tags = json_decode($_POST['tags'], 1);
448: else if(array_key_exists('tag',$_POST))
449: $tags = array($_POST['tag']);
450: else
451: $this->_sendResponse(400, 'Parameter "tags" (json-encoded list of tags) or "tag" (single tag to add) requried.');
452: if($model->addTags($tags))
453: $this->_sendResponse(200, sprintf('Record "%s" (%s) tagged with "%s"', $model->name, get_class($model), implode('","', $tags)));
454: else
455: $this->_sendResponse(500,Yii::t('api','Tags not added.'));
456: case 'DELETE':
457:
458: if(array_key_exists('tag',$_GET))
459: $tag = "#".ltrim($_GET['tag'],'#');
460: else
461: $this->_sendResponse(400, 'Please specify a tag to be deleted.');
462: $removed = $model->removeTags($tag);
463: if($removed)
464: $this->_sendResponse(200, sprintf('Tag "%s" deleted from "%s" (%s).', $tag, $model->name, get_class($model)));
465: else
466: $this->_sendResponse(404, 'Did not delete any existing tags.');
467: break;
468: }
469: }
470:
471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483:
484: public function actionUpdate() {
485: $model = $this->model;
486: $model->setX2Fields($_POST);
487:
488:
489:
490: if ($model->save()) {
491: switch ($this->modelClass) {
492: case 'Actions':
493: $model->syncGoogleCalendar('update');
494: break;
495: default:
496: $this->_sendResponse(200, $model->attributes,true);
497: }
498: $this->response['model'] = $model->attributes;
499: $this->_sendResponse(200, 'Model created successfully');
500: } else {
501:
502: $this->response['modelErrors'] = $model->errors;
503: $msg = $this->validationMsg('update', $model);
504: $this->_sendResponse(500,$msg);
505: }
506: }
507:
508: 509: 510: 511: 512: 513: 514: 515: 516: 517: 518:
519: public function actionView() {
520: $this->_sendResponse(200,$this->model->attributes,true);
521: }
522:
523: 524: 525: 526: 527: 528: 529: 530: 531: 532: 533: 534: 535: 536: 537: 538: 539: 540: 541: 542:
543: public function actionVoip($actionHist=0) {
544:
545: if (isset($_GET['data'])) {
546:
547: $matches = array();
548: if (preg_match('/\d{10,}/', $_GET['data'], $matches)) {
549: $number = ltrim($matches[0],'1');
550: $phoneCrit = new CDbCriteria(array(
551: 'condition' => "modelType='Contacts' AND number LIKE :number",
552: 'params' => array(':number'=>"%$number%")
553: ));
554: $phoneCrit->join =
555: 'join x2_contacts on modelId=x2_contacts.id AND '.
556: Contacts::model ()->getHiddenCondition ('x2_contacts');
557: $phoneNumber = PhoneNumber::model()->find($phoneCrit);
558: if(!empty($phoneNumber)){
559: $contact = X2Model::model('Contacts')->findByPk($phoneNumber->modelId);
560: if(isset($contact)){
561:
562: $contact->disableBehavior('changelog');
563: $contact->updateLastActivity();
564:
565: $assignees = array($contact->assignedTo);
566: if($contact->assignedTo == 'Anyone' || $contact->assignedTo == null) {
567: $users = User::model()->findAll();
568: $assignees = array_map(function($u){return $u->username;},$users);
569: }
570: $multiUser = count($assignees) > 1;
571: $usersSuccess = array();
572: $usersFailure = array();
573:
574: $formattedNumber = '';
575: $strNumber = (string) $number;
576: $strl = strlen($strNumber);
577: $formattedNumber = substr($strNumber, $strl - 4, $strl);
578: $formattedNumber = substr($strNumber, $strl - 7, 3)."-$formattedNumber";
579: if($strl >= 10){
580: $formattedNumber = substr($strNumber, $strl - 10, 3)."-$formattedNumber";
581: if($strl > 10){
582: $formattedNumber = substr($strNumber, 0, $strl - 10)."-$formattedNumber";
583: }
584: }
585: $time = time();
586:
587: foreach($assignees as $user){
588: $notif = new Notification;
589: $notif->type = 'voip_call';
590: $notif->user = $user;
591: $notif->modelType = 'Contacts';
592: $notif->modelId = $contact->id;
593: $notif->value = $formattedNumber;
594: $notif->createDate = $time;
595: if($notif->save()){
596: $usersSuccess[] = $user;
597: }else{
598: $usersFailure = array();
599: }
600: }
601: if($actionHist){
602:
603: $action = new Actions();
604: $action->assignedTo = 'Anyone';
605: $action->visibility = 1;
606: $action->associationId = $contact->id;
607: $action->associationType = 'contacts';
608: $action->associationName = $contact->name;
609: $action->dueDate = $time;
610: $action->createDate = $time;
611: $action->completeDate = $time;
612: $action->lastUpdated = $time;
613: $action->type = 'call';
614: $action->complete = 'Yes';
615: $action->completedBy = 'Anyone';
616: $action->save();
617: $action->actionText = Yii::t('app', 'Phone system reported inbound call from contact.');
618: }
619:
620: $failure = count($usersSuccess) == 0;
621: $partialFailure = count($usersFailure) > 0;
622: if($failure) {
623: $message = 'Saving notifications failed.';
624: } else {
625: 626: 627: 628:
629: $message = 'Notifications created for user(s): '.implode(',',$usersSuccess);
630: if($partialFailure) {
631: $message .= '; saving notifications failed for users(s): '.implode(',',$usersFailure);
632: }
633: }
634:
635:
636: $event = new Events();
637: $event->type = 'voip_call';
638: $event->associationType = get_class($contact);
639: $event->associationId = $contact->id;
640: $event->save();
641:
642: $this->_sendResponse($failure ? 500 : 200,$message);
643: } else {
644: $this->_sendResponse(
645: 404,'Phone number record refers to a contact that no longer exists.');
646: }
647: }else{
648: $this->_sendResponse(404,'No matching phone number found.');
649:
650:
651:
652:
653:
654:
655:
656: }
657:
658: } else
659: $this->_sendResponse(400,'Invalid phone number format.');
660: } else {
661: $this->_sendResponse(400,'Phone number required as "data" URL parameter.');
662: }
663: }
664:
665:
666:
667:
668: 669: 670:
671: public function checkValidModel(){
672: $this->log("Checking for valid model class.");
673: $noModel = empty($_GET['model']);
674: if(!$noModel)
675: $noModel = preg_match('/^\s*$/', $_GET['model']);
676: if($noModel){
677: $this->log('Parameter "model" missing.');
678: $this->_sendResponse(400, "Model class name required.");
679: }
680: if(!class_exists($_GET['model'])){
681: $this->log("Class {$_GET['model']} not found.");
682: $this->_sendResponse(501, "Model class \"{$_GET['model']}\" not found or does not exist.");
683: }
684: $modelRef = new $_GET['model'];
685: if(get_parent_class($modelRef) != 'X2Model'){
686: $this->log("Class {$_GET['model']} is not a child of X2Model.");
687: $this->_sendResponse(403, "Model class \"{$_GET['model']}\" is not a child of X2Model and cannot be used in API calls.");
688: }
689:
690: $this->modelClass = $_GET['model'];
691: }
692:
693: 694: 695: 696: 697:
698: public function filterAuthenticate($filterChain) {
699: $haveCred = false;
700: $this->log("Checking user record.");
701: if (Yii::app()->request->requestType == 'POST') {
702: $haveCred = isset($_POST['userKey']) && isset($_POST['user']);
703: $params = $_POST;
704: } else {
705: $haveCred = isset($_GET['userKey']) && isset($_GET['user']);
706: $params = $_GET;
707: }
708:
709: if ($haveCred) {
710: $this->user = User::model()->findByAttributes(array('username' => $params['user'], 'userKey' => $params['userKey']));
711: if ((bool) $this->user) {
712: Yii::app()->suModel = $this->user;
713: if(!empty($this->user->userKey)){
714: Yii::app()->params->groups = Groups::getUserGroups($this->user->id);
715: Yii::app()->params->roles = Roles::getUserRoles($this->user->id);
716:
717: $roles = RoleToUser::model()->findAllByAttributes(array('userId' => $this->user->id));
718: $access = false;
719: $auth = Yii::app()->authManager;
720: foreach ($roles as $role) {
721: $access = $access || $auth->checkAccess('AdminIndex', $role->roleId);
722: }
723: if($access)
724: Yii::app()->params->isAdmin = true;
725: $filterChain->run();
726: } else
727: $this->_sendResponse(403, "User \"{$this->user->username}\" cannot use API; userKey not set.");
728: } else {
729: $this->log("Authentication failed; invalid user credentials; IP = {$_SERVER['REMOTE_ADDR']}; get or post params = " . CJSON::encode($params).'');
730: $this->_sendResponse(401, "Invalid user credentials.");
731: }
732: } else {
733: $this->log('No user credentials provided; IP = '.$_SERVER['REMOTE_ADDR']);
734: $this->_sendResponse(401, "No user credentials provided.");
735: }
736: }
737:
738: 739: 740: 741: 742:
743: public function filterAvailable($filterChain) {
744: if(is_int(Yii::app()->locked)) {
745: $this->_sendResponse(503,"X2Engine is currently undergoing maintenance. Please try again later.");
746: }
747:
748: $filterChain->run();
749: }
750:
751: 752: 753: 754: 755: 756: 757: 758:
759: public function filterCheckCRUDPermissions($filterChain) {
760: $model = new $this->modelClass;
761: $module = ucfirst($model->module);
762: $action = $this->action->id;
763: if(array_key_exists($action,$this->actionAuthItemMap))
764: $action = $this->actionAuthItemMap[$action];
765: else
766: $action = ucfirst($action);
767: $level = $this->actionCheckPermissions($module . $action);
768: if($level)
769: $filterChain->run();
770: else {
771: $this->log("User \"{$this->user->username}\" denied API action; does not have permission for $module$action",'application.automation.api');
772: $this->_sendResponse(403, 'This user does not have permission to perform operation "'.$action."\" on model <b>{$this->modelClass}</b>");
773: }
774: }
775:
776: public function filterNoSession($filterChain) {
777: Yii::app()->params->noSession = true;
778: $filterChain->run();
779: }
780:
781: 782: 783: 784: 785:
786: public function filterValidModel($filterChain) {
787: if (!isset($this->modelClass)) {
788: $this->checkValidModel();
789:
790: Yii::app()->setSuModel($this->user);
791: }
792: $filterChain->run();
793: }
794:
795: 796: 797: 798:
799: public function getModel($new=false){
800: if(!isset($this->_model)){
801: if($new){
802: $this->_model = new $this->modelClass;
803: }else{
804: $mSingle = X2Model::model($this->modelClass);
805: $params = array_merge($_POST,$_GET);
806: $this->_model = $mSingle->findByPkInArray($params);
807:
808: if(empty($this->_model))
809: $this->_respondBadPk($mSingle,$params);
810: }
811: }
812: return $this->_model;
813: }
814:
815: 816: 817: 818: 819:
820: public function modelSetUsernameFields(&$model) {
821: X2ChangeLogBehavior::usernameFieldsSet($model,$this->user->username);
822:
823: if($model->hasAttribute('assignedTo')){
824: if(array_key_exists('assignedTo', $_POST)){
825: $model->assignedTo = $_POST['assignedTo'];
826: }else{
827: $model->assignedTo = $this->user->username;
828: }
829: }
830: }
831:
832: 833: 834: 835: 836: 837: 838:
839: public function validationMsg($action, $model){
840: $msg = "<h1>".Yii::t('api', 'Error')."</h1>";
841: $msg .= Yii::t('api',"Couldn't perform {a} on model {m}", array('{a}' => $action, '{m}' => "<b>".get_class($model)."</b>"));
842: $msg .= "<ul>";
843: foreach($model->errors as $attribute => $attr_errors){
844: $msg .= "<li>$attribute</li>";
845: $msg .= "<ul>";
846: foreach($attr_errors as $attr_error)
847: $msg .= "<li>$attr_error</li>";
848: $msg .= "</ul>";
849: }
850: $msg .= "</ul>";
851: return $msg;
852: }
853:
854: public function log($message,$level='trace') {
855: Yii::log($message,$level,'application.api');
856: }
857:
858: 859: 860: 861: 862: 863: 864: 865: 866: 867:
868: protected function _sendResponse($status = 200, $body = '',$direct = false) {
869:
870:
871: if($direct) {
872:
873:
874: $this->response->body = json_encode($body);
875: $this->response->sendHttp($status);
876: }
877:
878:
879: if ($body == '') {
880:
881: $message = '';
882:
883:
884:
885:
886: switch ($status) {
887: case 401:
888: $message = 'You must be authorized to view this page.';
889: break;
890: case 404:
891: $message = 'The requested URL ' . $_SERVER['REQUEST_URI'] . ' was not found.';
892: break;
893: case 500:
894: $message = 'The server encountered an error processing your request.';
895: break;
896: case 501:
897: $message = 'The requested method is not implemented.';
898: break;
899: case 503:
900: $message = "X2Engine is currently unavailable.";
901: break;
902: }
903:
904:
905:
906: $signature = ($_SERVER['SERVER_SIGNATURE'] == '') ? $_SERVER['SERVER_SOFTWARE'] . ' Server at ' . $_SERVER['SERVER_NAME'] . ' Port ' . $_SERVER['SERVER_PORT'] : $_SERVER['SERVER_SIGNATURE'];
907:
908:
909: $body = '<h1>' . $this->_getStatusCodeMessage($status) . '</h1>
910: <p>' . $message . '</p>
911: <hr />
912: <address>' . $signature . '</address>';
913: }
914: $this->response->sendHttp($status,$body);
915: }
916:
917: 918: 919: 920: 921: 922:
923: protected function _getStatusCodeMessage($status) {
924:
925:
926:
927: $codes = Array(
928: 200 => 'OK',
929: 400 => 'Bad Request',
930: 401 => 'Unauthorized',
931: 402 => 'Payment Required',
932: 403 => 'Forbidden',
933: 404 => 'Not Found',
934: 500 => 'Internal Server Error',
935: 501 => 'Not Implemented',
936: );
937: return (isset($codes[$status])) ? $codes[$status] : '';
938: }
939:
940: 941: 942: 943: 944:
945: protected function _respondBadPk(X2Model $modelSingle, array $params) {
946: $pkc = $modelSingle->tableSchema->primaryKey;
947: $pk = array();
948: if (is_array($pkc)) {
949: foreach ($pkc as $colName) {
950: if (array_key_exists($colName, $params)) {
951: $pk[$colName] = $params[$colName];
952: }
953: }
954: $pkc = array_keys($pkc);
955: } else {
956: if (array_key_exists($pkc, $params))
957: $pk[$pkc] = $params[$pkc];
958: $pkc = array($pkc);
959: }
960: if (!empty($pk)) {
961: $this->_sendResponse(404, "No record of model {$this->modelClass} found with specified primary key value (" . implode('-', array_keys($pk)) . '): ' . (implode('-', array_values($pk))));
962: } else {
963: $this->_sendResponse(400, sprintf("No parameters matching primary key column(s) <b>%s</b> for model <b>%s</b>.",implode('-',$pkc),$this->modelClass));
964: }
965: }
966:
967: }
968: