1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36:
37:
38: Yii::import('application.components.util.*');
39:
40: 41: 42: 43: 44: 45: 46: 47:
48: class AdminController extends X2Controller {
49:
50: public $modelClass = 'Admin';
51: public $portlets = array();
52: public $layout = '//layouts/column1';
53:
54: 55: 56:
57: public $noBackdrop = false;
58:
59: 60: 61: 62:
63: public static $behaviorClasses = array(
64: 'LeadRoutingBehavior',
65: 'UpdaterBehavior',
66: 'CommonControllerBehavior',
67: 'ImportExportBehavior',
68:
69: );
70:
71: 72: 73: 74:
75: public static $behaviorProperties = array('UpdaterBehavior' => array('isConsole' => false));
76:
77: 78: 79: 80: 81:
82: public static $dependencies = array(
83: 'util/FileUtil', 'util/EncryptUtil', 'util/ResponseUtil', 'ResponseBehavior',
84: 'views/requirements');
85:
86: 87: 88: 89:
90: private $_noRemoteAccess;
91: private $_behaviors;
92: private $_exportFile;
93:
94: 95: 96: 97: 98: 99: 100: 101:
102: public function actions() {
103: return array_merge($this->webUpdaterActions, array(
104: 'ajaxGetModelAutocomplete' => array(
105: 'class' => 'application.components.actions.AjaxGetModelAutocompleteAction',
106: ),
107:
108: 'viewLog' => array(
109: 'class' => 'LogViewerAction',
110: ),
111: ));
112: }
113:
114: 115: 116: 117: 118: 119: 120: 121: 122:
123: public function actionCalculateMissingTranslations() {
124: $untranslated = array();
125: $languages = scandir('protected/messages');
126: foreach ($languages as $lang) {
127: if (!in_array($lang, array('template', '.', '..'))) {
128: $untranslated[$lang] = 0;
129: $files = scandir('protected/messages/' . $lang);
130: foreach ($files as $file) {
131: if ($file != '.' && $file != '..') {
132: $translations = array_values(include('protected/messages/' . $lang . '/' . $file));
133: foreach ($translations as $message) {
134: if (empty($message)) {
135: $untranslated[$lang] ++;
136: }
137: }
138: }
139: }
140: }
141: }
142: printR($untranslated);
143: }
144:
145: 146: 147: 148: 149: 150: 151: 152: 153: 154:
155: public function actionCalculateTranslationRedundancy() {
156: $max = array('file1' => 'null', 'file2' => 'null', 'redundancy' => 0);
157: $files = scandir('protected/messages/template');
158: $duplicates = array();
159: $languageList = array();
160: $totalWords = array();
161: $untranslated = 0;
162: foreach ($files as $file) {
163: if ($file != '.' && $file != '..') {
164: $languageList[$file] = array_keys(include("protected/messages/template/$file"));
165: }
166: }
167: $keys = array_keys($languageList);
168: for ($i = 0; $i < count($languageList); $i++) {
169: $totalWords = array_merge($totalWords, $languageList[$keys[$i]]);
170: for ($j = $i + 1; $j < count($languageList); $j++) {
171: $intersect = array_intersect($languageList[$keys[$i]], $languageList[$keys[$j]]);
172: if (!empty($intersect)) {
173: $duplicates = array_unique(array_merge($duplicates, $intersect));
174: printR($intersect);
175: $unique = count($languageList[$keys[$i]]) + count($languageList[$keys[$j]]) - count($intersect);
176: $redundancy = round(count($intersect) / $unique * 100, 2);
177: echo "Between " . $keys[$i] . " and " . $keys[$j] . ": " . $redundancy . "% items identical.<br />";
178: if ($redundancy > $max['redundancy']) {
179: $max['file1'] = $keys[$i];
180: $max['file2'] = $keys[$j];
181: $max['redundancy'] = $redundancy;
182: }
183: }
184: }
185: }
186: echo "<br>The most redundant files are " . $max['file1'] . " and " . $max['file2'] . " with a redundancy of " . $max['redundancy'] . "%<br><br>";
187: echo "There are " . count($duplicates) . " entries which occur more than once.<br><br>";
188: echo "There are " . count($totalWords) . " entries in the translation files.";
189: }
190:
191: private static function findMissingPermissions() {
192: $controllers = array(
193: 'AdminController' => 'application.controllers.AdminController',
194: 'StudioController' => 'application.controllers.StudioController',
195: 'AccountsController' => 'application.modules.accounts.controllers.AccountsController',
196: 'ActionsController' => 'application.modules.actions.controllers.ActionsController',
197: 'CalendarController' => 'application.modules.calendar.controllers.CalendarController',
198: 'ContactsController' => 'application.modules.contacts.controllers.ContactsController',
199: 'DocsController' => 'application.modules.docs.controllers.DocsController',
200: 'GroupsController' => 'application.modules.groups.controllers.GroupsController',
201: 'MarketingController' =>
202: 'application.modules.marketing.controllers.MarketingController',
203: 'MediaController' => 'application.modules.media.controllers.MediaController',
204: 'OpportunitiesController' =>
205: 'application.modules.opportunities.controllers.OpportunitiesController',
206: 'ProductsController' => 'application.modules.products.controllers.ProductsController',
207: 'QuotesController' => 'application.modules.quotes.controllers.QuotesController',
208: 'ServicesController' => 'application.modules.services.controllers.ServicesController',
209: 'TopicsController' => 'application.modules.topics.controllers.TopicsController',
210: 'UsersController' => 'application.modules.users.controllers.UsersController',
211: 'WorkflowController' => 'application.modules.workflow.controllers.WorkflowController',
212: 'X2LeadsController' => 'application.modules.x2Leads.controllers.X2LeadsController',
213: 'BugReportsController' =>
214: 'application.modules.bugReports.controllers.BugReportsController',
215:
216: );
217: $missingPermissions = array();
218: $auth = Yii::app()->authManager;
219: foreach ($controllers as $class => $controller) {
220: Yii::import($controller);
221: $methods = get_class_methods($class);
222: $arr = explode('Controller', $class);
223: $name = $arr[0];
224: if (is_array($methods)) {
225: foreach ($methods as $method) {
226:
227: if (strpos($method, 'action') === 0 && $method != 'actions') {
228: $method = $name . substr($method, 6);
229: $authItem = $auth->getAuthItem($method);
230:
231: if (is_null($authItem))
232: $missingPermissions[] = $method;
233: }
234: }
235: }
236: if (preg_match('/modules/', $controller)) {
237: $moduleName = preg_replace(
238: '/application.modules.([^.]+)\..*/', '$1', $controller);
239: $moduleClassName = ucfirst($moduleName) . 'Module';
240: Yii::import(preg_replace('/controller.*/', '*', $controller));
241: $controller = new $class('', new $moduleClassName($moduleName, null));
242: $actions = $controller->actions();
243: foreach ($actions as $actionName => $params) {
244: $method = $name . ucfirst($actionName);
245: $authItem = $auth->getAuthItem($method);
246: if (is_null($authItem))
247: $missingPermissions[] = $method;
248: }
249: } else {
250: Yii::import(preg_replace('/controller.*/', '*', $controller));
251: $controller = new $class('');
252: $actions = $controller->actions();
253: foreach ($actions as $actionName => $params) {
254: $method = $name . ucfirst($actionName);
255: $authItem = $auth->getAuthItem($method);
256: if (is_null($authItem))
257: $missingPermissions[] = $method;
258: }
259: }
260: }
261: return $missingPermissions;
262: }
263:
264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274:
275: public function actionFindMissingPermissions() {
276: printR(self::findMissingPermissions());
277: }
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303: 304: 305:
306: public function actionIndex() {
307:
308:
309: $this->render('index');
310: }
311:
312: 313: 314: 315: 316: 317: 318: 319: 320: 321:
322: protected function beforeAction($action = null) {
323: $this->validateMobileRequest ($action);
324: $auth = Yii::app()->authManager;
325: $action = ucfirst($this->getId()) . ucfirst($this->getAction()->getId());
326: $authItem = $auth->getAuthItem($action);
327:
328: $imAdmin = false;
329: if (Yii::app()->params->hasProperty('isAdmin')) {
330: $imAdmin = Yii::app()->params->isAdmin || Yii::app()->user->checkAccess($action);
331: } else if (version_compare(Yii::app()->params->version, '2.0') >= 0) {
332: $imAdmin = Yii::app()->user->checkAccess('AdminIndex');
333: }
334: if ($imAdmin) {
335: return true;
336: } elseif (Yii::app()->user->isGuest) {
337: Yii::app()->user->returnUrl = Yii::app()->request->requestUri;
338: $this->redirect($this->createUrl('/site/login'));
339: } else {
340: throw new CHttpException(403, 'You are not authorized to perform this action.');
341: }
342: }
343:
344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360:
361:
362: 363: 364: 365: 366: 367: 368: 369: 370:
371: public function filters() {
372:
373: return array(
374:
375: 'clearCache',
376:
377: );
378: }
379:
380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407:
408: public function behaviors() {
409: if (!isset($this->behaviors)) {
410: $missingClasses = array();
411: $behaviors = array();
412: $maxTries = 3;
413: $GithubUrl = 'https://raw.github.com/X2Engine/X2Engine/master/x2engine/protected';
414: $x2planUrl = 'https://x2planet.com/updates/x2engine/protected';
415: $files = array_merge(array_fill_keys(self::$behaviorClasses, 'behavior'), array_fill_keys(self::$dependencies, 'dependency'));
416: $tryCurl = in_array(ini_get('allow_url_fopen'), array(0, 'Off', 'off'));
417: foreach ($files as $class => $type) {
418:
419: $path = "components/$class.php";
420: $absPath = Yii::app()->basePath . "/$path";
421: if (!file_exists($absPath)) {
422: if (!is_dir(dirname($absPath))) {
423: mkdir(dirname($absPath));
424: }
425: $i = 0;
426: while (!$this->copyRemote("$x2planUrl/$path", $absPath, $tryCurl) && $i < $maxTries) {
427: $i++;
428: }
429:
430: if ($i >= $maxTries) {
431: $i = 0;
432: while (!$this->copyRemote("$GithubUrl/$path", $path, $tryCurl) && $i < $maxTries) {
433: $i++;
434: }
435: }
436:
437: if ($i >= $maxTries) {
438: $missingClasses[] = "protected/$path";
439: }
440: }
441: if ($type == 'behavior') {
442: $behaviors[$class] = array(
443: 'class' => $class
444: );
445: }
446: }
447:
448:
449:
450:
451: if (count($missingClasses))
452: $this->missingClassesException($missingClasses);
453:
454:
455: foreach (self::$behaviorProperties as $class => $properties) {
456: foreach ($properties as $name => $value) {
457: $behaviors[$class][$name] = $value;
458: }
459: }
460: $this->_behaviors = $behaviors;
461: }
462: return $this->_behaviors;
463: }
464:
465: 466: 467: 468: 469: 470: 471: 472:
473: public function accessRules() {
474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501:
502: }
503:
504: 505: 506: 507: 508: 509: 510: 511: 512: 513:
514: public function filterClearCache($filterChain) {
515: $cache = Yii::app()->cache;
516: if (isset($cache))
517: $cache->flush();
518: $filterChain->run();
519: }
520:
521: 522: 523: 524:
525: public function filterClearAuthCache($filterChain) {
526:
527: if (!is_null(Yii::app()->db->getSchema()->getTable('x2_auth_cache'))) {
528: if (Yii::app()->hasComponent('authCache')) {
529: $authCache = Yii::app()->authCache;
530: if (isset($authCache))
531: $authCache->clear();
532: }
533: }
534: $filterChain->run();
535: }
536:
537: 538: 539: 540: 541: 542: 543:
544: public function actionManageTags() {
545: $dataProvider = new CActiveDataProvider('Tags', array(
546: 'criteria' => array(
547: 'group' => 'tag'
548: ),
549: 'pagination' => array(
550: 'pageSize' => isset($pageSize) ? $pageSize : Profile::getResultsPerPage(),
551: ),
552: ));
553:
554: $this->render('manageTags', array(
555: 'dataProvider' => $dataProvider,
556: ));
557: }
558:
559: 560: 561: 562:
563: public function actionDeleteTag($tag) {
564: if (is_string ($tag) && strlen ($tag)) {
565: if ($tag != 'all') {
566: X2Model::model('Tags')->deleteAllByAttributes(array('tag' => $tag));
567: } else {
568: X2Model::model('Tags')->deleteAll();
569: }
570: }
571: $this->redirect('manageTags');
572: }
573:
574: 575: 576: 577:
578: public function actionManageSessions() {
579: $dataProvider = new CActiveDataProvider('Session');
580:
581: $this->render('manageSessions', array(
582: 'dataProvider' => $dataProvider,
583: ));
584: }
585:
586: 587: 588: 589: 590:
591: private function fixupImportedModuleDropdowns($modules) {
592: foreach ($modules as $module) {
593: $fields = Yii::app()->db->createCommand()
594: ->select('id, linkType')
595: ->from('x2_fields')
596: ->where('type = "dropdown" AND modelName = :model', array(
597: ':model' => $module
598: ))->queryAll();
599: foreach ($fields as $field) {
600: if (!ctype_digit($field['linkType'])) {
601: $dropdownId = Yii::app()->db->createCommand()
602: ->select('id')
603: ->from('x2_dropdowns')
604: ->where('name = :name', array(
605: ':name' => $field['linkType']
606: ))
607: ->queryScalar();
608: if ($dropdownId) {
609: Yii::app()->db->createCommand()
610: ->update(
611: 'x2_fields',
612: array('linkType' => $dropdownId),
613: 'id = :id AND type = "dropdown"',
614: array(':id' => $field['id'])
615: );
616: }
617: }
618: }
619: }
620: }
621:
622:
623:
624: 625: 626: 627:
628: public function actionToggleSession($id) {
629: if (isset($_GET['id'])) {
630: $id = $_GET['id'];
631: $session = Session::model()->findByPk($id);
632: if (isset($session)) {
633: $session->status = !$session->status;
634: $ret = $session->status;
635: if ($session->save()) {
636: echo $ret;
637: }
638: }
639: }
640: }
641:
642: 643: 644: 645: 646:
647: public function actionEndSession($id) {
648: echo Session::model()->deleteByPk($id);
649: }
650:
651: 652: 653: 654: 655: 656: 657: 658: 659: 660:
661: public function actionViewSessionLog() {
662: $sessionLog = new CActiveDataProvider('SessionLog', array(
663: 'sort' => array(
664: 'defaultOrder' => 'timestamp DESC',
665: ),
666: 'pagination' => array(
667: 'pageSize' => Profile::getResultsPerPage()
668: )
669: ));
670: $this->render('viewSessionLog', array(
671: 'dataProvider' => $sessionLog,
672: ));
673: }
674:
675: 676: 677: 678: 679:
680: public function actionViewSessionHistory($id) {
681: $sessions = X2Model::model('SessionLog')->findAllByAttributes(array('sessionId' => $id));
682: $firstTimestamp = 0;
683: $lastTimestamp = 0;
684: $str = "<table class='items'><thead><tr><th>User</th><th>Status</th><th>Timestamp</th></tr></thead>";
685: foreach ($sessions as $session) {
686: $str.="<tr>";
687: $str.="<td>" . User::getUserLinks($session->user) . "</td>";
688: $str.="<td>" . SessionLog::parseStatus($session->status) . "</td>";
689: $str.="<td>" . Formatter::formatCompleteDate($session->timestamp) . "</td>";
690: $str.="</tr>";
691: }
692: $str.="</table>";
693: echo $str;
694: }
695:
696: 697: 698: 699:
700: public function actionUserViewLog() {
701: $dataProvider = new CActiveDataProvider('ViewLog', array(
702: 'sort' => array(
703: 'defaultOrder' => 'timestamp DESC',
704: ),
705: 'pagination' => array(
706: 'pageSize' => Profile::getResultsPerPage()
707: )
708: ));
709: $this->render('userViewLog', array(
710: 'dataProvider' => $dataProvider,
711: ));
712: }
713:
714: 715: 716:
717: public function actionClearViewHistory() {
718: X2model::model('ViewLog')->deleteAll();
719: $this->redirect('userViewLog');
720: }
721:
722: 723: 724: 725: 726: 727: 728:
729: public function actionGetRoutingType() {
730: $assignee = $this->getNextAssignee();
731:
732: if ($assignee == "Anyone")
733: $assignee = "";
734: echo $assignee;
735: }
736:
737: 738: 739: 740: 741: 742: 743: 744:
745: public function actionRoundRobinRules() {
746: $model = new LeadRouting;
747: $users = User::getNames();
748: unset($users['Anyone']);
749: unset($users['admin']);
750: $priorityArray = array();
751: for ($i = 1; $i <= LeadRouting::model()->count() + 1; $i++) {
752: $priorityArray[$i] = $i;
753: }
754: $dataProvider = new CActiveDataProvider('LeadRouting', array(
755: 'criteria' => array(
756: 'order' => 'priority ASC',
757: )
758: ));
759: if (isset($_POST['LeadRouting'])) {
760: $values = $_POST['Values'];
761: $criteria = array();
762: for ($i = 0; $i < count($values['field']); $i++) {
763: $tempArr = array(
764: $values['field'][$i], $values['comparison'][$i], $values['value'][$i]);
765: $criteria[] = implode(',', $tempArr);
766: }
767: $model->criteria = json_encode($criteria);
768: $model->attributes = $_POST['LeadRouting'];
769: $model->priority = $_POST['LeadRouting']['priority'];
770: if (isset($_POST['group'])) {
771: $group = true;
772: $model->groupType = $_POST['groupType'];
773: } else {
774: $model->groupType = null;
775: }
776:
777: $model->users = Fields::parseUsers($model->users);
778: $check = LeadRouting::model()->findByAttributes(array('priority' => $model->priority));
779: if (isset($check)) {
780: $query = "UPDATE x2_lead_routing " .
781: "SET priority=priority+1 " .
782: "WHERE priority>='$model->priority'";
783: $command = Yii::app()->db->createCommand($query);
784: $command->execute();
785: }
786: if ($model->save()) {
787: $this->redirect('roundRobinRules');
788: }
789: }
790:
791: $this->render('customRules', array(
792: 'model' => $model,
793: 'users' => $users,
794: 'dataProvider' => $dataProvider,
795: 'priorityArray' => $priorityArray,
796: ));
797: }
798:
799: 800: 801: 802: 803: 804: 805:
806: public function actionDeleteRole() {
807: $auth = Yii::app()->authManager;
808: $roleId = filter_input(INPUT_POST, 'role', FILTER_SANITIZE_STRING);
809: if ($roleId) {
810: $role = Roles::model()->findByPk($roleId);
811: if (!isset($role)) {
812:
813: Yii::app()->user->setFlash('error', Yii::t('admin', 'Role does not exist'));
814: } elseif (!in_array (
815: strtolower ($role->name), array('authenticated', 'guest', 'admin'))) {
816:
817: $auth->removeAuthItem($role->name);
818: $role->delete();
819: }
820: }
821: $this->redirect('manageRoles');
822: }
823:
824: 825: 826: 827: 828: 829:
830: public function actionEditRole() {
831: $roleInput = FilterUtil::filterArrayInput ($_POST, 'Roles');
832: if (!empty($roleInput)) {
833: $roleName = isset($roleInput['name']) ? filter_var($roleInput['name'], FILTER_SANITIZE_STRING) : '';
834: $timeout = filter_input(INPUT_POST, 'timeout', FILTER_SANITIZE_NUMBER_INT);
835: $role = Roles::model()->findByAttributes(array('name' => $roleName));
836: if (isset($role)) {
837: $viewPermissions = FilterUtil::filterArrayInput ($_POST, 'viewPermissions');
838: $editPermissions = FilterUtil::filterArrayInput ($_POST, 'editPermissions');
839: $users = FilterUtil::filterArrayInput ($_POST, 'users');
840: $timeout = $timeout * 60;
841: if ($timeout === 0) {
842: $timeout = null;
843: }
844: $role->timeout = $timeout;
845: $role->setUsers($users);
846:
847: $role->setViewPermissions($viewPermissions);
848: $role->setEditPermissions($editPermissions);
849: if ($role->save()) {
850:
851: } else {
852: foreach ($model->getErrors() as $err)
853: $errors = $err;
854: $errors = implode(',', $errors);
855: Yii::app()->user->setFlash('error', Yii::t('admin', "Unable to save role: {errors}", array('{errors}' => $errors)));
856: }
857: }
858: }
859: $this->redirect('manageRoles');
860: }
861:
862: 863: 864: 865: 866: 867: 868: 869:
870: public function actionRoleException() {
871: $model = new Roles;
872: $temp = Workflow::model()->findAll();
873: $workflows = array();
874: foreach ($temp as $workflow) {
875: $workflows[$workflow->id] = $workflow->name;
876: }
877: $roleInput = filter_input(INPUT_POST,'Roles',FILTER_DEFAULT,FILTER_REQUIRE_ARRAY);
878: if (!empty($roleInput)) {
879: $workflowId = filter_input(INPUT_POST,'workflow',FILTER_SANITIZE_NUMBER_INT);
880: if (!empty($workflowId)){
881: $workflowName = Workflow::model()->findByPk($workflowId)->name;
882: } else {
883: $this->redirect('manageRoles');
884: }
885: $stage = $_POST['workflowStages'];
886: if (isset($stage) && !empty($stage))
887: $stageName = X2Model::model('WorkflowStage')->findByAttributes(array('workflowId' => $workflow, 'stageNumber' => $stage))->name;
888: else
889: $this->redirect('manageRoles');
890: if (!isset($_POST['viewPermissions']))
891: $viewPermissions = array();
892: else
893: $viewPermissions = $_POST['viewPermissions'];
894: if (!isset($_POST['editPermissions']))
895: $editPermissions = array();
896: else
897: $editPermissions = $_POST['editPermissions'];
898: $model->attributes = $_POST['Roles'];
899: $model->timeout *= 60;
900: $oldRole = Roles::model()->findByAttributes(array('name' => $model->name));
901: $model->users = "";
902: $model->name.=" - $workflowName: $stageName";
903: if ($model->save()) {
904: $replacement = new RoleToWorkflow;
905: $replacement->workflowId = $workflow;
906: $replacement->stageId = $stage;
907: $replacement->roleId = $oldRole->id;
908: $replacement->replacementId = $model->id;
909: $replacement->save();
910: $fields = Fields::model()->findAll();
911: $temp = array();
912: foreach ($fields as $field) {
913: $temp[] = $field->id;
914: }
915:
916: $both = array_intersect($viewPermissions, $editPermissions);
917: $view = array_diff($viewPermissions, $editPermissions);
918: $neither = array_diff($temp, $viewPermissions);
919: foreach ($both as $field) {
920: $rolePerm = new RoleToPermission;
921: $rolePerm->roleId = $model->id;
922: $rolePerm->fieldId = $field;
923: $rolePerm->permission = 2;
924: $rolePerm->save();
925: }
926: foreach ($view as $field) {
927: $rolePerm = new RoleToPermission;
928: $rolePerm->roleId = $model->id;
929: $rolePerm->fieldId = $field;
930: $rolePerm->permission = 1;
931: $rolePerm->save();
932: }
933: foreach ($neither as $field) {
934: $rolePerm = new RoleToPermission;
935: $rolePerm->roleId = $model->id;
936: $rolePerm->fieldId = $field;
937: $rolePerm->permission = 0;
938: $rolePerm->save();
939: }
940: }
941: $this->redirect('manageRoles');
942: }
943: }
944:
945: 946: 947: 948: 949: 950: 951: 952:
953: public function actionWorkflowSettings() {
954: $admin = &Yii::app()->settings;
955: if (isset($_POST['Admin'])) {
956:
957: $admin->attributes = $_POST['Admin'];
958:
959:
960:
961: if ($admin->save()) {
962:
963: }
964: }
965:
966: $this->render('workflowSettings', array(
967: 'model' => $admin,
968: ));
969: }
970:
971: 972: 973: 974: 975: 976:
977: public function actionGetWorkflowStages() {
978: if (isset($_POST['workflow'])) {
979: $id = $_POST['workflow'];
980: $stages = Workflow::getStages($id);
981: foreach ($stages as $key => $value) {
982: echo CHtml::tag('option', array('value' => $key + 1), CHtml::encode($value), true);
983: }
984: } else {
985: echo CHtml::tag('option', array('value' => ''), CHtml::encode(var_dump($_POST)), true);
986: }
987: }
988:
989: 990: 991: 992: 993: 994: 995: 996:
997: public function actionGetRole() {
998: $output = "";
999: $roleInput = FilterUtil::filterArrayInput ($_POST, 'Roles');
1000: if (!empty($roleInput)) {
1001: $roleName = isset($roleInput['name']) ?
1002: filter_var($roleInput['name'], FILTER_SANITIZE_STRING) : '';
1003: $role = Roles::model()->findByAttributes(array('name' => $roleName));
1004: if (isset($role)) {
1005: $usernames = Yii::app()->db->createCommand()
1006: ->select('a.username')
1007: ->from('x2_users a')
1008: ->join('x2_role_to_user b', 'a.id=b.userId')
1009: ->where('b.roleId=:roleId AND b.type="user"', array(':roleId' => $role->id))
1010: ->queryColumn();
1011: $groupIds = Yii::app()->db->createCommand()
1012: ->select('a.id')
1013: ->from('x2_groups a')
1014: ->join('x2_role_to_user b', 'a.id=b.userId')
1015: ->where('b.roleId=:roleId AND b.type="group"', array(':roleId' => $role->id))
1016: ->queryColumn();
1017: $selected = array_merge($usernames, $groupIds);
1018:
1019: $allUsers = X2Model::getAssignmentOptions(false, true, false);
1020: unset($allUsers['admin']);
1021:
1022: $sliderId = 'editTimeoutSlider';
1023: $textfieldId = 'editTimeout';
1024: if (isset($_GET['mode']) && in_array($_GET['mode'], array('edit', 'exception'))) {
1025:
1026:
1027: $sliderId .= "-" . $_GET['mode'];
1028: $textfieldId .= "-" . $_GET['mode'];
1029: }
1030:
1031: $timeoutSet = $role->timeout !== null;
1032: $output.= "
1033: <div class='row' id='set-session-timeout-row'>
1034: <input id='set-session-timeout' type='checkbox' class='left' " .
1035: ($timeoutSet ? 'checked="checked"' : '') . ">
1036: <label>" . Yii::t('admin', 'Enable Session Timeout') . "</label>
1037: </div>
1038: ";
1039: $output.= "<div id='timeout-row' class='row' " .
1040: ($timeoutSet ? '' : "style='display: none;'") . ">";
1041: $output.= Yii::t('admin', 'Set role session expiration time (in minutes).');
1042: $output.= "<br />";
1043: $output.= $this->widget('zii.widgets.jui.CJuiSlider', array(
1044: 'value' => $role->timeout / 60,
1045:
1046: 'options' => array(
1047: 'min' => 5,
1048: 'max' => 1440,
1049: 'step' => 5,
1050: 'change' => "js:function(event,ui) {
1051: $('#" . $textfieldId . "').val(ui.value);
1052: $('#save-button').addClass('highlight');
1053: }",
1054: 'slide' => "js:function(event,ui) {
1055: $('#" . $textfieldId . "').val(ui.value);
1056: }",
1057: ),
1058: 'htmlOptions' => array(
1059: 'style' => 'width:340px;margin:10px 9px;',
1060: 'id' => $sliderId
1061: ),
1062: ), true);
1063: $output.= CHtml::activeTextField(
1064: $role, 'timeout', array(
1065: 'id' => $textfieldId,
1066: 'disabled' => ($role->timeout !== null ? '' : 'disabled'),
1067: ));
1068: $output.= "</div>";
1069: Yii::app()->clientScript->registerScript('timeoutScript', "
1070: $('#set-session-timeout').change (function () {
1071: if ($(this).is (':checked')) {
1072: $('#timeout-row').slideDown ();
1073: $('#" . $textfieldId . "').removeAttr ('disabled');
1074: } else {
1075: $('#timeout-row').slideUp ();
1076: $('#" . $textfieldId . "').attr ('disabled', 'disabled');
1077: }
1078: });
1079: $('#" . $textfieldId . "').val( $('#" . $sliderId . "').slider('value') );
1080: ", CClientScript::POS_READY);
1081: $output.= "<script>";
1082: $output.= Yii::app()->clientScript->echoScripts(true);
1083: $output.= "</script>";
1084:
1085: $output.= "<div id='users'><label>Users</label>";
1086: $output.= CHtml::dropDownList(
1087: 'users[]', $selected, $allUsers,
1088: array(
1089: 'class' => 'multiselect',
1090: 'multiple' => 'multiple',
1091: 'size' => 8
1092: ));
1093: $output.= "</div>";
1094: $fields = Fields::getFieldsOfModelsWithFieldLevelPermissions ();
1095: $fieldIds = array_flip (array_map (function ($field) {
1096: return $field->id;
1097: }, $fields));
1098: $viewSelected = array();
1099: $editSelected = array();
1100: $fieldUnselected = array();
1101: $fieldPerms = RoleToPermission::model()
1102: ->findAllByAttributes(array('roleId' => $role->id));
1103: foreach ($fieldPerms as $perm) {
1104: if (!isset ($fieldIds[$perm->fieldId])) continue;
1105: if ($perm->permission == 2) {
1106: $viewSelected[] = $perm->fieldId;
1107: $editSelected[] = $perm->fieldId;
1108: } else if ($perm->permission == 1) {
1109: $viewSelected[] = $perm->fieldId;
1110: }
1111: }
1112: foreach ($fields as $field) {
1113: $fieldUnselected[$field->id] = X2Model::getModelTitle($field->modelName) .
1114: " - " . $field->attributeLabel;
1115: }
1116: assert (
1117: count ($fieldUnselected) ===
1118: count (array_unique (array_keys ($fieldUnselected))));
1119: $output.= "<br /><label>View Permissions</label>";
1120: $output.= CHtml::dropDownList(
1121: 'viewPermissions[]',
1122: $viewSelected,
1123: $fieldUnselected,
1124: array(
1125: 'class' => 'multiselect',
1126: 'multiple' => 'multiple',
1127: 'size' => 8,
1128: 'id' => 'edit-role-field-view-permissions'
1129: ));
1130: $output.= "<br /><label>Edit Permissions</label>";
1131:
1132: $output.= CHtml::dropDownList(
1133: 'editPermissions[]',
1134: $editSelected,
1135: $fieldUnselected,
1136: array(
1137: 'class' => 'multiselect',
1138: 'multiple' => 'multiple',
1139: 'size' => 8,
1140: 'id' => 'edit-role-field-edit-permissions'
1141: ));
1142: }
1143: }
1144: echo $output;
1145: }
1146:
1147: 1148: 1149: 1150: 1151: 1152: 1153:
1154: public function actionManageRoles() {
1155: $dataProvider = new CActiveDataProvider('Roles');
1156: $roles = Yii::app()->db->createCommand()
1157: ->select('id, name')
1158: ->from('x2_roles')
1159: ->queryAll();
1160:
1161: $model = new Roles;
1162: $model->timeout = 60;
1163: $roleInput = FilterUtil::filterArrayInput ($_POST, 'Roles');
1164: if (!empty($roleInput)) {
1165: $model->attributes = $roleInput;
1166: $model->users = '';
1167: $viewPermissions = FilterUtil::filterArrayInput ($_POST, 'viewPermissions');
1168: $editPermissions = FilterUtil::filterArrayInput ($_POST, 'editPermissions');
1169: $users = FilterUtil::filterArrayInput ($roleInput, 'users');
1170: $model->timeout *= 60;
1171: if ($model->timeout === 0) {
1172: $model->timeout = null;
1173: }
1174: $model->setUsers($users);
1175: $model->setViewPermissions($viewPermissions);
1176: $model->setEditPermissions($editPermissions);
1177:
1178: if ($model->save()) {
1179:
1180: } else {
1181: foreach ($model->getErrors() as $err)
1182: $errors = $err;
1183: $errors = implode(',', $errors);
1184: Yii::app()->user->setFlash('error', Yii::t('admin', "Unable to save role: {errors}", array('{errors}' => $errors)));
1185: }
1186: $this->redirect('manageRoles');
1187: }
1188:
1189:
1190: $this->render('manageRoles', array(
1191: 'dataProvider' => $dataProvider,
1192: 'model' => $model,
1193: 'roles' => $roles,
1194: ));
1195: }
1196:
1197: 1198: 1199: 1200: 1201: 1202:
1203: public function actionViewChangelog() {
1204:
1205: $model = new Changelog('search');
1206: if (isset($_GET['Changelog'])) {
1207: foreach ($_GET['Changelog'] as $field => $value) {
1208: if ($model->hasAttribute($field)) {
1209: $model->$field = $value;
1210: }
1211: }
1212: }
1213: $this->render('viewChangelog', array(
1214: 'model' => $model,
1215: ));
1216: }
1217:
1218: 1219: 1220:
1221: public function actionExportChangelog() {
1222: ini_set('memory_limit', -1);
1223: $csv = $this->safePath('changelog.csv');
1224: $fp = fopen($csv, 'w+');
1225: $meta = array_keys(Changelog::model()->attributes);
1226: fputcsv($fp, $meta);
1227: $records = Changelog::model()->findAll();
1228: foreach ($records as $record) {
1229: $line = $record->attributes;
1230: fputcsv($fp, $line);
1231: }
1232: fclose($fp);
1233: }
1234:
1235: 1236: 1237:
1238: public function actionClearChangelog() {
1239: Changelog::model()->deleteAll();
1240: $this->redirect('viewChangelog');
1241: }
1242:
1243: 1244: 1245: 1246: 1247: 1248:
1249: public function actionAddCriteria() {
1250: $criteria = new Criteria;
1251: $users = User::getNames();
1252: $dataProvider = new CActiveDataProvider('Criteria');
1253: unset($users['']);
1254: unset($users['Anyone']);
1255: $criteria->users = Yii::app()->user->getName();
1256: if (isset($_POST['Criteria'])) {
1257: $criteria->attributes = $_POST['Criteria'];
1258: $str = "";
1259: $arr = $criteria->users;
1260: if ($criteria->type == 'assignment' && count($arr) > 1) {
1261: $this->redirect('addCriteria');
1262: }
1263: if (isset($arr)) {
1264: $str = implode(', ', $arr);
1265: }
1266: $criteria->users = $str;
1267: if ($criteria->modelType != null && $criteria->comparisonOperator != null) {
1268: if ($criteria->save()) {
1269:
1270: }
1271: $this->refresh();
1272: }
1273: }
1274: $this->render('addCriteria', array(
1275: 'users' => $users,
1276: 'model' => $criteria,
1277: 'dataProvider' => $dataProvider,
1278: ));
1279: }
1280:
1281: 1282: 1283: 1284: 1285: 1286: 1287: 1288:
1289: public function actionDeleteCriteria($id) {
1290:
1291: Criteria::model()->deleteByPk($id);
1292: $this->redirect(array('addCriteria'));
1293: }
1294:
1295: 1296: 1297: 1298: 1299: 1300: 1301:
1302: public function actionDeleteRouting($id) {
1303:
1304: LeadRouting::model()->deleteByPk($id);
1305: $this->redirect(array('roundRobinRules'));
1306: }
1307:
1308: 1309: 1310: 1311: 1312: 1313: 1314: 1315: 1316: 1317: 1318: 1319: 1320: 1321: 1322: 1323: 1324: 1325: 1326: 1327: 1328: 1329: 1330: 1331:
1332: 1333: 1334: 1335: 1336: 1337: 1338: 1339: 1340: 1341: 1342: 1343: 1344: 1345: 1346: 1347: 1348: 1349: 1350: 1351: 1352: 1353: 1354: 1355:
1356:
1357: 1358: 1359: 1360: 1361: 1362: 1363: 1364:
1365: public function actionAppSettings() {
1366:
1367: $admin = &Yii::app()->settings;
1368: if (isset($_POST['Admin'])) {
1369:
1370:
1371:
1372: $oldFormat = $admin->contactNameFormat;
1373: $admin->attributes = $_POST['Admin'];
1374: foreach ($_POST['Admin'] as $attribute => $value) {
1375: if ($admin->hasAttribute($attribute)) {
1376: $admin->$attribute = $value;
1377: }
1378: }
1379: if (isset($_POST['currency'])) {
1380: if ($_POST['currency'] == 'other') {
1381: $admin->currency = $_POST['currency2'];
1382: if (empty($admin->currency))
1383: $admin->addError('currency', Yii::t('admin', 'Please enter a valid currency type.'));
1384: } else
1385: $admin->currency = $_POST['currency'];
1386: }
1387: if ($oldFormat != $admin->contactNameFormat) {
1388: if ($admin->contactNameFormat == 'lastName, firstName') {
1389: $command = Yii::app()->db->createCommand()->setText('UPDATE x2_contacts SET name=CONCAT(lastName,", ",firstName)')->execute();
1390: } elseif ($admin->contactNameFormat == 'firstName lastName') {
1391: $command = Yii::app()->db->createCommand()->setText('UPDATE x2_contacts SET name=CONCAT(firstName," ",lastName)')->execute();
1392: }
1393: }
1394: $admin->timeout *= 60;
1395:
1396:
1397: if ($admin->save()) {
1398: $this->redirect('appSettings');
1399: }
1400: }
1401: $admin->timeout = ceil($admin->timeout / 60);
1402: $this->render('appSettings', array(
1403: 'model' => $admin,
1404: ));
1405: }
1406:
1407: 1408: 1409: 1410: 1411: 1412: 1413: 1414:
1415: public function actionActivitySettings() {
1416:
1417: $admin = &Yii::app()->settings;
1418: $admin->eventDeletionTypes = json_decode($admin->eventDeletionTypes, true);
1419: if (isset($_POST['Admin'])) {
1420:
1421: $admin->eventDeletionTime = $_POST['Admin']['eventDeletionTime'];
1422: $admin->eventDeletionTypes = json_encode($_POST['Admin']['eventDeletionTypes']);
1423: if ($admin->save()) {
1424: $this->redirect('activitySettings');
1425: }
1426: }
1427: $this->render('activitySettings', array(
1428: 'model' => $admin,
1429: ));
1430: }
1431:
1432: 1433: 1434: 1435: 1436: 1437:
1438: public function actionSetLeadRouting() {
1439:
1440: $admin = &Yii::app()->settings;
1441: if (isset($_POST['Admin'])) {
1442: $routing = $_POST['Admin']['leadDistribution'];
1443: $online = $_POST['Admin']['onlineOnly'];
1444: if ($routing == 'singleUser') {
1445: $user = $_POST['Admin']['rrId'];
1446: $admin->rrId = $user;
1447: }
1448:
1449: $admin->leadDistribution = $routing;
1450: $admin->onlineOnly = $online;
1451:
1452: if ($admin->save()) {
1453: $this->redirect('index');
1454: }
1455: }
1456:
1457: $this->render('leadRouting', array(
1458: 'admin' => $admin,
1459: ));
1460: }
1461:
1462: 1463: 1464: 1465: 1466: 1467:
1468: public function actionSetServiceRouting() {
1469:
1470: $admin = &Yii::app()->settings;
1471: if (isset($_POST['Admin'])) {
1472: $routing = $_POST['Admin']['serviceDistribution'];
1473: $online = $_POST['Admin']['serviceOnlineOnly'];
1474: if ($routing == 'singleUser') {
1475: $user = $_POST['Admin']['srrId'];
1476: $admin->srrId = $user;
1477: } else if ($routing == 'singleGroup') {
1478: $group = $_POST['Admin']['sgrrId'];
1479: $admin->sgrrId = $group;
1480: }
1481:
1482: $admin->serviceDistribution = $routing;
1483: $admin->serviceOnlineOnly = $online;
1484:
1485: if ($admin->save()) {
1486: $this->redirect('index');
1487: }
1488: }
1489:
1490: $this->render('serviceRouting', array(
1491: 'admin' => $admin,
1492: ));
1493: }
1494:
1495: 1496: 1497: 1498: 1499: 1500: 1501:
1502: public function actionGoogleIntegration() {
1503:
1504:
1505:
1506:
1507:
1508:
1509:
1510:
1511:
1512:
1513:
1514:
1515:
1516:
1517:
1518:
1519:
1520:
1521:
1522: $credId = Yii::app()->settings->googleCredentialsId;
1523:
1524: if ($credId && ($cred = Credentials::model()->findByPk($credId))) {
1525: $params = array('id' => $credId);
1526: } else {
1527: $params = array('class' => 'GoogleProject');
1528: }
1529: $url = Yii::app()->createUrl('/profile/createUpdateCredentials', $params);
1530: $this->redirect($url);
1531: }
1532:
1533: public function () {
1534: $credId = Yii::app()->settings->twitterCredentialsId;
1535:
1536: if ($credId && ($cred = Credentials::model()->findByPk($credId))) {
1537: $params = array('id' => $credId);
1538: } else {
1539: $params = array('class' => 'TwitterApp');
1540: }
1541: $url = Yii::app()->createUrl('/profile/createUpdateCredentials', $params);
1542: $this->redirect($url);
1543: }
1544:
1545: 1546: 1547: 1548: 1549: 1550:
1551: public function actionEmailSetup() {
1552:
1553: $admin = &Yii::app()->settings;
1554: Yii::app()->clientScript->registerScriptFile(Yii::app()->baseUrl . '/js/manageCredentials.js');
1555: if (isset($_POST['Admin'])) {
1556: $admin->attributes = $_POST['Admin'];
1557:
1558: if ($admin->save()) {
1559: $this->redirect('emailSetup');
1560: }
1561: } else {
1562:
1563: if (!isset($admin->doNotEmailLinkText))
1564: $admin->doNotEmailLinkText = Admin::getDoNotEmailLinkDefaultText();
1565: if (!isset($admin->doNotEmailPage))
1566: $admin->doNotEmailPage = Admin::getDoNotEmailDefaultPage();
1567: }
1568:
1569: $this->render('emailSetup', array(
1570: 'model' => $admin,
1571: ));
1572: }
1573:
1574: 1575: 1576: 1577: 1578: 1579: 1580: 1581: 1582: 1583:
1584: public function actionCreateUpdateField($search = 0, $save = 0, $override = 0) {
1585: $changedType = false;
1586: if ($search) {
1587:
1588:
1589: $new = false;
1590: if (isset($_POST['Fields'])) {
1591: $model = Fields::model()->findByAttributes(array_intersect_key($_POST['Fields'], array_fill_keys(array('modelName', 'fieldName'), null)));
1592: }
1593: } else {
1594:
1595: $new = true;
1596: }
1597: if (!isset($model) || !(bool) $model) {
1598:
1599: $model = new Fields;
1600: }
1601:
1602: if (isset($_POST['Fields']) && ($model->isNewRecord || $override)) {
1603: $oldType = $model->type;
1604: $model->attributes = $_POST['Fields'];
1605:
1606: if ($model->fieldName && $model->type !== $oldType)
1607: $changedType = true;
1608: }
1609:
1610: $message = '';
1611: $error = false;
1612:
1613: if (isset($_POST['Fields']) && $save) {
1614: $model->attributes = $_POST['Fields'];
1615: if (!isset($_POST['Fields']['linkType'])) {
1616:
1617:
1618: $model->linkType = null;
1619: }
1620:
1621:
1622: if (isset($_POST['AmorphousModel'])) {
1623: $aModel = $_POST['AmorphousModel'];
1624: $model->defaultValue = $model->parseValue($aModel['customized_field']);
1625: }
1626:
1627: $new = $model->isNewRecord;
1628: $model->modified = 1;
1629: if ($new)
1630: $model->custom = 1;
1631:
1632: if ($model->save()) {
1633:
1634: $cache = Yii::app()->cache;
1635: if (isset($cache))
1636: $cache->flush();
1637:
1638: $message = $new ? Yii::t('admin', 'Field added.') : Yii::t('admin', 'Field modified successfully.');
1639: if ($new) {
1640: $model = new Fields;
1641: }
1642: } else {
1643: $error = true;
1644: $message = Yii::t('admin', 'Please correct the following errors.');
1645: }
1646: }
1647: $dummyModel = new AmorphousModel;
1648: $dummyModel->addField($model, 'customized_field');
1649: $dummyModel->setAttribute('customized_field', $model->defaultValue);
1650:
1651: $this->renderPartial('createUpdateField', array(
1652: 'model' => $model,
1653: 'new' => $new,
1654: 'dummyModel' => $dummyModel,
1655: 'message' => $message,
1656: 'error' => $error,
1657: 'changedType' => $changedType,
1658: ));
1659: }
1660:
1661: 1662: 1663: 1664: 1665: 1666:
1667: public function actionRemoveField($getCount = false) {
1668:
1669: if (isset($_POST['field']) && $_POST['field'] != "") {
1670: $id = $_POST['field'];
1671: $field = Fields::model()->findByPk($id);
1672: if ($getCount) {
1673: $nonNull = $field->countNonNull();
1674: if ($nonNull) {
1675: echo Yii::t('admin', 'This field contains data; it is non-empty in {n} records.', array(
1676: '{n}' => '<span style="color:red;font-weight:bold">' . $nonNull . '</span>'
1677: )
1678: );
1679: } else {
1680: echo Yii::t('admin', 'The field appears to be empty. Deleting it will not result in any data loss.');
1681: }
1682: Yii::app()->end();
1683: }
1684: $field->delete();
1685: }
1686: $this->redirect('manageFields');
1687: }
1688:
1689: 1690: 1691: 1692: 1693: 1694:
1695: public function actionManageFields() {
1696:
1697: $model = new Fields;
1698:
1699:
1700: $searchModel = new Fields('search');
1701: $criteria = new CDbCriteria;
1702: $criteria->addCondition('modified=1');
1703: $searchModel->setAttributes(
1704: isset($_GET['Fields']) ? $_GET['Fields'] : array(), false);
1705: foreach ($searchModel->attributes as $name => $value) {
1706: $criteria->compare($name, $value);
1707: }
1708: $pageSize = Profile::getResultsPerPage();
1709: $dataProvider = new SmartActiveDataProvider('Fields', array(
1710: 'criteria' => $criteria,
1711: 'pagination' => array(
1712: 'pageSize' => Profile::getResultsPerPage(),
1713: ),
1714: ));
1715:
1716:
1717: $fields = Fields::model()->findAllByAttributes(array('custom' => '1'));
1718: $arr = array();
1719: foreach ($fields as $field) {
1720: $arr[$field->id] = $field->attributeLabel;
1721: }
1722:
1723: $this->render('manageFields', array(
1724: 'dataProvider' => $dataProvider,
1725: 'model' => $model,
1726: 'searchModel' => $searchModel,
1727: 'fields' => $arr,
1728: ));
1729: }
1730:
1731: public function () {
1732: if (!isset ($_POST['id'])) $this->badRequest ();
1733: $model = Modules::model ()->findByPk ($_POST['id']);
1734: if (!$model || !in_array ($model->moduleType, array ('link', 'recordLink'))) {
1735: $this->badRequest ();
1736: }
1737: if ($model->delete ()) {
1738: echo 'success';
1739: }
1740: }
1741:
1742: public function actionEditMobileForms () {
1743: Yii::import ('application.modules.mobile.models.*');
1744: Yii::import ('application.modules.mobile.*');
1745: Yii::import ('application.models.formModels.*');
1746: $model = new EditMobileFormsFormModel;
1747: if (isset ($_POST['EditMobileFormsFormModel'])) {
1748: $model->setAttributes ($_POST['EditMobileFormsFormModel']);
1749: if ($model->validate ()) {
1750: Yii::app()->db->createCommand ()
1751: ->delete (
1752: 'x2_mobile_layouts',
1753: 'modelName=:modelName',
1754: array (':modelName' => $model->modelName));
1755: foreach (array ('defaultView', 'defaultForm') as $layoutName) {
1756: $layout = new MobileLayouts;
1757: $layout->modelName = $model->modelName;
1758: $layout->layout = $model->$layoutName;
1759: $layout->defaultView = $layoutName === 'defaultView';
1760: $layout->defaultForm = $layoutName === 'defaultForm';
1761: $layout->save ();
1762: }
1763: Yii::app()->user->setFlash (
1764: 'success', Yii::t('app', 'Layout updated'));
1765: }
1766: }
1767:
1768: $modules = MobileModule::supportedModules (new CDbCriteria (array (
1769: 'condition' => 'editable'
1770: )));
1771:
1772: $modelList = array('' => '---');
1773: foreach ($modules as $module) {
1774: if ($module->name == 'marketing')
1775: $modelList['Campaign'] = Yii::t('marketing', 'Campaign');
1776: elseif ($module->name == 'opportunities')
1777: $modelList['Opportunity'] = Yii::t('opportunities', 'Opportunity');
1778: elseif ($module->name == 'products')
1779: $modelList['Product'] = Yii::t('products', 'Product');
1780: elseif ($module->name == 'quotes')
1781: $modelList['Quote'] = Yii::t('quotes', 'Quote');
1782: else
1783: $modelList[ucfirst($module->name)] = Yii::t('app', $module->title);
1784: }
1785:
1786: $this->render('editMobileForms', array(
1787: 'model' => $model,
1788: 'recordTypes' => $modelList,
1789: ));
1790: }
1791:
1792: public function actionGetMobileLayouts ($modelName) {
1793: Yii::import ('application.modules.mobile.models.*');
1794:
1795:
1796: $formLayout = MobileLayouts::model ()->findByAttributes (array (
1797: 'modelName' => $modelName,
1798: 'defaultView' => 1
1799: ));
1800: $viewLayout = MobileLayouts::model ()->findByAttributes (array (
1801: 'modelName' => $modelName,
1802: 'defaultForm' => 1
1803: ));
1804: $formLayout = $formLayout ? $formLayout->layout : null;
1805: $viewLayout = $viewLayout ? $viewLayout->layout : null;
1806: if (!$formLayout)
1807: $formLayout = MobileLayouts::generateDefaultLayout ('form', $modelName);
1808: if (!$viewLayout)
1809: $viewLayout = MobileLayouts::generateDefaultLayout ('view', $modelName);
1810:
1811: list ($formLayout, $unselectedForm) = MobileLayouts::getFieldOptions (
1812: $formLayout, $modelName);
1813: list ($viewLayout, $unselectedView) = MobileLayouts::getFieldOptions (
1814: $viewLayout, $modelName);
1815:
1816: echo CJSON::encode (array (
1817: 'defaultForm' => $formLayout,
1818: 'defaultView' => $viewLayout,
1819: 'defaultFormUnselected' => $unselectedForm,
1820: 'defaultViewUnselected' => $unselectedView,
1821: ));
1822: }
1823:
1824: 1825: 1826: 1827: 1828: 1829: 1830:
1831: public function actionCreatePage() {
1832: $model = Yii::createComponent (array (
1833: 'class' => 'application.models.formModels.CreatePageFormModel',
1834: ));
1835: if (isset ($_POST[get_class ($model)])) {
1836: $model->setAttributes ($_POST[get_class ($model)]);
1837: if ($model->validate ()) {
1838: $module = new Modules;
1839: $module->adminOnly = 0;
1840: $module->toggleable = 1;
1841: $module->custom = 1;
1842: $module->visible = 1;
1843: $module->editable = 0;
1844: $module->searchable = 0;
1845: $module->menuPosition = Modules::model()->count();
1846: $module->linkOpenInNewTab = $model->openInNewTab;
1847: $type = $model->getSelection () === 'topLinkUrl' ? 'link' : 'recordLink';
1848: $module->moduleType = $type;
1849: if ($type === 'link') {
1850: $module->title = $model->topLinkText;
1851: $module->linkHref = $model->topLinkUrl;
1852: } else {
1853: $module->linkRecordType = $model->recordType;
1854: $module->linkRecordId = $model->recordId;
1855: }
1856: if ($module->save()) {
1857: Yii::app()->user->setFlash (
1858: 'success', Yii::t('app', 'Created top bar link.'));
1859: $this->redirect(array('/admin/createPage'));
1860: } else {
1861: Yii::app()->user->setFlash (
1862: 'error', Yii::t('app', 'Failed to create top bar link.'));
1863: }
1864: }
1865: }
1866:
1867: $this->render('createPage', array(
1868: 'model' => $model,
1869: ));
1870: }
1871:
1872: 1873: 1874: 1875: 1876: 1877: 1878: 1879: 1880: 1881: 1882:
1883: public function actionViewPage($id) {
1884: $model = CActiveRecord::model('Docs')->findByPk($id);
1885: if (!isset($model))
1886: $this->redirect(array('/docs/docs/index'));
1887:
1888: $this->render('viewTemplate', array(
1889: 'model' => $model,
1890: ));
1891: }
1892:
1893: public function actionEditGlobalCss () {
1894: $formModel = new GlobalCSSFormModel;
1895: if (isset ($_POST['GlobalCSSFormModel'])) {
1896: $formModel->setAttributes ($_POST['GlobalCSSFormModel']);
1897: if ($formModel->save ()) {
1898: $formModel->css = GlobalCSSFormModel::getGlobalCss ();
1899: X2Flashes::addFlash (
1900: 'success',
1901: Yii::t('app', 'CSS saved'));
1902: }
1903: } else {
1904: $formModel->css = GlobalCSSFormModel::getGlobalCss ();
1905: if (!$formModel->css) {
1906: X2Flashes::addFlash (
1907: 'error',
1908: Yii::t('app', 'Could not read file '.GlobalCSSFormModel::getGlobalCssPath ()));
1909: }
1910: }
1911: $this->render('editGlobalCss', array(
1912: 'formModel' => $formModel,
1913: ));
1914: }
1915:
1916: 1917: 1918: 1919: 1920: 1921:
1922: public function actionRenameModules() {
1923: $order = Modules::model()->findAllByAttributes(array(
1924: 'visible' => 1,
1925: ));
1926: $menuItems = array();
1927: $itemNames = array();
1928: foreach ($order as $module) {
1929: $menuItems[$module->name] = Yii::t('app', $module->title);
1930: if ($module->moduleType === 'module' && ($module->custom || $module->name === 'bugReports'))
1931: $itemNames[$module->name] = Modules::itemDisplayName($module->name);
1932: }
1933: foreach ($menuItems as $key => $value) {
1934: $menuItems[$key] = preg_replace('/:/', ':', $value);
1935: }
1936:
1937: if (isset($_POST['module']) && isset($_POST['name'])) {
1938: $module = $_POST['module'];
1939: $name = $_POST['name'];
1940: if (empty($module)) {
1941: Yii::app()->user->setFlash('error', Yii::t('admin', "You must select a module."));
1942: } else {
1943: $moduleRecord = Modules::model()->findByAttributes(
1944: array(
1945: 'name' => $module,
1946: 'title' => $menuItems[$module],
1947: )
1948: );
1949: if(isset($moduleRecord)){
1950: $match = Modules::model()->findByAttributes(array('title'=>$name));
1951: $itemName = isset($_POST['itemName'])? $_POST['itemName'] : "";
1952:
1953: if (empty($name)) {
1954: Yii::app()->user->setFlash('error', Yii::t('admin', "You must specify a title."));
1955: } else if (isset($match) && ($match->name !== $moduleRecord->name)) {
1956: Yii::app()->user->setFlash('error', Yii::t('admin', "A module with this title already exists."));
1957: } else {
1958: $moduleRecord->title = $name;
1959: if (!empty($itemName) && ($moduleRecord->custom || $moduleRecord->name === 'bugReports'))
1960: $moduleRecord->itemName = $itemName;
1961:
1962: if ($moduleRecord->retitle ($name)) {
1963: $this->redirect('index');
1964: }
1965: }
1966: }
1967: }
1968: }
1969:
1970: $this->render('renameModules', array(
1971: 'modules' => $menuItems,
1972: 'itemNames' => $itemNames,
1973: ));
1974: }
1975:
1976:
1977:
1978: 1979: 1980: 1981: 1982: 1983:
1984: public function actionManageModules() {
1985:
1986: $modules = Modules::model()->findAll();
1987: usort ($modules, function ($a, $b) {
1988: $aPos = $a->menuPosition === null ? INF : ((int) $a->menuPosition);
1989: $bPos = $b->menuPosition === null ? INF : ((int) $b->menuPosition);
1990: if ($aPos < $bPos) {
1991: return -1;
1992: } elseif ($aPos > $bPos) {
1993: return 1;
1994: } else {
1995: return 0;
1996: }
1997: });
1998:
1999: $selectedItems = array ();
2000: $deletableOptions = array ();
2001: $menuItems = array ();
2002:
2003: foreach ($modules as $module) {
2004: if ($module->name != 'users') {
2005: if (in_array ($module->moduleType, array ('link', 'recordLink'))) {
2006: $deletableOptions[] = $module->id;
2007: }
2008: $menuItems[$module->id] = $module->getTitle ();
2009: if ($module->visible) {
2010: $selectedItems[] = $module->id;
2011: }
2012: }
2013: }
2014:
2015:
2016: if (isset($_POST['formSubmit'])) {
2017: $selectedItems = isset($_POST['menuItems']) ? $_POST['menuItems'] : array();
2018: $hiddenModuleIds = array_keys (
2019: array_diff_key ($menuItems, array_flip ($selectedItems)));
2020:
2021:
2022: $qpg = new QueryParamGenerator;
2023: $count = (int) Yii::app()->db->createCommand ("
2024: select count(*) from x2_modules
2025: where id in ".$qpg->bindArray (
2026: array_merge ($selectedItems, $hiddenModuleIds), true))
2027: ->queryScalar ($qpg->getParams ());
2028:
2029: if ($count !== count (array_merge ($selectedItems, $hiddenModuleIds))) {
2030: Yii::app()->user->setFlash (
2031: 'error', Yii::t('app', 'Selected module(s) not found.'));
2032: } elseif (Modules::updateTopBarLinks ($selectedItems, $hiddenModuleIds)) {
2033: Yii::app()->user->setFlash (
2034: 'success', Yii::t('app', 'Updated top bar links.'));
2035: $this->redirect ('manageModules');
2036: } else {
2037: Yii::app()->user->setFlash (
2038: 'error', Yii::t('app', 'Failed to update top bar links.'));
2039: }
2040: }
2041:
2042: $this->render('manageModules', array(
2043: 'selectedItems' => $selectedItems,
2044: 'menuItems' => $menuItems,
2045: 'deletableOptions' => $deletableOptions
2046: ));
2047: }
2048:
2049: 2050: 2051: 2052: 2053: 2054:
2055: public function actionUploadLogo() {
2056: Yii::import ('application.models.formModels.UploadLogoFormModel');
2057: $formModel = new UploadLogoFormModel;
2058:
2059: if (isset ($_POST['UploadLogoFormModel']) &&
2060: (isset ($_FILES['UploadLogoFormModel']))) {
2061:
2062: $adminProf = Yii::app()->params->adminProfile;
2063: $formModel->setAttributes($_POST['UploadLogoFormModel']);
2064: $formModel->menuLogoUpload = CUploadedFile::getInstance($formModel, 'menuLogoUpload');
2065:
2066: $uploaded = false;
2067: if ($formModel->validate ()) {
2068: foreach (array (
2069: 'menuLogoUpload') as $upload) {
2070:
2071: if ($formModel->$upload) {
2072: $fileName = 'uploads/protected/logos/' . $formModel->$upload->getName ();
2073: if ($formModel->$upload->saveAs ($fileName)) {
2074: $uploaded = true;
2075: if ($upload === 'menuLogoUpload') {
2076: $associationType = 'logo';
2077: } else {
2078: $associationType = 'loginLogo';
2079: }
2080: $oldLogo = Media::model()->findByAttributes(
2081: array(
2082: 'associationId' => $adminProf->id,
2083: 'associationType' => $associationType
2084: ));
2085: $logo = new Media;
2086: $logo->associationType = $associationType;
2087: $logo->associationId = $adminProf->id;
2088: $logo->name = $fileName;
2089: $logo->fileName = $fileName;
2090:
2091: if ($logo->save () && $oldLogo) {
2092: $oldLogo->delete ();
2093: }
2094: } else {
2095: $formModel->addError(
2096: $upload, Yii::t('admin', 'File could not be uploaded'));
2097: }
2098: }
2099: }
2100: }
2101: if (!$formModel->hasErrors () && $uploaded) {
2102: Yii::app()->user->setFlash(
2103: 'success', Yii::t('admin', 'Logo uploaded.'));
2104: $this->redirect ('uploadLogo');
2105: }
2106: }
2107:
2108: $this->render('uploadLogo', array (
2109: 'formModel' => $formModel
2110: ));
2111: }
2112:
2113: 2114: 2115:
2116: public function actionToggleDefaultLogo($logoType) {
2117: if (!in_array ($logoType, array ('logo'))) {
2118: throw new CHttpException (400, Yii::t('admin', 'Bad request'));
2119: }
2120:
2121: $adminProf = Yii::app()->params->adminProfile;
2122: $logo = Media::model()->findByAttributes(array(
2123: 'associationId' => $adminProf->id, 'associationType' => $logoType));
2124: if ($logo) {
2125: $logo->delete();
2126: Yii::app()->user->setFlash(
2127: 'success', Yii::t('admin', 'Logo restored.'));
2128: } else {
2129: Yii::app()->user->setFlash(
2130: 'error', Yii::t('admin', 'Failed to restore logo.'));
2131: }
2132: $this->redirect(array('uploadLogo'));
2133: }
2134:
2135: 2136: 2137: 2138: 2139: 2140: 2141:
2142: public function actionTranslationManager() {
2143: $this->layout = null;
2144: $messagePath = 'protected/messages';
2145: include('protected/components/TranslationManager.php');
2146:
2147: }
2148:
2149: 2150: 2151: 2152: 2153: 2154: 2155: 2156: 2157: 2158: 2159:
2160: public function actionConvertCustomModules() {
2161: $status = array();
2162: if (!empty($_POST)) {
2163: $updateFlag = false;
2164: if (isset($_POST['updateFlag']) && $_POST['updateFlag'] == "Yes") {
2165: $updateFlag = true;
2166: }
2167: $modules = X2Model::model('Modules')->findAllByAttributes(array('custom' => 1));
2168: if (count($modules) == 0) {
2169: $status['admin']['error'] = Yii::t('admin', 'Fatal error - No custom modules found.');
2170: $status['admin']['title'] = Yii::t('admin', 'Module Conversion');
2171: }
2172: foreach ($modules as $module) {
2173: $moduleName = $module->name;
2174: if (empty ($moduleName)) {
2175: $status['admin']['messages'][] = Yii::t('admin', 'Warning: custom module with id :id exists without a "name." Skipping...', array(
2176: ':id' => $module->id,
2177: ));
2178: $status['admin']['title'] = Yii::t('admin', 'Module Conversion');
2179: continue;
2180: }
2181: $modulePath = 'protected/modules/' . $moduleName;
2182: $ucName = ucfirst($moduleName);
2183: if (is_dir($modulePath)) {
2184: $failed = false;
2185:
2186: $status[$moduleName] = array(
2187: 'title' => $module->title,
2188: 'messages' => array(),
2189: 'error' => null
2190: );
2191: $status[$moduleName]['messages'][] = Yii::t('admin', "Module exists") .
2192: ": $moduleName";
2193:
2194: if (FileUtil::ccopy($modulePath, 'backup/modules/' . $moduleName)) {
2195: $backupFlag = true;
2196: $status[$moduleName]['messages'][] = Yii::t('admin', 'Module successfully ' .
2197: 'backed up in backup/modules/{moduleName}', array(
2198: '{moduleName}' => $moduleName
2199: ));
2200: } else {
2201: $backupFlag = false;
2202: $status[$moduleName]['error'] = Yii::t('admin', 'Backup failed. Unable to write to backup directory. ' .
2203: 'Aborting module conversion.');
2204: $this->render('convertCustomModules', array(
2205: 'status' => $status,
2206: ));
2207: Yii::app()->end();
2208: }
2209: if (file_exists($modulePath . '/controllers/DefaultController.php')) {
2210:
2211: $renamed = rename($modulePath . '/controllers/DefaultController.php', $modulePath . '/controllers/' . $ucName . 'Controller.php'
2212: );
2213: if ($renamed) {
2214: $status[$moduleName]['messages'][] = Yii::t('admin', '{default} still existed and was successfully renamed to ' .
2215: '{controller}.', array(
2216: '{default}' => 'DefaultController',
2217: '{controller}' => $ucName . 'Controller',
2218: ));
2219: $file = Yii::app()->file->set($modulePath . '/controllers/' .
2220: $ucName . 'Controller.php');
2221: $contents = $file->getContents();
2222: $contents = str_replace(array('DefaultController'), array($ucName . 'Controller'), $contents);
2223: $success = $file->setContents($contents);
2224:
2225: if ($success !== false) {
2226: $status[$moduleName]['messages'][] = Yii::t('admin', 'Class declaration successfully altered.');
2227: } else {
2228: $status[$moduleName]['error'] = Yii::t('admin', 'Fatal error - Unable to change class declaration. ' .
2229: 'Aborting module conversion.');
2230: $failed = true;
2231: if ($backupFlag) {
2232: FileUtil::rrmdir($modulePath);
2233: if (FileUtil::ccopy('backup/modules/' . $moduleName, $modulePath)) {
2234: $status[$moduleName]['error'] .= " " . Yii::t('admin', 'Module backup was successfully restored.');
2235: }
2236: }
2237: }
2238: } else {
2239: $status[$moduleName]['error'] = Yii::t('admin', 'Fatal error - Unable to rename controller class. ' .
2240: 'Aborting module conversion.');
2241: $failed = true;
2242: if ($backupFlag) {
2243: FileUtil::rrmdir($modulePath);
2244: if (FileUtil::ccopy('backup/modules/' . $moduleName, $modulePath)) {
2245: $status[$moduleName]['error'].=" " . Yii::t('admin', 'Module backup was successfully restored.');
2246: }
2247: }
2248: }
2249: }
2250: if (is_dir($modulePath . '/views/default' && !$failed)) {
2251:
2252: if (is_dir($modulePath . '/views/' . $moduleName)) {
2253: FileUtil::ccopy($modulePath . '/views/default/', $modulePath . '/views/' . $moduleName);
2254: $status[$moduleName]['messages'][] = Yii::t('admin', 'Module view folder already exists. View files successfully copied.');
2255: } else {
2256: $renamed = rename($modulePath . '/views/default', $modulePath . '/views/' . $moduleName);
2257: if ($renamed) {
2258: $status[$moduleName]['messages'][] = Yii::t('admin', 'Module view folder successfully renamed.');
2259: } else {
2260: $status[$moduleName]['error'] = Yii::t('admin', 'Fatal error - Unable to rename module view folder. ' .
2261: 'Aborting module conversion.');
2262: $failed = true;
2263: if ($backupFlag) {
2264: FileUtil::rrmdir($modulePath);
2265: if (FileUtil::ccopy('backup/modules/' . $moduleName, $modulePath)) {
2266: $status[$moduleName]['error'] .= " " . Yii::t('admin', 'Module backup was successfully restored.');
2267: }
2268: }
2269: }
2270: }
2271: }
2272: $viewDir = $modulePath . '/views/' . $moduleName;
2273: if (is_dir($viewDir) && !$failed) {
2274:
2275: $viewFiles = scandir($viewDir);
2276: $success = true;
2277: foreach ($viewFiles as $filename) {
2278: if (!preg_match('/^\w+\.php$/', $filename))
2279: continue;
2280: $file = Yii::app()->file->set($viewDir . "/" . $filename);
2281: $contents = $file->getContents();
2282: $contents = str_replace('$moduleConfig[\'recordName\']', 'Modules::itemDisplayName()', $contents);
2283: if ($filename === 'index.php') {
2284:
2285: $searchPattern = '\'title\'=>$moduleConfig[\'title\']';
2286: $replacement = '\'title\'=>Modules::displayName(true, ' .
2287: '$moduleConfig[\'moduleName\'])';
2288: $contents = str_replace($searchPattern, $replacement, $contents);
2289: }
2290: $success = $success && $file->setContents($contents);
2291: }
2292: if (!$success) {
2293: $status[$moduleName]['error'] = Yii::t('admin', 'Fatal error - Unable to update view files. ' .
2294: 'Aborting module conversion.');
2295: $failed = true;
2296: if ($backupFlag) {
2297: FileUtil::rrmdir($modulePath);
2298: if (FileUtil::ccopy('backup/modules/' . $moduleName, $modulePath)) {
2299: $status[$moduleName]['error'] .= " " . Yii::t('admin', 'Module backup was successfully restored.');
2300: }
2301: }
2302: }
2303: }
2304:
2305: $auth = Yii::app()->authManager;
2306:
2307: $testItem = $auth->getAuthItem($ucName . 'ReadOnlyAccess');
2308:
2309: if (is_null($testItem)) {
2310: $this->createDefaultModulePermissions($ucName);
2311: $status[$moduleName]['messages'][] = Yii::t('admin', 'Permissions configuration complete.');
2312: }
2313: if ($updateFlag) {
2314:
2315:
2316: include('protected/modules/' . $moduleName . '/' . $moduleName . 'Config.php');
2317: $this->createSkeletonDirectories($moduleName, $module->title);
2318: $this->writeConfig($moduleConfig['title'], $moduleConfig['moduleName'], $moduleConfig['recordName']);
2319: $status[$moduleName]['messages'][] = Yii::t('admin', 'Module files updated to the latest version.');
2320: }
2321: }
2322: }
2323: $authCache = Yii::app()->authCache;
2324: if (isset($authCache))
2325: $authCache->clear();
2326: }
2327: $this->render('convertCustomModules', array(
2328: 'status' => $status,
2329: ));
2330: }
2331:
2332: 2333: 2334: 2335: 2336: 2337: 2338:
2339: public function actionCreateModule() {
2340:
2341: $errors = array();
2342:
2343: if (isset($_POST['moduleName'])) {
2344:
2345: $title = trim($_POST['title']);
2346: $recordName = trim($_POST['recordName']);
2347:
2348: $moduleName = trim($_POST['moduleName']);
2349:
2350:
2351: if (preg_match('/\W/', $moduleName) || preg_match('/^[^a-zA-Z]+/', $moduleName)) {
2352: $errors[] = Yii::t('module', 'Invalid table name');
2353: }
2354:
2355: if ($moduleName == '')
2356: $moduleName = $title;
2357:
2358: if ($recordName == '')
2359: $recordName = $title;
2360:
2361: $trans = include('protected/data/transliteration.php');
2362:
2363:
2364: $moduleName = strtolower(strtr($moduleName, $trans));
2365:
2366:
2367: $moduleName = preg_replace('/\W/', '', $moduleName);
2368:
2369:
2370: $moduleName = preg_replace('/^[0-9_]+/', '', $moduleName);
2371:
2372:
2373: if ($moduleName == '') {
2374: $moduleName = 'module' . substr(time(), 5);
2375: }
2376:
2377: if (!is_null(Modules::model()->findByAttributes(array('title' => $title))) ||
2378: !is_null(Modules::model()->findByAttributes(array('name' => $moduleName)))) {
2379: $errors[] = Yii::t('module', 'A module with that name already exists');
2380: }
2381: if (empty($errors)) {
2382: $dirFlag = false;
2383: $configFlag = false;
2384: $tableFlag = false;
2385: try {
2386: $this->createSkeletonDirectories($moduleName, $title);
2387: $dirFlag = true;
2388: $this->writeConfig($title, $moduleName, $recordName);
2389: $configFlag = true;
2390: $this->createNewTable($moduleName);
2391: $tableFlag = true;
2392: } catch (Exception $e) {
2393: 2394: 2395: 2396: 2397: 2398:
2399: if ($dirFlag) {
2400: FileUtil::rrmdir('protected/modules/' . $moduleName);
2401: } else {
2402: $errors[] = Yii::t('module', 'Unable to create custom module directory.');
2403: }
2404: if ($configFlag) {
2405:
2406: } elseif ($dirFlag) {
2407: $errors[] = Yii::t('module', 'Unable to create config file for custom module.');
2408: }
2409: if ($tableFlag) {
2410: $this->deleteTable($moduleName);
2411: } elseif ($dirFlag && $configFlag) {
2412: $errors[] = Yii::t('module', 'Unable to create table for custom module.');
2413: }
2414: }
2415: if (empty($errors)) {
2416: $moduleRecord = new Modules;
2417: $moduleRecord->name = $moduleName;
2418: $moduleRecord->title = $title;
2419: $moduleRecord->custom = 1;
2420: $moduleRecord->visible = 1;
2421: $moduleRecord->editable = $_POST['editable'];
2422: $moduleRecord->adminOnly = $_POST['adminOnly'];
2423: $moduleRecord->searchable = $_POST['searchable'];
2424: $moduleRecord->toggleable = 1;
2425: $moduleRecord->menuPosition = Modules::model()->count();
2426: $moduleRecord->save();
2427:
2428: Yii::import('application.modules.' . $moduleName . '.models.*');
2429: $layoutModel = new FormLayout;
2430: $layoutModel->model = ucfirst($moduleName);
2431: $layoutModel->version = "Default";
2432: $layoutModel->layout = X2Model::getDefaultFormLayout($moduleName);
2433: $layoutModel->createDate = time();
2434: $layoutModel->lastUpdated = time();
2435: $layoutModel->defaultView = true;
2436: $layoutModel->defaultForm = true;
2437: $layoutModel->save();
2438:
2439: $this->redirect(array('/' . $moduleName . '/index'));
2440: }
2441: }
2442: }
2443:
2444: $this->render('createModule', array('errors' => $errors));
2445: }
2446:
2447: 2448: 2449: 2450: 2451: 2452: 2453: 2454: 2455:
2456: private function createNewTable($moduleName) {
2457: $moduleTitle = ucfirst($moduleName);
2458: $sqlList = array("CREATE TABLE x2_" . $moduleName . "(
2459: id INT NOT NULL AUTO_INCREMENT primary key,
2460: assignedTo VARCHAR(250),
2461: name VARCHAR(250) NOT NULL,
2462: nameId VARCHAR(250) DEFAULT NULL,
2463: description TEXT,
2464: createDate INT,
2465: lastUpdated INT,
2466: updatedBy VARCHAR(250),
2467: UNIQUE(nameId)
2468: ) COLLATE = utf8_general_ci",
2469: "INSERT INTO x2_fields (modelName, fieldName, attributeLabel, custom, readOnly, keyType) VALUES ('$moduleTitle', 'id', 'ID', '0', '1','PRI')",
2470: "INSERT INTO x2_fields (modelName, fieldName, attributeLabel, custom, readOnly, keyType) VALUES ('$moduleTitle', 'nameId', 'nameId', '0', '1','FIX')",
2471: "INSERT INTO x2_fields (modelName, fieldName, attributeLabel, custom, type, required) VALUES ('$moduleTitle', 'name', 'Name', '0', 'varchar', '1')",
2472: "INSERT INTO x2_fields (modelName, fieldName, attributeLabel, custom, type) VALUES ('$moduleTitle', 'assignedTo', 'Assigned To', '0', 'assignment')",
2473: "INSERT INTO x2_fields (modelName, fieldName, attributeLabel, custom, type) VALUES ('$moduleTitle', 'description', 'Description', '0', 'text')",
2474: "INSERT INTO x2_fields (modelName, fieldName, attributeLabel, custom, type, readOnly) VALUES ('$moduleTitle', 'createDate', 'Create Date', '0', 'date', '1')",
2475: "INSERT INTO x2_fields (modelName, fieldName, attributeLabel, custom, type, readOnly) VALUES ('$moduleTitle', 'lastUpdated', 'Last Updated', '0', 'date', '1')",
2476: "INSERT INTO x2_fields (modelName, fieldName, attributeLabel, custom, type, readOnly) VALUES ('$moduleTitle', 'updatedBy', 'Updated By', '0', 'assignment', '1')");
2477: foreach ($sqlList as $sql) {
2478: $command = Yii::app()->db->createCommand($sql);
2479: $command->execute();
2480: }
2481: $this->createDefaultModulePermissions($moduleTitle);
2482: }
2483:
2484: 2485: 2486: 2487: 2488:
2489: private function createDefaultModulePermissions($moduleName) {
2490: $auth = Yii::app()->authManager;
2491: $authRule = 'return $this->checkAssignment($params);';
2492: $guestSite = $auth->getAuthItem('GuestSiteFunctionsTask');
2493: $auth->createOperation($moduleName . 'GetItems');
2494: $auth->createOperation($moduleName . 'View');
2495: $auth->createOperation($moduleName . 'Create');
2496: $auth->createOperation($moduleName . 'Update');
2497: $auth->createOperation($moduleName . 'Index');
2498: $auth->createOperation($moduleName . 'Admin');
2499: $auth->createOperation($moduleName . 'Delete');
2500: $auth->createOperation($moduleName . 'GetTerms');
2501: $auth->createOperation($moduleName . 'DeleteNote');
2502: $auth->createOperation($moduleName . 'Search');
2503:
2504: $auth->createOperation($moduleName . 'MobileView');
2505: $auth->createOperation($moduleName . 'MobileCreate');
2506: $auth->createOperation($moduleName . 'MobileUpdate');
2507: $auth->createOperation($moduleName . 'MobileDelete');
2508: $auth->createOperation($moduleName . 'QuickView');
2509: $auth->createOperation($moduleName . 'MobileIndex');
2510: $auth->createOperation($moduleName . 'GetX2ModelInput');
2511: $auth->createOperation($moduleName . 'AjaxGetModelAutocomplete');
2512: $auth->createOperation($moduleName . 'X2GridViewMassAction');
2513: $auth->createOperation($moduleName . 'InlineEmail');
2514:
2515:
2516: $roleAdminAccess = $auth->createTask($moduleName . 'AdminAccess');
2517: $roleFullAccess = $auth->createTask($moduleName . 'FullAccess');
2518: $rolePrivateFullAccess = $auth->createTask($moduleName . 'PrivateFullAccess');
2519: $roleUpdateAccess = $auth->createTask($moduleName . 'UpdateAccess');
2520: $rolePrivateUpdateAccess = $auth->createTask($moduleName . 'PrivateUpdateAccess');
2521: $roleBasicAccess = $auth->createTask($moduleName . 'BasicAccess');
2522: $roleReadOnlyAccess = $auth->createTask($moduleName . 'ReadOnlyAccess');
2523: $rolePrivateReadOnlyAccess = $auth->createTask($moduleName . 'PrivateReadOnlyAccess');
2524: $roleMinimumRequirements = $auth->createTask($moduleName . 'MinimumRequirements');
2525:
2526:
2527: $rolePrivateDelete = $auth->createTask($moduleName . 'DeletePrivate', 'Delete their own records', $authRule);
2528: $rolePrivateDelete->addChild($moduleName . 'Delete');
2529: $rolePrivateDelete->addChild($moduleName . 'DeleteNote');
2530: $rolePrivateDelete->addChild($moduleName . 'MobileDelete');
2531: $rolePrivateUpdate = $auth->createTask($moduleName . 'UpdatePrivate', 'Update their own records', $authRule);
2532: $rolePrivateUpdate->addChild($moduleName . 'Update');
2533: $rolePrivateUpdate->addChild ($moduleName.'MobileUpdate');
2534: $rolePrivateView = $auth->createTask($moduleName . 'ViewPrivate', 'View their own record', $authRule);
2535: $rolePrivateView->addChild($moduleName . 'View');
2536: $rolePrivateView->addChild($moduleName . 'MobileView');
2537:
2538:
2539: $guestSite->addChild($moduleName . 'GetItems');
2540:
2541:
2542: $roleMinimumRequirements->addChild($moduleName . 'Index');
2543: $roleMinimumRequirements->addChild($moduleName . 'MobileIndex');
2544: $roleMinimumRequirements->addChild($moduleName . 'GetTerms');
2545: $roleMinimumRequirements->addChild($moduleName . 'Search');
2546: $roleMinimumRequirements->addChild($moduleName . 'AjaxGetModelAutocomplete');
2547: $roleMinimumRequirements->addChild($moduleName . 'X2GridViewMassAction');
2548:
2549:
2550: $roleReadOnlyAccess->addChild($moduleName . 'MinimumRequirements');
2551: $roleReadOnlyAccess->addChild($moduleName . 'View');
2552: $roleReadOnlyAccess->addChild($moduleName . 'MobileView');
2553: $roleReadOnlyAccess->addChild($moduleName . 'QuickView');
2554: $roleReadOnlyAccess->addChild($moduleName . 'InlineEmail');
2555:
2556:
2557: $rolePrivateReadOnlyAccess->addChild($moduleName . 'MinimumRequirements');
2558: $rolePrivateReadOnlyAccess->addChild($moduleName . 'ViewPrivate');
2559: $rolePrivateReadOnlyAccess->addChild($moduleName . 'QuickView');
2560: $rolePrivateReadOnlyAccess->addChild($moduleName . 'InlineEmail');
2561:
2562:
2563: $roleBasicAccess->addChild($moduleName . 'MinimumRequirements');
2564: $roleBasicAccess->addChild($moduleName . 'Create');
2565: $roleBasicAccess->addChild($moduleName . 'MobileCreate');
2566:
2567:
2568: $roleUpdateAccess->addChild($moduleName . 'MinimumRequirements');
2569: $roleUpdateAccess->addChild($moduleName . 'Update');
2570: $roleUpdateAccess->addChild($moduleName . 'MobileUpdate');
2571: $roleUpdateAccess->addChild($moduleName . 'GetX2ModelInput');
2572:
2573:
2574: $rolePrivateUpdateAccess->addChild($moduleName . 'MinimumRequirements');
2575: $rolePrivateUpdateAccess->addChild($moduleName . 'UpdatePrivate');
2576: $rolePrivateUpdateAccess->addChild($moduleName . 'GetX2ModelInput');
2577:
2578:
2579: $roleFullAccess->addChild($moduleName . 'MinimumRequirements');
2580: $roleFullAccess->addChild($moduleName . 'Delete');
2581: $roleFullAccess->addChild($moduleName . 'MobileDelete');
2582: $roleFullAccess->addChild($moduleName . 'DeleteNote');
2583:
2584:
2585: $rolePrivateFullAccess->addChild($moduleName . 'MinimumRequirements');
2586: $rolePrivateFullAccess->addChild($moduleName . 'DeletePrivate');
2587:
2588:
2589: $roleAdminAccess->addChild($moduleName . 'MinimumRequirements');
2590: $roleAdminAccess->addChild($moduleName . 'Admin');
2591:
2592:
2593: $defaultRole = $auth->getAuthItem('DefaultRole');
2594: $defaultRole->removeChild($moduleName . 'Index');
2595: $defaultRole->addChild($moduleName . 'UpdateAccess');
2596: $defaultRole->addChild($moduleName . 'BasicAccess');
2597: $defaultRole->addChild($moduleName . 'ReadOnlyAccess');
2598: $defaultRole->addChild($moduleName . 'MinimumRequirements');
2599:
2600: $adminRole = $auth->getAuthItem('administrator');
2601: $adminRole->removeChild($moduleName . 'Admin');
2602: $adminRole->addChild($moduleName . 'AdminAccess');
2603: $adminRole->addChild($moduleName . 'FullAccess');
2604: $adminRole->addChild($moduleName . 'UpdateAccess');
2605: $adminRole->addChild($moduleName . 'PrivateUpdateAccess');
2606: $adminRole->addChild($moduleName . 'BasicAccess');
2607: $adminRole->addChild($moduleName . 'ReadOnlyAccess');
2608: $adminRole->addChild($moduleName . 'MinimumRequirements');
2609: }
2610:
2611: 2612: 2613: 2614: 2615:
2616: private function deleteTable($moduleName) {
2617: $moduleTitle = ucfirst($moduleName);
2618: $ucName = $moduleTitle;
2619: $sqlList = array(
2620: 'DROP TABLE IF EXISTS `x2_' . $moduleName . '`',
2621: 'DELETE FOM x2_fields WHERE modelName="' . $moduleTitle . '"',
2622: );
2623: foreach ($sqlList as $sql) {
2624: $command = Yii::app()->db->createCommand($sql);
2625: $command->execute();
2626: }
2627: $auth = Yii::app()->authManager;
2628: $auth->removeAuthItem($ucName . 'GetItems');
2629: $auth->removeAuthItem($ucName . 'View');
2630: $auth->removeAuthItem($ucName . 'Create');
2631: $auth->removeAuthItem($ucName . 'Update');
2632: $auth->removeAuthItem($ucName . 'Index');
2633: $auth->removeAuthItem($ucName . 'Admin');
2634: $auth->removeAuthItem($ucName . 'Delete');
2635: $auth->removeAuthItem($ucName . 'GetTerms');
2636: $auth->removeAuthItem($ucName . 'DeleteNote');
2637: $auth->removeAuthItem($ucName . 'Search');
2638: $auth->removeAuthItem($ucName . 'AdminAccess');
2639: $auth->removeAuthItem($ucName . 'FullAccess');
2640: $auth->removeAuthItem($ucName . 'PrivateFullAccess');
2641: $auth->removeAuthItem($ucName . 'UpdateAccess');
2642: $auth->removeAuthItem($ucName . 'PrivateUpdateAccess');
2643: $auth->removeAuthItem($ucName . 'BasicAccess');
2644: $auth->removeAuthItem($ucName . 'ReadOnlyAccess');
2645: $auth->removeAuthItem($ucName . 'PrivateReadOnlyAccess');
2646: $auth->removeAuthItem($ucName . 'MinimumRequirements');
2647: }
2648:
2649: 2650: 2651: 2652: 2653: 2654: 2655: 2656: 2657: 2658: 2659:
2660: private function createSkeletonDirectories($moduleName, $moduleTitle) {
2661:
2662: $errors = array();
2663:
2664: $templateFolderPath = 'protected/modules/template/';
2665: $moduleFolderPath = 'protected/modules/' . $moduleName . '/';
2666:
2667: $moduleFolder = Yii::app()->file->set($moduleFolderPath);
2668: if (!$moduleFolder->exists && $moduleFolder->createDir() === false)
2669: throw new Exception('Error creating module folder "' . $moduleFolderPath . '".');
2670:
2671: if (Yii::app()->file->set($templateFolderPath)->copy($moduleName) === false)
2672: throw new Exception('Error copying Template folder "' . $templateFolderPath . '".');
2673:
2674:
2675: $fileNames = array(
2676: 'register.php',
2677: 'templatesConfig.php',
2678: 'TemplatesModule.php',
2679: 'controllers/TemplatesController.php',
2680: 'data/install.sql',
2681: 'data/uninstall.sql',
2682: 'models/Templates.php',
2683: 'views/templates/_search.php',
2684: 'views/templates/_view.php',
2685: 'views/templates/admin.php',
2686: 'views/templates/create.php',
2687: 'views/templates/index.php',
2688: 'views/templates/update.php',
2689: 'views/templates/view.php',
2690: );
2691:
2692: foreach ($fileNames as $fileName) {
2693:
2694: $fileName = $moduleFolderPath . $fileName;
2695:
2696: $file = Yii::app()->file->set($fileName);
2697: if (!$file->exists)
2698: throw new Exception('Unable to find template file "' . $fileName . '".');
2699:
2700:
2701: $newFileName = str_replace(array('templates', 'Templates'), array($moduleName, ucfirst($moduleName)), $file->filename);
2702: if ($file->setFileName($newFileName) === false)
2703: throw new Exception('Error renaming template file "' . $fileName . '" to "' . $newFileName . '".');
2704:
2705:
2706:
2707:
2708: $contents = $file->getContents();
2709: $contents = str_replace(array('templates', 'TemplatesTitle', 'Templates'), array($moduleName, $moduleTitle, ucfirst($moduleName)), $contents);
2710:
2711: if ($file->setContents($contents) === false)
2712: throw new Exception('Error modifying template file "' . $newFileName . '".');
2713: }
2714: if (!is_dir('protected/modules/' . $moduleName . '/views/' . $moduleName)) {
2715: rename('protected/modules/' . $moduleName . '/views/templates', 'protected/modules/' . $moduleName . '/views/' . $moduleName);
2716: } else {
2717: FileUtil::ccopy('protected/modules/' . $moduleName . '/views/templates', 'protected/modules/' . $moduleName . '/views/' . $moduleName);
2718: }
2719: }
2720:
2721: 2722: 2723: 2724: 2725: 2726: 2727: 2728: 2729: 2730:
2731: private function writeConfig($title, $moduleName, $recordName) {
2732:
2733: $configFilePath = 'protected/modules/' . $moduleName . '/' . $moduleName . 'Config.php';
2734: $configFile = Yii::app()->file->set($configFilePath, true);
2735:
2736: $contents = str_replace(
2737: array(
2738: '{title}',
2739: '{moduleName}',
2740: '{recordName}',
2741: ), array(
2742: addslashes($title),
2743: addslashes($moduleName),
2744: addslashes($recordName),
2745: ), $configFile->getContents()
2746: );
2747:
2748: if ($configFile->setContents($contents) === false)
2749: throw new Exception('Error writing to config file "' . $configFilePath . '".');
2750: }
2751:
2752: 2753: 2754: 2755: 2756: 2757:
2758: public function actionDeleteModule() {
2759: if (isset($_POST['name'])) {
2760: $moduleName = $_POST['name'];
2761: $module = Modules::model()->findByPk($moduleName);
2762: $moduleName = $module->name;
2763: if (isset($module)) {
2764: if ($module->name != 'document' && $module->delete())
2765: $this->deleteModuleData($moduleName);
2766: else
2767: $module->delete();
2768: }
2769: $this->redirect(array('/admin/index'));
2770: }
2771:
2772: $arr = array();
2773: $modules = Modules::model()->findAllByAttributes(array('toggleable' => 1));
2774: foreach ($modules as $item) {
2775: $arr[$item->id] = $item->title;
2776: }
2777:
2778: $this->render('deleteModule', array(
2779: 'modules' => $arr,
2780: ));
2781: }
2782:
2783: 2784: 2785: 2786:
2787: private function deleteModuleData($moduleName) {
2788: $registerFile = 'protected/modules/' . $moduleName . '/register.php';
2789: if (!is_file ($registerFile))
2790: return;
2791: $config = include($registerFile);
2792: $uninstall = $config['uninstall'];
2793: if (isset($config['version'])) {
2794: foreach ($uninstall as $sql) {
2795:
2796:
2797:
2798: $sqlComm = $sql;
2799: if (is_string($sql)) {
2800: if (file_exists($sql)) {
2801: $sqlComm = explode('/*&*/', file_get_contents($sql));
2802: }
2803: }
2804: foreach ($sqlComm as $sqlLine) {
2805: $query = Yii::app()->db->createCommand($sqlLine);
2806: try {
2807: $query->execute();
2808: } catch (CDbException $e) {
2809:
2810: }
2811: }
2812: }
2813: } else {
2814:
2815: foreach ($uninstall as $sql) {
2816: $query = Yii::app()->db->createCommand($sql);
2817: $query->execute();
2818: }
2819: }
2820: X2Model::model('Fields')->deleteAllByAttributes(array('modelName' => ucfirst($moduleName)));
2821: X2Model::model('Fields')->updateAll(array('linkType' => null, 'type' => 'varchar'), "linkType='$moduleName'");
2822: X2Model::model('FormLayout')->deleteAllByAttributes(array('model' => $moduleName));
2823: X2Model::model('Relationships')->deleteAll('firstType = :model OR secondType = :model', array(':model' => $moduleName));
2824: $auth = Yii::app()->authManager;
2825: $ucName = ucfirst($moduleName);
2826: $auth->removeAuthItem($ucName . 'GetItems');
2827: $auth->removeAuthItem($ucName . 'View');
2828: $auth->removeAuthItem($ucName . 'Create');
2829: $auth->removeAuthItem($ucName . 'Update');
2830: $auth->removeAuthItem($ucName . 'Index');
2831: $auth->removeAuthItem($ucName . 'Admin');
2832: $auth->removeAuthItem($ucName . 'Delete');
2833: $auth->removeAuthItem($ucName . 'GetTerms');
2834: $auth->removeAuthItem($ucName . 'DeleteNote');
2835: $auth->removeAuthItem($ucName . 'Search');
2836: $auth->removeAuthItem($ucName . 'AdminAccess');
2837: $auth->removeAuthItem($ucName . 'FullAccess');
2838: $auth->removeAuthItem($ucName . 'PrivateFullAccess');
2839: $auth->removeAuthItem($ucName . 'UpdateAccess');
2840: $auth->removeAuthItem($ucName . 'PrivateUpdateAccess');
2841: $auth->removeAuthItem($ucName . 'BasicAccess');
2842: $auth->removeAuthItem($ucName . 'ReadOnlyAccess');
2843: $auth->removeAuthItem($ucName . 'PrivateReadOnlyAccess');
2844: $auth->removeAuthItem($ucName . 'MinimumRequirements');
2845: $auth->removeAuthItem($ucName . 'ViewPrivate');
2846: $auth->removeAuthItem($ucName . 'UpdatePrivate');
2847: $auth->removeAuthItem($ucName . 'DeletePrivate');
2848:
2849: $auth->removeAuthItem($ucName . 'MobileView');
2850: $auth->removeAuthItem($ucName . 'QuickView');
2851: $auth->removeAuthItem($ucName . 'MobileIndex');
2852: $auth->removeAuthItem($ucName . 'MobileCreate');
2853: $auth->removeAuthItem($ucName . 'MobileDelete');
2854: $auth->removeAuthItem($ucName . 'MobileUpdate');
2855: $auth->removeAuthItem($ucName . 'GetX2ModelInput');
2856: $auth->removeAuthItem($ucName . 'AjaxGetModelAutocomplete');
2857: $auth->removeAuthItem($ucName . 'X2GridViewMassAction');
2858: $auth->removeAuthItem($ucName . 'InlineEmail');
2859:
2860:
2861: foreach (Profile::model()->findAll () as $profile) {
2862: $settings = $profile->getProfileWidgetLayout();
2863: foreach ($settings as $key => $data)
2864: if (isset ($data['modelType']) && $data['modelType'] === $ucName)
2865: $settings[$key] = null;
2866: $profile->setProfileWidgetLayout($settings);
2867: $profile->save();
2868: }
2869:
2870: FileUtil::rrmdir('protected/modules/' . $moduleName);
2871: }
2872:
2873: 2874: 2875:
2876: public function actionExportMapping() {
2877: $model = $_POST['model'];
2878: $name = (isset($_POST['name']) && !empty($_POST['name'])) ? $_POST['name'] : "Unknown";
2879: $name .= " to X2Engine " . Yii::app()->params->version;
2880: $filename = (isset($_POST['name']) && !empty($_POST['name'])) ? lcfirst($_POST['name']) : "importMapping";
2881: $keys = $_POST['keys'];
2882: $attributes = $_POST['attributes'];
2883: $mappingResult = $this->verifyImportMap ($model, $keys, $attributes, true);
2884: if (!empty($_SESSION['importMap'])) {
2885: $map = array(
2886: 'name' => $name,
2887: 'mapping' => $_SESSION['importMap']
2888: );
2889: $mapFile = fopen ($this->safePath($filename . '.json'), 'w');
2890: fwrite ($mapFile, CJSON::encode($map));
2891: fclose ($mapFile);
2892: $mappingResult['map_filename'] = $filename. '.json';
2893: }
2894: echo CJSON::encode ($mappingResult);
2895: Yii::app()->end();
2896: }
2897:
2898: 2899: 2900:
2901: public function actionExportModels($listId = null) {
2902: unset($_SESSION['modelExportFile'], $_SESSION['exportModelCriteria'],
2903: $_SESSION['modelExportMeta'], $_SESSION['exportModelListId']);
2904: $modelList = Modules::getExportableModules();
2905:
2906: if (isset($_GET['model']) || isset($_POST['model'])) {
2907: $model = (isset($_GET['model'])) ? $_GET['model'] : $_POST['model'];
2908: $modelName = str_replace(' ', '', $model);
2909: }
2910: if (isset($model) && in_array($modelName, array_keys($modelList))) {
2911: $staticModel = X2Model::model($modelName);
2912: $modulePath = '/' . $staticModel->module;
2913: $modulePath .= $modulePath;
2914: if (is_null($listId) || $model != 'Contacts') {
2915: $file = "records_export.csv";
2916: $listName = CHtml::link(
2917: Yii::t('admin', 'All {model}', array(
2918: '{model}' => $model)), array($modulePath . '/index'), array('style' => 'text-decoration:none;')
2919: );
2920:
2921:
2922: $_SESSION['exportModelCriteria'] = new CDbCriteria();
2923: $_SESSION['exportModelCriteria']->with = array();
2924: } else {
2925: $list = X2List::load($listId);
2926: $_SESSION['exportModelListId'] = $listId;
2927: $_SESSION['exportModelCriteria'] = $list->queryCriteria();
2928: $file = "list" . $listId . ".csv";
2929: $listName = CHtml::link(Yii::t('admin', 'List') . " $listId: " . $list->name, array($modulePath . '/list', 'id' => $listId), array('style' => 'text-decoration:none;'));
2930: }
2931: $_SESSION['modelExportFile'] = $file;
2932: } else {
2933:
2934:
2935: if (isset($model))
2936: unset($model);
2937: }
2938:
2939: $viewParam = array(
2940: 'modelList' => $modelList,
2941: 'listId' => $listId,
2942: 'model' => '',
2943: 'modelDisplayName' => isset($model)?Modules::displayName (true, $model):'',
2944: );
2945: if (isset($model)) {
2946: $viewParam['model'] = $model;
2947: if ($model == 'Contacts') {
2948: $viewParam['listName'] = $listName;
2949: } else if (in_array ($modelName, array('Quote', 'Product'))) {
2950: $viewParam['modelDisplayName'] = Modules::displayName (true, $model.'s');
2951: } else if ($modelName === 'Campaign') {
2952: $viewParam['modelDisplayName'] = Yii::t ('common', 'Campaigns');
2953: } else if ($modelName === 'Opportunity') {
2954: $viewParam['modelDisplayName'] = Modules::displayName (true, 'Opportunities');
2955: }
2956: }
2957:
2958: $this->render('exportModels', $viewParam);
2959: }
2960:
2961: 2962: 2963: 2964: 2965:
2966: public function actionExportModelRecords($page, $model) {
2967: X2Model::$autoPopulateFields = false;
2968: $file = $this->safePath($_SESSION['modelExportFile']);
2969: $staticModel = X2Model::model(str_replace(' ', '', $model));
2970: $fields = $staticModel->getFields();
2971: $fp = fopen($file, 'a+');
2972:
2973:
2974: $excludeHidden = !isset($_GET['includeHidden']) || $_GET['includeHidden'] === 'false';
2975: if ($page == 0 && $excludeHidden && isset($_SESSION['exportModelCriteria']) &&
2976: ($_SESSION['exportModelCriteria'] instanceof CDbCriteria)) {
2977:
2978:
2979: $hiddenConditions = $staticModel->getHiddenCondition();
2980: $_SESSION['exportModelCriteria']->addCondition($hiddenConditions);
2981: }
2982: $dp = new CActiveDataProvider($model, array(
2983: 'criteria' => isset($_SESSION['exportModelCriteria']) ? $_SESSION['exportModelCriteria'] : array(),
2984: 'pagination' => array(
2985: 'pageSize' => 100,
2986: ),
2987: ));
2988:
2989: $pg = $dp->getPagination();
2990: $pg->setCurrentPage($page);
2991: $dp->setPagination($pg);
2992: $records = $dp->getData();
2993: $pageCount = $dp->getPagination()->getPageCount();
2994:
2995:
2996:
2997: foreach ($records as $record) {
2998: foreach ($fields as $field) {
2999: $fieldName = $field->fieldName;
3000: if ($field->type == 'date' || $field->type == 'dateTime') {
3001: if (is_numeric($record->$fieldName))
3002: $record->$fieldName = Formatter::formatLongDateTime($record->$fieldName);
3003: }elseif ($field->type == 'link') {
3004: $name = $record->$fieldName;
3005: if (!empty($field->linkType)) {
3006: list($name, $id) = Fields::nameAndId($name);
3007: }
3008: if (!empty($name))
3009: $record->$fieldName = $name;
3010: }elseif ($fieldName == 'visibility') {
3011: switch ($record->$fieldName) {
3012: case 0:
3013: $record->$fieldName = 'Private';
3014: break;
3015: case 1:
3016: $record->$fieldName = 'Public';
3017: break;
3018: case 2:
3019: $record->$fieldName = 'User\'s Groups';
3020: break;
3021: default:
3022: $record->$fieldName = 'Private';
3023: }
3024: }
3025: }
3026:
3027: $combinedMeta = array_combine($_SESSION['modelExportMeta'], $_SESSION['modelExportMeta']);
3028: $recordAttributes = $record->attributes;
3029: if ($model === 'Actions') {
3030:
3031: $actionText = $record->actionText;
3032: if ($actionText) {
3033: $actionDescription = $actionText->text;
3034: $recordAttributes = array_merge($recordAttributes, array(
3035: 'actionDescription' => $actionDescription
3036: ));
3037: }
3038: }
3039: if ($_SESSION['includeTags']) {
3040: $tags= $record->getTags();
3041: $recordAttributes = array_merge ($recordAttributes, array(
3042: 'tags' => implode(',', $tags),
3043: ));
3044: }
3045: $tempAttributes = array_intersect_key($recordAttributes, $combinedMeta);
3046: $tempAttributes = array_merge($combinedMeta, $tempAttributes);
3047: fputcsv($fp, $tempAttributes, $this->importDelimeter, $this->importEnclosure);
3048: }
3049:
3050: unset($dp);
3051:
3052: fclose($fp);
3053: if ($page + 1 < $pageCount) {
3054: $this->respond (CJSON::encode(array(
3055: 'page' => $page + 1
3056: )));
3057: } else {
3058: $success = $this->prepareExportDeliverable ($file, $_SESSION['exportFormat']);
3059: if ($_SESSION['exportFormat']['exportDestination'] === 'download') {
3060: if ($_SESSION['exportFormat']['compressOutput']) {
3061: $_SESSION['modelExportFile'] = $this->adjustExportPath (
3062: $_SESSION['modelExportFile'],
3063: $_SESSION['exportFormat']
3064: );
3065: }
3066: } else {
3067: $_SESSION['modelExportFile'] = '';
3068: }
3069: unset ($_SESSION['exportFormat']);
3070:
3071: $this->respond (CJSON::encode(array(
3072: 'success' => $success,
3073: 'dlUrl' => $_SESSION['modelExportFile'],
3074: )));
3075: }
3076: }
3077:
3078: protected function generateModuleSqlData($moduleName) {
3079: $sql = "";
3080: $disallow = array(
3081: "id",
3082: "assignedTo",
3083: "name",
3084: "nameId",
3085: "description",
3086: "createDate",
3087: "lastUpdated",
3088: "updatedBy",
3089: );
3090:
3091: $fields = Fields::model()->findAllByAttributes(array(
3092: 'modelName' => ucfirst($moduleName)
3093: ));
3094: foreach ($fields as $field) {
3095: if (array_search($field->fieldName, $disallow) === false) {
3096: $fieldType = $field->type;
3097: $columnDefinitions = Fields::getFieldTypes('columnDefinition');
3098: if (isset($columnDefinitions[$fieldType])) {
3099: $fieldType = $columnDefinitions[$fieldType];
3100: } else {
3101: $fieldType = 'VARCHAR(250)';
3102: }
3103:
3104: $linkType = $field->linkType;
3105: if ($field->type === 'dropdown') {
3106:
3107: $dropdown = Dropdowns::model()->findByPk($field->linkType);
3108: if ($dropdown) {
3109: $sql .= "/*&*/INSERT INTO x2_dropdowns " .
3110: "(name, options, multi, parent, parentVal) " .
3111: "VALUES " .
3112: "('$dropdown->name', '$dropdown->options', '$dropdown->multi', " .
3113: "'$dropdown->parent', '$dropdown->parentVal');";
3114:
3115:
3116: $linkType = $dropdown->name;
3117: }
3118: }
3119:
3120: $sql .= "/*&*/ALTER TABLE x2_$moduleName ADD COLUMN $field->fieldName $fieldType;";
3121: $sql .= "/*&*/INSERT INTO x2_fields " .
3122: "(modelName, fieldName, attributeLabel, modified, custom, type, linkType) " .
3123: "VALUES " .
3124: "('$moduleName', '$field->fieldName', '$field->attributeLabel', '1', '1', " .
3125: "'$field->type', '$linkType');";
3126: }
3127: }
3128: $formLayouts = X2Model::model('FormLayout')->findAllByAttributes(array(
3129: 'model' => $moduleName
3130: ));
3131: foreach ($formLayouts as $layout) {
3132: $attributes = $layout->attributes;
3133: unset($attributes['id']);
3134: $attributeKeys = array_keys($attributes);
3135: $attributeValues = array_values($attributes);
3136: $keys = implode(", ", $attributeKeys);
3137: $values = "'" . implode("', '", $attributeValues) . "'";
3138: $sql.="/*&*/INSERT INTO x2_form_layouts ($keys) VALUES ($values);";
3139: }
3140: return $sql;
3141: }
3142:
3143: 3144: 3145: 3146: 3147: 3148: 3149:
3150: public function actionExportModule() {
3151: $dlFlag = false;
3152: if (isset($_POST['name'])) {
3153: $module = Modules::model()->findByAttributes (array(
3154: 'name' => $_POST['name'],
3155: ));
3156: if ($module) {
3157: $moduleName = $module->name;
3158:
3159: $sql = $this->generateModuleSqlData($moduleName);
3160: $db = Yii::app()->file->set("protected/modules/$moduleName/sqlData.sql");
3161: $db->create();
3162: $db->setContents($sql);
3163:
3164: if (file_exists($moduleName . ".zip")) {
3165: unlink($moduleName . ".zip");
3166: }
3167:
3168: $zip = Yii::app()->zip;
3169: $zip->makeZip('protected/modules/' . $moduleName, $moduleName . ".zip");
3170: $dlFlag = true;
3171: } else {
3172: Yii::app()->user->setFlash ('error', Yii::t('admin', 'The module you have selected no longer exists.'));
3173: }
3174: }
3175:
3176: $arr = array();
3177:
3178: $modules = Modules::model()->findAll();
3179: foreach ($modules as $module) {
3180: if ($module->custom) {
3181: $arr[$module->name] = $module->title;
3182: }
3183: }
3184:
3185: $this->render('exportModules', array(
3186: 'modules' => $arr,
3187: 'dlFlag' => $dlFlag? : false,
3188: 'file' => $dlFlag ? ($_POST['name']) : ''
3189: ));
3190: }
3191:
3192: 3193: 3194:
3195: public function actionImportModels() {
3196:
3197: if (isset($_GET['model']) || isset($_POST['model'])) {
3198: $_SESSION['model'] = (isset($_GET['model'])) ? $_GET['model'] : $_POST['model'];
3199: }
3200:
3201: $_SESSION['delimeter'] = (isset($_POST['delimeter']) ? $_POST['delimeter'] : ',');
3202: $_SESSION['enclosure'] = (isset($_POST['enclosure']) ? $_POST['enclosure'] : '"');
3203:
3204: $defaultMapping = (isset($_POST['defaultMapOption']) ? $_POST['defaultMapOption'] : '');
3205:
3206: if (isset($_FILES['data'])) {
3207: $temp = CUploadedFile::getInstanceByName('data');
3208: $temp->saveAs($filePath = $this->safePath('data.csv'));
3209: ini_set('auto_detect_line_endings', 1);
3210: $_SESSION['csvLength'] = 0;
3211: if (file_exists($filePath)) {
3212: $fp = fopen($filePath, 'r+');
3213: $csvLength = $this->calculateCsvLength($filePath);
3214: $this->fixCsvLineEndings($filePath);
3215: } else {
3216: throw new Exception('There was an error saving the models file.');
3217: }
3218:
3219: list($meta, $x2attributes) = $this->initializeModelImporter($fp);
3220: $preselectedMap = false;
3221:
3222: if (isset($_POST['x2maps'])) {
3223:
3224: $importMap = $this->loadImportMap($_POST['x2maps']);
3225: if (empty($importMap)) {
3226: $_SESSION['errors'] = Yii::t('admin', 'Unable to load import map');
3227: $this->redirect('importModels');
3228: }
3229: $_SESSION['importMap'] = $this->normalizeImportMap ($importMap['mapping'], $meta);
3230: $_SESSION['mapName'] = $importMap['name'];
3231:
3232: $importMap = $_SESSION['importMap'];
3233: $preselectedMap = true;
3234: } else if (CUploadedFile::getInstanceByName('mapping') instanceof CUploadedFile && CUploadedFile::getInstanceByName('mapping')->size > 0) {
3235: $this->loadUploadedImportMap();
3236: $_SESSION['importMap'] = $this->normalizeImportMap ($_SESSION['importMap'], $meta);
3237: $preselectedMap = true;
3238: $importMap = $_SESSION['importMap'];
3239: } else {
3240:
3241: $this->createImportMap($x2attributes, $meta);
3242:
3243: $importMap = $_SESSION['importMap'];
3244:
3245:
3246: $importMap = array_flip($importMap);
3247: }
3248: $sampleRecords = $this->prepareImportSampleRecords($meta, $fp);
3249: fclose($fp);
3250:
3251:
3252: $meta = array_filter($meta, function($x) {
3253: return $x !== 'X2_Import_Failures';
3254: });
3255:
3256:
3257:
3258: $linkFields = Fields::model()->findAllByAttributes(array(
3259: 'modelName' => $_SESSION['model'],
3260: 'type' => 'link',
3261: ));
3262: $linkFieldModelMap = array();
3263: foreach ($linkFields as $field) {
3264: $linkFieldModelMap[$field['fieldName']] = $field['linkType'];
3265: }
3266: $possibleModels = array_keys(Modules::getExportableModules());
3267: foreach ($possibleModels as $model) {
3268: $attributes = Fields::model()->findAllByAttributes(array(
3269: 'modelName' => $model,
3270: ));
3271: foreach ($attributes as $attr)
3272: $listData[$attr['fieldName']] = $attr['attributeLabel'];
3273: $dropdown = CHtml::dropDownList ('attr', 'name', $listData, array(
3274: 'class' => 'linkMatchSelector',
3275: ));
3276: $linkedRecordDropdowns[$model] = $dropdown;
3277: }
3278:
3279: $this->render('processModels', array(
3280: 'defaultMapping' => $defaultMapping,
3281: 'attributes' => $x2attributes,
3282: 'meta' => $meta,
3283: 'csvLength' => isset ($csvLength) ? $csvLength : null,
3284: 'fields' => $_SESSION['fields'],
3285: 'model' => str_replace(' ', '', $_SESSION['model']),
3286: 'sampleRecords' => $sampleRecords,
3287: 'importMap' => $importMap,
3288: 'preselectedMap' => $preselectedMap,
3289: 'linkFieldModelMap' => $linkFieldModelMap,
3290: 'linkedRecordDropdowns' => $linkedRecordDropdowns,
3291: ));
3292: } else {
3293: $modelList = Modules::getExportableModules();
3294: $errors = (isset($_SESSION['errors']) ? $_SESSION['errors'] : "");
3295: $this->render('importModels', array(
3296: 'model' => isset($_SESSION['model']) ? $_SESSION['model'] : '',
3297: 'modelList' => $modelList,
3298: 'errors' => $errors,
3299: ));
3300: }
3301: }
3302:
3303: 3304: 3305: 3306: 3307: 3308: 3309:
3310: public function actionImportModelRecords() {
3311: if (isset($_POST['count']) && file_exists($path = $this->safePath('data.csv')) &&
3312: isset($_POST['model'])) {
3313:
3314: ini_set('auto_detect_line_endings', 1);
3315: $importedIds = array();
3316: $modelName = ucfirst($_POST['model']);
3317: $count = $_POST['count'];
3318: $metaData = $_SESSION['metaData'];
3319: $importMap = $_SESSION['importMap'];
3320: $fp = fopen($path, 'r+');
3321: fseek($fp, $_SESSION['offset']);
3322: $mappedId = false;
3323:
3324:
3325: if (!ArrayUtil::setEquals (array_keys ($importMap), $metaData)) {
3326: throw new CHttpException (400, Yii::t('app', 'Bad import map'));
3327: }
3328:
3329:
3330:
3331: for ($i = 0; $i < $count; $i++) {
3332:
3333: $csvLine = fgetcsv($fp, 0, $this->importDelimeter, $this->importEnclosure);
3334: if ($csvLine !== false && !is_null($csvLine)) {
3335: if ($csvLine === array(null)) {
3336:
3337: continue;
3338: }
3339: if (count($csvLine) > count($metaData))
3340: $csvLine = array_slice($csvLine, 0, count($metaData));
3341: else if (count($csvLine) < count($metaData))
3342: $csvLine = array_pad($csvLine, count($metaData), null);
3343: unset($_POST);
3344: if ($modelName === 'Actions')
3345: $this->setCurrentActionText();
3346:
3347:
3348: $csvLine = array_map('Formatter::mbSanitize', $csvLine);
3349: if (!empty($metaData) && !empty($csvLine))
3350: $importAttributes = array_combine($metaData, $csvLine);
3351: else
3352: continue;
3353:
3354:
3355: $model = new $modelName;
3356:
3357:
3358: foreach ($metaData as $attribute) {
3359: if ($importMap[$attribute] === 'id')
3360: $mappedId = true;
3361:
3362: $isActionText = ($modelName === 'Actions' &&
3363: $importMap[$attribute] === 'actionDescription');
3364: if ($importMap[$attribute] === 'applyTags') {
3365: $this->importTags ($modelName, $importAttributes[$attribute]);
3366: continue;
3367: }
3368: if (isset($importMap[$attribute]) &&
3369: ($model->hasAttribute($importMap[$attribute]) || $isActionText)) {
3370: $model = $this->importRecordAttribute ($modelName, $model, $importMap[$attribute], $importAttributes[$attribute]);
3371: $_POST[$importMap[$attribute]] = $model->$importMap[$attribute];
3372: }
3373: }
3374: $this->fixupImportedAttributes ($modelName, $model);
3375:
3376: if (!$model->hasErrors() && $model->validate())
3377: $importedIds = $this->saveImportedModel ($model, $modelName, $importedIds);
3378: else
3379: $this->markFailedRecord ($modelName, $model, $csvLine, $metaData);
3380: } else {
3381: $this->finishImportBatch ($modelName, $mappedId, true);
3382: return;
3383: }
3384: }
3385:
3386: $_SESSION['offset'] = ftell($fp);
3387: $this->finishImportBatch ($modelName, $mappedId);
3388: }
3389: }
3390:
3391: 3392: 3393: 3394: 3395: 3396:
3397: public function actionImportModule() {
3398:
3399: if (isset($_FILES['data'])) {
3400:
3401: $module = Yii::app()->file->set('data');
3402: if (!$module->exists) {
3403: Yii::app()->user->setFlash('error', Yii::t('admin', 'There was an error uploading the module.'));
3404: $this->redirect('importModule');
3405: }
3406:
3407: $moduleName = $module->filename;
3408:
3409: if (X2Model::model('Modules')->findByAttributes(array('name' => $moduleName))) {
3410: Yii::app()->user->setFlash('error', Yii::t('admin', 'Unable to upload module. A module with this name already exists.'));
3411: $this->redirect('importModule');
3412: }
3413: if ($module->extension !== 'zip') {
3414: Yii::app()->user->setFlash('error', Yii::t('admin', 'There was an error uploading the module. Please select a valid zip archive.'));
3415: $this->redirect('importModule');
3416: }
3417:
3418: $filename = $this->asa('ImportExportBehavior')->safePath($moduleName . ".zip");
3419: if ($module->copy($filename) === false || !file_exists($filename)) {
3420: Yii::app()->user->setFlash('error', Yii::t('admin', "There was an error saving the module."));
3421: $this->redirect('importModule');
3422: }
3423: $zip = Yii::app()->zip;
3424: if ($zip->extractZip($filename, 'protected/modules/') === false) {
3425: Yii::app()->user->setFlash('error', Yii::t('admin', "There was an error unzipping the module. Please ensure the zip archive is not corrupt."));
3426: $this->redirect('importModule');
3427: }
3428:
3429: if ($this->loadModuleData($moduleName)) {
3430: unlink($filename);
3431:
3432: $this->createDefaultModulePermissions(ucfirst($moduleName));
3433: $this->fixupImportedModuleDropdowns(array($moduleName));
3434:
3435: $this->redirect(array($moduleName . '/index'));
3436: } else {
3437: Yii::app()->user->setFlash(
3438: 'error',
3439: Yii::t('admin', 'Failed to load module data. Please ensure that the archive '.
3440: 'is in the expected format.')
3441: );
3442: $this->redirect('importModule');
3443: }
3444: }
3445: $this->render('importModule');
3446: }
3447:
3448: 3449: 3450: 3451: 3452:
3453: private function loadModuleData($moduleName) {
3454: $regPath = implode(DIRECTORY_SEPARATOR, array(
3455: 'protected', 'modules', $moduleName, 'register.php'
3456: ));
3457: $regFile = realpath($regPath);
3458: if ($regFile) {
3459: $install = require_once($regFile);
3460: foreach ($install['install'] as $sql) {
3461: $sqlComm = $sql;
3462: if (is_string($sql)) {
3463: if (file_exists($sql)) {
3464: $sqlComm = explode('/*&*/', file_get_contents($sql));
3465: }
3466: }
3467: foreach ($sqlComm as $sqlLine) {
3468: if (!empty($sqlLine)) {
3469: $command = Yii::app()->db->createCommand($sqlLine);
3470: $command->execute();
3471: }
3472: }
3473: }
3474: return true;
3475: } else {
3476: return false;
3477: }
3478: }
3479:
3480: 3481: 3482: 3483: 3484: 3485: 3486: 3487: 3488: 3489:
3490: public function actionRegisterModules() {
3491:
3492: $modules = scandir('protected/modules');
3493: $modules = array_combine($modules, $modules);
3494: $arr = array();
3495: foreach ($modules as $module) {
3496: if (file_exists("protected/modules/$module/register.php") && is_null(Modules::model()->findByAttributes(array('name' => $module)))) {
3497: $arr[] = ($module);
3498: }
3499: }
3500: $registeredModules = Modules::model()->findAll();
3501:
3502: $this->render('registerModules', array(
3503: 'modules' => $arr,
3504: 'registeredModules' => $registeredModules,
3505: ));
3506: }
3507:
3508: 3509: 3510: 3511: 3512: 3513: 3514: 3515: 3516: 3517:
3518: public function actionToggleModule($module) {
3519:
3520: $config = include("protected/modules/$module/register.php");
3521: $exists = Modules::model()->findByAttributes(array('name' => $module));
3522: if (!isset($exists)) {
3523: $moduleRecord = new Modules;
3524: $moduleRecord->editable = $config['editable'] ? 1 : 0;
3525: $moduleRecord->searchable = $config['searchable'] ? 1 : 0;
3526: $moduleRecord->adminOnly = $config['adminOnly'] ? 1 : 0;
3527: $moduleRecord->custom = $config['custom'] ? 1 : 0;
3528: $moduleRecord->toggleable = $config['toggleable'] ? 1 : 0;
3529: $moduleRecord->name = $module;
3530: $moduleRecord->title = $config['name'];
3531: $moduleRecord->visible = 1;
3532: $moduleRecord->menuPosition = Modules::model()->count();
3533:
3534: if ($moduleRecord->save()) {
3535: $install = $config['install'];
3536: }
3537: } else {
3538: $exists->visible = $exists->visible ? 0 : 1;
3539:
3540: if ($exists->save()) {
3541: if ($exists->toggleable) {
3542: $uninstall = $config['uninstall'];
3543: } else {
3544:
3545: }
3546: }
3547: }
3548: $this->redirect('registerModules');
3549: }
3550:
3551: 3552: 3553: 3554: 3555: 3556:
3557: public function actionEditor() {
3558:
3559: $layoutModel = null;
3560: $defaultView = false;
3561: $defaultForm = false;
3562:
3563: if (isset($_GET['id']) && !empty($_GET['id'])) {
3564:
3565: $id = $_GET['id'];
3566: $layoutModel = FormLayout::model()->findByPk($id);
3567:
3568: if (!isset($layoutModel))
3569: $this->redirect(array('editor'));
3570:
3571: $modelName = $layoutModel->model;
3572:
3573: if (isset($_POST['layout'])) {
3574: $layoutModel->layout = urldecode($_POST['layout']);
3575: $layoutModel->defaultView = isset($_POST['defaultView']) && $_POST['defaultView'] == 1;
3576: $layoutModel->defaultForm = isset($_POST['defaultForm']) && $_POST['defaultForm'] == 1;
3577: $layoutModel->scenario = isset($_POST['scenario']) ? $_POST['scenario'] : 'Default';
3578:
3579:
3580: if ($layoutModel->defaultView)
3581: FormLayout::clearDefaultFormLayouts('view', $modelName, $layoutModel->scenario);
3582:
3583: if ($layoutModel->defaultForm)
3584: FormLayout::clearDefaultFormLayouts('form', $modelName, $layoutModel->scenario);
3585:
3586: $layoutModel->save();
3587: $this->redirect(array('editor', 'id' => $id));
3588: }
3589: }else {
3590: $modelName = isset($_GET['model']) ? $_GET['model'] : '';
3591: if (!empty($modelName)) {
3592: try {
3593: $model = X2Model::model($modelName);
3594: } catch (Exception $e) {
3595: throw new CHttpException(400, 'The model you have requested does not exist. Please do not repeat this request.');
3596: }
3597: }
3598: $id = '';
3599: }
3600:
3601: $modules = Modules::model()->findAllByAttributes(array('editable' => 1));
3602:
3603: $modelList = array('' => '---');
3604: foreach ($modules as $module) {
3605: if ($module->name == 'marketing')
3606: $modelList['Campaign'] = Yii::t('marketing', 'Campaign');
3607: elseif ($module->name == 'opportunities')
3608: $modelList['Opportunity'] = Yii::t('opportunities', 'Opportunity');
3609: elseif ($module->name == 'products')
3610: $modelList['Product'] = Yii::t('products', 'Product');
3611: elseif ($module->name == 'quotes')
3612: $modelList['Quote'] = Yii::t('quotes', 'Quote');
3613: else
3614: $modelList[ucfirst($module->name)] = Yii::t('app', $module->title);
3615: }
3616:
3617: $versionList = array('' => '---');
3618: if (!empty($modelName)) {
3619: $layouts = FormLayout::model()->findAllByAttributes(array('model' => $modelName));
3620:
3621: foreach ($layouts as &$layout)
3622: $versionList[$layout->id] = $layout->version . (($layout->defaultView || $layout->defaultForm) ? ' (' . Yii::t('admin', 'Default') . ')' : '');
3623: unset($layout);
3624: }
3625:
3626: $this->render('editor', array(
3627: 'modelName' => $modelName,
3628: 'id' => $id,
3629: 'layoutModel' => $layoutModel,
3630: 'modelList' => $modelList,
3631: 'versionList' => $versionList,
3632: 'defaultView' => isset($layoutModel->defaultView) ? $layoutModel->defaultView : false,
3633: 'defaultForm' => isset($layoutModel->defaultForm) ? $layoutModel->defaultForm : false,
3634: ));
3635: }
3636:
3637: 3638: 3639: 3640: 3641: 3642:
3643: public function actionCreateFormLayout() {
3644: if (isset($_GET['newLayout'], $_GET['model'], $_GET['layoutName'])) {
3645:
3646:
3647: $newLayout = new FormLayout;
3648:
3649: if (isset($_POST['layout']))
3650: $newLayout->layout = urldecode($_POST['layout']);
3651:
3652: $newLayout->version = $_GET['layoutName'];
3653: $newLayout->model = $_GET['model'];
3654: $newLayout->createDate = time();
3655: $newLayout->lastUpdated = time();
3656: $newLayout->defaultView = false;
3657: $newLayout->defaultForm = false;
3658: $newLayout->save();
3659: $this->redirect(array('editor', 'id' => $newLayout->id));
3660: }
3661: }
3662:
3663: 3664: 3665: 3666: 3667:
3668: public function actionDeleteFormLayout($id) {
3669:
3670: $layout = FormLayout::model()->findByPk($id);
3671: if (isset($layout)) {
3672: $modelName = $layout->model;
3673: $defaultView = $layout->defaultView;
3674: $defaultForm = $layout->defaultForm;
3675: $layout->delete();
3676:
3677:
3678: if ($defaultView) {
3679: $newDefaultView = FormLayout::model()->findByAttributes(array('model' => $modelName));
3680: if (isset($newDefaultView)) {
3681: $newDefaultView->defaultView = true;
3682: $newDefaultView->save();
3683: }
3684: }
3685: if ($defaultForm) {
3686: $newDefaultForm = FormLayout::model()->findByAttributes(array('model' => $modelName));
3687: if (isset($newDefaultForm)) {
3688: $newDefaultForm->defaultForm = true;
3689: $newDefaultForm->save();
3690: }
3691: }
3692: $this->redirect(array('editor', 'model' => $modelName));
3693: } else
3694: $this->redirect('editor');
3695: }
3696:
3697: 3698: 3699: 3700: 3701: 3702:
3703: public function actionManageDropDowns() {
3704:
3705: $dataProvider = new CActiveDataProvider('Dropdowns');
3706: $model = new Dropdowns;
3707:
3708: $dropdowns = $dataProvider->getData();
3709: foreach ($dropdowns as $dropdown) {
3710: $temp = json_decode($dropdown->options, true);
3711: if (is_array($temp)) {
3712: $str = implode(", ", $temp);
3713: } else {
3714: $str = $dropdown->options;
3715: }
3716: $dropdown->options = $str;
3717: }
3718: $dataProvider->setData($dropdowns);
3719:
3720: $this->render('manageDropDowns', array(
3721: 'dataProvider' => $dataProvider,
3722: 'model' => $model,
3723: 'dropdowns' => Dropdowns::model()->findAll(),
3724: ));
3725: }
3726:
3727: 3728: 3729: 3730: 3731: 3732:
3733: public function actionDropDownEditor() {
3734: $model = new Dropdowns;
3735:
3736: if (isset($_POST['Dropdowns'])) {
3737: $model->attributes = $_POST['Dropdowns'];
3738: $temp = array();
3739: if (isset($model->options)) {
3740: foreach ($model->options as $option) {
3741: if ($option != "") {
3742: $temp[$option] = $option;
3743: }
3744: }
3745: }
3746: if (count($temp) > 0) {
3747: $model->options = json_encode($temp);
3748: if ($model->save()) {
3749:
3750: }
3751: }
3752: $this->redirect(
3753: 'manageDropDowns'
3754: );
3755: }
3756: }
3757:
3758: 3759: 3760:
3761: public function actionDeleteDropdown() {
3762: $dropdowns = Dropdowns::model()->findAll('id>=1000');
3763:
3764: if (isset($_POST['dropdown'])) {
3765: if ($_POST['dropdown'] != Actions::COLORS_DROPDOWN_ID) {
3766: $model = Dropdowns::model()->findByPk($_POST['dropdown']);
3767: $model->delete();
3768: $this->redirect('manageDropDowns');
3769: }
3770: }
3771:
3772: $this->redirect ('manageDropdowns');
3773: }
3774:
3775: 3776: 3777:
3778: public function actionEditDropdown() {
3779: $model = new Dropdowns;
3780:
3781:
3782: if (isset($_POST['Dropdowns']['id']) && ctype_digit($_POST['Dropdowns']['id'])) {
3783: $model = Dropdowns::model()->findByPk(
3784: $_POST['Dropdowns']['id']);
3785: if (!isset($model)) {
3786: throw new CHttpException(404, Yii::t('app', 'Dropdown could not be found'));
3787: }
3788: if ($model->id == Actions::COLORS_DROPDOWN_ID) {
3789: if (AuxLib::issetIsArray($_POST['Dropdowns']['values']) &&
3790: AuxLib::issetIsArray($_POST['Dropdowns']['labels']) &&
3791: count($_POST['Dropdowns']['values']) ===
3792: count($_POST['Dropdowns']['labels'])) {
3793:
3794: if (AuxLib::issetIsArray($_POST['Admin']) &&
3795: isset($_POST['Admin']['enableColorDropdownLegend'])) {
3796:
3797: Yii::app()->settings->enableColorDropdownLegend = $_POST['Admin']['enableColorDropdownLegend'];
3798: Yii::app()->settings->save();
3799: }
3800:
3801: $options = array_combine(
3802: $_POST['Dropdowns']['values'], $_POST['Dropdowns']['labels']);
3803: $temp = array();
3804: foreach ($options as $value => $label) {
3805: if ($value != "")
3806: $temp[$value] = $label;
3807: }
3808: $model->options = json_encode($temp);
3809: $model->save();
3810: }
3811: } else {
3812: $model->attributes = $_POST['Dropdowns'];
3813: $temp = array();
3814: if (is_array($model->options) && count($model->options) > 0) {
3815: foreach ($model->options as $option) {
3816: if ($option != "")
3817: $temp[$option] = $option;
3818: }
3819: $model->options = json_encode($temp);
3820: if ($model->save()) {
3821:
3822: }
3823: }
3824: }
3825: }
3826: $this->redirect(
3827: 'manageDropDowns'
3828: );
3829: }
3830:
3831: 3832: 3833: 3834: 3835: 3836:
3837: public function actionGetDropdown() {
3838: if (isset($_POST['Dropdowns']['id'])) {
3839: $id = $_POST['Dropdowns']['id'];
3840: $model = Dropdowns::model()->findByPk($id);
3841: if ($model === null) {
3842: return;
3843: }
3844:
3845: $options = json_decode($model->options);
3846: if ($id == Actions::COLORS_DROPDOWN_ID) {
3847: $this->renderPartial(
3848: 'application.modules.actions.views.actions._colorDropdownForm', array(
3849: 'model' => $model,
3850: 'options' => $options,
3851: ), false, true);
3852: } else {
3853: $this->renderPartial(
3854: 'application.components.views._dropdownForm', array(
3855: 'model' => $model,
3856: 'options' => $options,
3857: ), false, true);
3858: }
3859: }
3860: }
3861:
3862: 3863: 3864: 3865: 3866: 3867:
3868: public function actionGetFieldType() {
3869: if (isset($_POST['Fields']['type'])) {
3870: $field = new Fields;
3871: $field->attributes = $_POST['Fields'];
3872: $type = $_POST['Fields']['type'];
3873: $model = new AmorphousModel();
3874: $model->addField($field, 'customized_field');
3875:
3876: $this->renderPartial('fieldDefault', array(
3877: 'field' => $field,
3878: 'dummyModel' => $model,
3879: 'type' => $type,
3880: 'echoScripts' => true
3881: ));
3882: }
3883: }
3884:
3885: 3886: 3887: 3888: 3889:
3890: public function actionExport() {
3891: $modelList = array(
3892: 'Admin' => array('name' => Yii::t('admin', 'Admin Settings'), 'count' => 1),
3893: );
3894: $modules = Modules::model()->findAll();
3895: foreach ($modules as $module) {
3896: $name = ucfirst($module->name);
3897: if ($name != 'Document') {
3898: $controllerName = $name . 'Controller';
3899: if (file_exists('protected/modules/' . $module->name . '/controllers/' . $controllerName . '.php')) {
3900: Yii::import("application.modules.$module->name.controllers.$controllerName");
3901: $controller = new $controllerName($controllerName);
3902: $model = $controller->modelClass;
3903: if (class_exists($model)) {
3904: $recordCount = X2Model::model($model)->count();
3905: if ($recordCount > 0) {
3906: $modelList[$model] = array('name' => Yii::t('app', $module->title), 'count' => $recordCount);
3907: }
3908: }
3909: }
3910: }
3911: }
3912: $extraModels = array('Fields', 'Dropdowns', 'FormLayout');
3913: foreach ($extraModels as $model) {
3914: if (class_exists($model)) {
3915: $fieldCount = X2Model::model($model)->count();
3916: if ($fieldCount > 0)
3917: $modelList[$model] = array('name' => Yii::t('app', $model), 'count' => $fieldCount);
3918: }
3919: }
3920:
3921: $this->render('export', array(
3922: 'modelList' => $modelList,
3923: ));
3924: }
3925:
3926:
3927:
3928:
3929:
3930: 3931: 3932:
3933: public function actionPrepareExport() {
3934:
3935: $_SESSION['importDelimeter'] = (isset($_GET['delimeter']) ? $_GET['delimeter'] : ',');
3936: $_SESSION['importEnclosure'] = (isset($_GET['enclosure']) ? $_GET['enclosure'] : '"');
3937: $_SESSION['exportFormat'] = $this->readExportFormatOptions($_GET);
3938:
3939: $fp = fopen($this->safePath(), 'w+');
3940: fputcsv($fp, array('v' . Yii::app()->params->version), $this->importDelimeter, $this->importEnclosure);
3941: fclose($fp);
3942: }
3943:
3944: 3945: 3946: 3947: 3948: 3949: 3950: 3951: 3952: 3953:
3954: public function actionGlobalExport($model, $page) {
3955: if (class_exists($model)) {
3956: ini_set('memory_limit', -1);
3957: $file = $this->safePath();
3958: $fp = fopen($file, 'a+');
3959: $tempModel = X2Model::model($model);
3960: $meta = array_keys($tempModel->attributes);
3961: $meta[] = $model;
3962: if ($page == 0)
3963: fputcsv ($fp, $meta, $this->importDelimeter, $this->importEnclosure);
3964: $dp = new CActiveDataProvider($model, array(
3965: 'pagination' => array(
3966: 'pageSize' => 100,
3967: ),
3968: ));
3969: $pg = $dp->getPagination();
3970: $pg->setCurrentPage($page);
3971: $dp->setPagination($pg);
3972: $records = $dp->getData();
3973: $pageCount = $dp->getPagination()->getPageCount();
3974:
3975: foreach ($records as $record) {
3976:
3977:
3978: foreach ($record->behaviors() as $name => $config) {
3979: $behavior = $record->asa($name);
3980: if ($behavior instanceof TransformedFieldStorageBehavior) {
3981: $behavior->packAll();
3982: $record->disableBehavior($name);
3983: }
3984: }
3985: $tempAttributes = $tempModel->attributes;
3986: $tempAttributes = array_merge($tempAttributes, $record->attributes);
3987: if ($model == 'Profile') {
3988: $tempAttributes['theme'] = json_encode($record->theme);
3989: }
3990: $tempAttributes[] = $model;
3991:
3992: fputcsv($fp, $tempAttributes, $this->importDelimeter, $this->importEnclosure);
3993: }
3994:
3995: unset($tempModel, $dp);
3996:
3997: fclose($fp);
3998: if ($page + 1 < $pageCount) {
3999: echo $page + 1;
4000: }
4001: }
4002: }
4003:
4004: 4005: 4006:
4007: public function actionFinishGlobalExport() {
4008: $success = $this->prepareExportDeliverable ($this->safePath(), $_SESSION['exportFormat']);
4009: if ($_SESSION['exportFormat']['exportDestination'] === 'download') {
4010: $_SESSION['modelExportFile'] = $this->safePath();
4011: if ($_SESSION['exportFormat']['compressOutput']) {
4012: $_SESSION['modelExportFile'] = $this->adjustExportPath (
4013: $this->safePath(),
4014: $_SESSION['exportFormat']
4015: );
4016: }
4017: } else {
4018: $_SESSION['modelExportFile'] = '';
4019: }
4020: echo basename ($_SESSION['modelExportFile']);
4021: unset ($_SESSION['exportFormat'], $_SESSION['modelExportFile']);
4022: }
4023:
4024:
4025: 4026: 4027: 4028:
4029: public function actionDownloadData($file) {
4030: $this->sendFile($file);
4031: }
4032:
4033: 4034: 4035: 4036: 4037: 4038: 4039: 4040: 4041: 4042:
4043: public function actionRollbackStage($model, $stage, $importId) {
4044: $stages = array(
4045:
4046: "tags" => "DELETE a FROM x2_tags a
4047: INNER JOIN
4048: x2_imports b ON b.modelId=a.itemId AND b.modelType=a.type
4049: WHERE b.modelType='$model' AND b.importId='$importId'",
4050:
4051: "relationships" => "DELETE a FROM x2_relationships a
4052: INNER JOIN
4053: x2_imports b ON b.modelId=a.firstId AND b.modelType=a.firstType
4054: WHERE b.modelType='$model' AND b.importId='$importId'",
4055:
4056: "actions" => "DELETE a FROM x2_actions a
4057: INNER JOIN
4058: x2_imports b ON b.modelId=a.associationId AND b.modelType=a.associationType
4059: WHERE b.modelType='$model' AND b.importId='$importId'",
4060:
4061: "records" => "DELETE a FROM " . X2Model::model($model)->tableName() . " a
4062: INNER JOIN
4063: x2_imports b ON b.modelId=a.id
4064: WHERE b.modelType='$model' AND b.importId='$importId'",
4065:
4066: "import" => "DELETE FROM x2_imports WHERE modelType='$model' AND importId='$importId'",
4067: );
4068: $sqlQuery = $stages[$stage];
4069: $command = Yii::app()->db->createCommand($sqlQuery);
4070: $result = $command->execute();
4071: echo $result;
4072: }
4073:
4074: 4075: 4076:
4077: public function actionRollbackImport() {
4078:
4079: if (isset($_GET['importId']) && ctype_digit($_GET['importId'])) {
4080: $importId = $_GET['importId'];
4081: $types = Yii::app()->db->createCommand()
4082: ->select('modelType')
4083: ->from('x2_imports')
4084: ->group('modelType')
4085: ->where('importId=:importId', array(':importId' => $importId))
4086: ->queryAll();
4087: $count = Yii::app()->db->createCommand()
4088: ->select('COUNT(*)')
4089: ->from('x2_imports')
4090: ->group('importId')
4091: ->where('importId=:importId', array(':importId' => $importId))
4092: ->queryRow();
4093: $count = $count['COUNT(*)'];
4094: $typeArray = array();
4095: foreach ($types as $tempArr) {
4096: $typeArray[] = $tempArr['modelType'];
4097: }
4098: $this->render('rollbackImport', array(
4099: 'typeArray' => $typeArray,
4100: 'dataProvider' => null,
4101: 'count' => $count,
4102: 'importId' => $importId,
4103: ));
4104: } else {
4105:
4106: $data = array();
4107: $imports = Yii::app()->db->createCommand()
4108: ->select('importId')
4109: ->from('x2_imports')
4110: ->group('importId')
4111: ->queryAll();
4112: foreach ($imports as $key => $array) {
4113: $data[$key]['id'] = $key;
4114: $data[$key]['importId'] = $array['importId'];
4115: $count = Yii::app()->db->createCommand()
4116: ->select('COUNT(*)')
4117: ->from('x2_imports')
4118: ->group('importId')
4119: ->where('importId=:importId', array(':importId' => $array['importId']))
4120: ->queryRow();
4121: $data[$key]['type'] = Yii::app()->db->createCommand()
4122: ->select('modelType')
4123: ->from('x2_imports')
4124: ->where('importId=:importId', array(':importId' => $array['importId']))
4125: ->queryScalar();
4126: $data[$key]['records'] = $count['COUNT(*)'];
4127: $timestamp = Yii::app()->db->createCommand()
4128: ->select('timestamp')
4129: ->from('x2_imports')
4130: ->group('importId')
4131: ->order('timestamp ASC')
4132: ->where('importId=:importId', array(':importId' => $array['importId']))
4133: ->queryRow();
4134: $data[$key]['timestamp'] = $timestamp['timestamp'];
4135: $data[$key]['link'] = "";
4136: }
4137: $dataProvider = new CArrayDataProvider($data);
4138: $this->render('rollbackImport', array(
4139: 'typeArray' => array(),
4140: 'dataProvider' => $dataProvider,
4141: ));
4142: }
4143: }
4144:
4145: 4146: 4147: 4148: 4149: 4150: 4151: 4152: 4153:
4154: public function actionImport() {
4155: $formModel = new GlobalImportFormModel;
4156:
4157: if (isset($_POST['GlobalImportFormModel']) && isset($_FILES['GlobalImportFormModel'])) {
4158: $formModel->setAttributes($_POST['GlobalImportFormModel']);
4159: $formModel->data = CUploadedFile::getInstance($formModel, 'data');
4160:
4161: if ($formModel->validate()) {
4162: $_SESSION['overwrite'] = $formModel->overwrite;
4163: $_SESSION['counts'] = array();
4164: $_SESSION['overwriten'] = array();
4165: $_SESSION['overwriteFailure'] = array();
4166: $_SESSION['model'] = "";
4167: $_SESSION['failed'] = 0;
4168: $_SESSION['importDelimeter'] = $formModel->delimeter;
4169: $_SESSION['importEnclosure'] = $formModel->enclosure;
4170:
4171: if ($formModel->data->saveAs($this->safePath())) {
4172:
4173: $this->render('processImport', array(
4174: 'overwrite' => $formModel->overwrite,
4175: ));
4176: Yii::app()->end();
4177: } else {
4178: $formModel->addError('data', Yii::t('admin', 'File could not be uploaded'));
4179: }
4180: }
4181: }
4182:
4183: $this->render('import', array(
4184: 'formModel' => $formModel
4185: ));
4186: }
4187:
4188: 4189: 4190: 4191: 4192: 4193:
4194: public function actionPrepareImport() {
4195: $fp = fopen($this->safePath(), 'r+');
4196:
4197: $version = fgetcsv($fp, 0, $this->importDelimeter, $this->importEnclosure);
4198: $version = $version[0];
4199: $tempMeta = fgetcsv($fp, 0, $this->importDelimeter, $this->importEnclosure);
4200: while ("" === end($tempMeta)) {
4201: array_pop($tempMeta);
4202: }
4203: $model = array_pop($tempMeta);
4204: $_SESSION['metaData'] = $tempMeta;
4205: $_SESSION['model'] = $model;
4206: $_SESSION['lastFailed'] = "";
4207: 4208: 4209: 4210: 4211:
4212: $_SESSION['offset'] = ftell($fp);
4213: fclose($fp);
4214: $criteria = new CDbCriteria;
4215: $criteria->order = "importId DESC";
4216: $criteria->limit = 1;
4217: $import = Imports::model()->find($criteria);
4218: if (isset($import)) {
4219: $_SESSION['importId'] = $import->importId + 1;
4220: } else {
4221: $_SESSION['importId'] = 1;
4222: }
4223: $failedImport = fopen($this->safePath('failedImport.csv'), 'w+');
4224: fputcsv($failedImport, array(Yii::app()->params->version), $this->importDelimeter, $this->importEnclosure);
4225: fclose($failedImport);
4226: echo json_encode(array($version));
4227: }
4228:
4229: 4230: 4231: 4232:
4233: public function actionPrepareModelExport() {
4234: if (isset($_GET['model']) || isset($_POST['model'])) {
4235: $model = (isset($_GET['model'])) ? $_GET['model'] : $_POST['model'];
4236: $modelName = str_replace(' ', '', $model);
4237: }
4238: $_SESSION['includeTags'] = isset($_GET['includeTags']) && $_GET['includeTags'] === 'true';
4239: $_SESSION['exportFormat'] = $this->readExportFormatOptions($_GET);
4240: $filePath = $this->safePath($_SESSION['modelExportFile']);
4241: $attributes = X2Model::model($modelName)->attributes;
4242:
4243:
4244: $_SESSION['importDelimeter'] = (isset($_GET['delimeter']) ? $_GET['delimeter'] : ',');
4245: $_SESSION['importEnclosure'] = (isset($_GET['enclosure']) ? $_GET['enclosure'] : '"');
4246:
4247: if ($modelName === 'Actions') {
4248:
4249: $attributes = array_merge($attributes, array('actionDescription' => null));
4250: }
4251: $meta = array_keys($attributes);
4252: if ($_SESSION['includeTags'])
4253: $meta[] = 'tags';
4254: if (isset($_SESSION['exportModelListId'])) {
4255:
4256: $gridviewSettings = json_decode(Yii::app()->params->profile->gridviewSettings, true);
4257: if (isset($gridviewSettings['contacts_list' . $_SESSION['exportModelListId']])) {
4258: $tempMeta = array_keys($gridviewSettings['contacts_list' . $_SESSION['exportModelListId']]);
4259: $meta = array_intersect($tempMeta, $meta);
4260: }
4261: }
4262:
4263: $_SESSION['modelExportMeta'] = $meta;
4264: $fp = @fopen($filePath, 'w+');
4265: if ($fp) {
4266: fputcsv($fp, $meta, $this->importDelimeter, $this->importEnclosure);
4267: fclose($fp);
4268: } else {
4269: $msg = Yii::t ('admin', 'Failed to open CSV file for writing. Please ensure the '.
4270: 'protected/data directory is writable by the web server process.');
4271: $this->respond ($msg, true);
4272: }
4273: }
4274:
4275: 4276: 4277: 4278:
4279: public function actionPrepareModelImport() {
4280:
4281: if (isset($_POST['attributes']) && isset($_POST['keys']) && isset($_POST['model'])) {
4282: $model = $_POST['model'];
4283: $keys = $_POST['keys'];
4284: $attributes = $_POST['attributes'];
4285: $preselectedMap = (isset($_POST['preselectedMap']) && $_POST['preselectedMap'] === 'true') ? true : false;
4286: $_SESSION['tags'] = array();
4287:
4288: if (isset($_POST['tags']) && !empty($_POST['tags'])) {
4289: $tags = explode(',', $_POST['tags']);
4290: foreach ($tags as $tag) {
4291: if (substr($tag, 0, 1) != "#")
4292: $tag = "#" . $tag;
4293: $_SESSION['tags'][] = $tag;
4294: }
4295: }
4296:
4297: $_SESSION['override'] = array();
4298: if (isset($_POST['forcedAttributes']) && isset($_POST['forcedValues'])) {
4299: $override = array_combine($_POST['forcedAttributes'], $_POST['forcedValues']);
4300: $_SESSION['override'] = $override;
4301: }
4302:
4303: $_SESSION['comment'] = "";
4304: if (isset($_POST['comment']) && !empty($_POST['comment'])) {
4305: $_SESSION['comment'] = $_POST['comment'];
4306: }
4307:
4308: $_SESSION['leadRouting'] = 0;
4309: if (isset($_POST['routing']) && $_POST['routing'] == 1) {
4310: $_SESSION['leadRouting'] = 1;
4311: }
4312:
4313: $_SESSION['skipActivityFeed'] = 0;
4314: if (isset($_POST['skipActivityFeed']) && $_POST['skipActivityFeed'] == 1) {
4315: $_SESSION['skipActivityFeed'] = 1;
4316: }
4317:
4318:
4319: $_SESSION['createRecords'] = $_POST['createRecords'] == "checked" ? "1" : "0";
4320: $_SESSION['linkMatchMap'] = empty($_POST['linkMatchMap']) ? array() : $_POST['linkMatchMap'];
4321: $_SESSION['imported'] = 0;
4322: $_SESSION['failed'] = 0;
4323: $_SESSION['created'] = array();
4324: if ($preselectedMap) {
4325: $keys = array_keys($_SESSION['importMap']);
4326: $attributes = array_values($_SESSION['importMap']);
4327: }
4328:
4329:
4330: $nonUniqueLinkMatches = array();
4331: foreach ($_SESSION['linkMatchMap'] as $attr => $match) {
4332: $linkedModel = Yii::app()->db->createCommand()
4333: ->select ('linkType')
4334: ->from ('x2_fields')
4335: ->where ('fieldName = :field AND modelName = :model', array(
4336: ':field' => $attr,
4337: ':model' => $model,
4338: ))
4339: ->queryScalar();
4340: $matchField = Fields::model()->findByAttributes (array(
4341: 'fieldName' => $match,
4342: 'modelName' => $linkedModel,
4343: 'uniqueConstraint' => 0,
4344: ));
4345: if ($matchField)
4346: $nonUniqueLinkMatches[$model.'.'.$attr] = $linkedModel.'.'.$matchField->fieldName;
4347: }
4348: $mappingResult = $this->verifyImportMap($model, $keys, $attributes);
4349:
4350: if (!empty($nonUniqueLinkMatches)) {
4351:
4352: $mappingResult['nonUniqAssocMatchAttr'] = '';
4353: foreach ($nonUniqueLinkMatches as $attr => $mapping)
4354: $mappingResult['nonUniqAssocMatchAttr'] .= "* {$attr}: {$mapping}\n";
4355: }
4356: echo CJSON::encode ($mappingResult);
4357: $cache = Yii::app()->cache;
4358: if (isset($cache)) {
4359: $cache->flush();
4360: }
4361: }
4362: }
4363:
4364: 4365: 4366: 4367: 4368: 4369: 4370:
4371: public function actionPublicInfo() {
4372: $admin = &Yii::app()->settings;
4373: if (isset($_POST['Admin'])) {
4374: $admin->attributes = $_POST['Admin'];
4375: $assetDomains = CJSON::decode ($admin->assetBaseUrls);
4376: if (is_array($assetDomains)) {
4377: if (!empty($assetDomains))
4378: $admin->assetBaseUrls = array_unique ($assetDomains);
4379: else
4380: $admin->enableAssetDomains = false;
4381: }
4382: if ($admin->save()) {
4383: $this->redirect('publicInfo');
4384: }
4385: }
4386:
4387: if ($admin->externalBaseUrl == '' && !$admin->hasErrors('externalBaseUrl'))
4388: $admin->externalBaseUrl = Yii::app()->request->getHostInfo();
4389: if ($admin->externalBaseUri == '' && !$admin->hasErrors('externalBaseUri'))
4390: $admin->externalBaseUri = Yii::app()->baseUrl;
4391: $this->render('publicInfo', array(
4392: 'model' => $admin,
4393: ));
4394: }
4395:
4396: 4397: 4398: 4399: 4400: 4401: 4402: 4403: 4404: 4405: 4406:
4407: public function actionGlobalImport() {
4408: if (isset($_POST['count']) && file_exists($this->safePath())) {
4409: $metaData = $_SESSION['metaData'];
4410: $modelType = $_SESSION['model'];
4411: $count = $_POST['count'];
4412: $fp = fopen($this->safePath(), 'r+');
4413: 4414: 4415: 4416: 4417: 4418:
4419: fseek($fp, $_SESSION['offset']);
4420: for ($i = 0; $i < $count; $i++) {
4421:
4422: $csvLine = fgetcsv ($fp, 0, $this->importDelimeter, $this->importEnclosure);
4423: if ($csvLine !== false && !is_null($csvLine)) {
4424: while ("" === end($csvLine)) {
4425: array_pop($csvLine);
4426: }
4427: $newType = array_pop($csvLine);
4428: if ($newType != $modelType) {
4429: 4430: 4431: 4432: 4433: 4434: 4435: 4436: 4437: 4438:
4439: $_SESSION['model'] = $newType;
4440: $_SESSION['metaData'] = $csvLine;
4441: $modelType = $_SESSION['model'];
4442: $metaData = $_SESSION['metaData'];
4443: } else {
4444: $attributes = array_combine($metaData, $csvLine);
4445: if ($modelType == "Actions" && (isset($attributes['type']) &&
4446: $attributes['type'] == 'workflow')) {
4447:
4448:
4449: $model = new Actions('workflow');
4450: } else {
4451: $model = new $modelType;
4452: }
4453: 4454: 4455: 4456: 4457: 4458: 4459: 4460: 4461:
4462: foreach ($attributes as $key => $value) {
4463: if ($model->hasAttribute($key) && isset($value)) {
4464: if ($value == "")
4465: $value = null;
4466: $model->$key = $value;
4467: }
4468: }
4469:
4470: $model->disableBehavior('changelog');
4471:
4472: $model->disableBehavior('X2TimestampBehavior');
4473: if ($model instanceof User || $model instanceof Profile) {
4474: if ($model->id == '1') {
4475: 4476: 4477: 4478: 4479:
4480: continue;
4481: }
4482:
4483: $model->setScenario('import');
4484: }
4485: if ($_SESSION['overwrite'] == 1 &&
4486: property_exists($model, 'subScenario')) {
4487:
4488: $model->subScenario = 'importOverwrite';
4489: }
4490:
4491:
4492: $lookup = X2Model::model($modelType)->findByPk($model->id);
4493: $lookupFlag = isset($lookup);
4494: 4495: 4496: 4497: 4498:
4499: if ($model->validate() || $modelType == "User" || $modelType == 'Profile') {
4500: $saveFlag = true;
4501: if ($lookupFlag) {
4502: if ($_SESSION['overwrite'] == 1) {
4503: if ($modelType === "Fields") {
4504: 4505: 4506: 4507:
4508: continue;
4509: }
4510: $lookup->disableBehavior('changelog');
4511: $lookup->delete();
4512: } else {
4513: $saveFlag = false;
4514: isset($_SESSION['overwriteFailure'][$modelType]) ? $_SESSION['overwriteFailure'][$modelType] ++ : $_SESSION['overwriteFailure'][$modelType] = 1;
4515: }
4516: if (!$model->validate()) {
4517: $saveFlag = false;
4518: $failedImport = fopen($this->safePath('failedImport.csv'), 'a+');
4519: $lastFailed = $_SESSION['lastFailed'];
4520: if ($lastFailed != $modelType) {
4521: $tempMeta = $metaData;
4522: $tempMeta[] = $modelType;
4523: fputcsv($failedImport, $tempMeta, $this->importDelimeter, $this->importEnclosure);
4524: }
4525: $attr = $model->attributes;
4526: $tempAttributes = X2Model::model($modelType)->attributes;
4527: $attr = array_merge($tempAttributes, $attr);
4528: $attr[] = $modelType;
4529: fputcsv($failedImport, $attr, $this->importDelimeter, $this->importEnclosure);
4530: $_SESSION['lastFailed'] = $modelType;
4531: isset($_SESSION['failed']) ? $_SESSION['failed'] ++ : $_SESSION['failed'] = 1;
4532: }
4533: }
4534: if ($saveFlag && $model->save()) {
4535: if ($modelType != "Admin" && !(($modelType == "User" || $modelType == "Profile") && ($model->id == '1' || $model->username == 'api'))) {
4536:
4537: $importLink = new Imports;
4538: $importLink->modelType = $modelType;
4539: $importLink->modelId = $model->id;
4540: $importLink->importId = $_SESSION['importId'];
4541: $importLink->timestamp = time();
4542: $importLink->save();
4543: }
4544: if ($modelType === "Fields") {
4545:
4546:
4547: if (isset($model->keyType))
4548: $model->createIndex($model->keyType === "UNI");
4549: } else if ($modelType === "FormLayout") {
4550: 4551: 4552: 4553: 4554: 4555:
4556: if ($_SESSION['overwrite']) {
4557: if ($model->defaultView)
4558: FormLayout::clearDefaultFormLayouts(
4559: 'view', $model->model);
4560: if ($model->defaultForm)
4561: FormLayout::clearDefaultFormLayouts(
4562: 'form', $model->model);
4563: $model->save();
4564: } else {
4565: $model->defaultView = false;
4566: $model->defaultForm = false;
4567: $model->save();
4568: }
4569: }
4570:
4571: if ($modelType == 'Actions' && isset($attributes['actionDescription'])) {
4572: $model->actionDescription = $attributes['actionDescription'];
4573: }
4574:
4575: isset($_SESSION['counts'][$modelType]) ? $_SESSION['counts'][$modelType] ++ : $_SESSION['counts'][$modelType] = 1;
4576: if ($lookupFlag) {
4577: isset($_SESSION['overwriten'][$modelType]) ? $_SESSION['overwriten'][$modelType] ++ : $_SESSION['overwriten'][$modelType] = 1;
4578: } else {
4579: isset($_SESSION['overwriten'][$modelType])? : $_SESSION['overwriten'][$modelType] = 0;
4580: }
4581: }
4582: } else {
4583:
4584:
4585:
4586: $failedImport = fopen($this->safePath('failedImport.csv'), 'a+');
4587: $lastFailed = $_SESSION['lastFailed'];
4588: if ($lastFailed != $modelType) {
4589: $tempMeta = $metaData;
4590: $tempMeta[] = $modelType;
4591: fputcsv($failedImport, $tempMeta, $this->importDelimeter, $this->importEnclosure);
4592: }
4593: $attr = $model->attributes;
4594: $tempAttributes = X2Model::model($modelType)->attributes;
4595: $attr = array_merge($tempAttributes, $attr);
4596: $attr[] = $modelType;
4597: fputcsv($failedImport, $attr, $this->importDelimeter, $this->importEnclosure);
4598: $_SESSION['lastFailed'] = $modelType;
4599: isset($_SESSION['failed']) ? $_SESSION['failed'] ++ : $_SESSION['failed'] = 1;
4600: }
4601: }
4602: } else {
4603:
4604:
4605: echo json_encode(array(
4606: 0,
4607: json_encode($_SESSION['counts']),
4608: json_encode($_SESSION['overwriten']),
4609: json_encode($_SESSION['failed']),
4610: json_encode($_SESSION['overwriteFailure']),
4611: ));
4612: return;
4613: }
4614: }
4615:
4616: $_SESSION['offset'] = ftell($fp);
4617: echo json_encode(array(
4618: 1,
4619: json_encode($_SESSION['counts']),
4620: json_encode($_SESSION['overwriten']),
4621: json_encode($_SESSION['failed']),
4622: json_encode($_SESSION['overwriteFailure']),
4623: ));
4624: }
4625: }
4626:
4627: 4628: 4629: 4630:
4631: public function actionCleanUpImport() {
4632: unlink($this->safePath());
4633: unset($_SESSION['counts']);
4634: unset($_SESSION['overwriten']);
4635: unset($_SESSION['model']);
4636: unset($_SESSION['overwrite']);
4637: unset($_SESSION['metaData']);
4638: unset($_SESSION['failed']);
4639: unset($_SESSION['lastFailed']);
4640: unset($_SESSION['overwriteFailure']);
4641: }
4642:
4643: 4644: 4645:
4646: public function actionCleanUpModelImport() {
4647: unset($_SESSION['tags']);
4648: unset($_SESSION['override']);
4649: unset($_SESSION['comment']);
4650: unset($_SESSION['leadRouting']);
4651: unset($_SESSION['createRecords']);
4652: unset($_SESSION['imported']);
4653: unset($_SESSION['failed']);
4654: unset($_SESSION['created']);
4655: unset($_SESSION['importMap']);
4656: unset($_SESSION['offset']);
4657: unset($_SESSION['metaData']);
4658: unset($_SESSION['fields']);
4659: unset($_SESSION['x2attributes']);
4660: unset($_SESSION['model']);
4661: if (file_exists($path = $this->safePath('data.csv'))) {
4662: unlink($path);
4663: }
4664: if (file_exists($path = $this->safePath('importMapping.json'))) {
4665: unlink($path);
4666: }
4667: }
4668:
4669: 4670: 4671: 4672: 4673:
4674: public function actionUpdaterSettings() {
4675: $admin = &Yii::app()->settings;
4676:
4677: $cf = new CronForm;
4678: $cf->jobs = array(
4679: 'app_update' => array(
4680: 'cmd' => Yii::app()->basePath . DIRECTORY_SEPARATOR . 'yiic update app --lock=1 &>/dev/null',
4681: 'desc' => Yii::t('admin', 'Automatic software updates cron job'),
4682: ),
4683: );
4684: if (isset($_POST['Admin'])) {
4685: $admin->setAttributes($_POST['Admin']);
4686: foreach (array('unique_id', 'edition') as $var)
4687: if (isset($_POST['unique_id']))
4688: $admin->$var = $_POST[$var];
4689: if ($admin->save()) {
4690: if (isset($_POST['cron'])) {
4691:
4692: $cf->save($_POST);
4693: } else {
4694:
4695: $cf->save(array());
4696: }
4697: $this->redirect('updaterSettings');
4698: }
4699: }
4700: foreach ($cf->jobs as $tag => $attributes) {
4701: $commands[$tag] = $attributes['cmd'];
4702: }
4703: if (isset($_POST['cron'])) {
4704:
4705: $cf->save($_POST);
4706: }
4707: $this->render('updaterSettings', array(
4708: 'model' => $admin,
4709: 'displayCmds' => $commands
4710: ));
4711: }
4712:
4713: 4714: 4715: 4716: 4717: 4718: 4719:
4720: private function _sendResponse($status = 200, $body = '', $content_type = 'text/html') {
4721:
4722: $status_header = 'HTTP/1.1 ' . $status . ' ' . $this->_getStatusCodeMessage($status);
4723: header($status_header);
4724:
4725: header('Content-type: ' . $content_type);
4726:
4727:
4728: if ($body != '') {
4729:
4730: echo $body;
4731: exit;
4732: }
4733:
4734: else {
4735:
4736: $message = '';
4737:
4738:
4739:
4740:
4741: switch ($status) {
4742: case 401:
4743: $message = 'You must be authorized to view this page.';
4744: break;
4745: case 404:
4746: $message = 'The requested URL ' . $_SERVER['REQUEST_URI'] . ' was not found.';
4747: break;
4748: case 500:
4749: $message = 'The server encountered an error processing your request.';
4750: break;
4751: case 501:
4752: $message = 'The requested method is not implemented.';
4753: break;
4754: }
4755:
4756:
4757:
4758: $signature = ($_SERVER['SERVER_SIGNATURE'] == '') ? $_SERVER['SERVER_SOFTWARE'] . ' Server at ' . $_SERVER['SERVER_NAME'] . ' Port ' . $_SERVER['SERVER_PORT'] : $_SERVER['SERVER_SIGNATURE'];
4759:
4760:
4761: $body = '
4762: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
4763: <html>
4764: <head>
4765: <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
4766: <title>' . $status . ' ' . $this->_getStatusCodeMessage($status) . '</title>
4767: </head>
4768: <body>
4769: <h1>' . $this->_getStatusCodeMessage($status) . '</h1>
4770: <p>' . $message . '</p>
4771: <hr />
4772: <address>' . $signature . '</address>
4773: </body>
4774: </html>';
4775:
4776: echo $body;
4777: exit;
4778: }
4779: }
4780:
4781: 4782: 4783: 4784: 4785: 4786:
4787: private function _getStatusCodeMessage($status) {
4788:
4789:
4790:
4791: $codes = Array(
4792: 200 => 'OK',
4793: 400 => 'Bad Request',
4794: 401 => 'Unauthorized',
4795: 402 => 'Payment Required',
4796: 403 => 'Forbidden',
4797: 404 => 'Not Found',
4798: 408 => 'Request Timeout',
4799: 500 => 'Internal Server Error',
4800: 501 => 'Not Implemented',
4801: );
4802: return (isset($codes[$status])) ? $codes[$status] : '';
4803: }
4804:
4805: 4806: 4807: 4808: 4809: 4810:
4811:
4812: 4813: 4814: 4815:
4816: public function missingClassesException($classes) {
4817: $message = Yii::t('admin', 'One or more dependencies of AdminController are missing and could not be automatically retrieved. They are {classes}', array('{classes}' => implode(', ', $classes)));
4818: $message .= "\n\n" . Yii::t('admin', 'To diagnose this error, please upload and run the requirements check script on your server.');
4819: $message .= "\nhttps://x2planet.com/installs/requirements.php";
4820: $message .= "\n\n" . Yii::t('admin', 'The error is most likely due to one of the following things:');
4821: $message .= "\n(1) " . Yii::t('admin', 'PHP processes run by the web server do not have permission to create or modify files');
4822: $message .= "\n(2) " . Yii::t('admin', 'x2planet.com and raw.github.com are currently unavailable');
4823: $message .= "\n(3) " . Yii::t('admin', 'This web server has no outbound internet connection. This could be because it is behind a firewall that does not permit outbound connections, operating within a private network with broken domain name resolution, or with no outbound route.');
4824: $message .= "\n\n" . Yii::t('admin', 'To stop this error from occurring, if the problem persists, restore the file {adminController} to the copy from your version of X2Engine:', array('{adminController}' => 'protected/controllers/AdminController.php'));
4825: $message .= "\n" . "https://raw.github.com/X2Engine/X2Engine/" . Yii::app()->params->version . "/x2engine/protected/controllers/AdminController.php";
4826: $this->error500($message);
4827: }
4828:
4829: 4830: 4831: 4832: 4833: 4834: 4835:
4836: public function actionAuthGraph() {
4837:
4838: if (!Yii::app()->params->isAdmin)
4839: return;
4840:
4841: $allTasks = array();
4842:
4843: $authGraph = array();
4844:
4845: $taskNames = Yii::app()->db->createCommand()
4846: ->select('name')
4847: ->from('x2_auth_item')
4848: ->where('type=1')
4849: ->queryColumn();
4850:
4851: foreach ($taskNames as $task) {
4852: $children = Yii::app()->db->createCommand()
4853: ->select('child')
4854: ->from('x2_auth_item_child')
4855: ->where('parent=:parent', array(':parent' => $task))
4856: ->queryColumn();
4857:
4858: foreach ($children as $child)
4859: $allTasks[$task][$child] = array();
4860: }
4861:
4862: $bizruleTasks = Yii::app()->db->createCommand()
4863: ->select('name')
4864: ->from('x2_auth_item')
4865: ->where('bizrule IS NOT NULL')
4866: ->queryColumn();
4867:
4868: function buildGraph($task, &$allTasks, &$authGraph) {
4869:
4870: if (!isset($allTasks[$task]) || empty($allTasks[$task])) {
4871: return array();
4872: } else {
4873: $children = array();
4874:
4875: foreach (array_keys($allTasks[$task]) as $child) {
4876:
4877: if (isset($authGraph[$child]) && $authGraph[$child] === false)
4878: continue;
4879:
4880: $childGraph = buildGraph($child, $allTasks, $authGraph);
4881:
4882: $children[$child] = $childGraph;
4883: $authGraph[$child] = false;
4884: }
4885: return $children;
4886: }
4887: }
4888:
4889: foreach (array_keys($allTasks) as $task)
4890: $authGraph[$task] = buildGraph($task, $allTasks, $authGraph);
4891:
4892: foreach (array_keys($authGraph) as $key) {
4893: if (empty($authGraph[$key]))
4894: unset($authGraph[$key]);
4895: }
4896:
4897: $this->render('authGraph', array('authGraph' => $authGraph, 'bizruleTasks' => $bizruleTasks));
4898: }
4899:
4900: 4901: 4902: 4903: 4904: 4905: 4906: 4907: 4908: 4909: 4910: 4911:
4912: public function copyRemote($remoteFile, $localFile, $curl) {
4913: $this->checkRemoteMethods();
4914: if (!$curl) {
4915: $context = stream_context_create(array(
4916: 'http' => array(
4917: 'timeout' => 15
4918: )));
4919: return copy($remoteFile, $localFile, $context) !== false;
4920: } else {
4921:
4922: $ch = curl_init($remoteFile);
4923: $curlopt = array(
4924: CURLOPT_RETURNTRANSFER => 1,
4925: CURLOPT_RETURNTRANSFER => 1,
4926: CURLOPT_BINARYTRANSFER => 1,
4927: CURLOPT_POST => 0,
4928: CURLOPT_TIMEOUT => 15
4929: );
4930: curl_setopt_array($ch, $curlopt);
4931: $contents = curl_exec($ch);
4932: if ((bool) $contents) {
4933: return file_put_contents($localFile, $contents) !== false;
4934: } else
4935: return false;
4936: }
4937: }
4938:
4939: 4940: 4941: 4942: 4943: 4944:
4945: public function getNoRemoteAccess() {
4946: if (!isset($this->_noRemoteAccess))
4947: $this->_noRemoteAccess = !extension_loaded('curl') && (
4948: in_array(ini_get('allow_url_fopen'), array(0, 'Off', 'off')) || !(function_exists('file_get_contents') && function_exists('copy'))
4949: );
4950: return $this->_noRemoteAccess;
4951: }
4952:
4953: 4954: 4955:
4956: public function checkRemoteMethods() {
4957: if ($this->noRemoteAccess)
4958: $this->error500(Yii::t('admin', 'X2Engine needs to retrieve one or more remote files, but no remote access methods are available on this web server, because allow_url_fopen is disabled and the CURL extension is missing.'));
4959: }
4960:
4961: 4962: 4963: 4964: 4965: 4966: 4967: 4968:
4969: public function error500($message) {
4970: $app = Yii::app();
4971: $email = Yii::app()->params->adminEmail;
4972: $inAction = $this->action instanceof CAction;
4973: if ($app->params->hasProperty('admin')) {
4974: if ($app->params->admin->hasProperty('emailFromAddr'))
4975: $email = $app->params->admin->emailFromAddr;
4976: } else if ($app->hasProperty('settings')) {
4977: if ($app->settings->hasProperty('emailFromAddr')) {
4978: $email = $app->settings->emailFromAddr;
4979: }
4980: }
4981: $inAction = @is_subclass_of($this->action, 'CAction');
4982: if ($inAction) {
4983: $data = array(
4984: 'scenario' => 'error',
4985: 'message' => Yii::t('admin', "Cannot run {action}.", array('{action}' => $this->action->id)),
4986: 'longMessage' => str_replace("\n", "<br />", $message),
4987: );
4988: $this->render('updater', $data);
4989: Yii::app()->end();
4990: } else {
4991: $data = array(
4992: 'time' => time(),
4993: 'admin' => $email,
4994: 'version' => Yii::getVersion(),
4995: 'message' => $message
4996: );
4997: header("HTTP/1.1 500 Internal Server Error");
4998: $this->renderPartial('system.views.error500', array('data' => $data));
4999: }
5000: Yii::app()->end();
5001: }
5002:
5003: 5004: 5005:
5006: public function actionChangeApplicationName() {
5007: $model = Admin::model()->findByPk(1);
5008: if (isset($_POST['Admin'])) {
5009: $model->setAttributes($_POST['Admin']);
5010: if ($model->save()) {
5011: $this->redirect('index');
5012: }
5013: }
5014: $this->render('changeApplicationName', array(
5015: 'model' => $model
5016: ));
5017: }
5018:
5019:
5020:
5021: 5022: 5023: 5024: 5025: 5026: 5027:
5028: public function actionGetAttributes() {
5029: $data = array();
5030: $type = null;
5031:
5032: if (isset($_POST['Criteria']['modelType']))
5033: $type = ucfirst($_POST['Criteria']['modelType']);
5034: if (isset($_POST['Fields']['modelName']))
5035: $type = $_POST['Fields']['modelName'];
5036:
5037: if (isset($type)) {
5038: if ($type == 'Marketing')
5039: $type = 'Campaign';
5040: elseif ($type == 'Quotes')
5041: $type = 'Quote';
5042: elseif ($type == 'Products')
5043: $type = 'Product';
5044: elseif ($type == 'Opportunities')
5045: $type = 'Opportunity';
5046:
5047: foreach (X2Model::model('Fields')->findAllByAttributes(array('modelName' => $type)) as $field) {
5048: if ($field->fieldName != 'id') {
5049: if (isset($_POST['Criteria']))
5050: $data[$field->fieldName] = $field->attributeLabel;
5051: else
5052: $data[$field->id] = $field->attributeLabel;
5053: }
5054: }
5055: }
5056: asort($data);
5057: $data = array('' => '-') + $data;
5058: $htmlOptions = array();
5059: echo CHtml::listOptions('', $data, $htmlOptions);
5060: }
5061:
5062:
5063:
5064: 5065: 5066:
5067: public function actionConvertEmailTemplates(){
5068: $status = null;
5069: if(isset($_POST['yt0'])){
5070: $docs = Docs::model()->findAllByAttributes(array('type'=>'email'));
5071: $converted = 0;
5072: foreach($docs as $doc){
5073: $changed = false;
5074: preg_match_all('|<img(.*?)src="(.*?)"(.*?)/?>|ism', $doc->text, $matches);
5075: $serverBasePath = Yii::app()->request->getServerName().Yii::app()->baseUrl;
5076: foreach($matches[2] as $filePath){
5077: if(strpos($filePath, $serverBasePath) !== false) {
5078: $uploadPath = str_replace($serverBasePath,'',$filePath);
5079: $pieces = explode('/',$uploadPath);
5080: $fileName = $pieces[sizeof($pieces)-1];
5081: $mediaObj = Media::model()->findByAttributes(array('fileName'=>$fileName));
5082: if(isset($mediaObj)){
5083: $doc->text = preg_replace('|<img(.*?)src="'.preg_quote($filePath).'"(.*?)/?>|ism','<img\1src="'.$mediaObj->getPublicUrl().'"\2/>',$doc->text);
5084: $changed = true;
5085: }
5086: }
5087: }
5088: if($changed){
5089: $doc->save();
5090: $converted++;
5091: }
5092: }
5093: $status = $converted;
5094: }
5095: $this->render('convertEmailTemplates',array(
5096: 'status'=>$status,
5097: ));
5098: }
5099:
5100:
5101:
5102:
5103: }
5104: