Router::getRoute('Storage_AclStruct')->getLink('', [ 'namespace' => $namespace ]), 'class' => "btn btn-md btn-link", ], " Wróć do struktury"), " | ", UI::h('a', [ 'href' => $this->getLink('viewXsdSource', [ 'namespace' => $namespace ]), 'class' => "btn btn-md btn-link", 'target' => "_blank", ], "Otwórz plik xsd (źródłowy)"), ]); if ('reinstall' == V::get('_postTask', '', $_POST)) { $this->reinstallAcl($namespace); return; } echo UI::hButtonPost("Reinstall", [ 'data' => [ '_postTask' => 'reinstall' ], 'class' => 'btn btn-md btn-danger', 'title' => "Reinstall structure" ]); echo '
'; try { $this->printReinstallPreview($namespace); } catch (Exception $e) { DBG::log($e); UI::alert('danger', $e->getMessage()); } } catch (Exception $e) { UI::alert('danger', "Error #" . $e->getCode() . "|" . $e->getLine() . ": " . $e->getMessage()); DBG::log($e); } UI::endContainer(); UI::dol(); } public function printReinstallPreview($namespace) { $objectItem = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => "*,field" ]); DBG::log($objectItem, 'array', '$objectItem preview'); switch ($objectItem['_type']) { case 'AntAcl': $this->printReinstallAntAclPreview($objectItem); break; case 'TableAcl': $this->printReinstallTableAclPreview($objectItem); break; case 'StorageAcl': $this->printReinstallStorageAclPreview($objectItem); break; default: throw new Exception("TODO: Not Implemented type '{$objectItem['_type']}'"); } } public function printReinstallAntAclPreview($item) { Lib::loadClass('Schema_SystemObjectFieldStorageAcl'); $antAclPath = Schema_SystemObjectFieldStorageAcl::getAntAclXsdBasePath($item['typeName']); if (!file_exists("{$antAclPath}/build.xml")) throw new Exception("Ant build file not exists"); Lib::loadClass('XML'); $xsdType = XML::getXsdTypeFromXsdSchema("{$antAclPath}/{$item['name']}.xsd", $namespace = $item['namespace'], $name = $item['name']); DBG::nicePrint($item, '$item'); DBG::nicePrint($xsdType, '$xsdType'); echo '
'; echo UI::h('h3', [], "Lista zmian:"); echo ($item['primaryKey'] != $xsdType['primaryKey']) ? UI::h('p', [ 'style' => "" ], "@primaryKey - zmiana z '{$item['primaryKey']}' na '{$xsdType['primaryKey']}'") : UI::h('p', [ 'style' => "font-style:italic; color:silver" ], "@primaryKey - bez zmian"); if (empty($xsdType['struct'])) throw new Exception("Field list not found for '{$item['namespace']}'"); foreach ($xsdType['struct'] as $fieldName => $x) { $listEnum = []; if (!empty($x['restrictions']['enumeration'])) { $listEnum = $x['restrictions']['enumeration']; unset($x['restrictions']['enumeration']); } if (!empty($listEnum)) { DBG::log($listEnum, 'array', "\$listEnum for field '{$fieldName}'"); } } $old = [ 'fields' => array_map(function ($field) { return $field['fieldNamespace']; }, $item['field']), ]; $new = [ 'fields' => array_keys($xsdType['struct']), ]; sort($old['fields']); sort($new['fields']); $diffFieldsToCreate = array_diff($new['fields'], $old['fields']); $diffFieldsToRemove = array_diff($old['fields'], $new['fields']); $sameFields = array_intersect($new['fields'], $old['fields']); echo (!empty($diffFieldsToCreate)) ? UI::h('details', [ 'open' => "open" ], [ UI::h('summary', [], "Pola do dodania (".count($diffFieldsToCreate)."):"), UI::h('ul', [], array_map(function ($fieldName) { return UI::h('li', [], $fieldName); }, $diffFieldsToCreate)), ]) : UI::h('p', [ 'style' => "font-style:italic; color:silver" ], "Brak pól do dodania"); echo (!empty($diffFieldsToRemove)) ? UI::h('details', [ 'open' => "open", 'style' => "margin:4px 0; color:#8a6d3b; background-color:#fcf8e3; border:1px solid #faebcc;" ], [ UI::h('summary', [ 'style' => "padding:4px; outline:none; cursor:pointer" ], "Pola do usunięcia (".count($diffFieldsToRemove)."):"), UI::h('ul', [], array_map(function ($fieldName) { return UI::h('li', [], $fieldName); }, $diffFieldsToRemove)), ]) : UI::h('p', [ 'style' => "font-style:italic; color:silver" ], "Brak pól do usunięcia"); foreach ($sameFields as $fieldName) { // UI::alert('warning', "TODO: is field changed? '{$fieldName}'"); $oldField = array_filter($item['field'], function ($field) use ($fieldName) { return ( $fieldName === $field['fieldNamespace'] ); }); $oldField = ($oldField) ? reset($oldField) : null; // DBG::nicePrint($oldField, "\$oldField '$fieldName'"); $newField = $xsdType['struct'][$fieldName]; // DBG::nicePrint($newField, "\$newField '$fieldName'"); $fieldDiff = []; if ($newField['type'] !== $oldField['xsdType']) $fieldDiff[] = 'xsdType'; if ($newField['minOccurs'] != $oldField['minOccurs']) $fieldDiff[] = 'minOccurs'; if ($newField['maxOccurs'] != $oldField['maxOccurs']) $fieldDiff[] = 'maxOccurs'; if (json_encode($newField['restrictions']) !== $oldField['xsdRestrictions']) $fieldDiff[] = 'xsdRestrictions'; if (json_encode($newField['appInfo']) !== $oldField['appInfo']) $fieldDiff[] = 'appInfo'; if (RefConfig::isRefField($item['namespace'], $fieldName)) { $typeNewField = Type_Field::build($newField); $typeOldField = Type_Field::build($oldField); if (RefConfig::needUpdate($item['namespace'], $oldField['fieldNamespace'], $typeNewField, $typeOldField)) { $fieldDiff[] = 'RefConfig'; } } echo (!empty($fieldDiff)) ? UI::h('p', [ 'style' => "" ], "Pole '{$fieldName}' - zmiany: " . implode(", ", $fieldDiff)) : UI::h('p', [ 'style' => "font-style:italic; color:silver" ], "Pole '{$fieldName}' - bez zmian"); } } public function printReinstallTableAclPreview($item) { throw new Exception("TODO: Podgląd zmian dla tabeli {$item['namespace']} ..."); } public function printReinstallStorageAclPreview($item) { DBG::nicePrint($item, '$item'); $acl = SchemaFactory::loadDefaultObject($item['name']); DBG::nicePrint($acl, '$acl'); $xsdType = [ 'primaryKey' => $acl->getPrimaryKeyField(), 'struct' => $acl->getFieldsWithXsdTypes() ]; DBG::nicePrint($xsdType, '$xsdType'); echo '
'; echo UI::h('h3', [], "Lista zmian:"); echo ($item['primaryKey'] != $xsdType['primaryKey']) ? UI::h('p', [ 'style' => "" ], "@primaryKey - zmiana z '{$item['primaryKey']}' na '{$xsdType['primaryKey']}'") : UI::h('p', [ 'style' => "font-style:italic; color:silver" ], "@primaryKey - bez zmian"); if (empty($xsdType['struct'])) throw new Exception("Field list not found for '{$item['namespace']}'"); foreach ($xsdType['struct'] as $fieldName => $x) { $listEnum = []; if (!empty($x['restrictions']['enumeration'])) { $listEnum = $x['restrictions']['enumeration']; unset($x['restrictions']['enumeration']); } if (!empty($listEnum)) { DBG::log($listEnum, 'array', "\$listEnum for field '{$fieldName}'"); } } $old = [ 'fields' => array_map(function ($field) { return $field['fieldNamespace']; }, $item['field']), ]; $new = [ 'fields' => array_keys($xsdType['struct']), ]; sort($old['fields']); sort($new['fields']); $diffFieldsToCreate = array_diff($new['fields'], $old['fields']); $diffFieldsToRemove = array_diff($old['fields'], $new['fields']); $sameFields = array_intersect($new['fields'], $old['fields']); echo (!empty($diffFieldsToCreate)) ? UI::h('details', [ 'open' => "open" ], [ UI::h('summary', [], "Pola do dodania (".count($diffFieldsToCreate)."):"), UI::h('ul', [], array_map(function ($fieldName) { return UI::h('li', [], $fieldName); }, $diffFieldsToCreate)), ]) : UI::h('p', [ 'style' => "font-style:italic; color:silver" ], "Brak pól do dodania"); echo (!empty($diffFieldsToRemove)) ? UI::h('details', [ 'open' => "open", 'style' => "margin:4px 0; color:#8a6d3b; background-color:#fcf8e3; border:1px solid #faebcc;" ], [ UI::h('summary', [ 'style' => "padding:4px; outline:none; cursor:pointer" ], "Pola do usunięcia (".count($diffFieldsToRemove)."):"), UI::h('ul', [], array_map(function ($fieldName) { return UI::h('li', [], $fieldName); }, $diffFieldsToRemove)), ]) : UI::h('p', [ 'style' => "font-style:italic; color:silver" ], "Brak pól do usunięcia"); foreach ($sameFields as $fieldName) { // UI::alert('warning', "TODO: is field changed? '{$fieldName}'"); $oldField = array_filter($item['field'], function ($field) use ($fieldName) { return ( $fieldName === $field['fieldNamespace'] ); }); $oldField = ($oldField) ? reset($oldField) : null; // DBG::nicePrint($oldField, "\$oldField '$fieldName'"); $newField = $xsdType['struct'][$fieldName]; // DBG::nicePrint($newField, "\$newField '$fieldName'"); $fieldDiff = []; if ($newField['type'] !== $oldField['xsdType']) $fieldDiff[] = 'xsdType'; if ($newField['minOccurs'] != $oldField['minOccurs']) $fieldDiff[] = 'minOccurs'; if ($newField['maxOccurs'] != $oldField['maxOccurs']) $fieldDiff[] = 'maxOccurs'; if (json_encode($newField['restrictions']) !== $oldField['xsdRestrictions']) $fieldDiff[] = 'xsdRestrictions'; if (json_encode($newField['appInfo']) !== $oldField['appInfo']) $fieldDiff[] = 'appInfo'; echo (!empty($fieldDiff)) ? UI::h('p', [ 'style' => "" ], "Pole '{$fieldName}' - zmiany: " . implode(", ", $fieldDiff)) : UI::h('p', [ 'style' => "font-style:italic; color:silver" ], "Pole '{$fieldName}' - bez zmian"); } } public function viewXsdSourceAction() { try { $namespace = V::get('namespace', '', $_GET); if (empty($namespace)) throw new Exception("Missing param namespace"); $objectItem = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => "*,field" ]); switch ($objectItem['_type']) { case 'AntAcl': $this->viewXsdSource($objectItem); break; // case 'TableAcl': $this->viewXsdSource($objectItem); break; default: throw new Exception("TODO: Not Implemented type '{$objectItem['_type']}'"); } } catch (Exception $e) { DBG::log($e); echo "Error #" . $e->getCode() . "|" . $e->getLine() . ": " . $e->getMessage(); } } function viewXsdSource($objectItem) { if (empty($objectItem)) throw new Exception("Missing objectItem in viewXsdSource"); DBG::log($objectItem, "viewXsdSource \$objectItem"); Lib::loadClass('Schema_SystemObjectFieldStorageAcl'); $antAclPath = Schema_SystemObjectFieldStorageAcl::getAntAclXsdBasePath($objectItem['typeName']); if (!file_exists("{$antAclPath}/build.xml")) throw new Exception("Ant build file not exists"); DBG::log(str_replace(APP_PATH_ROOT, '~', $antAclPath), "viewXsdSource \$antAclPath"); $xsdFile = "{$antAclPath}/{$objectItem['name']}.xsd"; if (!file_exists($xsdFile)) throw new Exception("Xsd file not exists"); DBG::log(str_replace(APP_PATH_ROOT, '~', $xsdFile), "viewXsdSource \$xsdFile"); header('Content-Type: application/xml; charset=utf-8'); $fd = fopen($xsdFile, 'r'); fpassthru($fd); exit; } function reinstallAcl($namespace) { Lib::loadClass('Schema_SystemObjectFieldStorageAcl'); $objFieldAcl = new Schema_SystemObjectFieldStorageAcl(); $objFieldAcl->updateCache($namespace); try { $dbgInfo = [ 'idInstance' => ACL::getInstanceId($namespace), // 'rootInstance' => InstanceConfig::getRootNamespace($namespace), // 'conf' => InstanceConfig::fetchInstanceConfig($namespace), // 'table' => ACL::getInstanceTable($namespace), // Object structure not installed 'default_db/{tableName}' ]; DBG::nicePrint($dbgInfo, "dbg"); } catch (Exception $e) { UI::alert('warning', $e->getMessage()); } $item = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ]); $childRefList = RefConfig::getChildRefFullList($namespace); DBG::nicePrint($childRefList, '$childRefList'); DBG::nicePrint($item, '$item'); $activeFields = array_filter($item['field'], function ($field) { return ($field['isActive'] > 0); }); $fieldNsList = array_map(function ($field) { return $field['fieldNamespace']; }, $activeFields); DBG::nicePrint($fieldNsList, '$fieldNsList'); if ('AntAcl' === $item['_type']) { // fix ref config status (turn on/off) foreach ($childRefList as $refConfig) { // [ namespace, A_STATUS ] if ($refConfig->status !== 'DELETED' && !in_array($refConfig->childName, $fieldNsList)) { UI::alert('danger', "remove ref config for '{$refConfig->childName}' ..."); if (!$refConfig->id) throw new Exception("Missing ref config ID"); RefConfig::remove($refConfig); } else if ($refConfig->status !== 'DELETED' && in_array($refConfig->childName, $fieldNsList)) { UI::alert('info', "ref config for '{$refConfig->childName}' active - OK"); } else if ($refConfig->status === 'DELETED' && in_array($refConfig->childName, $fieldNsList)) { UI::alert('warning', "activate ref config for '{$refConfig->childName}' ..."); if (!$refConfig->id) throw new Exception("Missing ref config ID"); RefConfig::reactivate($refConfig); } else if ($refConfig->status === 'DELETED' && !in_array($refConfig->childName, $fieldNsList)) { UI::alert('info', "ref config for '{$refConfig->childName}' removed - OK"); } else { UI::alert('danger', "Not implemented action for '{$refConfig->childName}'"); } } // TODO: create missing refConfig - field is not in $childRefList } if ('AntAcl' === $item['_type']) { // fix ref tables by appInfo $refFields = array_filter($item['field'], function ($field) { return ('ref:' === substr($field['xsdType'], 0, 4)); }); DBG::log($refFields, 'array', "DBG \$refFields"); foreach ($refFields as $field) { $typeNewField = Type_Field::build($field); // if (RefConfig::needUpdate($item['namespace'], $oldField['fieldNamespace'], $typeNewField, $typeOldField)) try { RefConfig::update($item['namespace'], $field['fieldNamespace'], $typeNewField); } catch (Exception $e) { // TODO: deactivate RefConfig if error DBG::log($e); UI::alert('danger', $e->getMessage()); } } } { if ('AntAcl' === $item['_type']) { $dbName = DB::getPDO()->getDatabaseName(); $sqlFunBody = ACL::generateIsInstanceFunctionBody($namespace, $item); DBG::nicePrint($sqlFunBody, "\$sqlFunBody"); $idInstance = ACL::getInstanceId($namespace); DB::getPDO()->execSql(" DROP FUNCTION IF EXISTS `{$dbName}`.`isInstance_{$idInstance}` "); // CREATE // [DEFINER = { user | CURRENT_USER }] // FUNCTION sp_name ([func_parameter[,...]]) // RETURNS type // [characteristic ...] routine_body DB::getPDO()->execSql(" CREATE DEFINER=`root`@`localhost` FUNCTION `{$dbName}`.`isInstance_{$idInstance}` ( pk INT(11) ) RETURNS TINYINT(1) {$sqlFunBody} "); } } } }