Storage.php 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291
  1. <?php
  2. // @requires $_SERVER['SERVER_NAME']
  3. Lib::loadClass('RouteBase');
  4. Lib::loadClass('Router');
  5. Lib::loadClass('Schema_TableFactory');
  6. Lib::loadClass('Response');
  7. Lib::loadClass('UI');
  8. Lib::loadClass('SchemaFactory');
  9. /*
  10. # Storage:
  11. - [x] view available storage (from Zasoby - type 'BAZA_DANYCH', 'DATABASE_MYSQL', ...)
  12. - [x] check config for connection
  13. - [x] add cells to Zasoby
  14. - [ ] create cells in Storage
  15. - [x] use PDO
  16. */
  17. class Route_Storage extends RouteBase {
  18. public function handleAuth() {
  19. if (!User::logged()) {
  20. User::authByRequest();
  21. }
  22. }
  23. public function defaultAction() {
  24. UI::gora();
  25. UI::menu();
  26. $this->navView();
  27. UI::startContainer();
  28. try {
  29. $sourceStorage = SchemaFactory::loadDefaultObject('SystemSource');
  30. try {
  31. $sourceStorage->getTotal();
  32. } catch (Exception $e) {
  33. UI::alert('warning', $e->getMessage());
  34. $sourceStorage->updateCache();
  35. UI::alert('info', "Lista dostępnych baz danych zaktualizowana");
  36. }
  37. if ('1' == V::get('refreshSourceList', '', $_POST)) {
  38. $sourceStorage->updateCache();
  39. UI::alert('info', "Lista dostępnych baz danych zaktualizowana");
  40. }
  41. UI::table([
  42. 'caption' => "Bazy danych " .
  43. UI::hButtonPost('<i class="glyphicon glyphicon-refresh"></i>' . " odśwież", [
  44. 'class' => "btn btn-xs btn-link",
  45. 'data' => [
  46. 'refreshSourceList' => '1'
  47. ]
  48. ]),
  49. 'rows' => array_merge(
  50. array_map(function ($item) {
  51. return [
  52. 'Nr zasobu' => $item['idZasob'],
  53. 'nazwa' => $item['name'],
  54. 'opis' => $item['description'],
  55. 'config?' => ($item['hasConfig']) ? '<span class="label label-success">TAK</span>' : '<span class="text text-muted">brak</span>',
  56. 'obiekty' => UI::h('a', [ 'href' => $this->getLink('tableList', [ 'idStorage' => $item['idZasob'] ]) ], "obiekty"),
  57. 'raw info' => UI::h('a', [ 'href' => $this->getLink('rawInfo', [ 'idStorage' => $item['idZasob'] ]) ], "raw info"),
  58. 'xsd' => UI::h('a', [ 'href' => $this->getLink('xsd', [ 'idStorage' => $item['idZasob'] ]) ], "xsd"),
  59. ];
  60. }, $sourceStorage->getItems())
  61. , [
  62. [
  63. 'Nr zasobu' => '',
  64. 'nazwa' => "Narzędzia systemowe",
  65. 'opis' => "SystemObjects",
  66. 'config?' => '<span class="text text-muted">n/d</span>',
  67. 'obiekty' => UI::h('a', [ 'href' => Router::getRoute('Storage_Tools')->getLink() ], "narzędzia"),
  68. ],
  69. [
  70. 'Nr zasobu' => '',
  71. 'nazwa' => '<span style="color:silver">' . "Obiekty" . '</span>',
  72. 'opis' => '<span style="color:silver">' . "SystemObjects" . '</span>',
  73. 'config?' => '<span class="text text-muted">brak</span>',
  74. 'obiekty' => UI::h('a', [ 'href' => $this->getLink('systemObjects') ], "obiekty"),
  75. ],
  76. [
  77. 'Nr zasobu' => '',
  78. 'nazwa' => '<span style="color:silver">' . "Obiekty Test" . '</span>',
  79. 'opis' => '<span style="color:silver">' . "Obiekty podstawowe (test json)" . '</span>',
  80. 'config?' => '<span class="text text-muted">brak</span>',
  81. 'obiekty' => UI::h('a', [ 'href' => Router::getRoute('Storage_TestObj')->getLink('coreObjectList') ], "obiekty"),
  82. 'raw info' => UI::h('a', [ 'href' => Router::getRoute('Storage_TestObj')->getLink('coreObjectParseAll') ], "raw info"),
  83. ],
  84. [
  85. 'Nr zasobu' => '',
  86. 'nazwa' => '<span style="color:silver">' . "Obiekty Test" . '</span>',
  87. 'opis' => '<span style="color:silver">' . "Obiekty dla domeny '" . str_replace(array(".", "-"), '_', $_SERVER['SERVER_NAME']) . "' (test json)" . '</span>',
  88. 'config?' => '<span class="text text-muted">brak</span>',
  89. 'obiekty' => UI::h('a', [ 'href' => Router::getRoute('Storage_TestObj')->getLink('objectList') ], "obiekty"),
  90. // 'raw info' => UI::h('a', [ 'href' => $this->getLink('objectRawInfo') ], "raw info"),
  91. ],
  92. ]
  93. )
  94. ]);
  95. // $sourceStorage = SchemaFactory::loadDefaultObject('SystemObject');
  96. // $sourceStorage->updateCache();
  97. } catch (Exception $e) {
  98. UI::alert('danger', "Error #" . $e->getCode() . "|" . $e->getLine() . ": " . $e->getMessage());
  99. }
  100. UI::endContainer();
  101. UI::dol();
  102. }
  103. public function getTableRows($tblName, $fields) {
  104. $sqlFields = array();
  105. foreach ($fields as $fldName) {
  106. $sqlFields[] = "t.`{$fldName}`";
  107. }
  108. $sqlFields = (!empty($sqlFields))? implode(", ", $sqlFields) : "t.*";
  109. $rows = DB::getPDO()->fetchAll("
  110. select {$sqlFields}
  111. from `{$tblName}` t
  112. where 1=1
  113. limit 10
  114. ");
  115. return $rows;
  116. }
  117. public function showTableWidget($tblName, $fields) {
  118. $rows = $this->getTableRows($tblName, $fields);
  119. UI::table(array('caption' => "table({$tblName})", 'rows' => $rows));
  120. }
  121. public function tableListAction() {
  122. UI::gora();
  123. UI::menu();
  124. $this->navView();
  125. UI::startContainer();
  126. try {
  127. $idStorage = V::get('idStorage', 0, $_REQUEST, 'int');
  128. if (empty($idStorage)) throw new Exception("Missing id storage");
  129. $sourceStorage = SchemaFactory::loadDefaultObject('SystemSource');
  130. $sourceItem = $sourceStorage->getItem($idStorage);
  131. if (!$sourceItem) throw new Exception("Storage id='{$idStorage}' not exists");
  132. DBG::log($sourceItem, 'array', '$sourceItem');
  133. // TODO: fetch SystemObject childrens from $sourceItem:
  134. // 1. 'SystemSource' -> getItems([ 'cols' => 'SystemObject/*', 'featureId' => $sourceItem['idZasob'] ])
  135. // 2. 'SystemObject' -> getItems([ 'refFrom' => $sourceItem['idZasob'] ])
  136. // 'default_objects' => _task=systemObjects
  137. $objectStorage = SchemaFactory::loadDefaultObject('SystemObject');
  138. try {
  139. $objectStorage->getTotal();
  140. } catch (Exception $e) {
  141. UI::alert('warning', $e->getMessage());
  142. DBG::log($e);
  143. $objectStorage->updateCache();
  144. UI::alert('info', "Lista obiketów zaktualizowana");
  145. }
  146. if ('1' == V::get('refreshObjectList', '', $_POST)) {
  147. $objectStorage->updateCache();
  148. UI::alert('info', "Lista obiketów zaktualizowana");
  149. }
  150. {
  151. echo UI::h('style', ['type' => "text/css"], "
  152. .p5UI__dropdown-content { min-width:300px; padding:8px; background-color: #f6f6f6; box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2) }
  153. .p5UI__dropdown-content a { display:block; color:#000; padding:8px; text-decoration:none }
  154. .p5UI__dropdown-content a:hover { background-color:#ebebeb }
  155. ");
  156. echo UI::h('script', [], "
  157. function p5_Storage_actions_filterInput(n) {
  158. var input, filter, ul, li, a, i, div;
  159. input = n // .id-myInput
  160. filter = input.value.toUpperCase()
  161. div = n.parentNode // .id-myDropdown
  162. a = div.getElementsByTagName('a')
  163. for (i = 0; i < a.length; i++) {
  164. if (a[i].innerHTML.toUpperCase().indexOf(filter) > -1) {
  165. a[i].style.display = ''
  166. } else {
  167. a[i].style.display = 'none'
  168. }
  169. }
  170. }
  171. ");
  172. }
  173. $thisGetLink = array($this, 'getLink');
  174. UI::table([
  175. 'caption' => "Obiekty w bazie '{$sourceItem['name']}' " .
  176. UI::hButtonPost('<i class="glyphicon glyphicon-refresh"></i>' . " odśwież", [
  177. 'class' => "btn btn-xs btn-link",
  178. 'data' => [
  179. 'refreshObjectList' => '1'
  180. ]
  181. ]),
  182. 'rows' => array_map(function ($item) use ($idStorage, $thisGetLink) {
  183. $typeName = $item['typeName']; // $typeName = Api_WfsNs::typeName($item['namespace']);
  184. return [
  185. 'namespace' => '<span style="color:#888">' . substr($item['namespace'], 0, strlen($item['namespace']) - strlen($item['name'])) . '</span>' .
  186. '<span>' . $item['name'] . '</span>',
  187. '_type' => $item['_type'], // TODO: editable?
  188. 'Nr zasobu' => ($item['idZasob'] > 0)
  189. ? $item['idZasob']
  190. : UI::hButtonAjax("Dodaj do zasobów", 'addAclObjectToZasobyAjax', [
  191. 'class' => "btn btn-xs btn-primary",
  192. 'href' => $this->getLink('addAclObjectToZasobyAjax'),
  193. 'data' => [
  194. 'idStorage' => $idStorage,
  195. 'namespace' => $item['namespace'],
  196. ]
  197. ]),
  198. // 'opis' => $item['description'],
  199. 'hasStruct' => ($item['hasStruct']) ? '<span class="label label-success">TAK</span>' : '<span class="text text-muted">nie</span>',
  200. 'installed' => $item['isStructInstalled'] ? '<span class="label label-success">TAK</span>' : '<span class="text text-muted">nie</span>',
  201. 'active?' => $item['isObjectActive'] ? '<span class="label label-success">TAK</span>' : '<span class="text text-muted">nie</span>',
  202. 'menu' => UI::h('div', ['class'=>"p5UI__dropdown-wrap"], [
  203. UI::h('button', ['onClick' => "p5UI__dropdown(event, this, 'left bottom')", 'class' => "btn btn-xs btn-default p5UI__dropdown-btn"], [
  204. '<i class="glyphicon glyphicon-menu-hamburger"></i>',
  205. " menu"
  206. ]),
  207. UI::h('div', ['class' => "p5UI__dropdown-content"], [
  208. UI::h('input', ['type' => "text", 'placeholder' => "Search..", 'class' => "p5UI__dropdown-input", 'onkeyup' => "p5_Storage_actions_filterInput(this)"], null),
  209. UI::h('a', [ 'href' => Router::getRoute('Storage_AclStruct')->getLink('', [ 'namespace' => $item['namespace'] ]) ], "struktura"),
  210. UI::h('a', [ 'href' => $item['reinstallLink'] ], "reinstall"),
  211. UI::h('a', [ 'href' => $this->getLink('rawInfo', [ 'idStorage' => $idStorage, 'table' => $item['name'] ]) ], "raw info"),
  212. UI::h('a', [ 'href' => Router::getRoute('ViewTableAjax')->getLink('', ['namespace' => $item['namespace']]) ], "view table"),
  213. UI::h('a', [ 'href' => Router::getRoute('ViewObject')->getLink('', ['namespace' => $item['namespace']]) ], "view object"),
  214. // 'xsd' => UI::h('a', [ 'href' => $this->getLink('xsd', [ 'idStorage' => $idStorage ]) ], "xsd"),
  215. UI::h('a', [ 'href' => "wfs-data.php/default_db/?SERVICE=WFS&VERSION=1.0.0&SRSNAME=EPSG:3003&REQUEST=DescribeFeatureType&TYPENAME={$typeName}" ], "wfs DescribeFeatureType"),
  216. UI::h('a', [ 'href' => "wfs-data.php/default_db/?SERVICE=WFS&VERSION=1.0.0&SRSNAME=EPSG:3003&REQUEST=DescribeFeatureTypeAdvanced&TYPENAME={$typeName}" ], "wfs DescribeFeatureTypeAdvanced"),
  217. UI::h('a', [ 'href' => "wfs-data.php/default_db/?SERVICE=WFS&VERSION=1.0.0&SRSNAME=EPSG:3003&REQUEST=GetFeature&TYPENAME={$typeName}&MAXFEATURES=10" ], "wfs GetFeature (max: 10)"),
  218. UI::h('a', [ 'href' => "wfs-data.php/default_db/?SERVICE=WFS&VERSION=1.0.0&SRSNAME=EPSG:3003&REQUEST=GetFeatureAdvanced&TYPENAME={$typeName}&MAXFEATURES=10" ], "wfs GetFeatureAdvanced (max: 10)"),
  219. UI::h('a', [ 'href' => "wfs-data.php/default_db/?SERVICE=WFS&VERSION=1.0.0&SRSNAME=EPSG:3003&REQUEST=GetFeature&TYPENAME={$typeName}&MAXFEATURES=3&resolve=all&resolveDepth=3" ], "wfs GetFeatureAdvanced (max: 3, resolveDepth: 3)"),
  220. ])
  221. ]),
  222. ];
  223. }, $objectStorage->getItems([
  224. '#refFrom' => [
  225. 'namespace' => 'default_objects/SystemSource',
  226. 'primaryKey' => $sourceItem['idZasob']
  227. ],
  228. 'order_by' => 'namespace',
  229. 'order_dir' => 'asc'
  230. ]))
  231. ]);
  232. UI::hButtonAjaxOnResponse('addAclObjectToZasobyAjax', /* payload, n */ "
  233. if (!payload.type) return false
  234. if ('success' === payload.type || 'info' === payload.type) {
  235. if (payload.body && payload.body.id && payload.body.id > 0) {
  236. n.parentNode.replaceChild(document.createTextNode(payload.body.id), n)
  237. } else {
  238. console.log('TODO: addAclObjectToZasobyAjax unknown response', payload);
  239. }
  240. jQuery.notify(payload.msg, payload.type);
  241. }
  242. ");
  243. } catch (Exception $e) {
  244. UI::alert('danger', "Error #" . $e->getCode() . "|" . $e->getLine() . ": " . $e->getMessage());
  245. DBG::log($e);
  246. }
  247. UI::endContainer();
  248. UI::dol();
  249. }
  250. public function rawInfoAction() {
  251. UI::gora();
  252. UI::menu();
  253. $this->navView();
  254. try {
  255. $idStorage = V::get('idStorage', 0, $_REQUEST, 'int');
  256. if (empty($idStorage)) throw new Exception("Missing id storage");
  257. $storageList = $this->getStorageList();
  258. if (empty($storageList)) throw new Exception("No storage defined");
  259. if (!array_key_exists($idStorage, $storageList)) throw new Exception("Storage not exists");
  260. $storagePdo = DB::getStorage($idStorage);
  261. $rawInfo = $storagePdo->getTableListWithInfo();
  262. DBG::table("rawInfo", $rawInfo, __CLASS__, __FUNCTION__, __LINE__);
  263. } catch (Exception $e) {
  264. UI::alert('danger', "Error #" . $e->getCode() . "|" . $e->getLine() . ": " . $e->getMessage());
  265. }
  266. UI::dol();
  267. }
  268. public function fetchActionListAjaxAction() {
  269. Response::sendTryCatchJson(array($this, 'fetchActionListAjax'), $args = 'JSON_FROM_REQUEST_BODY');
  270. }
  271. public function fetchActionListAjax($args) {
  272. return [
  273. 'type' => 'success',
  274. '__args' => $args,
  275. 'options' => DB::getPDO()->fetchAll("
  276. select z.ID, z.`DESC`, z.OPIS
  277. from CRM_LISTA_ZASOBOW z
  278. where z.`TYPE` = 'URL_ACTION'
  279. and z.A_STATUS != 'DELETED'
  280. and z.ALIAS_ID = 0
  281. ")
  282. ];
  283. }
  284. public function addActionAjaxAction() {
  285. Response::sendTryCatchJson(array($this, 'addActionAjax'), $args = 'JSON_FROM_REQUEST_BODY');
  286. }
  287. public function addActionAjax($args) {
  288. $idStorage = V::get('idStorage', 0, $args, 'int');
  289. if ($idStorage <= 0) throw new Exception("Missing id storage");
  290. $idAction = V::get('idAction', 0, $args, 'int');
  291. if ($idAction <= 0) throw new Exception("Missing id action");
  292. $storageList = $this->getStorageList();
  293. if (empty($storageList)) throw new Exception("No storage defined");
  294. if (!array_key_exists($idStorage, $storageList)) throw new Exception("Storage not exists");
  295. $tblName = V::get('table', '', $args, 'word');
  296. if (empty($tblName)) throw new Exception("No table name");
  297. $storagePdo = DB::getStorage($idStorage);
  298. // $tblStruct = $storagePdo->getTableStruct($tblName);
  299. $idTable = $this->fetchTableId($idStorage, $tblName);
  300. if ($idTable <= 0) throw new Exception("Zasob tabela '{$tblName}' nie istnieje");
  301. $action = DB::getPDO()->fetchFirst("
  302. select z.ID, z.`DESC`, z.OPIS
  303. from CRM_LISTA_ZASOBOW z
  304. where z.ID = {$idAction}
  305. ");
  306. if (empty($action)) throw new Exception("Action '{$idAction}' not exists");
  307. $idInsertedAction = DB::getPDO()->insert('CRM_LISTA_ZASOBOW', [
  308. 'PARENT_ID' => $idTable,
  309. 'ALIAS_ID' => $idAction,
  310. 'TYPE' => 'URL_ACTION',
  311. 'DESC' => $action['DESC'],
  312. 'OPIS' => V::get('OPIS', $action['DESC'], $action),
  313. ]);
  314. if (!$idInsertedAction) throw new Exception("Nie udało się dodać akcji");
  315. try {
  316. DB::getPDO()->insert('CRM_LISTA_ZASOBOW_HIST', [
  317. 'ID_USERS2' => $idInsertedAction,
  318. 'PARENT_ID' => $idTable,
  319. 'ALIAS_ID' => $idAction,
  320. 'TYPE' => 'URL_ACTION',
  321. 'DESC' => $action['DESC'],
  322. 'OPIS' => V::get('OPIS', $action['DESC'], $action),
  323. ]);
  324. } catch (Exception $e) {
  325. DBG::log($e);
  326. }
  327. return [
  328. 'type' => 'success',
  329. 'msg' => "Dodano akcję - rekord nr {$idInsertedAction}",
  330. '__DBG__' => [
  331. '$args' => $args,
  332. '$idStorage' => $idStorage,
  333. '$tblName' => $tblName,
  334. // '$tblStruct' => $tblStruct,
  335. '$idTable' => $idTable,
  336. '$action' => $action,
  337. ]
  338. ];
  339. }
  340. public function addTableBaseProcesAction() {
  341. Response::sendTryCatchJson(array($this, 'addTableBaseProces'), $_REQUEST);
  342. }
  343. public function addTableBaseProces($args) {
  344. $return = [
  345. 'type' => 'error',
  346. 'msg' => 'todo: F.' . __FUNCTION__ . ' L.' . __LINE__,
  347. ];
  348. $idStorage = V::get('idStorage', 0, $args, 'int');
  349. if ($idStorage <= 0) throw new HttpException("Missing idStorage", 400);
  350. $storage = DB::getStorage($idStorage);
  351. $tblName = V::get('tblName', 0, $args, 'word');
  352. if (empty($tblName)) throw new HttpException("Missing tblName", 400);
  353. $tableStruct = $storage->getTableStruct($tblName);
  354. $return['$tableStruct'] = $tableStruct;
  355. $idTable = $this->fetchTableId($idStorage, $tblName);
  356. if ($idTable <= 0) {
  357. UI::alert('warning', "Zasob tabela '{$tblName}' nie istnieje");// TODO: add p5UI btn
  358. DBG::table("tblStruct", $tblStruct, __CLASS__, __FUNCTION__, __LINE__);
  359. throw new Exception("Zasob tabela '{$tblName}' nie istnieje");
  360. }
  361. $cellZasobList = array();
  362. foreach (DB::getPDO()->fetchAllByKey("
  363. select z.ID, z.`DESC`, z.A_STATUS
  364. from CRM_LISTA_ZASOBOW z
  365. where z.PARENT_ID = '{$idTable}'
  366. ", $key = 'DESC') as $ind => $row) {
  367. $cellZasobList[strtolower($ind)] = $row;
  368. }
  369. $return['$cellZasobList'] = $cellZasobList;
  370. $idProces = DB::getDB()->ADD_NEW_OBJ('CRM_PROCES', (object)[
  371. 'TYPE' => 'PROCES_INIT',
  372. 'DESC' => "Proces dla tabeli '{$tblName}'",
  373. ]);
  374. if (!$idProces) throw new Exception("DB ERROR - nie udało się dodać procesu");
  375. foreach ($cellZasobList as $loverName => $row) {
  376. DB::getDB()->ADD_NEW_OBJ('CRM_WSKAZNIK', (object)[
  377. 'ID_PROCES' => $idProces,
  378. 'ID_ZASOB' => $row['ID'],
  379. 'TYP' => 'P',
  380. 'ID_PRZYPADEK' => 2
  381. ]);
  382. }
  383. $return['type'] = 'success';
  384. $return['msg'] = "Utworzono proces {{$idProces}}";
  385. return $return;
  386. }
  387. public function addObjectBaseProcesAjaxAction() {
  388. Response::sendTryCatchJson(array($this, 'addObjectBaseProcesAjax'), $_REQUEST);
  389. }
  390. public function addObjectBaseProcesAjax($args) {
  391. $return = [
  392. 'type' => 'error',
  393. 'msg' => 'todo: F.' . __FUNCTION__ . ' L.' . __LINE__,
  394. ];
  395. $namespace = V::get('namespace', 0, $args);
  396. if (empty($namespace)) throw new HttpException("Missing namespace", 400);
  397. $item = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ]);
  398. DBG::log($item, 'array', "TODO: addObjectBaseProcesAjax for \$item");
  399. if (!$item['idZasob']) throw new Exception("Missing id zasob for object '{$namespace}'");
  400. if (!$item['idDatabase']) throw new Exception("Missing id database for object '{$namespace}'");
  401. if (!$item['_rootTableName']) throw new Exception("Missing root table name for object '{$namespace}'");
  402. if ('AntAcl' != $item['_type']) throw new Exception("Not implemented type '{$item['_type']}' for namespace '{$namespace}' - only AntAcl supported");
  403. if (!$item['hasStruct']) throw new Exception("Missing structure for object '{$namespace}'");
  404. if (!$item['isStructInstalled']) throw new Exception("Structure not installed for object '{$namespace}'");
  405. if (!$item['isObjectActive']) throw new Exception("Object is not active '{$namespace}'");
  406. $fieldsWithIdZasob = array_filter($item['field'], function ($field) {
  407. if (!$field['idZasob']) return false;
  408. return true;
  409. });
  410. if (empty($fieldsWithIdZasob)) throw new Exception("Missing fields with id zasob in object '{$namespace}'");
  411. $idProces = DB::getDB()->ADD_NEW_OBJ('CRM_PROCES', (object)[
  412. 'TYPE' => 'PROCES_INIT',
  413. 'DESC' => "TODO: Proces dla obiektu '{$namespace}'",
  414. ]);
  415. if (!$idProces) throw new Exception("DB ERROR - nie udało się dodać procesu");
  416. array_map(function ($field) use ($idProces) {
  417. DB::getDB()->ADD_NEW_OBJ('CRM_WSKAZNIK', (object)[
  418. 'ID_PROCES' => $idProces,
  419. 'ID_ZASOB' => $field['idZasob'],
  420. 'TYP' => 'P',
  421. 'ID_PRZYPADEK' => 2
  422. ]);
  423. }, $fieldsWithIdZasob);
  424. $return['type'] = 'success';
  425. $return['msg'] = "Utworzono proces {{$idProces}}";
  426. return $return;
  427. }
  428. public function addGeomEtykietaCellsAction() {
  429. Response::sendTryCatchJson(array($this, 'addGeomEtykietaCells'), $_REQUEST);
  430. }
  431. public function addGeomEtykietaCells($args) {
  432. $return = [
  433. 'type' => 'error',
  434. 'msg' => 'todo: F.' . __FUNCTION__ . ' L.' . __LINE__,
  435. ];
  436. $return['_DBG_request'] = $args;
  437. // idStorage: "36"
  438. // tblName: "test_geom_linestring"
  439. $idStorage = V::get('idStorage', 0, $args, 'int');
  440. if ($idStorage <= 0) throw new HttpException("Missing idStorage", 400);
  441. $storage = DB::getStorage($idStorage);
  442. $tblName = V::get('tblName', 0, $args, 'word');
  443. if (empty($tblName)) throw new HttpException("Missing tblName", 400);
  444. $tableStruct = $storage->getTableStruct($tblName);
  445. $return['_DBG_$tableStruct'] = $tableStruct;
  446. if ('mysql' == DB::getPDO($idStorage)->getType()) {
  447. $dbName = DB::getPDO($idStorage)->getDatabaseName();
  448. $fixedTableName = DB::getPDO($idStorage)->fetchValue("
  449. select t.TABLE_NAME
  450. from `information_schema`.`TABLES` t
  451. where t.TABLE_SCHEMA = '{$dbName}'
  452. and t.TABLE_NAME LIKE '{$tblName}'
  453. ");
  454. $return['_DBG_sql_fix__$tblName'] = "
  455. select t.TABLE_NAME
  456. from `information_schema`.`TABLES` t
  457. where t.TABLE_SCHEMA = '{$dbName}'
  458. and t.TABLE_NAME LIKE '{$tblName}'
  459. ";
  460. if (empty($fixedTableName)) return $return;
  461. if (empty($fixedTableName)) throw new HttpException("Database Error", 500);
  462. $return['_DBG_$fixedTableName'] = $fixedTableName;
  463. $tblName = $fixedTableName;
  464. }
  465. $return['_DBG_$tableStruct'] = $tableStruct;
  466. $return['_DBG_has_field__etykieta_x'] = (null != V::geti('etykieta_x', null, $tableStruct));
  467. $return['_DBG_has_field__etykieta_y'] = (null != V::geti('etykieta_y', null, $tableStruct));
  468. $return['_DBG_has_field__etykieta_obrot'] = (null != V::geti('etykieta_obrot', null, $tableStruct));
  469. if (!V::geti('etykieta_x', null, $tableStruct)) {
  470. try {
  471. DB::getPDO($idStorage)->exec("ALTER TABLE `{$tblName}_HIST` ADD `etykieta_x` varchar(16) DEFAULT 'N/S;'");
  472. } catch (Exception $e) {
  473. $return['__DBG_hist_errors__etykieta_x'] = $e->getMessage();
  474. }
  475. DB::getPDO($idStorage)->exec("ALTER TABLE `{$tblName}` ADD `etykieta_x` decimal(16,10) DEFAULT NULL COMMENT 'przesuniecie etykiety elementu w GIS'");
  476. }
  477. if (!V::geti('etykieta_y', null, $tableStruct)) {
  478. try {
  479. DB::getPDO($idStorage)->exec("ALTER TABLE `{$tblName}_HIST` ADD `etykieta_y` varchar(16) DEFAULT 'N/S;'");
  480. } catch (Exception $e) {
  481. $return['__DBG_hist_errors__etykieta_y'] = $e->getMessage();
  482. }
  483. DB::getPDO($idStorage)->exec("ALTER TABLE `{$tblName}` ADD `etykieta_y` decimal(16,10) DEFAULT NULL COMMENT 'przesuniecie etykiety elementu w GIS'");
  484. }
  485. if (!V::geti('etykieta_obrot', null, $tableStruct)) {
  486. try {
  487. DB::getPDO($idStorage)->exec("ALTER TABLE `{$tblName}_HIST` ADD `etykieta_obrot` varchar(16) DEFAULT 'N/S;'");
  488. } catch (Exception $e) {
  489. $return['__DBG_hist_errors__etykieta_obrot'] = $e->getMessage();
  490. }
  491. DB::getPDO($idStorage)->exec("ALTER TABLE `{$tblName}` ADD `etykieta_obrot` decimal(16,10) DEFAULT NULL");
  492. }
  493. return $return;
  494. }
  495. public function xsdAction() {
  496. $idStorage = V::get('idStorage', 0, $_REQUEST, 'int');
  497. $storage = DB::getStorage($idStorage);
  498. $tableRealList = $storage->getTableList();
  499. $srvName = $_SERVER['SERVER_NAME'];
  500. $storageZasobId = $storage->getZasobId();
  501. $objNs = "p5_{$storageZasobId}_{$tblName}";
  502. $objNsUri = "https://biuro.biall-net.pl/api/{$storageZasobId}/{$tblName}";
  503. $p5TypePrefix = "p5Type";
  504. $p5TypeNsUri = "http://biuro.biall-net.pl/p5/schema/types";
  505. $p5TypeNsLocation = "http://biuro.biall-net.pl/p5/schema/types.xsd";
  506. header('Content-type: text/plain; charset=utf-8');// TODO: test
  507. //header('Content-type: application/xml; charset=utf-8');
  508. $xmlWriter = new XMLWriter();
  509. $xmlWriter->openUri('php://output');
  510. $xmlWriter->setIndent(true);
  511. if (!$xmlWriter) throw new HttpException("Error no XMLWriter", 404);
  512. $xmlWriter->startDocument('1.0', 'UTF-8');
  513. $xmlWriter->startElement('xs:schema');
  514. $xmlWriter->writeAttribute('xmlns:xs', 'http://www.w3.org/2001/XMLSchema');
  515. $xmlWriter->writeAttribute('xmlns:vc', 'http://www.w3.org/2007/XMLSchema-versioning');
  516. $xmlWriter->writeAttribute("xmlns:{$p5TypePrefix}", $p5TypeNsUri);
  517. $xmlWriter->writeAttribute('elementFormDefault', 'qualified');
  518. $xmlWriter->writeAttribute('targetNamespace', $objNsUri);
  519. $xmlWriter->writeAttribute('vc:minVersion', '1.1');
  520. $xmlWriter->startElement('xs:import');
  521. $xmlWriter->writeAttribute('namespace', $p5TypeNsUri);
  522. $xmlWriter->writeAttribute('schemaLocation', $p5TypeNsLocation);
  523. $xmlWriter->endElement();// xs:import
  524. foreach ($tableRealList as $tbl) {
  525. $tblName = $tbl['table_name'];
  526. $this->tableXsdViewXmlWriter($xmlWriter, $idStorage, $tblName);
  527. }
  528. $xmlWriter->endElement();// xs:schema
  529. $xmlWriter->endDocument();
  530. }
  531. public function tableXsdAction() {
  532. $idStorage = V::get('idStorage', '', $_GET);
  533. $tblName = V::get('table', '', $_GET, 'word');
  534. if (empty($tblName)) die("Wrong table name");
  535. header('Content-type: text/plain; charset=utf-8');// TODO: test
  536. $storage = DB::getStorage($idStorage);
  537. $storageZasobId = $storage->getZasobId();
  538. $objNs = "p5_{$storageZasobId}_{$tblName}";
  539. $objNsUri = "https://biuro.biall-net.pl/api/{$storageZasobId}/{$tblName}";
  540. $p5TypePrefix = "p5Type";
  541. $p5TypeNsUri = "http://biuro.biall-net.pl/p5/schema/types";
  542. $p5TypeNsLocation = "http://biuro.biall-net.pl/p5/schema/types.xsd";
  543. //header('Content-type: application/xml; charset=utf-8');
  544. $xmlWriter = new XMLWriter();
  545. $xmlWriter->openUri('php://output');
  546. $xmlWriter->setIndent(true);
  547. if (!$xmlWriter) throw new HttpException("Error no XMLWriter", 404);
  548. $xmlWriter->startDocument('1.0', 'UTF-8');
  549. $xmlWriter->startElement('xs:schema');
  550. $xmlWriter->writeAttribute('xmlns:xs', 'http://www.w3.org/2001/XMLSchema');
  551. $xmlWriter->writeAttribute('xmlns:vc', 'http://www.w3.org/2007/XMLSchema-versioning');
  552. $xmlWriter->writeAttribute("xmlns:{$p5TypePrefix}", $p5TypeNsUri);
  553. $xmlWriter->writeAttribute('elementFormDefault', 'qualified');
  554. $xmlWriter->writeAttribute('targetNamespace', $objNsUri);
  555. $xmlWriter->writeAttribute('vc:minVersion', '1.1');
  556. $xmlWriter->startElement('xs:import');
  557. $xmlWriter->writeAttribute('namespace', $p5TypeNsUri);
  558. $xmlWriter->writeAttribute('schemaLocation', $p5TypeNsLocation);
  559. $xmlWriter->endElement();// xs:import
  560. $this->tableXsdViewXmlWriter($xmlWriter, $idStorage, $tblName);
  561. $xmlWriter->endElement();// xs:schema
  562. $xmlWriter->endDocument();
  563. }
  564. public function tableXsdViewXmlWriter(&$xmlWriter, $idStorage, $tblName) {
  565. $storage = DB::getStorage($idStorage);
  566. $schema = Schema_TableFactory::build($tblName, $idStorage, $_SERVER['SERVER_NAME']);
  567. $struct = $schema->getStruct();
  568. DBG::_('DBG', '>1', "struct", $struct, __CLASS__, __FUNCTION__, __LINE__);
  569. $typeName = "{$tblName}Type";
  570. $xmlWriter->startElement('xs:complexType');
  571. $xmlWriter->writeAttribute('name', $typeName);
  572. $xmlWriter->startElement('xs:sequence');
  573. $foreignKeys = [];
  574. {
  575. $dbName = DB::getPDO($idStorage)->getDatabaseName();
  576. if ('mysql' === DB::getPDO($idStorage)->getType()) {
  577. $foreignKeys = DB::getPDO($idStorage)->fetchAll("
  578. SELECT i.TABLE_SCHEMA, i.TABLE_NAME, i.CONSTRAINT_TYPE, i.CONSTRAINT_NAME, k.COLUMN_NAME, k.REFERENCED_TABLE_NAME, k.REFERENCED_COLUMN_NAME
  579. FROM information_schema.TABLE_CONSTRAINTS i
  580. LEFT JOIN information_schema.KEY_COLUMN_USAGE k ON i.CONSTRAINT_NAME = k.CONSTRAINT_NAME
  581. WHERE i.TABLE_SCHEMA = :db_name
  582. and i.TABLE_NAME = :tbl_name
  583. and i.CONSTRAINT_TYPE = 'FOREIGN KEY'
  584. ORDER BY i.TABLE_NAME
  585. ", [
  586. ':db_name' => $dbName,
  587. ':tbl_name' => $tblName,
  588. ]);
  589. // if ('CRM_WSKAZNIK' === $tblName) { // @example: CRM_WSKAZNIK.ID_ZASOB => CRM_LISTA_ZASOBOW.ID
  590. // $foreignKeys = [
  591. // [ 'TABLE_SCHEMA' => "SES_USERS2"
  592. // , 'TABLE_NAME' => "CRM_WSKAZNIK"
  593. // , 'CONSTRAINT_TYPE' => "FOREIGN KEY"
  594. // , 'CONSTRAINT_NAME' => "zasob"
  595. // , 'COLUMN_NAME' => "ID_ZASOB"
  596. // , 'REFERENCED_TABLE_NAME' => "CRM_LISTA_ZASOBOW"
  597. // , 'REFERENCED_COLUMN_NAME' => "ID"
  598. // ]
  599. // ];
  600. // }
  601. // $xmlWriter->writeComment("\$foreignKeys: " . var_export($foreignKeys, true));
  602. // TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_TYPE, CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
  603. // * * FOREIGN KEY * * * *
  604. }
  605. }
  606. foreach ($struct as $field) {
  607. $xmlWriter->startElement('xs:element');
  608. $xmlWriter->writeAttribute('name', $field['name']);
  609. $xmlWriter->writeAttribute('minOccurs', 0);// TODO: set minOccurs by default, etc.
  610. if ($field['is_nullable']) $xmlWriter->writeAttribute('nillable', 'true');
  611. if (null !== $field['default_value']) {
  612. $xmlWriter->writeAttribute('default', $field['default_value']);
  613. } else if (null === $field['default_value'] && $field['is_nullable']) {
  614. $xmlWriter->writeAttribute('default', $field['default_value']);
  615. } else {
  616. // TODO: Schema BUG?
  617. }
  618. if (empty($field['p5_restrictions'])) {
  619. $xmlWriter->writeAttribute('type', "p5Type:{$field['p5_type']}");
  620. } else {
  621. $xmlWriter->startElement('xs:simpleType');
  622. $xmlWriter->writeAttribute('base', "p5Type:{$field['p5_type']}");
  623. $xmlWriter->startElement('xs:restriction');
  624. if (!empty($field['p5_restrictions']['enumeration'])) {
  625. foreach ($field['p5_restrictions']['enumeration'] as $enumValue) {
  626. $xmlWriter->startElement('xs:enumeration');
  627. $xmlWriter->writeAttribute('value', $enumValue);
  628. $xmlWriter->endElement();// xs:enumeration
  629. }
  630. } else {
  631. // TODO: another restrictions...
  632. }
  633. $xmlWriter->endElement();// xs:restriction
  634. $xmlWriter->endElement();// xs:simpleType
  635. }
  636. $xmlWriter->endElement();// xs:element
  637. }
  638. if (!empty($foreignKeys)) {
  639. foreach ($foreignKeys as $key) {
  640. $xmlWriter->startElement('xs:element');
  641. $refPrefix = (DB::getPDO()->getZasobId() === $idStorage) ? 'p5_default_db' : "p5_zasob_{$idStorage}";
  642. $xmlWriter->writeAttribute('ref', "{$refPrefix}:{$key['REFERENCED_TABLE_NAME']}");
  643. $xmlWriter->startElement('xs:annotation');
  644. $xmlWriter->startElement('xs:appinfo');
  645. $xmlWriter->startElement('system_cache__appinfo:flat_relation_cache');
  646. $xmlWriter->writeAttribute("system_cache__appinfo:name", $key['COLUMN_NAME']);
  647. $xmlWriter->writeAttribute("system_cache__appinfo:xpath", "{$refPrefix}:{$key['REFERENCED_TABLE_NAME']}/{$key['REFERENCED_COLUMN_NAME']}");
  648. $xmlWriter->endElement();// system_cache__appinfo:flat_relation_cache
  649. $xmlWriter->endElement();// xs:appinfo
  650. $xmlWriter->endElement();// xs:annotation
  651. $xmlWriter->endElement();// xs:element
  652. }
  653. }
  654. $xmlWriter->endElement();// xs:sequence
  655. $xmlWriter->endElement();// xs:complexType
  656. return;
  657. // <xs:element maxOccurs="1" minOccurs="0" name="{$fldName}" nillable="true" type="xs:integer"/>
  658. $pKeyField = 'ID';//$storageObject->getPrimaryKeyFieldName();
  659. //DBG::_(true, true, "struct", $struct, __CLASS__, __FUNCTION__, __LINE__);
  660. foreach ($struct as $field) {
  661. $fldName = $vField->getName();
  662. $fldType = $vField->getType();
  663. $xsdType = $fldType->getTypeForXsd();
  664. if ($fldType->hasDefault()) {
  665. $fldDefault = $fldType->getDefault();
  666. if (!empty($fldDefault) || '0' === $fldDefault) {
  667. $elNode->setAttribute('default', $fldDefault);
  668. }
  669. }
  670. $fldRestrictions = $fldType->getRestrictions();
  671. if (empty($fldRestrictions)) {
  672. $elNode->setAttribute('type', "{$p5TypePrefix}:{$xsdType}");
  673. } else {
  674. $sType = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:simpleType');
  675. $elNode->appendChild($sType);
  676. $sTypeRes = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:restriction');
  677. $sType->appendChild($sTypeRes);
  678. $sTypeRes->setAttribute('base', "{$p5TypePrefix}:{$xsdType}");
  679. $enumList = $fldType->getEnumeration();
  680. if (empty($enumList)) {
  681. foreach ($fldRestrictions as $restricionName => $restrictionValue) {
  682. if ('maxLength' == $restricionName) {
  683. $sTypeResMaxLength = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:maxLength');
  684. $sTypeRes->appendChild($sTypeResMaxLength);
  685. $sTypeResMaxLength->setAttribute('value', $restrictionValue);
  686. } else if ('minLength' == $restricionName) {
  687. $sTypeResMinLength = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:minLength');
  688. $sTypeRes->appendChild($sTypeResMinLength);
  689. $sTypeResMinLength->setAttribute('value', $restrictionValue);
  690. } else if ('pattern' == $restricionName) {
  691. $sTypeResPattern = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:pattern');
  692. $sTypeRes->appendChild($sTypeResPattern);
  693. $sTypeResPattern->setAttribute('value', $restrictionValue);
  694. } else if ('fractionDigits' == $restricionName) {
  695. $sTypeResFractionDigits = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:fractionDigits');
  696. $sTypeRes->appendChild($sTypeResFractionDigits);
  697. $sTypeResFractionDigits->setAttribute('value', $restrictionValue);
  698. } else if ('totalDigits' == $restricionName) {
  699. $sTypeResTotalDigits = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:totalDigits');
  700. $sTypeRes->appendChild($sTypeResTotalDigits);
  701. $sTypeResTotalDigits->setAttribute('value', $restrictionValue);
  702. } else if ('maxExclusive' == $restricionName) {
  703. $sTypeResMaxExclusive = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:maxExclusive');
  704. $sTypeRes->appendChild($sTypeResMaxExclusive);
  705. $sTypeResMaxExclusive->setAttribute('value', $restrictionValue);
  706. } else if ('minExclusive' == $restricionName) {
  707. $sTypeResMinExclusive = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:minExclusive');
  708. $sTypeRes->appendChild($sTypeResMinExclusive);
  709. $sTypeResMinExclusive->setAttribute('value', $restrictionValue);
  710. } else if ('maxInclusive' == $restricionName) {
  711. $sTypeResMaxInclusive = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:maxInclusive');
  712. $sTypeRes->appendChild($sTypeResMaxInclusive);
  713. $sTypeResMaxInclusive->setAttribute('value', $restrictionValue);
  714. } else if ('minInclusive' == $restricionName) {
  715. $sTypeResMinInclusive = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:minInclusive');
  716. $sTypeRes->appendChild($sTypeResMinInclusive);
  717. $sTypeResMinInclusive->setAttribute('value', $restrictionValue);
  718. }
  719. /* TODO: xsd restrictions:
  720. enumeration Defines a list of acceptable values
  721. fractionDigits Specifies the maximum number of decimal places allowed. Must be equal to or greater than zero
  722. length Specifies the exact number of characters or list items allowed. Must be equal to or greater than zero
  723. maxExclusive Specifies the upper bounds for numeric values (the value must be less than this value)
  724. maxInclusive Specifies the upper bounds for numeric values (the value must be less than or equal to this value)
  725. maxLength Specifies the maximum number of characters or list items allowed. Must be equal to or greater than zero
  726. minExclusive Specifies the lower bounds for numeric values (the value must be greater than this value)
  727. minInclusive Specifies the lower bounds for numeric values (the value must be greater than or equal to this value)
  728. minLength Specifies the minimum number of characters or list items allowed. Must be equal to or greater than zero
  729. pattern Defines the exact sequence of characters that are acceptable
  730. totalDigits Specifies the exact number of digits allowed. Must be greater than zero
  731. whiteSpace Specifies how white space (line feeds, tabs, spaces, and carriage returns) is handled
  732. */
  733. }
  734. } else {
  735. foreach ($enumList as $enumValue) {
  736. $sTypeResEnum = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:enumeration');
  737. $sTypeRes->appendChild($sTypeResEnum);
  738. $sTypeResEnum->setAttribute('value', $enumValue);
  739. }
  740. }
  741. }
  742. }
  743. $elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xs:element');
  744. $rootNode->appendChild($elNode);
  745. $elNode->setAttribute('name', $tblName);
  746. $elNode->setAttribute('type', "{$objNs}:{$typeName}");
  747. header('Content-type: application/xml');
  748. echo $dom->saveXML();
  749. exit;
  750. }
  751. public function navView() {
  752. $backLabel = 'back';
  753. $backLink = 'index.php?_route=Storage';
  754. $backDisabled = true;
  755. $currentLabel = 'Storage';
  756. $currentLink = 'index.php?_route=Storage';
  757. if ($task = V::get('_task', '', $_REQUEST)) {
  758. $currentLink = "index.php?_route=Storage&_task={$task}";
  759. $backDisabled = false;
  760. $idStorage = V::get('idStorage', 0, $_REQUEST, 'int');
  761. $tblName = V::get('table', '', $_REQUEST, 'word');
  762. $objName = V::get('object', '', $_REQUEST, 'word');
  763. $namespace = V::get('namespace', '', $_REQUEST, 'word');
  764. switch ($task) {
  765. case 'obejctList':
  766. $backLabel = 'Storage';
  767. $backLink = $this->getLink();
  768. $currentLink = $this->getLink('obejctList', ['idStorage' => $idStorage]);
  769. break;
  770. case 'tableList':
  771. $backLabel = 'Storage';
  772. $backLink = $this->getLink();
  773. $currentLink = $this->getLink('tableList', ['idStorage' => $idStorage]);
  774. break;
  775. case 'viewList':
  776. $backLabel = 'Storage';
  777. $backLink = $this->getLink();
  778. $currentLink = $this->getLink('viewList', ['idStorage' => $idStorage]);
  779. break;
  780. case 'rawInfo':
  781. $backLabel = 'Storage';
  782. $backLink = $this->getLink();
  783. $currentLink = $this->getLink('rawInfo', ['idStorage' => $idStorage]);
  784. break;
  785. case 'tableStruct':
  786. $backLabel = "Tabele [{$idStorage}]";
  787. $backLink = $this->getLink('tableList', ['idStorage' => $idStorage]);
  788. $currentLink = $this->getLink('tableStruct', ['idStorage' => $idStorage, 'table' => $tblName]);
  789. break;
  790. case 'objectStruct':
  791. $backLabel = "Obiekty [{$idStorage}]";
  792. $backLink = $this->getLink('tableList', ['idStorage' => $idStorage]);// TODO: mv tableList to objectList
  793. $currentLink = $this->getLink('objectStruct', ['idStorage' => $idStorage, 'namespace' => $namespace]);
  794. break;
  795. case 'coreObjectStruct':
  796. $backLabel = "Obiekty podstawowe";
  797. $backLink = Router::getRoute('Storage_TestObj')->getLink('coreObjectList', ['idStorage' => $idStorage]);
  798. $currentLink = $this->getLink('coreObjectStruct', ['idStorage' => $idStorage, 'object' => $objName]);
  799. break;
  800. }
  801. switch ($task) {
  802. case 'tableList': $currentLabel = "Tabele [{$idStorage}]"; break;
  803. case 'viewList': $currentLabel = "Widoki [{$idStorage}]"; break;
  804. case 'rawInfo': $currentLabel = "Raw info [{$idStorage}]"; break;
  805. case 'tableStruct': $currentLabel = "Struktura tabeli '{$tblName}'"; break;
  806. case 'objectStruct': $currentLabel = "Obiekt '{$namespace}'"; break;
  807. case 'coreObjectList': $currentLabel = "Obiekty podstawowe"; break;
  808. case 'coreObjectStruct': $currentLabel = "Obiekt '{$objName}'"; break;
  809. case 'objectList': $currentLabel = "Obiekty z aktualnej domeny"; break;// TODO: domain from $_GET
  810. }
  811. }
  812. echo UI::h('nav', ['class'=>"navbar navbar-default navbar-static-top", 'style'=>"z-index:999"], [
  813. UI::h('div', ['class'=>"container-fluid"], [
  814. UI::h('div', ['class'=>"navbar-left"], [
  815. UI::h('ul', ['class'=>"nav navbar-nav navbar-center"], [
  816. UI::h('li', [], [
  817. UI::h('a', ['href'=>$backLink, 'class'=>"btn" . ($backDisabled ? ' disabled' : '')], '<i class="glyphicon glyphicon-chevron-left"></i> ' . $backLabel)
  818. ])
  819. ])
  820. ]),
  821. UI::h('div', ['class'=>"navbar-left"], [
  822. UI::h('ul', ['class'=>"nav navbar-nav navbar-center"], [
  823. UI::h('li', [], [
  824. UI::h('a', ['href'=>$currentLink, 'class'=>"btn"], $currentLabel)
  825. ])
  826. ])
  827. ]),
  828. UI::h('div', ['class'=>"navbar-right"], [
  829. // <ul class="nav navbar-nav navbar-right">
  830. // <li><a href="#">Link</a></li>
  831. // <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
  832. // <ul class="dropdown-menu">
  833. // <li><a href="#">Action</a></li>
  834. // <li><a href="#">Another action</a></li>
  835. // <li><a href="#">Something else here</a></li>
  836. // <li role="separator" class="divider"></li>
  837. // <li><a href="#">Separated link</a></li>
  838. // </ul>
  839. // </li>
  840. // </ul>
  841. ])
  842. ])
  843. ]);
  844. }
  845. public function getStorageList() {
  846. $storageList = array();
  847. $sth = DB::getPDO()->prepare("
  848. select z.ID, z.`DESC`, z.`TYPE`
  849. from CRM_LISTA_ZASOBOW z
  850. where z.TYPE in('BAZA_DANYCH','DATABASE_MYSQL','DATABASE_POSTGRESQL')
  851. ");
  852. $sth->execute();
  853. $rows = $sth->fetchAll();
  854. foreach ($rows as $row) {
  855. $storageList[$row['ID']] = $row;
  856. }
  857. return $storageList;
  858. }
  859. public function addAclObjectToZasobyAction() {// sends JSON
  860. $response = new stdClass();
  861. try {
  862. $idStorage = V::get('idStorage', '', $_GET);
  863. $namespace = V::get('namespace', '', $_GET);
  864. if (empty($idStorage)) throw new HttpException("Missing idStorage param");
  865. if (empty($namespace)) throw new HttpException("Missing namespace param");
  866. $objectStorage = SchemaFactory::loadDefaultObject('SystemObject');
  867. $items = $objectStorage->getItems([
  868. 'f_namespace' => "={$namespace}",
  869. ]);
  870. if (empty($items)) throw new Exception("SystemObject '{$namespace}' not found");
  871. $objectItem = reset($items);
  872. if (empty($objectItem)) throw new Exception("SystemObject '{$namespace}' not found");
  873. DBG::log($objectItem, 'array', 'object acl $objectItem');
  874. if ($objectItem['idZasob'] > 0) {
  875. // TODO: check if realy exists? @see SchemaFactory::loadDefaultObject('SystemObject')::updateCache()
  876. $response->_replaceButtonNode = "[{$objectItem['idZasob']}]";
  877. throw new AlertInfoException("Zasob '{$objectItem['namespace']}' już istnieje - nr '{$objectItem['idZasob']}'");
  878. }
  879. $idZasobFound = 0;
  880. switch ($objectItem['_type']) {
  881. case 'TableAcl': $idZasobFound = DB::getPDO()->fetchValue(" select ID from CRM_LISTA_ZASOBOW where PARENT_ID = {$objectItem['idDatabase']} and `DESC` = '{$objectItem['name']}' "); break;
  882. case 'AntAcl': $idZasobFound = DB::getPDO()->fetchValue(" select ID from CRM_LISTA_ZASOBOW where PARENT_ID = {$objectItem['idDatabase']} and `DESC` = '{$objectItem['namespace']}' "); break;
  883. default: throw new Exception("Not implemented acl type '{$objectItem['_type']}'");
  884. }
  885. if ($idZasobFound > 0) {
  886. DB::getPDO()->update($objectStorage->_rootTableName, 'namespace', $objectItem['namespace'], [
  887. 'idZasob' => $idZasobFound
  888. ]);
  889. $response->id = $idZasobFound;
  890. throw new AlertSuccessException("Zasob '{$objectItem['namespace']}' już istnieje - nr '{$idZasobFound}' - cache zaktualizowany");
  891. }
  892. try {
  893. $acl = User::getAcl()->getObjectAcl('default_db', 'crm_lista_zasobow');
  894. } catch (Exception $e) {
  895. DBG::log($e);
  896. throw new Exception("Brak dostępu do tabeli Zasoby");
  897. }
  898. if (empty($objectItem['idDatabase'])) throw new Exception("Missing database id");
  899. if ($idStorage != $objectItem['idDatabase']) throw new Exception("Database id must be the same");
  900. if (empty($objectItem['_rootTableName'])) throw new Exception("Missing root table name");
  901. switch ($objectItem['_type']) {
  902. case 'TableAcl':
  903. $newZasobItem = [
  904. 'PARENT_ID' => $objectItem['idDatabase'],
  905. 'TYPE' => 'TABELA',
  906. 'DESC' => $objectItem['_rootTableName'],
  907. 'DESC_PL' => $objectItem['name'],
  908. ];
  909. break;
  910. case 'AntAcl':
  911. $newZasobItem = [
  912. 'PARENT_ID' => $objectItem['idDatabase'],
  913. 'TYPE' => 'TABELA',
  914. 'DESC' => $objectItem['namespace'],
  915. 'DESC_PL' => $objectItem['name'],
  916. ];
  917. break;
  918. default: throw new Exception("Not implemented acl type '{$objectItem['_type']}'");
  919. }
  920. $idCreated = $acl->addItem($newZasobItem);
  921. if (!$idCreated) throw new Exception("Nie udało się utworzyć nowego rekordu!");
  922. try {
  923. DB::getPDO()->update($objectStorage->_rootTableName, 'namespace', $objectItem['namespace'], [
  924. 'idZasob' => $idCreated
  925. ]);
  926. } catch (Exception $e) {
  927. DBG::log($e);
  928. }
  929. $response->id = $idCreated;
  930. $response->record = $acl->getItem($idCreated);
  931. $response->_replaceButtonNode = "[{$idCreated}]";
  932. throw new AlertSuccessException("Utworzono pomyślnie rekord nr {$idCreated}");
  933. } catch (AlertSuccessException $e) {
  934. $response->type = 'success';
  935. $response->msg = $e->getMessage();
  936. } catch (AlertInfoException $e) {
  937. $response->type = 'info';
  938. $response->msg = $e->getMessage();
  939. } catch (Exception $e) {
  940. $response->type = 'error';
  941. $response->msg = $e->getMessage();
  942. DBG::log($e);
  943. }
  944. Response::sendJsonExit($response);
  945. }
  946. public function addAclObjectToZasobyAjaxAction() {
  947. DBG::log($_REQUEST, 'array', '$_REQUEST');
  948. Response::sendTryCatchJson(array($this, 'addAclObjectToZasobyAjax'), $_REQUEST);
  949. }
  950. public function addAclObjectToZasobyAjax($args) {
  951. $namespace = V::get('namespace', '', $args);
  952. if (empty($namespace)) throw new HttpException("Missing namespace");
  953. $idStorage = V::get('idStorage', '', $args);
  954. if (empty($idStorage)) throw new HttpException("Missing idStorage");
  955. $objectStorage = SchemaFactory::loadDefaultObject('SystemObject');
  956. $items = $objectStorage->getItems([
  957. 'f_namespace' => "={$namespace}",
  958. ]);
  959. if (empty($items)) throw new Exception("SystemObject '{$namespace}' not found");
  960. $objectItem = reset($items);
  961. if (empty($objectItem)) throw new Exception("SystemObject '{$namespace}' not found");
  962. DBG::log($objectItem, 'array', 'object acl $objectItem');
  963. if ($objectItem['idZasob'] > 0) {
  964. // TODO: check if realy exists? @see SchemaFactory::loadDefaultObject('SystemObject')::updateCache()
  965. return [
  966. 'type' => 'info',
  967. 'msg' => "Zasob '{$objectItem['namespace']}' już istnieje - nr '{$objectItem['idZasob']}'",
  968. 'body' => [
  969. 'id' => $objectItem['idZasob'],
  970. 'record' => $acl->getItem($objectItem['idZasob']),
  971. '_replaceButtonNode' => "[{$objectItem['idZasob']}]",
  972. ]
  973. ];
  974. }
  975. $idZasobFound = 0;
  976. if ('StorageAcl' === $objectItem['_type']) {
  977. if (!$objectItem['idDatabase']) throw new Exception("Brak idDatabase dla '{$objectItem['namespace']}'");
  978. }
  979. switch ($objectItem['_type']) {
  980. case 'TableAcl': $idZasobFound = DB::getPDO()->fetchValue(" select ID from CRM_LISTA_ZASOBOW where PARENT_ID = {$objectItem['idDatabase']} and `DESC` = '{$objectItem['name']}' "); break;
  981. case 'AntAcl': $idZasobFound = DB::getPDO()->fetchValue(" select ID from CRM_LISTA_ZASOBOW where PARENT_ID = {$objectItem['idDatabase']} and `DESC` = '{$objectItem['namespace']}' "); break;
  982. case 'StorageAcl': $idZasobFound = DB::getPDO()->fetchValue(" select ID from CRM_LISTA_ZASOBOW where PARENT_ID = {$objectItem['idDatabase']} and `DESC` = '{$objectItem['namespace']}' "); break;
  983. default: throw new Exception("Not implemented acl type '{$objectItem['_type']}'");
  984. }
  985. if ($idZasobFound > 0) {
  986. DB::getPDO()->update($objectStorage->_rootTableName, 'namespace', $objectItem['namespace'], [
  987. 'idZasob' => $idZasobFound
  988. ]);
  989. return [
  990. 'type' => 'info',
  991. 'msg' => "Zasob '{$objectItem['namespace']}' już istnieje - nr '{$idZasobFound}' - cache zaktualizowany",
  992. 'body' => [
  993. 'id' => $idZasobFound,
  994. 'record' => $acl->getItem($idZasobFound),
  995. '_replaceButtonNode' => "[{$idZasobFound}]",
  996. ]
  997. ];
  998. }
  999. try {
  1000. $acl = User::getAcl()->getObjectAcl('default_db', 'crm_lista_zasobow');
  1001. } catch (Exception $e) {
  1002. DBG::log($e);
  1003. throw new Exception("Brak dostępu do tabeli Zasoby");
  1004. }
  1005. if (empty($objectItem['idDatabase'])) throw new Exception("Missing database id");
  1006. if ($idStorage != $objectItem['idDatabase']) throw new Exception("Database id must be the same");
  1007. if (empty($objectItem['_rootTableName'])) throw new Exception("Missing root table name");
  1008. switch ($objectItem['_type']) {
  1009. case 'TableAcl':
  1010. $newZasobItem = [
  1011. 'PARENT_ID' => $objectItem['idDatabase'],
  1012. 'TYPE' => 'TABELA',
  1013. 'DESC' => $objectItem['_rootTableName'],
  1014. 'DESC_PL' => $objectItem['name'],
  1015. ];
  1016. break;
  1017. case 'AntAcl':
  1018. $newZasobItem = [
  1019. 'PARENT_ID' => $objectItem['idDatabase'],
  1020. 'TYPE' => 'TABELA',
  1021. 'DESC' => $objectItem['namespace'],
  1022. 'DESC_PL' => $objectItem['name'],
  1023. ];
  1024. break;
  1025. case 'StorageAcl':
  1026. $newZasobItem = [
  1027. 'PARENT_ID' => $objectItem['idDatabase'],
  1028. 'TYPE' => 'TABELA',
  1029. 'DESC' => $objectItem['namespace'],
  1030. 'DESC_PL' => $objectItem['name'],
  1031. ];
  1032. break;
  1033. default: throw new Exception("Not implemented acl type '{$objectItem['_type']}'");
  1034. }
  1035. $idCreated = $acl->addItem($newZasobItem);
  1036. if (!$idCreated) throw new Exception("Nie udało się utworzyć nowego rekordu!");
  1037. try {
  1038. DB::getPDO()->update($objectStorage->_rootTableName, 'namespace', $objectItem['namespace'], [
  1039. 'idZasob' => $idCreated
  1040. ]);
  1041. } catch (Exception $e) {
  1042. DBG::log($e);
  1043. }
  1044. return [
  1045. 'type' => 'success',
  1046. 'msg' => "Utworzono pomyślnie rekord nr {$idCreated}",
  1047. 'body' => [
  1048. 'id' => $idCreated,
  1049. 'record' => $acl->getItem($idCreated),
  1050. '_replaceButtonNode' => "[{$idCreated}]",
  1051. ]
  1052. ];
  1053. }
  1054. public function addCellToZasobyAction() {// sends JSON
  1055. $response = new stdClass();
  1056. try {
  1057. $idStorage = V::get('storageId', '', $_GET);
  1058. $tblName = V::get('tblName', '', $_GET, 'word');
  1059. $cellName = V::get('cellName', '', $_GET, 'word');
  1060. if (empty($tblName)) throw new HttpException("Wrong table name");
  1061. if (empty($tblName)) throw new HttpException("Wrong cell name");
  1062. $storage = DB::getStorage($idStorage);
  1063. $tableStruct = $storage->getTableStruct($tblName);
  1064. $zasobStorageId = $storage->getZasobId();
  1065. if (!is_numeric($zasobStorageId)) throw new HttpException("Storage id is not set in config file");
  1066. $idTable = $this->fetchTableId($zasobStorageId, $tblName);
  1067. if ($idTable <= 0) throw new Exception("Zasob tabela '{$tblName}' nie istnieje");
  1068. try {
  1069. $acl = User::getAcl()->getObjectAcl('default_db', 'crm_lista_zasobow');
  1070. } catch (Exception $e) {
  1071. throw new Exception("Brak dostępu do tabeli Zasoby");
  1072. }
  1073. $item = array();
  1074. $item['PARENT_ID'] = $idTable;
  1075. $item['TYPE'] = 'KOMORKA';
  1076. $item['DESC'] = $cellName;
  1077. $item['DESC_PL'] = $cellName;
  1078. if (DBG::isActive()) $response->_itemToCreate = $item;
  1079. $createdId = $acl->addItem($item);
  1080. if (!$createdId) throw new Exception("Nie udało się utworzyć nowego rekordu!");
  1081. $response->id = $createdId;
  1082. $response->record = $acl->getItem($createdId);
  1083. $response->_replaceButtonNode = "[{$createdId}]";
  1084. throw new AlertSuccessException("Utworzono pomyślnie rekord nr {$createdId}");
  1085. } catch (AlertSuccessException $e) {
  1086. $response->type = 'success';
  1087. $response->msg = $e->getMessage();
  1088. } catch (AlertInfoException $e) {
  1089. $response->type = 'info';
  1090. $response->msg = $e->getMessage();
  1091. } catch (Exception $e) {
  1092. $response->type = 'error';
  1093. $response->msg = $e->getMessage();
  1094. }
  1095. Response::sendJsonExit($response);
  1096. }
  1097. public function fetchTableId($idZasobStorage, $tblName) {
  1098. $rows = DB::getPDO()->fetchAll("
  1099. select z.`ID`, z.`DESC`
  1100. from `CRM_LISTA_ZASOBOW` z
  1101. where z.`PARENT_ID`='{$idZasobStorage}'
  1102. and z.`DESC`='{$tblName}'
  1103. and z.`A_STATUS` in('NORMAL','WAITING')
  1104. ");
  1105. if (!empty($rows)) return (int)$rows[0]['ID'];
  1106. return null;
  1107. }
  1108. public function systemObjectsStructAction() {
  1109. UI::gora();
  1110. UI::menu();
  1111. $this->navView();
  1112. try {
  1113. throw new Exception("TODO: F." . __FUNCTION__ . ' L.' . __LINE__);
  1114. // $coreObjlist = OBJXSD::getSystemObjectsStruct();
  1115. // $objectList = array();
  1116. // foreach ($coreObjlist as $objName) {
  1117. // $objItem = array();
  1118. // $objItem['name'] = $objName;
  1119. // $objItem['struktura'] = '<a href="index.php?_route=Storage&_task=systemObjectsStruct&object=' . $objName . '">' . "struct" . '</a>';
  1120. // // $objItem['label'] = "";// TODO: read from json
  1121. // $objectList[] = $objItem;
  1122. // }
  1123. // usort($objectList, function($rowA, $rowB) {
  1124. // $a = $rowA['nazwa']; $b = $rowB['nazwa'];
  1125. // if ($a == $b) return 0;
  1126. // return ($a < $b) ? -1 : 1;
  1127. // });
  1128. //
  1129. // DBG::table("objectList", $objectList, __CLASS__, __FUNCTION__, __LINE__);
  1130. } catch (Exception $e) {
  1131. UI::alert('danger', "Error #" . $e->getCode() . "|" . $e->getLine() . ": " . $e->getMessage());
  1132. }
  1133. UI::dol();
  1134. }
  1135. public function systemObjectsAction() {// TableAjax view: index.php?_route=ViewTableAjax&namespace=default_objects/SystemObject
  1136. UI::gora();
  1137. UI::menu();
  1138. $this->navView();
  1139. try {
  1140. Lib::loadClass('Schema_SystemObjectStorageAcl');
  1141. $acl = new Schema_SystemObjectStorageAcl();
  1142. UI::table([
  1143. 'rows' => array_map(
  1144. function ($item) {
  1145. return [
  1146. 'ns' => $item['namespace'],
  1147. 'nazwa' => $item['name'],
  1148. 'type' => $item['_type'],
  1149. 'edit' => '<a href="index.php?_route=ViewTableAjax&namespace=' . $item['namespace'] . '">edit</a>',
  1150. 'wfs Describe' => '<a href="wfs-data.php/default_db/?SERVICE=WFS&VERSION=1.0.0&SRSNAME=EPSG:3003&REQUEST=DescribeFeatureType&TYPENAME=' . $item['typeName'] . '">DescribeFeatureType</a>',
  1151. 'wfs getFeature' => '<a href="wfs-data.php/default_db/?SERVICE=WFS&VERSION=1.0.0&SRSNAME=EPSG:3003&REQUEST=GetFeature&TYPENAME=' . $item['typeName'] . '&MAXFEATURES=10">GetFeature</a> (max:10)'
  1152. ];
  1153. }
  1154. , $acl->getItems([
  1155. 'order_by' => 'namespace',
  1156. 'order_dir' => 'asc'
  1157. ])
  1158. )
  1159. ]);
  1160. } catch (Exception $e) {
  1161. UI::alert('danger', "Error #" . $e->getCode() . "|" . $e->getLine() . ": " . $e->getMessage());
  1162. DBG::log($e);
  1163. }
  1164. UI::dol();
  1165. }
  1166. public function activateObjectAjaxAction() {
  1167. DBG::log($_REQUEST, 'array', '$_REQUEST');
  1168. Response::sendTryCatchJson(array($this, 'activateObjectAjax'), $_REQUEST);
  1169. }
  1170. public function activateObjectAjax($args) {
  1171. $namespace = V::get('namespace', '', $args);
  1172. if (empty($namespace)) throw new Exception("Missing param namespace");
  1173. $item = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ]);
  1174. if (empty($item)) throw new HttpException("Namespace not found", 404);
  1175. DBG::log($item, 'array', "TODO: activateObjectAjax \$item");
  1176. if ($item['isObjectActive']) throw new AlertSuccessException("Namespace '{$namespace}' already active");
  1177. if (!$item['hasStruct']) throw new Exception("Missing struct for namespace '{$namespace}'");
  1178. if (!$item['isStructInstalled']) throw new Exception("Namespace struct not installed '{$namespace}'");
  1179. $activeFields = array_filter($item['field'], function ($field) {
  1180. if (!$field['isActive']) return false;
  1181. if (!$field['idZasob']) return false;
  1182. return true;
  1183. });
  1184. if (empty($activeFields)) throw new Exception("Missing active fields for namespace '{$namespace}'");
  1185. $affected = SchemaFactory::loadDefaultObject('SystemObject')->updateItem([
  1186. 'namespace' => $item['namespace'],
  1187. 'isObjectActive' => 1
  1188. ]);
  1189. if ($affected < 0) throw new Exception("Nie udało się aktywować obiektu '{$namespace}'");
  1190. return [
  1191. 'type' => "success",
  1192. 'msg' => "Aktywowano obiekt '{$namespace}'",
  1193. 'body' => [
  1194. 'isObjectActive' => 1
  1195. ]
  1196. ];
  1197. }
  1198. }