Notify.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. <?php
  2. Lib::loadClass('RouteBase');
  3. /*
  4. # Nofitication system:
  5. Sends mail by settings `CRM_NOTIFY`:
  6. - who - user login
  7. - when - shedule (once a day, once on houd)
  8. - what - action type
  9. - last_exec_time
  10. */
  11. class Route_Notify extends RouteBase {
  12. public function handleAuth() {
  13. if (!User::logged()) {
  14. throw new HttpException('Unauthorized', 401);
  15. }
  16. }
  17. public function defaultAction() {
  18. SE_Layout::gora();
  19. ?>
  20. <div class="container">
  21. <h1>Nofitication system</h1>
  22. ...
  23. </div>
  24. <?php
  25. SE_Layout::dol();
  26. }
  27. public function reinstallAction() {
  28. try {
  29. $this->reinstall();
  30. } catch (Exception $e) {
  31. echo "Error #" . $e->getCode() . "|" . $e->getLine() . ": " . $e->getMessage();
  32. }
  33. die('OK');
  34. }
  35. public function reinstallFunctionsAction() {
  36. $this->reinstallFunctions();
  37. die('OK');
  38. }
  39. public function runAction() {
  40. $msgId = V::get('_msgId', 0, $_REQUEST, 'int');
  41. if ($msgId > 0) {
  42. $this->runByMessageId($msgId);
  43. }
  44. $jsonData = new stdClass();
  45. $jsonData->type = 'success';
  46. $jsonData->msg = 'Gotowe';
  47. echo json_encode($jsonData);
  48. exit;
  49. }
  50. public function reinstallFunctions() {
  51. $sqlList = array();
  52. $db = DB::getDB();
  53. if ($db->has_errors()) {
  54. throw new Exception("DB Errors: " . implode("\n<br>", $db->get_errors()));
  55. }
  56. foreach ($sqlList as $sqlName => $sql) {
  57. $res = $db->query($sql);
  58. if ($db->has_errors()) {
  59. throw new Exception("DB Errors at sql '{$sqlName}': " . implode("\n<br>", $db->get_errors()));
  60. }
  61. }
  62. }
  63. public function reinstall() {
  64. $sqlList = array();
  65. $pdo = DB::getPDO();
  66. /*
  67. `CRM_NOTIFY`:
  68. - who - user login
  69. - when - shedule (once a day, once on houd)
  70. - what - action type
  71. - last_exec_time
  72. */
  73. if(1){// TEST
  74. $expectedStruct = array();
  75. $expectedStruct['who'] = array('type'=>'varchar', 'max_length'=>20, 'is_nullable'=>false);// `who` varchar(20) -- TODO: NOT NULL
  76. $expectedStruct['when'] = array('type'=>'varchar', 'max_length'=>255, 'is_nullable'=>false);// `when` varchar(255) NOT NULL
  77. $expectedStruct['what'] = array('type'=>'varchar', 'max_length'=>255, 'is_nullable'=>false);// `what` varchar(255) NOT NULL
  78. $expectedStruct['last_exec_time'] = array('type'=>'datetime', 'is_nullable'=>true);// `last_exec_time` datetime
  79. $expectedStruct['_created'] = array('type'=>'datetime', 'is_nullable'=>false);// `_created` datetime
  80. $expectedStruct['uniq_key_1'] = array('type'=>'UNIQUE KEY', 'key_fields'=>array('who','when','what'));// UNIQUE KEY `uniq_key_1` (`who`,`when`,`what`)
  81. $expectedStruct['key_who'] = array('type'=>'KEY', 'key_fields'=>array('who'));// KEY `key_who` (`who`)
  82. // $expectedStruct['t1'] = array('type'=>'varchar', 'max_length'=>300, 'default_value'=>null);
  83. // $expectedStruct['t2'] = array('type'=>'int');
  84. // $expectedStruct['t3'] = array('type'=>'int', 'num_precision'=>11, 'default_value'=>null);
  85. // $expectedStruct['t_dec_11_x'] = array('type'=>'decimal', 'num_precision'=>11);
  86. // $expectedStruct['t_dec_11_2'] = array('type'=>'decimal', 'num_precision'=>11, 'num_scale'=>2);
  87. $expectedStruct['t_int'] = array('type'=>'int');
  88. $expectedStruct['t_tinyint'] = array('type'=>'tinyint');
  89. $expectedStruct['t_smallint'] = array('type'=>'smallint');
  90. $expectedStruct['t_mediumint'] = array('type'=>'mediumint');
  91. $expectedStruct['t_bigint'] = array('type'=>'bigint');
  92. $expectedStruct['t_decimal'] = array('type'=>'decimal');
  93. $expectedStruct['t_float'] = array('type'=>'float');
  94. $expectedStruct['t_double'] = array('type'=>'double');
  95. $expectedStruct['t_real'] = array('type'=>'real');
  96. $expectedStruct['t_date'] = array('type'=>'date');
  97. $expectedStruct['t_datetime'] = array('type'=>'datetime');
  98. $expectedStruct['t_timestamp'] = array('type'=>'timestamp');
  99. $expectedStruct['t_time'] = array('type'=>'time');
  100. $expectedStruct['t_year'] = array('type'=>'year');
  101. $expectedStruct['t_char'] = array('type'=>'char');
  102. $expectedStruct['t_varchar'] = array('type'=>'varchar');
  103. $expectedStruct['t_text'] = array('type'=>'text');
  104. $expectedStruct['t_tinytext'] = array('type'=>'tinytext');
  105. $expectedStruct['t_mediumtext'] = array('type'=>'mediumtext');
  106. $expectedStruct['t_longtext'] = array('type'=>'longtext');
  107. $expectedStruct['t_enum'] = array('type'=>'enum', 'values'=>array('v1'));
  108. $expectedStruct['t_set'] = array('type'=>'set', 'values'=>array('v1'));
  109. $expectedStruct['t_bit'] = array('type'=>'bit', 'max_length'=>2);
  110. $expectedStruct['t_boolean'] = array('type'=>'boolean');
  111. $expectedStruct['t_serial'] = array('type'=>'serial');
  112. $expectedStruct['t_binary'] = array('type'=>'binary');
  113. $expectedStruct['t_varbinary'] = array('type'=>'varbinary');
  114. $expectedStruct['t_blob'] = array('type'=>'blob');
  115. $expectedStruct['t_tinyblob'] = array('type'=>'tinyblob');
  116. $expectedStruct['t_mediumblob'] = array('type'=>'mediumblob');
  117. $expectedStruct['t_longblob'] = array('type'=>'longblob');
  118. $expectedStruct['t_geometry'] = array('type'=>'geometry');
  119. $expectedStruct['t_point'] = array('type'=>'point');
  120. $expectedStruct['t_linestring'] = array('type'=>'linestring');
  121. $expectedStruct['t_polygon'] = array('type'=>'polygon');
  122. $expectedStruct['t_multipoint'] = array('type'=>'multipoint');
  123. $expectedStruct['t_multilinestring'] = array('type'=>'multilinestring');
  124. $expectedStruct['t_multipolygon'] = array('type'=>'multipolygon');
  125. $expectedStruct['t_geometrycollection'] = array('type'=>'geometrycollection');
  126. $sqlCreate = $pdo->showCreateStructMysql('CRM_NOTIFY', $expectedStruct, array('char_encoding'=>'latin2'));
  127. DBG::_(true, true, "fixedEpectedStruct", $sqlCreate, __CLASS__, __FUNCTION__, __LINE__);
  128. $pdo->assertTableStruct('CRM_NOTIFY', $expectedStruct, array('char_encoding'=>'latin2'));
  129. {// force - drop/create
  130. $pdo->exec("DROP TABLE IF EXISTS CRM_NOTIFY");
  131. $pdo->exec($sqlCreate);
  132. }
  133. return;
  134. }
  135. $sth = $pdo->prepare("
  136. CREATE TABLE IF NOT EXISTS CRM_NOTIFY (
  137. `who` varchar(20) -- TODO: NOT NULL
  138. , `when` varchar(255) NOT NULL
  139. , `what` varchar(255) NOT NULL
  140. , `last_exec_time` datetime -- TODO: DEFAULT NULL
  141. , `_created` datetime
  142. , UNIQUE KEY `uniq` (`who`,`when`,`what`)
  143. , KEY `who` (`who`)
  144. ) ENGINE=MyISAM DEFAULT CHARSET=latin2
  145. ");
  146. $sth->execute();
  147. if(1){// TEST nulls
  148. $sth = $pdo->prepare("DROP TABLE IF EXISTS CRM_NOTIFY");
  149. $sth->execute();
  150. $sth = $pdo->prepare("
  151. CREATE TABLE IF NOT EXISTS CRM_NOTIFY (
  152. `who` varchar(20)
  153. , `when` varchar(255) NOT NULL
  154. , `what` varchar(255) DEFAULT ''
  155. , `t1` varchar(255) NOT NULL -- same as with DEFAULT ''
  156. , `t2` varchar(255) NOT NULL DEFAULT ''
  157. , `t2z` varchar(255) NOT NULL DEFAULT '0'
  158. -- , `t3` varchar(255) NOT NULL DEFAULT NULL -- SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value
  159. , `t4` varchar(255) NULL -- same as with DEFAULT NULL
  160. , `t5` varchar(255) NULL DEFAULT ''
  161. , `t6` varchar(255) NULL DEFAULT NULL
  162. , `i1` int(11) NOT NULL -- same as with DEFAULT 0
  163. , `i2` int(11) NOT NULL DEFAULT 0
  164. -- , `i3` int(11) NOT NULL DEFAULT NULL -- SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value
  165. , `i4` int(11) NULL -- same as with DEFAULT NULL
  166. , `i5` int(11) NULL DEFAULT 0
  167. , `i6` int(11) NULL DEFAULT NULL
  168. , `last_exec_time` datetime DEFAULT NULL
  169. , KEY `who` (`who`)
  170. ) ENGINE=MyISAM DEFAULT CHARSET=latin2
  171. ");
  172. $sth->execute();
  173. $sth = $pdo->prepare("insert into CRM_NOTIFY (`last_exec_time`) values (NULL)");
  174. $sth->execute();
  175. // INSERT INTO CRM_NOTIFY (t1, t2, t2z, t4, t5, t6, i1, i2, i4, i5, i6, last_exec_time)
  176. // VALUES ('', '', '0', NULL, '', NULL, 0, 0, NULL, 0, NULL, NULL);
  177. $struct = $pdo->getTableStruct('CRM_NOTIFY');
  178. DBG::_(true, true, "struct", $struct, __CLASS__, __FUNCTION__, __LINE__);
  179. DBG::_(true, true, "`t2`: is_null(struct[4]['Default'])=(".is_null($struct[4]['Default']).")", null, __CLASS__, __FUNCTION__, __LINE__);
  180. DBG::_(true, true, "`t4`: is_null(struct[6]['Default'])=(".is_null($struct[6]['Default']).")", null, __CLASS__, __FUNCTION__, __LINE__);
  181. DBG::_(true, true, "`t5`: is_null(struct[7]['Default'])=(".is_null($struct[7]['Default']).")", null, __CLASS__, __FUNCTION__, __LINE__);
  182. DBG::_(true, true, "`t6`: is_null(struct[8]['Default'])=(".is_null($struct[8]['Default']).")", null, __CLASS__, __FUNCTION__, __LINE__);
  183. $expectedStruct = array();
  184. $expectedStruct['t1'] = array('type'=>'varchar', 'max_length'=>300, 'default_value'=>null);
  185. //$expectedStruct['t2'] = array('type'=>'int', 'num_precision'=>11, 'default_value'=>null);
  186. $pdo->assertTableStruct('CRM_NOTIFY', $expectedStruct);
  187. return;
  188. }
  189. $struct = $pdo->getTableStruct('CRM_NOTIFY');
  190. DBG::_(true, true, "struct", $struct, __CLASS__, __FUNCTION__, __LINE__);
  191. $expectedStruct = array();
  192. $expectedStruct['who'] = array('type'=>'varchar', 'max_length'=>20);
  193. $expectedStruct['when'] = array('type'=>'varchar', 'max_length'=>255);
  194. $expectedStruct['what'] = array('type'=>'varchar', 'max_length'=>255);
  195. $expectedStruct['last_exec_time'] = array('type'=>'datetime');
  196. $expectedStruct['_created'] = array('type'=>'datetime');
  197. $expectedStruct['tX'] = array('type'=>'varchar', 'max_length'=>255, 'default_value'=>null, 'is_nullable'=>true);
  198. DBG::_(true, true, "is_null('')=(".is_null('').") is_null()=(".is_null().") is_null(null)=(".is_null(null).")", null, __CLASS__, __FUNCTION__, __LINE__);
  199. if(0){// keys
  200. $sth = $pdo->prepare("show keys from CRM_NOTIFY");
  201. $sth->execute();
  202. $keys = $sth->fetchAll();
  203. DBG::_(true, true, "keys", $keys, __CLASS__, __FUNCTION__, __LINE__);
  204. }
  205. //$this->reinstallFunctions();
  206. }
  207. public function getActiveMessagesForTable($tblName) {
  208. if (empty($tblName)) return;
  209. $db = DB::getDB();
  210. $tblName = $db->_($tblName);
  211. $usrLogin = User::getLogin();
  212. $msgs = null;
  213. $sql = "select m.*
  214. from `CRM_UI_MSGS` m
  215. where m.`uiTargetType`='default_db_table'
  216. and m.`A_STATUS`='WAITING'
  217. and m.`uiTargetName`='{$tblName}'
  218. and (m.`userTargetType` in('everyone')
  219. or (m.`userTargetType`='user' and m.`userTargetName`='{$usrLogin}')
  220. -- TODO: use 'admin', 'group'
  221. )
  222. ";
  223. $db = DB::getDB();
  224. $res = $db->query($sql);
  225. while ($r = $db->fetch($res)) {
  226. if ($msg = $this->parseMessage($r)) {
  227. $msg['link'] = 'index.php?_route=Msgs&_task=run&_msgId=' . $r->ID;
  228. $msg['linkType'] = 'ajax';
  229. $msgs[$r->ID] = $msg;
  230. }
  231. }
  232. return $msgs;
  233. }
  234. public function getActiveMessagesForTableRecord($tblName, $id) {
  235. if (empty($tblName)) return;
  236. $db = DB::getDB();
  237. $tblName = $db->_($tblName);
  238. $usrLogin = User::getLogin();
  239. $msgs = null;
  240. $sql = "select m.*
  241. from `CRM_UI_MSGS` m
  242. where m.`uiTargetType`='default_db_table_record'
  243. and m.`uiTargetName`='{$tblName}.{$id}'
  244. and (m.`userTargetType` in('everyone')
  245. or (m.`userTargetType`='user' and m.`userTargetName`='{$usrLogin}')
  246. -- TODO: use group id
  247. )
  248. and m.`A_STATUS`='WAITING'
  249. order by m.`ID` DESC
  250. ";
  251. $db = DB::getDB();
  252. $res = $db->query($sql);
  253. while ($r = $db->fetch($res)) {
  254. if ($msg = $this->parseMessage($r)) {
  255. $msg['link'] = 'index.php?_route=Msgs&_task=run&_msgId=' . $r->ID;
  256. $msg['linkType'] = 'ajax';
  257. $msgs[$r->ID] = $msg;
  258. }
  259. }
  260. return $msgs;
  261. }
  262. public function parseMessage($r) {
  263. $msg = null;// ['type'=>'info', 'message'=>'...']
  264. // $r->app_className - for automatic msgs to search for msg text
  265. // $r->msg - for automatic msgs to search for msg text
  266. // $r->msgType - 'info','danger','warning','success'
  267. if (!empty($r->app_className)) {
  268. $route = Router::getRoute($r->app_className);
  269. $msg = array();
  270. $msg['message'] = $route->parseMessageFromMsgsSystem($r->msg);
  271. $msg['type'] = $r->msgType;
  272. $msg['_raw'] = $r;
  273. } else {
  274. $msg = array();
  275. $msg['message'] = $this->parseMessageFromMsgsSystem($r->msg);
  276. $msg['type'] = $r->msgType;
  277. $msg['_raw'] = $r;
  278. }
  279. return $msg;
  280. }
  281. public function parseMessageFromMsgsSystem($msg) {
  282. return $msg;
  283. }
  284. public function runByMessageId($id) {
  285. $msgRow = $this->getActiveMessage($id);
  286. $execNotes = '';
  287. if (!empty($msgRow->app_className)) {
  288. $route = Router::getRoute($msgRow->app_className);
  289. $route->runByMessageFromMsgsSystem($msgRow->msg, $execNotes);
  290. }
  291. $this->forceFinishMessage($id, $execNotes);
  292. }
  293. public function getMessage($id) {
  294. if (empty($id)) return;
  295. $id = intval($id);
  296. if ($id <= 0) return;
  297. $msg = null;
  298. $sql = "select * from `CRM_UI_MSGS` where `ID`='{$id}' ";
  299. $db = DB::getDB();
  300. $res = $db->query($sql);
  301. if ($r = $db->fetch($res)) {
  302. $msg = $r;
  303. }
  304. return $msg;
  305. }
  306. public function getActiveMessage($id) {
  307. if (empty($id)) return;
  308. $id = intval($id);
  309. if ($id <= 0) return;
  310. $msg = null;
  311. $sql = "select m.*
  312. from `CRM_UI_MSGS` m
  313. where m.`ID`='{$id}'
  314. and m.`A_STATUS`='WAITING'
  315. ";
  316. $db = DB::getDB();
  317. $res = $db->query($sql);
  318. if ($r = $db->fetch($res)) {
  319. $msg = $r;
  320. }
  321. if (!$msg) {
  322. throw new HttpException("Message not found", 404);
  323. }
  324. return $msg;
  325. }
  326. public function forceFinishMessage($id, $execNotes) {
  327. if (empty($id)) return;
  328. $id = intval($id);
  329. if ($id <= 0) return;
  330. $usrLogin = User::getLogin();
  331. $db = DB::getDB();
  332. $execNotes = $db->_($execNotes);
  333. $sql = "update `CRM_UI_MSGS`
  334. set `A_STATUS`='OFF_HARD'
  335. , `actionExecutedTime`=NOW()
  336. , `actionNotes`='{$execNotes}'
  337. , `A_RECORD_UPDATE_DATE`=NOW()
  338. , `A_RECORD_UPDATE_AUTHOR`='{$usrLogin}'
  339. where `ID`='{$id}'
  340. ";
  341. $db->query($sql);
  342. return;
  343. }
  344. public function removeMessage($id) {
  345. if (empty($id)) return;
  346. $id = intval($id);
  347. if ($id <= 0) return;
  348. $sql = "update `CRM_UI_MSGS` set `A_STATUS`='DELETED' where `ID`='{$id}' ";
  349. $db = DB::getDB();
  350. $db->query($sql);
  351. }
  352. public function removeTableRecordMsg($idMsg) {
  353. // IDEA: do kosza - add trigger to insert into `CRM_UI_MSGS__TRASH` after DELETE on `CRM_UI_MSGS`
  354. $idMsg = intval($idMsg);
  355. if ($idMsg <= 0) throw new Exception("Brak wiadomości!");
  356. $usrLogin = User::getLogin();
  357. $db = DB::getDB();
  358. if (!$db) throw new Exception("Brak dazy danych!");
  359. if ($db->has_errors()) throw new Exception("DB Errors: " . implode("\n<br>", $db->get_errors()));
  360. $sqlTODO = "delete `CRM_UI_MSGS` where `ID`='{$idMsg}' ";
  361. $sql = "update `CRM_UI_MSGS`
  362. set `A_STATUS`=IF('{$usrLogin}'=`A_RECORD_CREATE_AUTHOR`, 'DELETED', 'OFF_SOFT')
  363. , `A_RECORD_DELETE_AUTHOR`='{$usrLogin}'
  364. , `A_RECORD_DELETE_DATE`=NOW()
  365. where `ID`='{$idMsg}'
  366. ";
  367. DBG::_('DBG_MSGS', '>1', "sql", $sql, __CLASS__, __FUNCTION__, __LINE__);
  368. $res = $db->query($sql);
  369. if (!$res || $db->has_errors()) throw new Exception("Wystąpiły błędy podczas próby zapisu wiadomości: " . implode("\n<br>", $db->get_errors()));
  370. }
  371. }