AclReinstall.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. Lib::loadClass('RouteBase');
  3. Lib::loadClass('Router');
  4. Lib::loadClass('Response');
  5. Lib::loadClass('UI');
  6. Lib::loadClass('SchemaFactory');
  7. class Route_Storage_AclReinstall extends RouteBase {
  8. public function handleAuth() {
  9. if (!User::logged()) {
  10. User::authByRequest();
  11. }
  12. }
  13. public function defaultAction() {
  14. UI::gora();
  15. UI::startContainer();
  16. try {
  17. $namespace = V::get('namespace', '', $_GET);
  18. if (empty($namespace)) throw new Exception("Missing param namespace");
  19. echo UI::h('h3', [], $namespace);
  20. echo UI::h('p', [], [
  21. UI::h('a', [
  22. 'href' => Router::getRoute('Storage_AclStruct')->getLink('', [ 'namespace' => $namespace ]),
  23. 'class' => "btn btn-md btn-link",
  24. ], "<i class=\"glyphicon glyphicon-arrow-left\"></i> Wróć do struktury"),
  25. ]);
  26. if ('reinstall' == V::get('_postTask', '', $_POST)) {
  27. Lib::loadClass('Schema_SystemObjectFieldStorageAcl');
  28. $objFieldAcl = new Schema_SystemObjectFieldStorageAcl();
  29. $objFieldAcl->updateCache($namespace);
  30. DBG::nicePrint([
  31. 'idInstance' => ACL::getInstanceId($namespace),
  32. 'rootInstance' => ACL::getRootNamespace($namespace),
  33. 'conf' => ACL::fetchInstanceConfig($namespace),
  34. 'table' => ACL::getInstanceTable($namespace),
  35. ], "dbg");
  36. $item = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ]);
  37. $childRefList = ACL::getChildRefFullList($namespace);
  38. DBG::nicePrint($childRefList, '$childRefList');
  39. DBG::nicePrint($item, '$item');
  40. $activeFields = array_filter($item['field'], function ($field) {
  41. return ($field['isActive'] > 0);
  42. });
  43. $fieldNsList = array_map(function ($field) {
  44. return $field['fieldNamespace'];
  45. }, $activeFields);
  46. DBG::nicePrint($fieldNsList, '$fieldNsList');
  47. if ('AntAcl' === $item['_type']) {
  48. foreach ($childRefList as $childRef) { // [ namespace, A_STATUS ]
  49. if ($childRef['A_STATUS'] !== 'DELETED' && !in_array($childRef['namespace'], $fieldNsList)) {
  50. UI::alert('danger', "remove ref config for '{$childRef['namespace']}' ...");
  51. if (!$childRef['ID']) throw new Exception("Missing ref config ID");
  52. DB::getPDO()->update('CRM_REF_CONFIG', 'ID', $childRef['ID'], [
  53. 'A_STATUS' => 'DELETED',
  54. 'A_LAST_ACTION_DATE' => 'NOW()',
  55. ]);
  56. }
  57. else if ($childRef['A_STATUS'] !== 'DELETED' && in_array($childRef['namespace'], $fieldNsList)) {
  58. UI::alert('info', "ref config for '{$childRef['namespace']}' active - OK");
  59. }
  60. else if ($childRef['A_STATUS'] === 'DELETED' && in_array($childRef['namespace'], $fieldNsList)) {
  61. UI::alert('warning', "activate ref config for '{$childRef['namespace']}' ...");
  62. if (!$childRef['ID']) throw new Exception("Missing ref config ID");
  63. DB::getPDO()->update('CRM_REF_CONFIG', 'ID', $childRef['ID'], [
  64. 'A_STATUS' => 'NORMAL',
  65. 'A_LAST_ACTION_DATE' => 'NOW()',
  66. ]);
  67. }
  68. else if ($childRef['A_STATUS'] === 'DELETED' && !in_array($childRef['namespace'], $fieldNsList)) {
  69. UI::alert('info', "ref config for '{$childRef['namespace']}' removed - OK");
  70. }
  71. else {
  72. UI::alert('danger', "Not implemented action for '{$childRef['namespace']}'");
  73. }
  74. }
  75. // TODO: create missing refConfig - field is not in $childRefList
  76. }
  77. {
  78. if ('AntAcl' === $item['_type']) {
  79. $dbName = DB::getPDO()->getDatabaseName();
  80. $sqlFunBody = ACL::generateIsInstanceFunctionBody($namespace, $item);
  81. DBG::nicePrint($sqlFunBody, "\$sqlFunBody");
  82. $idInstance = ACL::getInstanceId($namespace);
  83. DB::getPDO()->execSql(" DROP FUNCTION IF EXISTS `{$dbName}`.`isInstance_{$idInstance}` ");
  84. // CREATE
  85. // [DEFINER = { user | CURRENT_USER }]
  86. // FUNCTION sp_name ([func_parameter[,...]])
  87. // RETURNS type
  88. // [characteristic ...] routine_body
  89. DB::getPDO()->execSql("
  90. CREATE DEFINER=`root`@`localhost`
  91. FUNCTION `{$dbName}`.`isInstance_{$idInstance}` ( pk INT(11) )
  92. RETURNS TINYINT(1)
  93. {$sqlFunBody}
  94. ");
  95. }
  96. }
  97. return;
  98. }
  99. echo UI::hButtonPost("Reinstall", [
  100. 'data' => [
  101. '_postTask' => 'reinstall'
  102. ],
  103. 'class' => 'btn btn-md btn-danger',
  104. 'title' => "Reinstall structure"
  105. ]);
  106. echo '<hr>';
  107. try {
  108. $this->printReinstallPreview($namespace);
  109. } catch (Exception $e) {
  110. DBG::log($e);
  111. UI::alert('danger', $e->getMessage());
  112. }
  113. } catch (Exception $e) {
  114. UI::alert('danger', "Error #" . $e->getCode() . "|" . $e->getLine() . ": " . $e->getMessage());
  115. DBG::log($e);
  116. }
  117. UI::endContainer();
  118. UI::dol();
  119. }
  120. public function printReinstallPreview($namespace) {
  121. $objectItem = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => "*,field" ]);
  122. DBG::log($objectItem, 'array', '$objectItem preview');
  123. switch ($objectItem['_type']) {
  124. case 'AntAcl': $this->printReinstallAntAclPreview($objectItem); break;
  125. case 'TableAcl': $this->printReinstallTableAclPreview($objectItem); break;
  126. default: throw new Exception("TODO: Not Implemented type '{$objectItem['_type']}'");
  127. }
  128. }
  129. public function printReinstallAntAclPreview($item) {
  130. Lib::loadClass('Schema_SystemObjectFieldStorageAcl');
  131. $antAclPath = Schema_SystemObjectFieldStorageAcl::getAntAclXsdBasePath($item['typeName']);
  132. if (!file_exists("{$antAclPath}/build.xml")) throw new Exception("Ant build file not exists");
  133. Lib::loadClass('XML');
  134. $xsdType = XML::getXsdTypeFromXsdSchema("{$antAclPath}/{$item['name']}.xsd", $namespace = $item['namespace'], $name = $item['name']);
  135. DBG::nicePrint($xsdType, '$xsdType');
  136. if (empty($xsdType['struct'])) throw new Exception("Field list not found for '{$item['namespace']}'");
  137. foreach ($xsdType['struct'] as $fieldName => $x) {
  138. $listEnum = [];
  139. if (!empty($x['restrictions']['enumeration'])) {
  140. $listEnum = $x['restrictions']['enumeration'];
  141. unset($x['restrictions']['enumeration']);
  142. }
  143. if (!empty($listEnum)) {
  144. DBG::log($listEnum, 'array', "\$listEnum for field '{$fieldName}'");
  145. }
  146. }
  147. $old = [
  148. 'fields' => array_map(function ($field) { return $field['fieldNamespace']; }, $item['field']),
  149. ];
  150. $new = [
  151. 'fields' => array_keys($xsdType['struct']),
  152. ];
  153. sort($old['fields']);
  154. sort($new['fields']);
  155. $diffFieldsToCreate = array_diff($new['fields'], $old['fields']);
  156. $diffFieldsToRemove = array_diff($old['fields'], $new['fields']);
  157. $sameFields = array_intersect($new['fields'], $old['fields']);
  158. echo (!empty($diffFieldsToCreate))
  159. ? UI::h('details', [ 'open' => "open" ], [
  160. UI::h('summary', [], "Pola do dodania (".count($diffFieldsToCreate)."):"),
  161. UI::h('ul', [], array_map(function ($fieldName) {
  162. return UI::h('li', [], $fieldName);
  163. }, $diffFieldsToCreate)),
  164. ])
  165. : UI::h('p', [ 'style' => "font-style:italic" ], "Brak pól do dodania");
  166. echo (!empty($diffFieldsToRemove))
  167. ? UI::h('details', [ 'open' => "open", 'style' => "margin:4px 0; color:#8a6d3b; background-color:#fcf8e3; border:1px solid #faebcc;" ], [
  168. UI::h('summary', [ 'style' => "padding:4px; outline:none; cursor:pointer" ], "Pola do usunięcia (".count($diffFieldsToRemove)."):"),
  169. UI::h('ul', [], array_map(function ($fieldName) {
  170. return UI::h('li', [], $fieldName);
  171. }, $diffFieldsToRemove)),
  172. ])
  173. : UI::h('p', [ 'style' => "font-style:italic" ], "Brak pól do usunięcia");
  174. foreach ($sameFields as $fieldName) {
  175. // UI::alert('warning', "TODO: is field changed? '{$fieldName}'");
  176. $oldField = array_filter($item['field'], function ($field) use ($fieldName) { return ( $fieldName === $field['fieldNamespace'] ); });
  177. $oldField = ($oldField) ? reset($oldField) : null;
  178. // DBG::nicePrint($oldField, "\$oldField '$fieldName'");
  179. $newField = $xsdType['struct'][$fieldName];
  180. // DBG::nicePrint($newField, "\$newField '$fieldName'");
  181. $fieldDiff = [];
  182. if ($newField['type'] !== $oldField['xsdType']) $fieldDiff[] = 'xsdType';
  183. if ($newField['minOccurs'] != $oldField['minOccurs']) $fieldDiff[] = 'minOccurs';
  184. if ($newField['maxOccurs'] != $oldField['maxOccurs']) $fieldDiff[] = 'maxOccurs';
  185. if (json_encode($newField['restrictions']) !== $oldField['xsdRestrictions']) $fieldDiff[] = 'xsdRestrictions';
  186. if (json_encode($newField['appInfo']) !== $oldField['appInfo']) $fieldDiff[] = 'appInfo';
  187. echo (!empty($fieldDiff))
  188. ? UI::h('p', [ 'style' => "" ], "Pole '{$fieldName}' - zmiany: " . implode(", ", $fieldDiff))
  189. : UI::h('p', [ 'style' => "font-style:italic" ], "Pole '{$fieldName}' - bez zmian");
  190. }
  191. throw new Exception("TODO: Podgląd zmian dla AntAcl {$item['namespace']} ...");
  192. }
  193. public function printReinstallTableAclPreview($item) {
  194. throw new Exception("TODO: Podgląd zmian dla tabeli {$item['namespace']} ...");
  195. }
  196. }