BxAccntGridAdministration.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup Accounts Accounts
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. class BxAccntGridAdministration extends BxBaseModProfileGridAdministration
  12. {
  13. protected $_sFilter2Name;
  14. protected $_sFilter2Value;
  15. protected $_aFilter2Values;
  16. public function __construct ($aOptions, $oTemplate = false)
  17. {
  18. $this->MODULE = 'bx_accounts';
  19. parent::__construct ($aOptions, $oTemplate);
  20. $CNF = &$this->_oModule->_oConfig->CNF;
  21. $this->_aFilter1Values = array_merge($this->_aFilter1Values, array(
  22. 'unconfirmed' => $CNF['T']['filter_item_unconfirmed'],
  23. 'locked' => $CNF['T']['filter_item_locked'],
  24. ));
  25. $this->_sFilter2Name = 'filter2';
  26. $this->_aFilter2Values = array(
  27. 'operators' => $CNF['T']['filter_item_operators']
  28. );
  29. $sFilter2 = bx_get($this->_sFilter2Name);
  30. if(!empty($sFilter2)) {
  31. $this->_sFilter2Value = bx_process_input($sFilter2);
  32. $this->_aQueryAppend[$this->_sFilter2Name] = $this->_sFilter2Value;
  33. }
  34. }
  35. protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
  36. {
  37. if(strpos($sFilter, $this->_sParamsDivider) !== false)
  38. list($this->_sFilter1Value, $this->_sFilter2Value, $sFilter) = explode($this->_sParamsDivider, $sFilter);
  39. if(!empty($this->_sFilter1Value))
  40. switch($this->_sFilter1Value) {
  41. case 'unconfirmed':
  42. $sCnfnType = getParam('sys_account_confirmation_type');
  43. switch($sCnfnType) {
  44. case 'email':
  45. $this->_aOptions['source'] .= " AND `ta`.`email_confirmed`='0'";
  46. break;
  47. case 'phone':
  48. $this->_aOptions['source'] .= " AND `ta`.`phone_confirmed`='0'";
  49. break;
  50. case 'email_and_phone':
  51. $this->_aOptions['source'] .= " AND (`ta`.`email_confirmed`='0' OR `ta`.`phone_confirmed`='0')";
  52. break;
  53. }
  54. break;
  55. case 'locked':
  56. $this->_aOptions['source'] .= " AND `ta`.`locked` = 1";
  57. break;
  58. default:
  59. $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `tp`.`status`=?", $this->_sFilter1Value);
  60. }
  61. if(!empty($this->_sFilter2Value))
  62. $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `ta`.`role` & " . BX_DOL_ROLE_ADMIN ." = " . BX_DOL_ROLE_ADMIN);
  63. return parent::_getDataSqlInner($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
  64. }
  65. protected function _getFilterControls()
  66. {
  67. parent::_getFilterControls();
  68. return $this->_getFilterSelectOne($this->_sFilter1Name, $this->_sFilter1Value, $this->_aFilter1Values) . $this->_getFilterSelectOne($this->_sFilter2Name, $this->_sFilter2Value, $this->_aFilter2Values) . $this->_getSearchInput();
  69. }
  70. public function getCode($isDisplayHeader = true)
  71. {
  72. return $this->_oModule->_oTemplate->getJsCode('main', array(
  73. 'aHtmlIds' => $this->_oModule->_oConfig->getHtmlIds()
  74. )) . parent::getCode($isDisplayHeader);
  75. }
  76. public function performActionActivate()
  77. {
  78. $this->_performActionEnable(true);
  79. }
  80. public function performActionSuspend()
  81. {
  82. $this->_performActionEnable(false);
  83. }
  84. public function performActionEditEmail()
  85. {
  86. $CNF = &$this->_oModule->_oConfig->CNF;
  87. $aIds = bx_get('ids');
  88. if(!$aIds || !is_array($aIds)) {
  89. $iId = (int)bx_get('id');
  90. if(!$iId)
  91. return echoJson(array());
  92. $aIds = array($iId);
  93. }
  94. $iId = $aIds[0];
  95. $oAccount = BxDolAccount::getInstance($iId);
  96. if(!$oAccount)
  97. return echoJson(array());
  98. $aAccount = $oAccount->getInfo();
  99. $sAction = 'edit_email';
  100. $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_ACCOUNT'], $CNF['OBJECT_FORM_ACCOUNT_DISPLAY_SETTINGS_EMAIL']);
  101. $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . 'grid.php?o=' . $this->_sObject . '&a=' . $sAction . '&id=' . $iId;
  102. $oForm->initChecker($aAccount);
  103. if($oForm->isSubmittedAndValid()) {
  104. $sEmail = $oForm->getCleanValue('email');
  105. if(strcmp($aAccount['email'], $sEmail) !== 0 && BxDolAccountQuery::getInstance()->getIdByEmail($sEmail))
  106. return echoJson(array('msg' => _t('_sys_form_account_input_email_uniq_error_loggedin')));
  107. if($oForm->update($aAccount['id'])) {
  108. bx_alert('account', 'edited', $aAccount['id'], BxDolAccount::getInstance()->id(), array('display' => $CNF['OBJECT_FORM_ACCOUNT_DISPLAY_SETTINGS_EMAIL']));
  109. $aRes = array('grid' => $this->getCode(false), 'blink' => $iId);
  110. $oAccount->doAudit($iId, '_sys_audit_action_account_email_changed', array('old_email' => $oAccount->getEmail(), 'new_email' => $sEmail));
  111. }
  112. else
  113. $aRes = array('msg' => _t('_sys_txt_error_account_update'));
  114. echoJson($aRes);
  115. }
  116. else {
  117. $sContent = BxTemplStudioFunctions::getInstance()->popupBox('bx-account-edit-email-popup', _t('_bx_accounts_form_display_account_settings_email_popup'), $this->_oModule->_oTemplate->parseHtmlByName('edit_email.html', array(
  118. 'form_id' => $oForm->id,
  119. 'form' => $oForm->getCode(true),
  120. 'object' => $this->_sObject,
  121. 'action' => $sAction
  122. )));
  123. echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false))));
  124. }
  125. }
  126. public function performActionAdd()
  127. {
  128. $CNF = &$this->_oModule->_oConfig->CNF;
  129. $sAction = 'add';
  130. $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_ACCOUNT'], $CNF['OBJECT_FORM_ACCOUNT_DISPLAY_CREATE']);
  131. $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . 'grid.php?o=' . $this->_sObject . '&a=' . $sAction;
  132. $oForm->initChecker();
  133. if($oForm->isSubmittedAndValid()) {
  134. $iAccountId = $oForm->insert();
  135. if (!$iAccountId) {
  136. $aRes = array('msg' => _t('_sys_txt_error_account_insert'));
  137. }
  138. else{
  139. $aRes = array('grid' => $this->getCode(false), 'blink' => $iAccountId);
  140. $oBxTemplAccountForms = new BxTemplAccountForms();
  141. $iProfileId = $oBxTemplAccountForms->onAccountCreated($iAccountId, $oForm->isSetPendingApproval(), BX_PROFILE_ACTION_MANUAL, false);
  142. // perform action
  143. BxDolAccount::isAllowedCreate ($iProfileId, true);
  144. // check
  145. $aModulesProfile = array();
  146. $aModules = BxDolModuleQuery::getInstance()->getModulesBy(array('type' => 'modules', 'active' => 1));
  147. foreach($aModules as $aModule) {
  148. $oModule = BxDolModule::getInstance($aModule['name']);
  149. if($oModule instanceof iBxDolProfileService && BxDolService::call($aModule['name'], 'act_as_profile') === true)
  150. $aModulesProfile[] = $aModule;
  151. }
  152. $sDefaultProfileType = getParam('sys_account_default_profile_type');
  153. if(count($aModulesProfile) == 1)
  154. $sProfileModule = $aModulesProfile[0]['name'];
  155. else if(!empty($sDefaultProfileType))
  156. $sProfileModule = $sDefaultProfileType;
  157. if (getParam('sys_account_auto_profile_creation') && !empty($sProfileModule)) {
  158. $oAccount = BxDolAccount::getInstance($iAccountId);
  159. $aProfileInfo = BxDolService::call($sProfileModule, 'prepare_fields', array(array(
  160. 'author' => $iProfileId,
  161. 'name' => $oAccount->getDisplayName(),
  162. )));
  163. $a = BxDolService::call($sProfileModule, 'entity_add', array($iProfileId, $aProfileInfo));
  164. if (isset($a['content']['profile_id']) && (int)$a['content']['profile_id'] > 0){
  165. BxDolAcl::getInstance()->setMembership((int)$a['content']['profile_id'], MEMBERSHIP_ID_STANDARD);
  166. }
  167. echoJson($aRes);
  168. }
  169. }
  170. }
  171. else {
  172. $sContent = BxTemplStudioFunctions::getInstance()->popupBox('bx-account-edit-email-popup', _t('_bx_accounts_form_display_account_create_popup'), $this->_oModule->_oTemplate->parseHtmlByName('create.html', array(
  173. 'form_id' => $oForm->id,
  174. 'form' => $oForm->getCode(true),
  175. 'object' => $this->_sObject,
  176. 'action' => $sAction
  177. )));
  178. echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false))));
  179. }
  180. }
  181. public function performActionConfirm()
  182. {
  183. $CNF = &$this->_oModule->_oConfig->CNF;
  184. $aIds = bx_get('ids');
  185. if(!$aIds || !is_array($aIds))
  186. return echoJson(array());
  187. $oAccount = BxDolAccount::getInstance();
  188. $iAffected = 0;
  189. $aIdsAffected = array();
  190. foreach($aIds as $iId){
  191. if (BxDolAccount::isNeedConfirmEmail()) {
  192. if($oAccount->updateEmailConfirmed(true, true, $iId)) {
  193. $aIdsAffected[] = $iId;
  194. $iAffected++;
  195. }
  196. }
  197. if (BxDolAccount::isNeedConfirmPhone()){
  198. if($oAccount->updatePhoneConfirmed(true, $iId)) {
  199. $aIdsAffected[] = $iId;
  200. $iAffected++;
  201. }
  202. }
  203. }
  204. echoJson($iAffected ? array('grid' => $this->getCode(false), 'blink' => $aIdsAffected) : array('msg' => _t($CNF['T']['grid_action_err_perform'])));
  205. }
  206. public function performActionResendCemail()
  207. {
  208. $CNF = &$this->_oModule->_oConfig->CNF;
  209. $aIds = bx_get('ids');
  210. if(!$aIds || !is_array($aIds))
  211. return echoJson(array());
  212. $oAccount = BxDolAccount::getInstance();
  213. $iAffected = 0;
  214. $aIdsAffected = array();
  215. foreach($aIds as $iId)
  216. if($oAccount->sendConfirmationEmail($iId)) {
  217. $aIdsAffected[] = $iId;
  218. $iAffected++;
  219. }
  220. echoJson($iAffected ? array('grid' => $this->getCode(false), 'blink' => $aIdsAffected) : array('msg' => _t($CNF['T']['grid_action_err_perform'])));
  221. }
  222. public function performActionResetPassword()
  223. {
  224. $aIds = bx_get('ids');
  225. if(!$aIds || !is_array($aIds))
  226. return echoJson(array());
  227. $iId = $aIds[0];
  228. $oAccount = BxDolAccount::getInstance($iId);
  229. if(!$oAccount)
  230. return echoJson(array());
  231. $aRes = array();
  232. $sPwd = genRndPwd();
  233. if (BxDolAccount::getInstance()->updatePassword($sPwd, $iId)){
  234. $sPopupId = $this->_oModule->_oConfig->getHtmlIds('password_popup');
  235. $sPopupTitle = _t('_bx_accounts_form_display_account_settings_password_popup');
  236. $sPopupContent = $this->_oModule->_oTemplate->parseHtmlByName('reset_password.html', array(
  237. 'js_object' => $this->_oModule->_oConfig->getJsObject('main'),
  238. 'html_id_text' => $this->_oModule->_oConfig->getHtmlIds('password_text'),
  239. 'html_id_button' => $this->_oModule->_oConfig->getHtmlIds('password_button'),
  240. 'password' => $sPwd,
  241. ));
  242. $aRes = array('popup' => BxTemplStudioFunctions::getInstance()->popupBox($sPopupId, $sPopupTitle, $sPopupContent));
  243. }
  244. else
  245. $aRes = array('msg' => _t('_bx_accnt_grid_action_err_perform'));
  246. return echoJson($aRes);
  247. }
  248. public function performActionResendRemail()
  249. {
  250. $CNF = &$this->_oModule->_oConfig->CNF;
  251. $aIds = bx_get('ids');
  252. if(!$aIds || !is_array($aIds))
  253. return echoJson(array());
  254. $oAccount = BxDolAccount::getInstance();
  255. $iAffected = 0;
  256. $aIdsAffected = array();
  257. foreach($aIds as $iId)
  258. if($oAccount->sendResetPasswordEmail($iId)) {
  259. $aIdsAffected[] = $iId;
  260. $iAffected++;
  261. }
  262. echoJson($iAffected ? array('grid' => $this->getCode(false), 'blink' => $aIdsAffected) : array('msg' => _t($CNF['T']['grid_action_err_perform'])));
  263. }
  264. public function performActionUnlockAccount()
  265. {
  266. $aIds = bx_get('ids');
  267. if(!$aIds || !is_array($aIds)) {
  268. echoJson(array());
  269. return;
  270. }
  271. $oAccountQuery = BxDolAccountQuery::getInstance();
  272. foreach($aIds as $iId) {
  273. $oAccount = BxDolAccount::getInstance($iId);
  274. if(!$oAccount)
  275. continue;
  276. if ($oAccount->isLocked()){
  277. $oAccountQuery->unlockAccount($iId);
  278. }
  279. $oAccount->doAudit($iId, '_sys_audit_action_account_unlock');
  280. }
  281. return echoJson(array('grid' => $this->getCode(false), 'blink' => $aIds));
  282. }
  283. public function performActionSetOperatorRole()
  284. {
  285. $aIds = bx_get('ids');
  286. if(!$aIds || !is_array($aIds))
  287. return echoJson(array());
  288. $oUtils = BxDolStudioRolesUtils::getInstance();
  289. $aRoles = $oUtils->getRoles();
  290. if(empty($aRoles) || !is_array($aRoles))
  291. return echoJson(array('msg' => _t('_sys_txt_error_occured')));
  292. $iId = (int)array_shift($aIds);
  293. $sPopupName = str_replace('_', '-', $this->MODULE) . '-set-role-popup';
  294. $sPopupContent = $this->_oModule->_oTemplate->getPopupSetRole($aRoles, $iId, $oUtils->getRole($iId));
  295. return echoJson(array('popup' => array(
  296. 'html' => BxTemplFunctions::getInstance()->transBox($sPopupName, $sPopupContent),
  297. 'options' => array(
  298. 'closeOnOuterClick' => true,
  299. 'removeOnClose' => true
  300. )
  301. )));
  302. }
  303. public function performActionSetOperatorRoleSubmit()
  304. {
  305. $aIds = bx_get('ids');
  306. if(!$aIds || !is_array($aIds))
  307. return echoJson(array());
  308. $iId = (int)array_shift($aIds);
  309. if(!$iId)
  310. return echoJson(array('msg' => _t('_sys_txt_error_occured')));
  311. if(!BxDolStudioRolesUtils::getInstance()->setRole($iId, bx_process_input(bx_get('role'), BX_DATA_INT)))
  312. return echoJson(array('msg' => _t('_error occured')));
  313. echoJson(array('grid' => $this->getCode(false), 'blink' => $iId));
  314. }
  315. public function performActionMakeOperator()
  316. {
  317. $this->_performActionChangeRole(3);
  318. }
  319. public function performActionUnmakeOperator()
  320. {
  321. $this->_performActionChangeRole(1);
  322. }
  323. protected function _performActionChangeRole($iRole)
  324. {
  325. $CNF = &$this->_oModule->_oConfig->CNF;
  326. $aIds = bx_get('ids');
  327. if(!$aIds || !is_array($aIds))
  328. return echoJson(array());
  329. $oAccount = BxDolAccount::getInstance();
  330. $oUtils = BxDolStudioRolesUtils::getInstance();
  331. $iAffected = 0;
  332. $aIdsAffected = array();
  333. foreach($aIds as $iId) {
  334. if(!$this->_oModule->_oDb->updateAccount(array('role' => $iRole), array('id' => $iId)))
  335. continue;
  336. $oUtils->setRole($iId, $iRole == 3 ? BX_DOL_STUDIO_ROLE_OPERATOR : 0);
  337. $oAccount->doAudit($iId, '_sys_audit_action_account_change_role_to_' . $iRole);
  338. $aIdsAffected[] = $iId;
  339. $iAffected++;
  340. }
  341. echoJson($iAffected ? array('grid' => $this->getCode(false), 'blink' => $aIdsAffected) : array('msg' => _t($CNF['T']['grid_action_err_perform'])));
  342. }
  343. protected function _performActionEnable($isChecked)
  344. {
  345. $CNF = &$this->_oModule->_oConfig->CNF;
  346. $aIds = bx_get('ids');
  347. if(!$aIds || !is_array($aIds)) {
  348. echoJson(array());
  349. return;
  350. }
  351. $iAffected = 0;
  352. $aIdsAffected = array();
  353. foreach($aIds as $iId)
  354. if($this->_enable($iId, $isChecked)) {
  355. $aIdsAffected[] = $iId;
  356. $iAffected++;
  357. $oAccount = BxDolAccount::getInstance($iId);
  358. $oAccount->doAudit($iId, '_sys_audit_action_account_' . $isChecked ? 'activated' : 'suspended');
  359. }
  360. echoJson($iAffected ? array('grid' => $this->getCode(false), 'blink' => $aIdsAffected) : array('msg' => _t($CNF['T']['grid_action_err_perform'])));
  361. }
  362. protected function _enable($mixedId, $isChecked)
  363. {
  364. $oProfile = BxDolProfile::getInstanceAccountProfile($mixedId);
  365. if(!$oProfile)
  366. return false;
  367. $iAction = BX_PROFILE_ACTION_MANUAL;
  368. $sMethod = $isChecked ? 'activate' : 'suspend';
  369. if(!$oProfile->$sMethod($iAction, 0 ,false))
  370. return false;
  371. sendMailTemplate('t_ChangeStatusAccount' . ucfirst($sMethod), $oProfile->getAccountObject()->id(), $oProfile->id(), array(), BX_EMAIL_SYSTEM);
  372. $aProfiles = $oProfile->getAccountObject()->getProfiles();
  373. foreach($aProfiles as $aProfile){
  374. BxDolProfile::getInstance($aProfile['id'])->$sMethod($iAction, 0 ,false);
  375. }
  376. return true;
  377. }
  378. //--- Layout methods ---//
  379. protected function _getActionEditEmail($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
  380. {
  381. return '';
  382. }
  383. protected function _getCellEmailConfirmed($mixedValue, $sKey, $aField, $aRow)
  384. {
  385. $mixedValue = (int)$mixedValue == 1 ? '_Yes' : '_No';
  386. return parent::_getCellDefault(_t($mixedValue), $sKey, $aField, $aRow);
  387. }
  388. protected function _getActionResetPassword($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
  389. {
  390. return '';
  391. }
  392. protected function _getActionResendRemail($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
  393. {
  394. if($sType == 'single')
  395. return '';
  396. return parent::_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
  397. }
  398. protected function _getActionUnlockAccount($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
  399. {
  400. return '';
  401. }
  402. protected function _getCellName($mixedValue, $sKey, $aField, $aRow)
  403. {
  404. $oAccount = BxDolAccount::getInstance($aRow['id']);
  405. if ($oAccount)
  406. $s = ($aRow['locked'] == 1 ? $this->_oTemplate->parseIcon("lock col-red1") . ' ' : '') . $oAccount->getDisplayName();
  407. return parent::_getCellDefault ($s, $sKey, $aField, $aRow);
  408. }
  409. protected function _getCellProfiles($mixedValue, $sKey, $aField, $aRow)
  410. {
  411. $s = $this->_oModule->_oTemplate->getProfilesByAccount($aRow);
  412. return parent::_getCellDefault ($s, $sKey, $aField, $aRow);
  413. }
  414. protected function _getCellLogged($mixedValue, $sKey, $aField, $aRow)
  415. {
  416. $mixedValue = !empty($mixedValue) ? bx_time_js($mixedValue) : _t('_sys_not_available');
  417. return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
  418. }
  419. protected function _getCellAdded($mixedValue, $sKey, $aField, $aRow)
  420. {
  421. $mixedValue = !empty($mixedValue) ? bx_time_js($mixedValue) : _t('_sys_not_available');
  422. return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
  423. }
  424. protected function _getCellIsConfirmed($mixedValue, $sKey, $aField, $aRow)
  425. {
  426. $oAccount = BxDolAccount::getInstance($aRow['id']);
  427. $s = "";
  428. if ($oAccount)
  429. $s = $oAccount->getCurrentConfirmationStatusValue();
  430. return parent::_getCellDefault(_t('_bx_accnt_grid_confirmation_status_' . $s), $sKey, $aField, $aRow);
  431. }
  432. protected function _isCheckboxDisabled($aRow)
  433. {
  434. return false;
  435. }
  436. protected function _getContentInfo($iId)
  437. {
  438. return BxDolAccountQuery::getInstance()->getInfoById($iId);
  439. }
  440. protected function _doDelete($iId, $aParams = array())
  441. {
  442. return BxDolAccount::getInstance($iId)->delete(isset($aParams['with_content']) && $aParams['with_content'] === true);
  443. }
  444. protected function _addJsCss()
  445. {
  446. parent::_addJsCss();
  447. $this->_oTemplate->addJs(array(
  448. 'main.css'
  449. ));
  450. $this->_oTemplate->addJs(array(
  451. 'jquery.form.min.js',
  452. 'clipboard.min.js',
  453. 'main.js'
  454. ));
  455. }
  456. protected function _isVisibleGrid($a)
  457. {
  458. if(isAdmin())
  459. return true;
  460. return parent::_isVisibleGrid($a);
  461. }
  462. }
  463. /** @} */