Msgs.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. <?php
  2. Lib::loadClass('RouteBase');
  3. /*
  4. ## Flash message system:
  5. System for automatic and custom messages for users.
  6. - `app_className` - for automatic msgs to search for msg text
  7. - `msg` - msg to show or to parse by `app_className`
  8. - `uiTargetType` - where to show this msg eg. 'default_db_table', 'after_login', 'everywhere'
  9. - `uiTargetName` - eg. database table name (if from default_db)
  10. - `userTargetType` - type of users allowed to see this msg eg. 'everyone', 'admin' (ADMIN_LEVEL=0?), 'user', 'group'
  11. - `userTargetName` - login, group name
  12. - `actionExecuted` - execution time if msg require user to run specific action (send msg.id in request)
  13. - `actionNotes` - notes/msgs/dbg for user actions executed from this msg
  14. Messages created by db triggers must define `app_className` that should parse `msg`. For example to use in FixProjectPath and FixZasobPath to keep correct paths.
  15. */
  16. class Route_Msgs extends RouteBase {
  17. public function handleAuth() {
  18. if (!User::logged()) {
  19. throw new HttpException('Unauthorized', 401);
  20. }
  21. }
  22. public function defaultAction() {
  23. SE_Layout::gora();
  24. ?>
  25. <div class="container">
  26. <h1>Messages system</h1>
  27. ...
  28. </div>
  29. <?php
  30. SE_Layout::dol();
  31. }
  32. public function reinstallAction() {
  33. $this->reinstall();
  34. die('OK');
  35. }
  36. public function reinstallFunctionsAction() {
  37. $this->reinstallFunctions();
  38. die('OK');
  39. }
  40. public function runAction() {
  41. $msgId = V::get('_msgId', 0, $_REQUEST, 'int');
  42. if ($msgId > 0) {
  43. $this->runByMessageId($msgId);
  44. }
  45. $jsonData = new stdClass();
  46. $jsonData->type = 'success';
  47. $jsonData->msg = 'Gotowe';
  48. echo json_encode($jsonData);
  49. exit;
  50. }
  51. public function addTestMsgAction() {
  52. $sql = "INSERT INTO `CRM_UI_MSGS` (`ID`, `app_className`, `msg`, `msgType`, `uiTargetType`, `uiTargetName`, `userTargetType`, `userTargetName`, `actionExecutedTime`, `actionNotes`, `A_RECORD_CREATE_DATE`, `A_RECORD_CREATE_AUTHOR`, `A_RECORD_UPDATE_DATE`, `A_RECORD_UPDATE_AUTHOR`)
  53. VALUES (NULL, 'FixZasobPath', 'Update all paths', 'danger', 'default_db_table', 'CRM_LISTA_ZASOBOW', 'user', 'plabudda', NULL, '', NULL, 'plabudda', NULL, '')";
  54. $db = DB::getDB();
  55. $db->query($sql);
  56. die('OK');
  57. }
  58. public function reinstallFunctions() {
  59. $sqlList = array();
  60. $sqlList['RemoveProcedureMarkAsExecuted'] = "DROP PROCEDURE IF EXISTS `CRM_UI_MSGS__markAsExecuted`";
  61. $sqlList['InstallProcedureMarkAsExecuted'] = <<<SQL_QUERY
  62. CREATE DEFINER=`root`@`localhost` PROCEDURE `CRM_UI_MSGS__markAsExecuted`(
  63. IN author VARCHAR(40),
  64. IN app_className VARCHAR(255),
  65. IN msg VARCHAR(255),
  66. IN uiTargetType VARCHAR(255),
  67. IN uiTargetName VARCHAR(255),
  68. IN userTargetType VARCHAR(255),
  69. IN userTargetName VARCHAR(255)
  70. )
  71. BEGIN
  72. update `CRM_UI_MSGS`
  73. set `A_STATUS`='OFF_HARD'
  74. , `actionExecutedTime`=NOW()
  75. , `A_RECORD_UPDATE_DATE`=NOW()
  76. , `A_RECORD_UPDATE_AUTHOR`=author
  77. where `A_STATUS`='WAITING' -- TODO: not in('DELETED', 'OFF_HARD')
  78. and `app_className`=app_className
  79. and `msg`=msg
  80. and `uiTargetType`=uiTargetType
  81. and `uiTargetName`=uiTargetName
  82. and `userTargetType`=userTargetType
  83. and `userTargetName`=userTargetName
  84. ;
  85. END
  86. SQL_QUERY;
  87. $sqlList['RemoveProcedureMarkTableEveryoneAsExecuted'] = "DROP PROCEDURE IF EXISTS `CRM_UI_MSGS__markTableEveryoneAsExecuted`";
  88. $sqlList['InstallProcedureMarkTableEveryoneAsExecuted'] = <<<SQL_QUERY
  89. CREATE DEFINER=`root`@`localhost` PROCEDURE `CRM_UI_MSGS__markTableEveryoneAsExecuted`(
  90. IN author VARCHAR(40),
  91. IN app_className VARCHAR(255),
  92. IN msg VARCHAR(255),
  93. IN uiTargetName VARCHAR(255)
  94. )
  95. BEGIN
  96. CALL CRM_UI_MSGS__markAsExecuted(author, app_className, msg, 'default_db_table', uiTargetName, 'everyone', '');
  97. END
  98. SQL_QUERY;
  99. $sqlList['RemoveProcedureAddUniqueMsg'] = "DROP PROCEDURE IF EXISTS `CRM_UI_MSGS__addUniqueMsg`";
  100. $sqlList['InstallProcedureAddUniqueMsg'] = <<<SQL_QUERY
  101. CREATE DEFINER=`root`@`localhost` PROCEDURE `CRM_UI_MSGS__addUniqueMsg`(
  102. IN author VARCHAR(40),
  103. IN app_className VARCHAR(255),
  104. IN msgType VARCHAR(16),
  105. IN msg VARCHAR(255),
  106. IN uiTargetType VARCHAR(255),
  107. IN uiTargetName VARCHAR(255),
  108. IN userTargetType VARCHAR(255),
  109. IN userTargetName VARCHAR(255)
  110. )
  111. BEGIN
  112. IF (select count(1)
  113. from `CRM_UI_MSGS`
  114. where `app_className`=app_className
  115. and `msg`=msg
  116. and `uiTargetType`=uiTargetType
  117. and `uiTargetName`=uiTargetName
  118. and `userTargetType`=userTargetType
  119. and `userTargetName`=userTargetName
  120. and `A_STATUS`='WAITING'
  121. ) = 0 THEN
  122. INSERT INTO `CRM_UI_MSGS` (`ID`
  123. , `app_className`, `msg`, `msgType`
  124. , `uiTargetType`, `uiTargetName`
  125. , `userTargetType`, `userTargetName`
  126. , `A_RECORD_CREATE_DATE`, `A_RECORD_CREATE_AUTHOR`)
  127. VALUES (NULL
  128. , app_className, msg, msgType
  129. , uiTargetType, uiTargetName
  130. , userTargetType, userTargetName
  131. , NOW(), author
  132. );
  133. END IF;
  134. END
  135. SQL_QUERY;
  136. $sqlList['RemoveProcedureAddTableEveryoneUniqueMsg'] = "DROP PROCEDURE IF EXISTS `CRM_UI_MSGS__addTableEveryoneUniqueMsg`";
  137. $sqlList['InstallProcedureAddTableEveryoneUniqueMsg'] = <<<SQL_QUERY
  138. CREATE DEFINER=`root`@`localhost` PROCEDURE `CRM_UI_MSGS__addTableEveryoneUniqueMsg`(
  139. IN author VARCHAR(40),
  140. IN app_className VARCHAR(255),
  141. IN msgType VARCHAR(16),
  142. IN msg VARCHAR(255),
  143. IN uiTargetName VARCHAR(255)
  144. )
  145. BEGIN
  146. CALL CRM_UI_MSGS__addUniqueMsg(author, app_className, msgType, msg, 'default_db_table', uiTargetName, 'everyone', '');
  147. END
  148. SQL_QUERY;
  149. $formFixCrmProcesIdx = <<<SQL_QUERY
  150. CALL CRM_UI_MSGS__addUniqueMsg(coalesce(NEW.A_RECORD_UPDATE_AUTHOR,':AFTER_INSERT'), 'FixCrmProcesInitIdx', 'danger', 'Update perms', 'default_db_table', 'CRM_PROCES', 'everyone');
  151. CALL CRM_UI_MSGS__addTableEveryoneUniqueMsg(coalesce(NEW.A_RECORD_CREATE_AUTHOR,':AFTER_INSERT'), 'FixCrmProcesInitIdx', 'danger', 'Update perms', 'CRM_PROCES');
  152. IF (select count(1) from `CRM_UI_MSGS` where `app_className`='FixCrmProcesInitIdx'
  153. and `msg`='Update perms'
  154. and `uiTargetType`='default_db_table'
  155. and `uiTargetName`='CRM_PROCES'
  156. and `A_STATUS`='WAITING'
  157. ) = 0 THEN
  158. INSERT INTO `CRM_UI_MSGS` (`ID`
  159. , `app_className`, `msg`, `msgType`
  160. , `uiTargetType`, `uiTargetName`
  161. , `userTargetType`
  162. , `A_RECORD_CREATE_DATE`, `A_RECORD_CREATE_AUTHOR`)
  163. VALUES (NULL
  164. , 'FixCrmProcesInitIdx', 'Update perms', 'danger'
  165. , 'default_db_table', 'CRM_PROCES'
  166. , 'everyone'
  167. , NOW(), coalesce(NEW.A_RECORD_CREATE_AUTHOR,'trigger:FixCrmProcesInitIdx_CRM_PROCES_AFTER_INSERT')
  168. );
  169. END IF;
  170. CALL CRM_UI_MSGS__addTableEveryoneUniqueMsg(coalesce(NEW.A_RECORD_UPDATE_AUTHOR,':AFTER_UPDATE'), 'FixCrmProcesInitIdx', 'danger', 'Update perms', 'CRM_PROCES');
  171. IF (select count(1) from `CRM_UI_MSGS` where `app_className`='FixCrmProcesInitIdx'
  172. and `msg`='Update perms'
  173. and `uiTargetType`='default_db_table'
  174. and `uiTargetName`='CRM_PROCES'
  175. and `A_STATUS`='WAITING'
  176. ) = 0 THEN
  177. INSERT INTO `CRM_UI_MSGS` (`ID`
  178. , `app_className`, `msg`, `msgType`
  179. , `uiTargetType`, `uiTargetName`
  180. , `userTargetType`
  181. , `A_RECORD_CREATE_DATE`, `A_RECORD_CREATE_AUTHOR`)
  182. VALUES (NULL
  183. , 'FixCrmProcesInitIdx', 'Update perms', 'danger'
  184. , 'default_db_table', 'CRM_PROCES'
  185. , 'everyone'
  186. , NOW(), coalesce(NEW.A_RECORD_UPDATE_AUTHOR,'trigger:FixCrmProcesInitIdx_CRM_PROCES_AFTER_UPDATE')
  187. );
  188. END IF;
  189. CALL CRM_UI_MSGS__addTableEveryoneUniqueMsg(coalesce(NEW.A_RECORD_CREATE_AUTHOR,':AFTER_INSERT_WSK'), 'FixCrmProcesInitIdx', 'danger', 'Update perms', 'CRM_PROCES');
  190. IF (select count(1) from `CRM_UI_MSGS` where `app_className`='FixCrmProcesInitIdx'
  191. and `msg`='Update perms'
  192. and `uiTargetType`='default_db_table'
  193. and `uiTargetName`='CRM_PROCES'
  194. and `A_STATUS`='WAITING'
  195. ) = 0 THEN
  196. INSERT INTO `CRM_UI_MSGS` (`ID`
  197. , `app_className`, `msg`, `msgType`
  198. , `uiTargetType`, `uiTargetName`
  199. , `userTargetType`
  200. , `A_RECORD_CREATE_DATE`, `A_RECORD_CREATE_AUTHOR`)
  201. VALUES (NULL
  202. , 'FixCrmProcesInitIdx', 'Update perms', 'danger'
  203. , 'default_db_table', 'CRM_PROCES'
  204. , 'everyone'
  205. , NOW(), coalesce(NEW.A_RECORD_CREATE_AUTHOR,'trigger:FixCrmProcesInitIdx_CRM_WSKAZNIK_AFTER_INSERT')
  206. );
  207. END IF;
  208. CALL CRM_UI_MSGS__addTableEveryoneUniqueMsg(coalesce(NEW.A_RECORD_UPDATE_AUTHOR,':AFTER_UPDATE_WSK'), 'FixCrmProcesInitIdx', 'danger', 'Update perms', 'CRM_PROCES');
  209. IF (select count(1) from `CRM_UI_MSGS` where `app_className`='FixCrmProcesInitIdx'
  210. and `msg`='Update perms'
  211. and `uiTargetType`='default_db_table'
  212. and `uiTargetName`='CRM_PROCES'
  213. and `A_STATUS`='WAITING'
  214. ) = 0 THEN
  215. INSERT INTO `CRM_UI_MSGS` (`ID`
  216. , `app_className`, `msg`, `msgType`
  217. , `uiTargetType`, `uiTargetName`
  218. , `userTargetType`
  219. , `A_RECORD_CREATE_DATE`, `A_RECORD_CREATE_AUTHOR`)
  220. VALUES (NULL
  221. , 'FixCrmProcesInitIdx', 'Update perms', 'danger'
  222. , 'default_db_table', 'CRM_PROCES'
  223. , 'everyone'
  224. , NOW(), coalesce(NEW.A_RECORD_UPDATE_AUTHOR,'trigger:FixCrmProcesInitIdx_CRM_WSKAZNIK_AFTER_UPDATE')
  225. );
  226. END IF;
  227. SQL_QUERY;
  228. $db = DB::getDB();
  229. if ($db->has_errors()) {
  230. throw new Exception("DB Errors: " . implode("\n<br>", $db->get_errors()));
  231. }
  232. foreach ($sqlList as $sqlName => $sql) {
  233. $res = $db->query($sql);
  234. if ($db->has_errors()) {
  235. throw new Exception("DB Errors at sql '{$sqlName}': " . implode("\n<br>", $db->get_errors()));
  236. }
  237. }
  238. }
  239. public function reinstall() {
  240. $sqlList = array();
  241. $sqlList['RemoveTable'] = "DROP TABLE IF EXISTS `CRM_UI_MSGS`";
  242. $sqlList['InstallTable'] = "
  243. CREATE TABLE IF NOT EXISTS `CRM_UI_MSGS` (
  244. `ID` int(11) NOT NULL AUTO_INCREMENT
  245. -- app_className - for automatic msgs to search for msg text
  246. , `app_className` varchar(255) DEFAULT NULL
  247. -- msg - msg to show or to parse by app_className
  248. , `msg` varchar(255) NOT NULL
  249. , `msgType` enum('info','danger','warning','success') NOT NULL DEFAULT 'info'
  250. -- uiTargetType - where to show this msg eg. 'default_db_table', 'after_login', 'everywhere'
  251. , `uiTargetType` varchar(255) NOT NULL DEFAULT ''
  252. -- uiTargetName - eg. database table name (if from default_db)
  253. , `uiTargetName` varchar(255) NOT NULL DEFAULT ''
  254. -- userTargetType - type of users allowed to see this msg eg. 'everyone', 'admin' (ADMIN_LEVEL=0?), 'user', 'group'
  255. , `userTargetType` enum('none','everyone','admin','user','group') NOT NULL DEFAULT 'none'
  256. -- userTargetName - login, group name
  257. , `userTargetName` varchar(255) NOT NULL DEFAULT ''
  258. -- actionExecutedTime - execution time if msg require user to run specific action (send msg.id in request)
  259. , `actionExecutedTime` datetime DEFAULT NULL
  260. -- actionNotes - notes/msgs/dbg for user actions executed from this msg
  261. , `actionNotes` varchar(255) NOT NULL DEFAULT ''
  262. , `A_STATUS` enum('WAITING','NORMAL','OFF_HARD','DELETED') NOT NULL DEFAULT 'WAITING'
  263. , `A_RECORD_CREATE_DATE` datetime DEFAULT NULL
  264. , `A_RECORD_CREATE_AUTHOR` varchar(40) NOT NULL DEFAULT ''
  265. , `A_RECORD_UPDATE_DATE` datetime DEFAULT NULL
  266. , `A_RECORD_UPDATE_AUTHOR` varchar(40) NOT NULL DEFAULT ''
  267. , PRIMARY KEY (`ID`)
  268. , KEY `app_className` (`app_className`)
  269. ) ENGINE=MyISAM DEFAULT CHARSET=latin2
  270. ";
  271. $db = DB::getDB();
  272. if ($db->has_errors()) {
  273. throw new Exception("DB Errors: " . implode("\n<br>", $db->get_errors()));
  274. }
  275. foreach ($sqlList as $sqlName => $sql) {
  276. $res = $db->query($sql);
  277. if ($db->has_errors()) {
  278. throw new Exception("DB Errors at sql '{$sqlName}': " . implode("\n<br>", $db->get_errors()));
  279. }
  280. }
  281. $this->reinstallFunctions();
  282. }
  283. public function getActiveMessagesForTable($tblName) {
  284. if (empty($tblName)) return;
  285. $db = DB::getDB();
  286. $tblName = $db->_($tblName);
  287. $usrLogin = User::getLogin();
  288. $msgs = null;
  289. $sql = "select m.*
  290. from `CRM_UI_MSGS` m
  291. where m.`uiTargetType`='default_db_table'
  292. and m.`A_STATUS`='WAITING'
  293. and m.`uiTargetName`='{$tblName}'
  294. and (m.`userTargetType` in('everyone')
  295. or (m.`userTargetType`='user' and m.`userTargetName`='{$usrLogin}')
  296. -- TODO: use 'admin', 'group'
  297. )
  298. ";
  299. $db = DB::getDB();
  300. $res = $db->query($sql);
  301. while ($r = $db->fetch($res)) {
  302. if ($msg = $this->parseMessage($r)) {
  303. $msg['link'] = 'index.php?_route=Msgs&_task=run&_msgId=' . $r->ID;
  304. $msg['linkType'] = 'ajax';
  305. $msgs[$r->ID] = $msg;
  306. }
  307. }
  308. return $msgs;
  309. }
  310. public function parseMessage($r) {
  311. $msg = null;// ['type'=>'info', 'message'=>'...']
  312. // $r->app_className - for automatic msgs to search for msg text
  313. // $r->msg - for automatic msgs to search for msg text
  314. // $r->msgType - 'info','danger','warning','success'
  315. if (!empty($r->app_className)) {
  316. $route = Router::getRoute($r->app_className);
  317. $msg = array();
  318. $msg['message'] = $route->parseMessageFromMsgsSystem($r->msg);
  319. $msg['type'] = $r->msgType;
  320. } else {
  321. $msg = array();
  322. $msg['message'] = $this->parseMessageFromMsgsSystem($r->msg);
  323. $msg['type'] = $r->msgType;
  324. }
  325. return $msg;
  326. }
  327. public function parseMessageFromMsgsSystem($msg) {
  328. return $msg;
  329. }
  330. public function runByMessageId($id) {
  331. $msgRow = $this->getActiveMessage($id);
  332. $execNotes = '';
  333. if (!empty($msgRow->app_className)) {
  334. $route = Router::getRoute($msgRow->app_className);
  335. $route->runByMessageFromMsgsSystem($msgRow->msg, $execNotes);
  336. }
  337. $this->forceFinishMessage($id, $execNotes);
  338. }
  339. public function getMessage($id) {
  340. if (empty($id)) return;
  341. $id = intval($id);
  342. if ($id <= 0) return;
  343. $msg = null;
  344. $sql = "select * from `CRM_UI_MSGS` where `ID`='{$id}' ";
  345. $db = DB::getDB();
  346. $res = $db->query($sql);
  347. if ($r = $db->fetch($res)) {
  348. $msg = $r;
  349. }
  350. return $msg;
  351. }
  352. public function getActiveMessage($id) {
  353. if (empty($id)) return;
  354. $id = intval($id);
  355. if ($id <= 0) return;
  356. $msg = null;
  357. $sql = "select m.*
  358. from `CRM_UI_MSGS` m
  359. where m.`ID`='{$id}'
  360. and m.`A_STATUS`='WAITING'
  361. ";
  362. $db = DB::getDB();
  363. $res = $db->query($sql);
  364. if ($r = $db->fetch($res)) {
  365. $msg = $r;
  366. }
  367. if (!$msg) {
  368. throw new HttpException("Message not found", 404);
  369. }
  370. return $msg;
  371. }
  372. public function forceFinishMessage($id, $execNotes) {
  373. if (empty($id)) return;
  374. $id = intval($id);
  375. if ($id <= 0) return;
  376. $usrLogin = User::getLogin();
  377. $db = DB::getDB();
  378. $execNotes = $db->_($execNotes);
  379. $sql = "update `CRM_UI_MSGS`
  380. set `A_STATUS`='OFF_HARD'
  381. , `actionExecutedTime`=NOW()
  382. , `actionNotes`='{$execNotes}'
  383. , `A_RECORD_UPDATE_DATE`=NOW()
  384. , `A_RECORD_UPDATE_AUTHOR`='{$usrLogin}'
  385. where `ID`='{$id}'
  386. ";
  387. $db->query($sql);
  388. return;
  389. }
  390. public function removeMessage($id) {
  391. if (empty($id)) return;
  392. $id = intval($id);
  393. if ($id <= 0) return;
  394. $sql = "update `CRM_UI_MSGS` set `A_STATUS`='DELETED' where `ID`='{$id}' ";
  395. $db = DB::getDB();
  396. $db->query($sql);
  397. }
  398. }