浏览代码

added support for SystemObjects alias for default_objects

Piotr Labudda 8 年之前
父节点
当前提交
32f1b63b14

+ 32 - 1
SE/se-lib/ACL.php

@@ -174,7 +174,19 @@ class ACL {
 		return $acl;
 	}
 
+	public static function getBaseNamespace($namespace) {
+		// map SystemObjects__x3A__{parent}/{name} to default_objects/{name}
+		if ('SystemObjects/' === substr($namespace, 0, strlen('SystemObjects/'))) {
+			$exNs = explode('/', $namespace);
+			if (3 === count($exNs)) {
+				return "default_objects/{$exNs[2]}";
+			}
+		}
+		return $namespace;
+	}
+
 	public static function getAclByNamespace($namespace, $forceTblAclInit = false) {
+		$namespace = ACL::getBaseNamespace($namespace);
 		return Core_AclHelper::getAclByNamespace($namespace, $forceTblAclInit);
 	}
 
@@ -208,6 +220,7 @@ class ACL {
 	public static function getRefTable($rootObjectNamespace, $childName) { // CRM_REF_CONFIG
 		static $cacheRefTables = array();
 		DBG::log("DBG get ref table ({$rootObjectNamespace}, {$childName}) ...");
+		$rootObjectNamespace = ACL::getBaseNamespace($rootObjectNamespace);
 		$cacheKey = "{$rootObjectNamespace}/{$childName}";
 		if (array_key_exists($cacheKey, $cacheRefTables)) return $cacheRefTables[$cacheKey];
 
@@ -255,6 +268,7 @@ class ACL {
 		return $refTableName;
 	}
 	public static function getRefSource($rootObjectNamespace, $childName) { // CRM_REF_CONFIG
+		$rootObjectNamespace = ACL::getBaseNamespace($rootObjectNamespace);
 		$refInfo = self::getRefConfig($rootObjectNamespace, $childName);
 		return V::get('SOURCE', 'table', $refInfo);
 	}
@@ -379,6 +393,7 @@ class ACL {
 			}
 		}
 		$sqlWhereFromRestrictions = (!empty($sqlWhereFromRestrictions)) ? implode(" and ", $sqlWhereFromRestrictions) : "1=1";
+		$sqlChildFieldName = $childAcl->getSqlFieldName($appInfoRootFieldName);
 		$sql = "
 			select root.{$rootPrimaryKeyField} as PRIMARY_KEY
 					, child.{$childPrimaryKeyField} as REMOTE_PRIMARY_KEY
@@ -387,7 +402,7 @@ class ACL {
 					, 0 as TRANSACTION_ID
 					, {$lastActionDateField} as A_LAST_ACTION_DATE
 			from `{$rootTableName}` root
-				join `{$childTableName}` child on(child.{$appInfoRootFieldName} = root.{$appInfoChildFieldName})
+				join `{$childTableName}` child on(child.{$sqlChildFieldName} = root.{$appInfoChildFieldName})
 			where {$sqlWhereFromRestrictions}
 		";
 		DBG::log($sql, 'sql', "generateRefSelectSqlByFlatRelationCache");
@@ -408,6 +423,7 @@ class ACL {
 		}
 	}
 	public static function getRefConfig($rootObjectNamespace, $childName, $childNamespace = null) { // CRM_REF_CONFIG
+		$rootObjectNamespace = ACL::getBaseNamespace($rootObjectNamespace);
 		if (!$childNamespace) {
 			$rootAcl = self::getAclByNamespace($rootObjectNamespace);
 			$childXsdType = $rootAcl->getXsdFieldType($childName);
@@ -458,6 +474,20 @@ class ACL {
 				'CHILD_NS' => $childNamespace
 			]);
 		}
+
+		// { // TODO: fix source if ref for `SystemObjects__x3A__*` and defined flat_relation_cache - move to AclReinstall?
+		// 	if ('SystemObjects__x3A__' === substr($childNamespace, 0, strlen('SystemObjects__x3A__'))) {
+		// 		if ('table' === $refInfo['SOURCE']) {
+		// 			$toUpdate = [
+		// 				'SOURCE' => 'view',
+		// 				'A_STATUS' => 'WAITING',
+		// 			];
+		// 			DB::getPDO()->update('CRM_REF_CONFIG', 'ID', $refInfo['ID'], $toUpdate);
+		// 			$refInfo = array_merge($refInfo, $toUpdate);
+		// 		}
+		// 	}
+		// }
+
 		if (!$refInfo['ID']) throw new Exception("Ref table not found in ref config table for field '{$childName}' in object '{$rootObjectNamespace}'");
 		return $refInfo;
 	}
