|
|
@@ -7,6 +7,7 @@ Lib::loadClass('UI');
|
|
|
Lib::loadClass('SchemaFactory');
|
|
|
Lib::loadClass('RefConfig');
|
|
|
Lib::loadClass('Type_Field');
|
|
|
+Lib::loadClass('Schema_SystemObjectFieldStorageAcl');
|
|
|
|
|
|
class Route_Storage_AclReinstall extends RouteBase {
|
|
|
|
|
|
@@ -75,7 +76,6 @@ class Route_Storage_AclReinstall extends RouteBase {
|
|
|
}
|
|
|
}
|
|
|
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 " . str_replace(APP_PATH_ROOT, 'SE', $antAclPath));
|
|
|
|
|
|
@@ -259,7 +259,6 @@ class Route_Storage_AclReinstall extends RouteBase {
|
|
|
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");
|
|
|
@@ -282,7 +281,6 @@ class Route_Storage_AclReinstall extends RouteBase {
|
|
|
UI::alert('danger', $e->getMessage());
|
|
|
}
|
|
|
|
|
|
- Lib::loadClass('Schema_SystemObjectFieldStorageAcl');
|
|
|
$objFieldAcl = new Schema_SystemObjectFieldStorageAcl();
|
|
|
$objFieldAcl->updateCache($namespace);
|
|
|
|
|
|
@@ -369,19 +367,19 @@ class Route_Storage_AclReinstall extends RouteBase {
|
|
|
|
|
|
function _createOrUpdateTableStructure($namespace) {
|
|
|
$item = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ]);
|
|
|
- DBG::nicePrint($item, 'DBG:_createOrUpdateTableStructure:$item');
|
|
|
- $storagePdo = DB::getStorage($item['idDatabase']);
|
|
|
- $tblStruct = [];
|
|
|
+ DBG::log($item, 'array', 'DBG:_createOrUpdateTableStructure:$item');
|
|
|
+ $currentStruct = [];
|
|
|
try {
|
|
|
- $tblStruct = $storagePdo->getTableStruct($item['_rootTableName']);
|
|
|
+ $currentStruct = DB::getStorage($item['idDatabase'])->getTableStruct($item['_rootTableName']);
|
|
|
} catch (Exception $e) {
|
|
|
+ DBG::log($e);
|
|
|
}
|
|
|
- DBG::nicePrint($tblStruct, 'DBG:_createOrUpdateTableStructure:$tblStruct');
|
|
|
+ DBG::log($currentStruct, 'array', 'DBG:_createOrUpdateTableStructure:$currentStruct');
|
|
|
|
|
|
if (DB::getPDO()->getZasobId() != $item['idDatabase']) throw new Exception("Not imeplemented Create/Update table structure in non default database");
|
|
|
|
|
|
- if (empty($tblStruct)) $this->_createTableStructure($item);
|
|
|
- else $this->_updateTableStructure($item, $tblStruct);
|
|
|
+ if (empty($currentStruct)) $this->_createTableStructure($item);
|
|
|
+ else $this->_updateTableStructure($item, $currentStruct);
|
|
|
}
|
|
|
// $item['idDatabase'] => int idDatabase
|
|
|
// $item['_rootTableName'] => string tableName
|
|
|
@@ -423,67 +421,178 @@ class Route_Storage_AclReinstall extends RouteBase {
|
|
|
// xsd:token
|
|
|
// ]
|
|
|
function _createTableStructure($item) {
|
|
|
- $tryConvertFields = array_map(function ($fieldInfo) {
|
|
|
- if ('ref:' === substr($fieldInfo['xsdType'], 0, 4)) return "Skipped create ref field '{$fieldInfo['xsdType']}'";
|
|
|
- switch ($fieldInfo['xsdType']) {
|
|
|
- case 'xsd:integer':
|
|
|
- case 'p5Type:integer':
|
|
|
- case 'xsd:positiveInteger':
|
|
|
- case 'xsd:int': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "int(11)" ];
|
|
|
- case 'xsd:float': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "float" ];
|
|
|
- case 'xsd:double': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "double" ];
|
|
|
- case 'xsd:date': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "date" ];
|
|
|
- case 'xsd:datetime': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "datetime" ];
|
|
|
- case 'xsd:string':
|
|
|
- case 'p5Type:string': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "varchar(255)" ];
|
|
|
- // TODO: implement more xsd types:
|
|
|
- // case 'p5Type:decimal':
|
|
|
- // case 'xsd:decimal': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "decimal" ];
|
|
|
- // default_db__x3A__BADANIA_W_TERENIE:A_STATUS_Type
|
|
|
- // default_db__x3A__CRM_PROCES:TYPE_Simple
|
|
|
- // gml:AbstractFeatureType
|
|
|
- // gml:PolygonPropertyType
|
|
|
- // p5:enum
|
|
|
- // p5:price
|
|
|
- // p5:www_link
|
|
|
- // p5Type:date
|
|
|
- // p5Type:dateTime
|
|
|
- // p5Type:decimal
|
|
|
- // p5Type:lineString
|
|
|
- // p5Type:point
|
|
|
- // p5Type:polygon
|
|
|
- // p5Type:text
|
|
|
- // xsd:decimal
|
|
|
- // xsd:gYear
|
|
|
- // xsd:hexBinary
|
|
|
- // xsd:long
|
|
|
- // xsd:short
|
|
|
- // xsd:time
|
|
|
- // xsd:token
|
|
|
- default: return "Not implemented type '{$fieldInfo['xsdType']}'";
|
|
|
- }
|
|
|
- }, $item['field']);
|
|
|
- DBG::nicePrint($tryConvertFields, "DBG:create table struct:\$tryConvertFields");
|
|
|
- $toCreateFields = array_filter($tryConvertFields, function ($fieldInfo) { return is_array($fieldInfo); });
|
|
|
- DBG::nicePrint($toCreateFields, "DBG:create table struct:\$toCreateFields");
|
|
|
+ $expectedStruct = $this->_makeTableStructure($item);
|
|
|
+ DB::getStorage($item['idDatabase'])->createTableStructure([
|
|
|
+ 'tableName' => $item['_rootTableName'],
|
|
|
+ 'fields' => $expectedStruct,
|
|
|
+ 'primaryKey' => $item['primaryKey'],
|
|
|
+ 'keys' => [],
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ function _updateTableStructure($item, $currentStruct) {
|
|
|
+ DBG::log($item, 'array', "DBG:update table struct:\$item");
|
|
|
+ DBG::log($currentStruct, 'array', "DBG:update table struct:\$currentStruct");
|
|
|
+ $expectedStruct = $this->_makeTableStructure($item);
|
|
|
+ DBG::log($expectedStruct, 'array', "DBG:update table struct:\$expectedStruct");
|
|
|
+
|
|
|
+ // $expectedStruct: [ fieldName => shortStruct ]
|
|
|
+ // shortStruct:
|
|
|
+ // 'name' => 'ID',
|
|
|
+ // 'raw_storage_type' => 'int(11)',
|
|
|
+ // 'extra' => 'auto_increment',
|
|
|
+
|
|
|
+ // $currentStruct: [ fieldName => fullStruct ]
|
|
|
+ // fullStruct:
|
|
|
+ // 'name' => 'ID',
|
|
|
+ // 'type' => 'int',
|
|
|
+ // 'is_nullable' => '0',
|
|
|
+ // 'default_value' => NULL,
|
|
|
+ // 'default_is_null' => '1',
|
|
|
+ // 'max_length' => NULL,
|
|
|
+ // 'num_precision' => '10',
|
|
|
+ // 'num_scale' => '0',
|
|
|
+ // 'char_encoding' => NULL,
|
|
|
+ // 'char_collation' => NULL,
|
|
|
+ // 'extra' => 'auto_increment',
|
|
|
+ // 'raw_storage_type' => 'int(11)',
|
|
|
+
|
|
|
+ $expectedFieldList = array_keys($expectedStruct);
|
|
|
+ $currentFieldList = array_keys($currentStruct);
|
|
|
+
|
|
|
+ // array_diff([ 'a', 'b', 'c' ], [ 'b', 'c', 'd' ]) => [ 'a' ]
|
|
|
+ // array_diff([ 'b', 'c', 'd' ], [ 'a', 'b', 'c' ]) => [ 'd' ]
|
|
|
+ // $toRemoveFieldFromStruct = array_diff($currentFieldList, $expectedFieldList); // TODO: not used, fields defined in base object
|
|
|
+ $toAddFieldToStruct = array_diff($expectedFieldList, $currentFieldList);
|
|
|
+ DBG::log($toRemoveFieldFromStruct, 'array', "DBG:update table struct:\$toRemoveFieldFromStruct");
|
|
|
+ DBG::log($toAddFieldToStruct, 'array', "DBG:update table struct:\$toAddFieldToStruct");
|
|
|
+ if (!empty($toAddFieldToStruct)) {
|
|
|
+ $rootTableName = $item['_rootTableName'];
|
|
|
+ array_map(function ($fieldName) use ($rootTableName, $expectedStruct) {
|
|
|
+ $expectedField = $expectedStruct[$fieldName];
|
|
|
+ $sqlNotNull = ""; // TODO: "NOT NULL" if field can not be null
|
|
|
+ $sqlDefault = ""; // TODO: "DEFAULT {$value}"
|
|
|
+ DB::getPDO()->execSql(" ALTER TABLE {$rootTableName} ADD {$fieldName} {$expectedField['raw_storage_type']} {$sqlNotNull} {$sqlDefault}");
|
|
|
+ }, $toAddFieldToStruct);
|
|
|
+ }
|
|
|
+ $maybeToUpdateFields = array_intersect($currentFieldList, $expectedFieldList);
|
|
|
+ DBG::log($maybeToUpdateFields, 'array', "DBG:update table struct:\$maybeToUpdateFields");
|
|
|
+ if (empty($maybeToUpdateFields)) {
|
|
|
+ UI::alert('info', "No fields to compare");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ $diffNotes = array_map(function ($fieldName) use ($currentStruct, $expectedStruct) {
|
|
|
+ $currentField = $currentStruct[$fieldName];
|
|
|
+ $expectedField = $expectedStruct[$fieldName];
|
|
|
+ return [
|
|
|
+ 'fieldName' => $fieldName,
|
|
|
+ 'current_raw_type' => $currentField['raw_storage_type'],
|
|
|
+ 'expected_raw_type' => $expectedField['raw_storage_type'],
|
|
|
+ 'diff' => ($currentField['raw_storage_type'] === $expectedField['raw_storage_type']) ? "same" : "diff",
|
|
|
+ ];
|
|
|
+ }, $maybeToUpdateFields);
|
|
|
+ UI::table([ 'caption' => "Fields types diff:", 'rows' => $diffNotes ]);
|
|
|
+
|
|
|
+ $diffFields = array_filter($diffNotes, function ($item) { return ("diff" === $item['diff']); });
|
|
|
+ if (empty($diffFields)) {
|
|
|
+ UI::alert('info', "Struct is ok");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ DBG::log($diffFields, 'array', "TODO: update table struct by \$diffFields");
|
|
|
+ throw new Exception("TODO: Not imeplemented Update table structure (Update existing fields)");
|
|
|
+ }
|
|
|
+ function _makeTableStructure($item) {
|
|
|
+ $tryConvertFields = array_map([ $this, '_makeFieldStructure' ], $item['field']);
|
|
|
+
|
|
|
+ DBG::log($tryConvertFields, 'array', "DBG:make table struct:\$tryConvertFields");
|
|
|
+ $toCreateFields = array_filter($tryConvertFields, function ($fieldInfo) { return null !== $fieldInfo; });
|
|
|
+ DBG::log($toCreateFields, 'array', "DBG:make table struct:\$toCreateFields");
|
|
|
|
|
|
$tblStruct = array_combine(
|
|
|
array_map(V::makePick('name'), $toCreateFields),
|
|
|
array_values($toCreateFields)
|
|
|
);
|
|
|
- DBG::nicePrint($tblStruct, "DBG:create table struct:\$tblStruct");
|
|
|
+ DBG::log($tblStruct, 'array', "DBG:make table struct:\$tblStruct");
|
|
|
if (!array_key_exists($item['primaryKey'], $tblStruct)) throw new Exception("BUG: primaryKey field definition not exists");
|
|
|
$tblStruct[$item['primaryKey']]['extra'] = "auto_increment";
|
|
|
|
|
|
- DB::getStorage($item['idDatabase'])->createTableStructure([
|
|
|
- 'tableName' => $item['_rootTableName'],
|
|
|
- 'fields' => $tblStruct,
|
|
|
- 'primaryKey' => $item['primaryKey'],
|
|
|
- 'keys' => [],
|
|
|
- ]);
|
|
|
+ return $tblStruct;
|
|
|
}
|
|
|
- function _updateTableStructure($item, $tblStruct) {
|
|
|
- throw new Exception("Not imeplemented Update table structure in non default database");
|
|
|
+ function _makeFieldStructure($fieldInfo) {
|
|
|
+ // select distinct xsdType from `CRM_#CACHE_ACL_OBJECT_FIELD` where xsdType not like 'ref:%' order by xsdType;
|
|
|
+ if ('ref:' === substr($fieldInfo['xsdType'], 0, 4)) {
|
|
|
+ DBG::log("Skipped create ref field '{$fieldInfo['xsdType']}'");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ $fieldName = $fieldInfo['fieldNamespace'];
|
|
|
+ if (!preg_match('/^[a-z_]+$/i', $fieldName)) {
|
|
|
+ DBG::log("Skipped create: not allowed field name '{$fieldName}'");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch ($fieldInfo['xsdType']) {
|
|
|
+ // number
|
|
|
+ case 'xsd:integer':
|
|
|
+ case 'p5Type:integer':
|
|
|
+ case 'xsd:positiveInteger':
|
|
|
+ case 'xsd:int': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "int(11)" ];
|
|
|
+ case 'xsd:short': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "int(11)" ];
|
|
|
+ case 'xsd:long': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "int(11)" ];
|
|
|
+ case 'xsd:float': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "float" ];
|
|
|
+ case 'xsd:double': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "double" ];
|
|
|
+ case 'xsd:decimal': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "decimal(12,2)" ];
|
|
|
+ case 'p5Type:decimal':
|
|
|
+ case 'p5:price': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "decimal(12,2)" ];
|
|
|
+ // time
|
|
|
+ case 'p5Type:date':
|
|
|
+ case 'xsd:date': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "date" ];
|
|
|
+ case 'p5Type:dateTime':
|
|
|
+ case 'xsd:datetime': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "datetime" ];
|
|
|
+ case 'xsd:time': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "time" ];
|
|
|
+ // string
|
|
|
+ case 'xsd:string':
|
|
|
+ case 'p5Type:string': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "varchar(255)" ];
|
|
|
+ case 'xsd:token': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "varchar(255)" ];
|
|
|
+ case 'p5Type:text': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "text" ];
|
|
|
+ // geom
|
|
|
+ case 'p5Type:polygon': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "polygon", 'default' => "NULL" ];
|
|
|
+ case 'p5Type:lineString': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "linestring", 'default' => "NULL" ];
|
|
|
+ case 'p5Type:point': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "point", 'default' => "NULL" ];
|
|
|
+ case 'gml:AbstractFeatureType': return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "polygon", 'default' => "NULL" ];
|
|
|
+ // TODO: ???: 'gml:PolygonPropertyType'
|
|
|
+
|
|
|
+ case 'p5:enum': {
|
|
|
+ // [A_STATUS] => Array:
|
|
|
+ // [type] => p5:enum
|
|
|
+ // [minOccurs] => 0
|
|
|
+ // [maxOccurs] => 1
|
|
|
+ // [restrictions] => Array:
|
|
|
+ // [enumeration] => Array:
|
|
|
+ // [NORMAL] => NORMAL
|
|
|
+ // [WAITING] => WAITING
|
|
|
+ // [MONITOR] => MONITOR
|
|
|
+ // [DELETED] => DELETED
|
|
|
+ // [WARNING] => WARNING
|
|
|
+ // [OFF_SOFT] => OFF_SOFT
|
|
|
+ // [OFF_HARD] => OFF_HARD
|
|
|
+ $xsdRestrictions = Schema_SystemObjectFieldStorageAcl::getXsdRestrictionsValue($fieldInfo);
|
|
|
+ DBG::log($xsdRestrictions, 'array', "DBG: p5:enum xsdRestrictions for field('{$fieldInfo['fieldNamespace']}')");
|
|
|
+ return [ 'name' => $fieldInfo['fieldNamespace'], 'raw_storage_type' => "enum(" .
|
|
|
+ implode(",", array_map(function ($value) { return "'{$value}'"; }, array_keys($xsdRestrictions['enumeration']))) .
|
|
|
+ ")" ];
|
|
|
+ }
|
|
|
+
|
|
|
+ // TODO: implement more xsd types:
|
|
|
+ // case 'default_db__x3A__BADANIA_W_TERENIE:A_STATUS_Type':
|
|
|
+ // case 'default_db__x3A__CRM_PROCES:TYPE_Simple':
|
|
|
+ // case 'p5:www_link':
|
|
|
+ // case 'xsd:gYear':
|
|
|
+ // case 'xsd:hexBinary':
|
|
|
+ default: {
|
|
|
+ DBG::log($fieldInfo, 'array', "TODO: _makeFieldStructure '{$fieldInfo['xsdType']}' (SystemObject/fieldInfo)"); // $fieldInfo = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ])['field'];
|
|
|
+ throw new Exception("Not implemented type '{$fieldInfo['xsdType']}'");
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
}
|