@@ -479,6 +509,7 @@ class ACL {
 		]);
 	}
 	public static function getChildRefFullList($namespace) {
+		$namespace = ACL::getBaseNamespace($namespace);
 		if (!$namespace) throw new Exception("Missing namespace");
 		return DB::getPDO()->fetchAll("
 			select c.CHILD_NAME as namespace

+ 76 - 0
SE/se-lib/Route/Storage/AclReinstall.php

@@ -141,6 +141,7 @@ class Route_Storage_AclReinstall extends RouteBase {
 		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']}'");
 		}
 	}
@@ -222,6 +223,81 @@ class Route_Storage_AclReinstall extends RouteBase {
 	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 '<hr>';
+		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 {

+ 2 - 0
SE/se-lib/Route/Storage/AclStruct.php

@@ -751,6 +751,7 @@ class Route_Storage_AclStruct extends RouteBase {
 			UI::table([
 				'rows' => array_map(function ($field) use ($thisGetLink) {
 					$refNamespace = str_replace(['__x3A__', ':'], '/', substr($field['xsdType'], strlen('ref:')));
+					$refNamespace = ACL::getBaseNamespace($refNamespace);
 					$isInstalled = (1 == DB::getPDO()->fetchValue("
 						select t.isObjectActive
 						from `CRM_#CACHE_ACL_OBJECT` t
@@ -789,6 +790,7 @@ class Route_Storage_AclStruct extends RouteBase {
 									// 	'href' => $thisGetLink('setFieldRefConfig'),
 									// 	'data' => [ 'namespace' => $refNamespace, 'field' => $field['fieldNamespace'], 'do' => 'view' ]
 									// ]),
+									( 'table' === $refSource ) ? 'Tabela ' : 'Widok ',
 									UI::hButtonPost("Tabela ref", [
 										'title' => "Według wygenerowanej tabeli REF",
 										'class' => "btn btn-xs btn-default" . ( 'table' === $refSource ? ' disabled' : '' ),

+ 8 - 0
SE/se-lib/Schema/AccessOwnerStorageAcl.php

@@ -41,6 +41,14 @@ class Schema_AccessOwnerStorageAcl extends Core_AclBase {
 		$fields[100002] = ['name'=>'name', 'perms'=>'R', 'opis'=>'', 'label'=>'', 'sort_prio'=>102];
 		return $fields;
 	}
+	public function getSqlFieldName($fieldName) {
+		switch ($fieldName) {
+			case 'id': return 'ID';
+			case 'login': return 'ADM_ACCOUNT';
+			case 'name': return 'ADM_NAME';
+		}
+		throw new Exception("Unknown field '{$fieldName}' in AccessOwner");
+	}
 	public function getFieldType($fieldName) { return null; }
 
 	// TODO: replace legacy functions: isAllowed, hasFieldPerm, getFieldIdByName

+ 2 - 1
SE/se-lib/Schema/SystemObjectFieldStorageAcl.php

@@ -310,7 +310,8 @@ class Schema_SystemObjectFieldStorageAcl extends Core_AclSimpleSchemaBase {
 		}
 		SchemaFactory::loadDefaultObject('SystemObject')->updateItem([
 			'namespace' => $item['namespace'],
-			'isStructInstalled' => 1
+			'isStructInstalled' => 1,
+			'primaryKey' => $fvAcl->getPrimaryKeyField(),
 		]);
 		// $zasobTableName = substr($item['objectNamespace'], strlen('default_db/'));
 		// $zasobTableName = (false !== strpos($zasobTableName, '/'))

+ 1 - 0
SE/se-lib/Schema/SystemObjectStorageAcl.php

@@ -423,6 +423,7 @@ class Schema_SystemObjectStorageAcl extends Core_AclSimpleSchemaBase {
 	}
 	public function getItem($pk, $params = []) {
 		// TODO: ceche query for: $pk = 'default_db/CRM_PROCES/PROCES', $params = [ 'propertyName' => "*,field" ]
+		$pk = ACL::getBaseNamespace($pk);
 		if (!$this->_cache) $this->_cache = [];
 		if (1 === count($params) && "*,field" === V::get('propertyName', '', $params)) {
 			if (array_key_exists($pk, $this->_cache)) return $this->_cache[$pk];