浏览代码

updated wfs ref, fixed bug in Insert with value 0 for null field

Piotr Labudda 9 年之前
父节点
当前提交
8dc858dfa6

+ 13 - 8
SE/se-lib/Api/WfsDataServer.php

@@ -125,7 +125,7 @@ class Api_WfsDataServer extends Api_WfsServerBase {
 		// get BBox from geom_field (only one geom fld is allowed)
 		// get BBox from geom_field (only one geom fld is allowed)
 		$geomFld = null;
 		$geomFld = null;
 		{
 		{
-			foreach ($fldList as $idZasob => $fldName) {
+			foreach ($fldList as $fldName) {
 				if ($acl->isGeomField($fldName)) {
 				if ($acl->isGeomField($fldName)) {
 					$geomFld = $fldName;
 					$geomFld = $fldName;
 				}
 				}
@@ -205,7 +205,7 @@ class Api_WfsDataServer extends Api_WfsServerBase {
 		// get BBox from geom_field (only one geom fld is allowed)
 		// get BBox from geom_field (only one geom fld is allowed)
 		$geomFld = null;
 		$geomFld = null;
 		{
 		{
-			foreach ($fldList as $idZasob => $fldName) {
+			foreach ($fldList as $fldName) {
 				if ($acl->isGeomField($fldName)) {
 				if ($acl->isGeomField($fldName)) {
 					$geomFld = $fldName;
 					$geomFld = $fldName;
 				}
 				}
@@ -282,10 +282,15 @@ if($DBG && !empty($geomFld)){echo 'item['.$itemKey.'] ('.$geomFld.')isEmpty('.em
 				$featureMemberNode->appendChild($featureNode);
 				$featureMemberNode->appendChild($featureNode);
 				$featureNode->setAttribute('fid', "{$type}.{$itemKey}");
 				$featureNode->setAttribute('fid', "{$type}.{$itemKey}");
 				if (!$simple) $featureNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:web_link", Request::getPathUri() . "index.php?_route=ViewTableAjax&typeName=p5_{$sourceName}:{$tblName}#EDIT/{$itemKey}");
 				if (!$simple) $featureNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:web_link", Request::getPathUri() . "index.php?_route=ViewTableAjax&typeName=p5_{$sourceName}:{$tblName}#EDIT/{$itemKey}");
-					foreach ($fldList as $idZasob => $fldName) {
-						$featureFldNode = $dom->createElementNS($wfsNsUri, "{$wfsNs}:{$fldName}");
-						if($DBG_DS){echo">>> acl->validateFieldAction('{$fldName}', 'R', \$item) ...\n";}
-						if ($acl->validateFieldAction($fldName, 'R', (object)$item)) {
+					foreach ($fldList as $fldName) {
+						$fldType = $acl->getXsdFieldType($fldName);
+						if ('alias_ref:' == substr($fldType, 0, 10)) {
+							$featureFldNode = $dom->createElementNS($wfsNsUri, "{$wfsNs}:" . $acl->getName() . "__x3A__{$fldName}");
+						} else {
+							$featureFldNode = $dom->createElementNS($wfsNsUri, "{$wfsNs}:{$fldName}");
+						}
+						if($DBG_DS){echo">>> acl->canReadObjectField('{$fldName}', \$item) ...\n";}
+						if ($acl->canReadObjectField($fldName, (object)$item)) {
 							if ($geomFld != null && $geomFld == $fldName) {
 							if ($geomFld != null && $geomFld == $fldName) {
 								$geomNode = $this->_typeConverter->createGmlFromWkt($item[$fldName], $dom);
 								$geomNode = $this->_typeConverter->createGmlFromWkt($item[$fldName], $dom);
 								if (!$geomNode) continue;
 								if (!$geomNode) continue;
@@ -314,10 +319,10 @@ if($DBG && !empty($geomFld)){echo 'item['.$itemKey.'] ('.$geomFld.')isEmpty('.em
 							}
 							}
 						}
 						}
 						if (!$simple) {
 						if (!$simple) {
-							if (!$acl->validateFieldAction($fldName, 'R', (object)$item)) {
+							if (!$acl->canReadObjectField($fldName, (object)$item)) {
 								$featureFldNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_read", "false");
 								$featureFldNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_read", "false");
 							}
 							}
-							if ($acl->validateFieldAction($fldName, 'W', (object)$item)) {
+							if ($acl->canWriteObjectField($fldName, (object)$item)) {
 								$featureFldNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_write", "true");
 								$featureFldNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_write", "true");
 							}
 							}
 						}
 						}

+ 27 - 341
SE/se-lib/Api/WfsServerBase.php

@@ -37,12 +37,10 @@ class Api_WfsServerBase {
 			if ($acl) {
 			if ($acl) {
 				return true;
 				return true;
 			}
 			}
-		} else if ('p5_objects' == $nsPrefix && 'File' == $type) {
-			return true;
-		} else if ('p5_objects' == $nsPrefix && 'TestPerms' == $type) {
-			return true;
-		} else if ('p5_objects' == $nsPrefix && 'Korespondencja' == $type) {
-			return true;
+		} else if ('p5_objects' == $nsPrefix) {
+			// TODO: generate class name like in: UserAcl->getObjectAcl($sourceName = $nsPrefix, $objName = $type)
+			$objClassName = "Schema_{$type}StorageAcl";
+			if (Lib::tryLoadClass($objClassName)) return true;
 		}
 		}
 		return false;
 		return false;
 	}
 	}
@@ -591,9 +589,7 @@ class Api_WfsServerBase {
 	public function _parseTransactionXmlStruct($requestXml, $requestXmlTags) {
 	public function _parseTransactionXmlStruct($requestXml, $requestXmlTags) {
 		$DBG = V::get('DBG_XML', 0, $_GET, 'int');// TODO: Profiler
 		$DBG = V::get('DBG_XML', 0, $_GET, 'int');// TODO: Profiler
 		$rootTagName = V::get('tag', '', $requestXmlTags[0]);
 		$rootTagName = V::get('tag', '', $requestXmlTags[0]);
-		if ('Transaction' != $rootTagName) {
-			throw new Api_WfsException("Parse Request XML Error - Missing Transaction as root xml tag", __LINE__, null, 'TransactionParseError', 'request');
-		}
+		if ('Transaction' != $rootTagName) throw new Api_WfsException("Parse Request XML Error - Missing Transaction as root xml tag", __LINE__, null, 'TransactionParseError', 'request');
 
 
 		// TODO: special actions if action on nested objects
 		// TODO: special actions if action on nested objects
 		// 1. convert request: wfs.transaction.convert-wfs-request.xsl
 		// 1. convert request: wfs.transaction.convert-wfs-request.xsl
@@ -679,16 +675,10 @@ class Api_WfsServerBase {
 				}
 				}
 				$action['typeName'] = $typeName;
 				$action['typeName'] = $typeName;
 				$actionXmlTags[$actionIdx] = $action;
 				$actionXmlTags[$actionIdx] = $action;
-				// $lvl = $action['tags'][0]['level'];
-				// for ($i = 1, $cnt = count($action['tags']); $i < $cnt - 1; $i++) {
-				// 	$tag = $action['tags'][$i];
-				// 	// if($DBG){echo 'L.' . __LINE__ . " actionXmlTags loop({$i}) \$tag:";print_r($tag);echo "\n";}
-				// 	// if ($tag['level'] > $lvl) $isDeepStructure = true;
-				// }
 			}
 			}
 		}
 		}
 
 
-		{
+		{// validate
 			// if($DBG){echo 'L.' . __LINE__ . ' before validate $actionXmlTags:';print_r($actionXmlTags);echo "\n";}
 			// if($DBG){echo 'L.' . __LINE__ . ' before validate $actionXmlTags:';print_r($actionXmlTags);echo "\n";}
 			foreach ($actionXmlTags as $actionIdx => $action) {
 			foreach ($actionXmlTags as $actionIdx => $action) {
 				if ('Insert' == $action['action']) {
 				if ('Insert' == $action['action']) {
@@ -708,6 +698,9 @@ class Api_WfsServerBase {
 				}
 				}
 				// continue;// TODO: validate all by type
 				// continue;// TODO: validate all by type
 			}
 			}
+		}
+
+		{// execute
 			$returnIds = array();
 			$returnIds = array();
 			$changesList = array();
 			$changesList = array();
 			foreach ($actionXmlTags as $actionIdx => $action) {
 			foreach ($actionXmlTags as $actionIdx => $action) {
@@ -730,326 +723,7 @@ class Api_WfsServerBase {
 				} else throw new Exception("TODO: {$action['action']} action not implemented", 501);
 				} else throw new Exception("TODO: {$action['action']} action not implemented", 501);
 			}
 			}
 			if($DBG){echo 'L.' . __LINE__ . ' $changesList:';print_r($changesList);echo "\n";}
 			if($DBG){echo 'L.' . __LINE__ . ' $changesList:';print_r($changesList);echo "\n";}
-
-			return $this->_transactionResponse($changesList);
-
-			if($DBG){echo 'L.' . __LINE__ . ' $actionXmlTags:';print_r($actionXmlTags);echo "\n";}
-			$requestNsUriList = array();// [ uri, ... ]
-			$requestNsUriToPrefixMap = array();// uri => prefix
-			$requestNsPrefixToUriMap = array();// prefix => uri
-			{
-				$tag = reset($requestXmlTags);// first tag: 'Transaction'
-				$itemsNsList = Api_WfsNs::getNsList();
-				if($DBG){echo 'L.' . __LINE__ . ' $itemsNsList:';print_r($itemsNsList);echo "\n";}
-				foreach ($tag['attributes'] as $attrName => $attrVal) {
-					if ('xmlns:' !== substr($attrName, 0, 6)) continue;
-					if ('xmlns:xsi' === $attrName) continue;
-					if ('xmlns:gml' === $attrName) continue;
-					if (array_key_exists($attrVal, $itemsNsList)) {
-						$requestNsUriList[$attrVal] = true;// ns uri used
-						$prefixNS = substr($attrName, 6);
-						$requestNsUriToPrefixMap[$attrVal] = $prefixNS;
-						$requestNsPrefixToUriMap[$prefixNS] = $attrVal;
-					}
-					echo "NS List: loop({$attrName}) isItemNsList(".(array_key_exists($attrVal, $itemsNsList)).") \t val:";var_dump($attrVal);echo"\n";
-				}
-			}
-			if($DBG){echo 'L.' . __LINE__ . ' $requestNsUriList:'.json_encode($requestNsUriList);echo "\n";}
-			if($DBG){echo 'L.' . __LINE__ . ' $requestNsUriToPrefixMap:'.json_encode($requestNsUriToPrefixMap);echo "\n";}
-			if($DBG){echo 'L.' . __LINE__ . ' $requestNsPrefixToUriMap:'.json_encode($requestNsPrefixToUriMap);echo "\n";}
-			// fix Insert tag - get typeName from first tag under Insert
-			foreach ($actionXmlTags as $actionIdx => $action) {
-				if ('Insert' !== $action['action']) continue;
-				$tag = reset($action['tags']);
-				$name = $tag['tag'];
-				// <p5_objects:File... or <File xmlns=".../wfs/objects"...
-				// V::get('xmlns', '', $tag['attributes']);
-				$actionXmlTags[$actionIdx]['ns_uri'] = V::get('xmlns', '', $tag['attributes']);
-			}
-			// fix ns_uri by @typeName prefix or @xmlns
-		}
-
-		$usedSourceNsList = array();
-		$sourceNsList = $this->_getSourceNsList();
-		if($DBG>3){echo 'L.' . __LINE__ . ' $requestXmlTags:';print_r($requestXmlTags);echo "\n";}
-		if($DBG>3){echo 'L.' . __LINE__ . ' $sourceNsList:';print_r($sourceNsList);echo "\n";}
-		{// get used typeNames
-			$usedTypeNames = array();
-			foreach ($actionXmlTags as $action) {
-				if ('Delete' == $action['action']) {
-					foreach ($sourceNsList as $nsInd => $ns) {
-						if ("p5_{$ns[0]}:{$ns[1]}" == $action['typeName']) {
-							$usedSourceNsList[$nsInd] = $ns;
-						}
-					}
-				} else if ('Update' == $action['action']) {
-					foreach ($sourceNsList as $nsInd => $ns) {
-						if ("p5_{$ns[0]}:{$ns[1]}" == $action['typeName']) {
-							$usedSourceNsList[$nsInd] = $ns;
-						}
-					}
-				} else if ('Insert' == $action['action']) {
-					foreach ($action['tags'] as $tag) {
-						if ('open' != $tag['type']) continue;
-						foreach ($sourceNsList as $nsInd => $ns) {
-							if ("{$ns[1]}" == $tag['tag']) {
-								$usedSourceNsList[$nsInd] = $ns;
-							}
-						}
-					}
-				}
-			}
-			if($DBG){echo 'L.' . __LINE__ . ' $usedSourceNsList after analyze split action tags:';print_r($usedSourceNsList);echo "\n";}
-			if($DBG){echo 'L.' . __LINE__ . ' exit';exit;}
-
-			// <Update xmlns="http://www.opengis.net/wfs" typeName="p5_default_db:TEST_PERMS">
-			foreach ($requestXmlTags as $tag) {
-				if ('Update' == $tag['tag'] && 'open' == $tag['type']) {
-					$typeName = $tag['attributes']['typeName'];
-					foreach ($sourceNsList as $nsInd => $ns) {
-						if ("p5_{$ns[0]}:{$ns[1]}" == $typeName) {
-							$usedSourceNsList[$nsInd] = $ns;
-						}
-					}
-				}
-			}
-			if($DBG){echo 'L.' . __LINE__ . ' $usedSourceNsList after Update:';print_r($usedSourceNsList);echo "\n";}
-			// TODO: check: <Transaction xmlns:p5_default_db="https://biuro.biall-net.pl/wfs/default_db/TEST_PERMS"
-			// <Insert xmlns="http://www.opengis.net/wfs">
-			//   <TEST_PERMS xmlns="https://biuro.biall-net.pl/wfs/default_db/TEST_PERMS">
-			$lastTagName = '';
-			foreach ($requestXmlTags as $tag) {
-				if ('Insert' == $lastTagName) {
-					$typeName = $tag['tag'];
-					if($DBG && 'File' == $typeName){echo 'L.' . __LINE__ . ' loop Insert: $typeName(File):';print_r($tag);echo "\n";}
-					foreach ($sourceNsList as $nsInd => $ns) {
-						if ("{$ns[1]}" == $typeName) {
-							$usedSourceNsList[$nsInd] = $ns;
-						}
-					}
-				}
-				$lastTagName = $tag['tag'];
-			}
-			if($DBG){echo 'L.' . __LINE__ . ' $usedSourceNsList after Insert:';print_r($usedSourceNsList);echo "\n";}
-
-			// <Delete xmlns="http://www.opengis.net/wfs" typeName="p5_default_db:TEST_GEOM_POINT">
-			foreach ($requestXmlTags as $tag) {
-				if ('Delete' == $tag['tag'] && 'open' == $tag['type']) {
-					$typeName = $tag['attributes']['typeName'];
-					foreach ($sourceNsList as $nsInd => $ns) {
-						if ("p5_{$ns[0]}:{$ns[1]}" == $typeName) {
-							$usedSourceNsList[$nsInd] = $ns;
-						}
-					}
-				}
-			}
-			if($DBG){echo 'L.' . __LINE__ . ' $usedSourceNsList after Delete:';print_r($usedSourceNsList);echo "\n";}
-		}
-		if (empty($usedSourceNsList)) {
-			throw new Api_WfsException("Parse Request XML Error - Empty source NS list", __LINE__, null, 'TransactionParseError', 'request');
-		}
-
-		$convertedTransaction = $this->_convertTransactionXml($requestXml, $usedSourceNsList);
-if($DBG){echo 'L.' . __LINE__ . ' $convertedTransaction:';print_r($convertedTransaction);echo "\n";}
-		if (empty($convertedTransaction)) {
-			throw new Api_WfsException("Parse Request XML Error - Empty transaction", __LINE__, null, 'TransactionParseError', 'request');
-		}
-		if (!$this->_validateConvertedTransactionXml($convertedTransaction, $usedSourceNsList)) {
-			// <Transaction version="1.0.0" service="WFS">
-			//     <InsertNs0 typeName="TEST_PERMS">
-			//         <ID>41</ID>
-			//         <ADM_ADMIN_LEVEL>3</ADM_ADMIN_LEVEL>
-			//     </InsertNs0>
-			// </Transaction>
-			$transXml = @simplexml_load_string($convertedTransaction);
-			foreach ($transXml->children() as $funcXml) {
-				$funcName = substr($funcXml->getName(), 0, 6);// Insert... , Update... , Delete...
-				if (empty($funcXml['typeName'][0])) throw new Api_WfsException("Missing typeName for function '{$funcName}'", __LINE__, null, 'MissingTypeName', 'request');
-				$typeName = $funcXml['typeName'][0];
-				$acl = $this->getAclFromTypeName("p5_default_db:{$typeName}");
-				$primaryKey = $acl->getPrimaryKeyField();
-				$pkObject = null;
-				foreach ($funcXml->children() as $fieldXml) {
-					if ($primaryKey == $fieldXml->getName()) $pkObject = $fieldXml[0];
-				}
-				if ('Insert' == $funcName && $pkObject) $funcName = 'Update';
-
-				if ('Update' == $funcName) {// check perm W - skip $primaryKey
-					if (!$pkObject) throw new Api_WfsException("Missing primary key ({$primaryKey}) for action Update", __LINE__, null, 'MissingPrimaryKey', 'request');
-					$toUpdateFields = array();
-					foreach ($funcXml->children() as $fieldXml) {
-						if ($primaryKey == $fieldXml->getName()) continue;// skip primary key
-						$toUpdateFields[] = $fieldXml->getName();
-					}
-					if (empty($toUpdateFields)) throw new Api_WfsException("Missing fields to update", __LINE__, null, 'MissingFieldToUpdate', 'request');
-					$oldObject = $acl->getItem($pkObject);
-					if (!$oldObject) throw new Api_WfsException("Object '{$typeName}.{$pkObject}' not exists", __LINE__, null, 'ObjectNotExists', 'request');
-					if (!$acl->canWriteRecord($oldObject) && !$acl->hasPermSuperWrite()) {
-						throw new Api_WfsException("Access Denied to Update object '{$typeName}.{$pkObject}'", __LINE__, null, 'MissingObjectPermUpdate', 'request');
-					}
-					foreach ($toUpdateFields as $fieldName) {
-						$aclIdFld = $acl->getFieldIdByName($fieldName);
-						if (!$acl->isAllowed($aclIdFld, 'W', $oldObject)) {
-							throw new Api_WfsException("Access Denied to Update field '{$fieldName}' in object '{$typeName}.{$pkObject}'", __LINE__, null, 'MissingFieldPermWrite', 'request');
-						}
-					}
-				} else if ('Insert' == $funcName) {// check perm C
-					foreach ($funcXml->children() as $fieldXml) {
-						$fieldName = $fieldXml->getName();
-						$aclIdFld = $acl->getFieldIdByName($fieldXml->getName());
-						if (!$acl->isAllowed($aclIdFld, 'C')) {
-							throw new Api_WfsException("Access Denied to Create field '{$fieldName}' in object '{$typeName}.{$pkObject}'", __LINE__, null, 'MissingFieldPermCreate', 'request');
-						}
-					}
-				} else {
-					// TODO: Delete, ... ?
-				}
-			}
-			throw new Exception("Parse Request xml error #" . __LINE__ . ": schema validation failed");
-		}
-
-		$parserXml = xml_parser_create();
-		xml_parser_set_option($parserXml, XML_OPTION_CASE_FOLDING, 0);
-		xml_parser_set_option($parserXml, XML_OPTION_SKIP_WHITE, 1);
-		if (0 == xml_parse_into_struct($parserXml, $convertedTransaction, $tags)) {
-			throw new Exception("Parse Request xml error #" . __LINE__ . ": parse converted transaction failed");
-		}
-		xml_parser_free($parserXml);
-		if (empty($tags)) {
-			throw new Exception("Parse Request xml error #" . __LINE__ . ": parse converted transaction returns empty structure");
-		}
-
-		// [{"tag":"Transaction","type":"open","level":1,"attributes":{"version":"1.0.0","service":"WFS"}},
-		//	{"tag":"Update","type":"open","level":2,"attributes":
-		//		{"typeName":"p5_default_db_13051:TEST_PERMS","featureId":"TEST_PERMS.25"}},
-		//			{"tag":"PARENT_ID","type":"complete","level":3,"value":"0"},
-		//	{"tag":"Update","type":"close","level":2},
-		//	{"tag":"Transaction","type":"close","level":1}]
-		if($DBG){echo "\ntags L." . __LINE__ . ":\n"; print_r($tags);echo "\n";}
-		$actionTag = null;
-		$prevTagName = '';
-		$theGeomField = 'the_geom';// TODO: get the geom field name from acl
-		$itemPatchs = array();
-		foreach ($tags as $tag) {
-			switch (substr($tag['tag'], 0, 6)) {
-				case 'Transa': continue; break;// Transaction
-				case 'Update':
-				case 'Insert':
-				case 'Delete':
-				case 'Native':
-					if ('open' == $tag['type'] // Insert, Update
-						|| 'complete' == $tag['type'] // Delete
-						) {
-						if($DBG){echo "\ntags loop 1 - tag: L." . __LINE__ . ":\n"; print_r($tag);echo "\n";}
-						$actionTag = array();
-						$actionTag['tag'] = substr($tag['tag'], 0, 6);
-						$actionTag['typeName'] = $tag['attributes']['typeName'];
-						if ('Insert' == substr($tag['tag'], 0, 6)) {
-							$typeNsPrefix = 'p5_default_db';
-							if (!empty($tag['attributes']['typeNsUri'])) {
-								$baseNsUri = Api_WfsNs::getBaseWfsUri();
-								if ("{$baseNsUri}/objects" == $tag['attributes']['typeNsUri']) {
-									$typeNsPrefix = 'p5_objects';
-								}
-							}
-							$actionTag['typeName'] = "{$typeNsPrefix}:{$tag['attributes']['typeName']}";
-						}
-						$featureEx = explode('.', $tag['attributes']['featureId'], 2);
-						$actionTag['featureId'] = $featureEx[1];
-						if ('Update' == substr($tag['tag'], 0, 6) && empty($actionTag['featureId'])) {
-							throw new Api_WfsException("Syntax error - could not read feature id!");
-						}
-						if ('Delete' == substr($tag['tag'], 0, 6) && empty($actionTag['featureId'])) {
-							throw new Api_WfsException("Syntax error - could not read feature id!");
-						}
-
-						if ('complete' == $tag['type']) {
-							$itemPatchs[] = $actionTag;
-							$actionTag = null;
-						} else {
-							$actionTag['itemPatch'] = array();
-						}
-					} else {
-						$itemPatchs[] = $actionTag;
-						$actionTag = null;
-					}
-					break;
-				default: {// fields
-						if($DBG){echo "\ntags loop 2 - tag: L." . __LINE__ . ":\n"; print_r($tag);echo "\n";}
-						if (3 != $tag['level'] && 'close' == $tag['type']) {
-							$actionTag = null;
-						}
-						if (3 != $tag['level']) continue;
-						if (empty($actionTag)) continue;
-						if ('Update' == $actionTag['tag']) {
-							if ($theGeomField == $tag['tag']) {
-								$actionTag['itemPatch'][$tag['tag']] = $this->_typeConverter->convertGmlCoordinatesToWkt($tag['value']);
-							} else {
-								$actionTag['itemPatch'][$tag['tag']] = $tag['value'];
-							}
-						}
-						else if ('Insert' == $actionTag['tag']) {
-							if ($theGeomField == $tag['tag']) {
-								$actionTag['itemPatch'][$tag['tag']] = $this->_typeConverter->convertGmlCoordinatesToWkt($tag['value']);
-							} else {
-								$actionTag['itemPatch'][$tag['tag']] = $tag['value'];
-							}
-						}
-						else if ('Delete' == $actionTag['tag']) {
-						}
-					}
-			}
-
-			if (empty($prevTagName)) $prevTagName = $tag['tag'];
-		}
-
-		if($DBG){echo "\nTODO: itemPatchs L." . __LINE__ . ":\n"; print_r($itemPatchs);echo "\n";}
-		if($DBG){echo "\nTODO: _user_id L." . __LINE__ . " '{$this->_usrAcl->_user_id}'" . "\n";}
-		$changesList = array();
-		if (!empty($itemPatchs)) {
-			foreach ($itemPatchs as $itemPatchInfo) {
-				if($DBG){echo "L." . __LINE__ . " itemPatchInfo: {typeName:'{$itemPatchInfo['typeName']}'}:\n";print_r($itemPatchInfo);}
-				$acl = $this->getAclFromTypeName($itemPatchInfo['typeName']);
-				if ('Delete' == $itemPatchInfo['tag']) {
-					$itemPatch = array();
-					$itemPatch[$acl->getPrimaryKeyField()] = $itemPatchInfo['featureId'];
-					$itemPatch['the_geom'] = 'NULL';
-				} else {
-					if (empty($itemPatchInfo['itemPatch'])) continue;
-					$itemPatch = $itemPatchInfo['itemPatch'];
-					if ('Update' == $itemPatchInfo['tag']) {
-						$itemPatch[$acl->getPrimaryKeyField()] = $itemPatchInfo['featureId'];
-					}
-					else if ('Insert' == $itemPatchInfo['tag']) {
-						if (!empty($itemPatch[$acl->getPrimaryKeyField()])) {
-							$itemPatchInfo['featureId'] = $itemPatch[$acl->getPrimaryKeyField()];
-						}
-						else {
-							//throw new Exception("TODO: Insert #" . __LINE__ . ": Create new record");
-						}
-					}
-				}
-
-				if($DBG){echo "L." . __LINE__ . " TODO '" . ($itemPatchInfo['tag'])? 'Insert' : 'Update' . "' itemPatch:\n";print_r($itemPatch);}
-				if ('Insert' == $itemPatchInfo['tag'] && empty($itemPatch[$acl->getPrimaryKeyField()])) {
-					$newId = $acl->addItem($itemPatch);
-					$changesList[$newId] = array('Status'=>(($newId > 0)? 'SUCCESS' : 'FAILED'), 'Message'=>"created {$newId}.");
-					if ($newId > 0) {
-						$changesList[$newId]['fid'] = $acl->getName() . '.' . $newId;
-					}
-					if($DBG){echo "created {$newId}.\n";}
-				} else {
-					$affected = $acl->updateItem($itemPatch);
-					$changesList[$itemPatchInfo['featureId']] = array('Status'=>(($affected >= 0)? 'SUCCESS' : 'FAILED'), 'Message'=>"affected {$affected}.");
-					if($DBG){echo "affected {$affected}.\n";}
-				}
-			}
-			//throw new Exception("TODO: run query #" . __LINE__ . " \nitemPatchs:\n" . json_encode($itemPatchs) . " \ntags:\n" . json_encode($tags) . "\n");
-		}
-		else {
-			throw new Exception("Parse Request xml error #" . __LINE__ . ": Nothing to change");
 		}
 		}
-
 		return $this->_transactionResponse($changesList);
 		return $this->_transactionResponse($changesList);
 	}
 	}
 
 
@@ -1673,7 +1347,7 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 			// <xsd:element maxOccurs="1" minOccurs="0" name="{$fldName}" nillable="true" type="xsd:integer"/>
 			// <xsd:element maxOccurs="1" minOccurs="0" name="{$fldName}" nillable="true" type="xsd:integer"/>
 			$pKeyField = $acl->getPrimaryKeyField();
 			$pKeyField = $acl->getPrimaryKeyField();
 			$p5Attributes = ($simple)? array() : $acl->getAttributesFromZasoby();
 			$p5Attributes = ($simple)? array() : $acl->getAttributesFromZasoby();
-			foreach ($fldList as $idZasob => $fldName) {
+			foreach ($fldList as $fldName) {
 				$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
 				$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
 				$seqNode->appendChild($elNode);
 				$seqNode->appendChild($elNode);
 				$minOccurs = 0;
 				$minOccurs = 0;
@@ -1691,8 +1365,13 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 				}
 				}
 				if ('ref:' == substr($fldType, 0, 4)) {
 				if ('ref:' == substr($fldType, 0, 4)) {
 					$elNode->setAttribute('ref', substr($fldType, 4));
 					$elNode->setAttribute('ref', substr($fldType, 4));
+					$elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:name", $fldName);
 				} else if ('local_ref:' == substr($fldType, 0, 10)) {
 				} else if ('local_ref:' == substr($fldType, 0, 10)) {
 					$elNode->setAttribute('type', "{$fldName}Type");
 					$elNode->setAttribute('type', "{$fldName}Type");
+					$elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:name", $fldName);
+				} else if ('alias_ref:' == substr($fldType, 0, 10)) {
+					$elNode->setAttribute('ref', "p5_" . $acl->getSourceName() . ":" . $acl->getName() . "__x3A__{$fldName}");
+					$elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:name", $fldName);
 				} else {
 				} else {
 					$elNode->setAttribute('name', $fldName);
 					$elNode->setAttribute('name', $fldName);
 					$elNode->setAttribute('type', $fldType);
 					$elNode->setAttribute('type', $fldType);
@@ -1705,9 +1384,9 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 						if (!empty($p5attrs['label'])) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:label", $p5attrs['label']);
 						if (!empty($p5attrs['label'])) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:label", $p5attrs['label']);
 						if (!empty($p5attrs['description'])) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:description", $p5attrs['description']);
 						if (!empty($p5attrs['description'])) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:description", $p5attrs['description']);
 					}
 					}
-					if ($acl->hasFieldPerm($idZasob, 'W')) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_write", "true");
-					if ($acl->hasFieldPerm($idZasob, 'C')) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_create", "true");
-					if (!$acl->hasFieldPerm($idZasob, 'R')) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_read", "false");
+					if ($acl->canWriteField($fldName)) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_write", "true");
+					if ($acl->canCreateField($fldName)) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_create", "true");
+					if (!$acl->canReadField($fldName)) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_read", "false");
 				}
 				}
 			}
 			}
 
 
@@ -1721,9 +1400,16 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 				$elNode->setAttribute('substitutionGroup', 'gml:AbstractFeature');
 				$elNode->setAttribute('substitutionGroup', 'gml:AbstractFeature');
 			}
 			}
 
 
-			foreach ($fldList as $idZasob => $fldName) {
+			foreach ($fldList as $fldName) {
 				$fldType = $acl->getXsdFieldType($fldName);
 				$fldType = $acl->getXsdFieldType($fldName);
-				if ('local_ref:' == substr($fldType, 0, 10)) {
+				if ('alias_ref:' == substr($fldType, 0, 10)) {
+					$localRefType = substr($fldType, 10);
+					// <xsd:element name="{$fldName}" ref="{$localRefType}">
+					$ctNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
+					$rootNode->appendChild($ctNode);
+					$ctNode->setAttribute('name', $acl->getName() . "__x3A__{$fldName}");
+					$ctNode->setAttribute('type', "{$localRefType}");
+				} else if ('local_ref:' == substr($fldType, 0, 10)) {
 					$localRefType = substr($fldType, 10);
 					$localRefType = substr($fldType, 10);
 					// <xsd:complexType name="produkt_Type">
 					// <xsd:complexType name="produkt_Type">
 					// 	<xsd:sequence>
 					// 	<xsd:sequence>

+ 58 - 29
SE/se-lib/Core/AclBase.php

@@ -1,40 +1,67 @@
 <?php
 <?php
 
 
 Lib::loadClass('Api_WfsNs');
 Lib::loadClass('Api_WfsNs');
-
+Lib::loadClass('Api_WfsException');
+
+// TODO: replace every methods using $idZasob to use $fieldName
+/* TODO: fetch ACL from acl tables:
+@example for TestPerms [13051]:
+  SELECT * FROM  `CRM_PROCES_idx_TABLE_TO_PROCES_PERMS_VIEW` WHERE  `ID_TABLE` =13051; -- fetch id proces to $csvIdProces
+  SELECT * FROM  `CRM_PROCES_idx_USER_to_PROCES_VIEW` WHERE  `ADM_ACCOUNT` = '{$userLogin}' and `ID_PROCES` in({$csvIdProces});
+*/
 class Core_AclBase {
 class Core_AclBase {
 
 
   public function getSourceName() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getSourceName() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getName() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getName() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getRootTableName() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getRootTableName() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
-  public function getXsdFieldType($fldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+  public function getXsdFieldType($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   // TODO: get more xsd restrictions like minOccurs, maxOccurs, nillable and restrictions
   // TODO: get more xsd restrictions like minOccurs, maxOccurs, nillable and restrictions
 
 
   public function getID() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }// TODO: Legacy
   public function getID() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }// TODO: Legacy
   public function init($force = false) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function init($force = false) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function isInitialized() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function isInitialized() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+  public function getFields() {// @returns array - $this->_fields
+    /*
+      $field = array();
+  		$field['name'] = $name;
+  		$field['perms'] = '';
+  		$field['opis'] = $opis;
+  		$field['sort_prio'] = $sort_prio;
+  		$field['label'] = $label;
+  		$this->_fields[$fieldID] = $field;
+    */
+    throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501);
+  }
   public function getRealFieldListByIdZasob() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getRealFieldListByIdZasob() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
-  public function getFieldIdByName($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
-  public function isIntegerField($fieldName) { return ('xsd:integer' == $this->getXsdFieldType($fldName)); }
+  public function isIntegerField($fieldName) { return ('xsd:integer' == $this->getXsdFieldType($fieldName)); }
   public function isDecimalField($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function isDecimalField($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
-  public function isGeomField($fldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
-  public function isDateField($fldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
-  public function isDateTimeField($fldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+  public function isGeomField($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+  public function isDateField($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+  public function isDateTimeField($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function isStringField($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function isStringField($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
-  public function isTextField($fldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+  public function isTextField($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function isBinaryField($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function isBinaryField($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
-  public function isEnumerationField($fldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
-  public function getEnumerations($fldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
-  public function getFieldType($colName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
-  public function isAllowed($idZasob, $taskPerm, $record = null) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
-  public function hasFieldPerm($idZasob, $taskPerm) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+  public function isEnumerationField($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+  public function getEnumerations($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+  public function getFieldType($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+
+  public function getFieldIdByName($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }// TODO: legacy
+  public function isAllowed($idZasob, $taskPerm, $record = null) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }// TODO: legacy
+  public function hasFieldPerm($idZasob, $taskPerm) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }// TODO: legacy
+
+  // TODO: replace isAllowed, hasFieldPerm, getFieldIdByName
+  public function canCreateField($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+  public function canReadField($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+  public function canReadObjectField($fieldName, $record) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+  public function canWriteField($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+  public function canWriteObjectField($fieldName, $record) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+
   public function getItems($params = array()) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getItems($params = array()) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function addItem($todoItem) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function addItem($todoItem) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function updateItem($itemPatch) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function updateItem($itemPatch) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
-  public function getGeomFieldType($fldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
+  public function getGeomFieldType($fieldName) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getPrimaryKeyField() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getPrimaryKeyField() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getAttributesFromZasoby() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getAttributesFromZasoby() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
-  public function validateFieldAction($fieldName, $perms, $record = null) { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
 
 
   public function validateDeleteXml($action) {// @returns action tags, throws Exceptions
   public function validateDeleteXml($action) {// @returns action tags, throws Exceptions
     $DBG = V::get('DBG_XML', 0, $_GET, 'int');
     $DBG = V::get('DBG_XML', 0, $_GET, 'int');
@@ -117,7 +144,7 @@ class Core_AclBase {
     $action['fields'] = $this->validateUpdatePropertyTags($action['tags']);
     $action['fields'] = $this->validateUpdatePropertyTags($action['tags']);
     if($DBG){echo 'C.'.get_class($this).' L.' . __LINE__ . " Update action after validate Property \$action['fields']:";print_r($action['fields']);echo "\n";}
     if($DBG){echo 'C.'.get_class($this).' L.' . __LINE__ . " Update action after validate Property \$action['fields']:";print_r($action['fields']);echo "\n";}
     foreach ($action['fields'] as $fieldName => $propertyTag) {
     foreach ($action['fields'] as $fieldName => $propertyTag) {
-      if (!$this->validateFieldAction($fieldName, 'W')) throw new Api_WfsException("Access Denied to Update field '{$fieldName}' in object '{$action['typeName']}'", __LINE__, null, 'MissingFieldPermWrite', 'request');
+      if (!$this->canWriteField($fieldName)) throw new Api_WfsException("Access Denied to Update field '{$fieldName}' in object '{$action['typeName']}'", __LINE__, null, 'MissingFieldPermWrite', 'request');
       $value = $propertyTag['value'];
       $value = $propertyTag['value'];
       $this->validateFieldRestrictions($fieldName, $value);
       $this->validateFieldRestrictions($fieldName, $value);
     }
     }
@@ -257,7 +284,7 @@ class Core_AclBase {
       $field['type'] = $tag['type'];
       $field['type'] = $tag['type'];
       if (!empty($tag['typeName'])) $field['typeName'] = $tag['typeName'];
       if (!empty($tag['typeName'])) $field['typeName'] = $tag['typeName'];
       if (!empty($tag['action'])) $field['action'] = $tag['action'];
       if (!empty($tag['action'])) $field['action'] = $tag['action'];
-      if (!empty($tag['value'])) $field['value'] = $tag['value'];
+      if (!empty($tag['value']) || '0' === $tag['value'] || 0 === $tag['value']) $field['value'] = $tag['value'];
       if (!empty($tag['tags'])) $field['tags'] = $tag['tags'];
       if (!empty($tag['tags'])) $field['tags'] = $tag['tags'];
       $action['fields'][$fieldName][] = $field;
       $action['fields'][$fieldName][] = $field;
     }
     }
@@ -271,7 +298,7 @@ class Core_AclBase {
     foreach ($action['fields'] as $fieldName => $childFields) {
     foreach ($action['fields'] as $fieldName => $childFields) {
       if ($fieldName == $fieldPK) continue;
       if ($fieldName == $fieldPK) continue;
       foreach ($childFields as $idx => $field) {
       foreach ($childFields as $idx => $field) {
-        if (!$this->validateFieldAction($fieldName, 'C')) throw new Api_WfsException("Access Denied to Create field '{$fieldName}' in object '{$action['typeName']}'", __LINE__, null, 'MissingFieldPermCreate', 'request');
+        if (!$this->canCreateField($fieldName)) throw new Api_WfsException("Access Denied to Create field '{$fieldName}' in object '{$action['typeName']}'", __LINE__, null, 'MissingFieldPermCreate', 'request');
         if ('open' == $field['type']) {
         if ('open' == $field['type']) {
           $fieldType = $this->getXsdFieldType($fieldName);
           $fieldType = $this->getXsdFieldType($fieldName);
           if($DBG){echo 'C.'.get_class($this).' L.' . __LINE__ . " F.".__FUNCTION__." validate fields loop({$idx}) loop({$fieldName}) \$fieldType({$fieldType})"."\n";}
           if($DBG){echo 'C.'.get_class($this).' L.' . __LINE__ . " F.".__FUNCTION__." validate fields loop({$idx}) loop({$fieldName}) \$fieldType({$fieldType})"."\n";}
@@ -413,12 +440,12 @@ class Core_AclBase {
 
 
   public function getAclFromTypeName($typeName) {// TODO: mv to another class, duplicate from Api_WfsServerBase::getAclFromTypeName($typeName)
   public function getAclFromTypeName($typeName) {// TODO: mv to another class, duplicate from Api_WfsServerBase::getAclFromTypeName($typeName)
 		$typeEx = explode(':', $typeName);
 		$typeEx = explode(':', $typeName);
-		if (2 != count($typeEx)) throw new Api_WfsException("Could not get acl for '{$typeName}' - syntax error");
-		if ('p5_' != substr($typeEx[0], 0, 3)) throw new Api_WfsException("Could not get acl for '{$typeName}' - prefix error");
+		if (2 != count($typeEx)) throw new Exception("Could not get acl for '{$typeName}' - syntax error");
+		if ('p5_' != substr($typeEx[0], 0, 3)) throw new Exception("Could not get acl for '{$typeName}' - prefix error");
 		$sourceName = substr($typeEx[0], 3);
 		$sourceName = substr($typeEx[0], 3);
 		$objName = $typeEx[1];
 		$objName = $typeEx[1];
 		$acl = User::getAcl()->getObjectAcl($sourceName, $objName);
 		$acl = User::getAcl()->getObjectAcl($sourceName, $objName);
-		if (!$acl) throw new Api_WfsException("Could not get acl for '{$typeName}'");
+		if (!$acl) throw new Exception("Could not get acl for '{$typeName}'");
 		$forceTblAclInit = 0;//('1' == V::get('_force', '', $_GET));
 		$forceTblAclInit = 0;//('1' == V::get('_force', '', $_GET));
 		$acl->init($forceTblAclInit);
 		$acl->init($forceTblAclInit);
 		return $acl;
 		return $acl;
@@ -465,15 +492,16 @@ class Core_AclBase {
     foreach ($sqlChildInsert as $fieldName => $childFields) {
     foreach ($sqlChildInsert as $fieldName => $childFields) {
       foreach ($childFields as $idx => $childInsertedId) {
       foreach ($childFields as $idx => $childInsertedId) {
         $childAcl = $this->getAclFromTypeName($action['fields'][$fieldName][$idx]['typeName']);// TODO: or $fieldType = $this->getXsdFieldType($fieldName);// TODO: ref:p5_objects:File
         $childAcl = $this->getAclFromTypeName($action['fields'][$fieldName][$idx]['typeName']);// TODO: or $fieldType = $this->getXsdFieldType($fieldName);// TODO: ref:p5_objects:File
-        $this->_insertRef($this->getRootTableName(), $childAcl->getRootTableName(), $insertedId, $childInsertedId);
+        // $this->_insertRef($this->getRootTableName(), $childAcl->getRootTableName(), $insertedId, $childInsertedId);
+        $this->_insertRef($fieldName, $insertedId, $childInsertedId);
       }
       }
     }
     }
 
 
     return $insertedId;
     return $insertedId;
   }
   }
 
 
-  public function _insertRef($tableName, $childTableName, $pk, $childPk) {// TODO: $idTransaction
-    $refTable = $this->createRefTable($tableName, $childTableName);
+  public function _insertRef($childName, $pk, $childPk) {// TODO: $idTransaction
+    $refTable = $this->createRefTable($childName);
     $sqlPk = DB::getPDO()->quote($pk, PDO::PARAM_STR);
     $sqlPk = DB::getPDO()->quote($pk, PDO::PARAM_STR);
     $sqlChildPk = DB::getPDO()->quote($childPk, PDO::PARAM_STR);
     $sqlChildPk = DB::getPDO()->quote($childPk, PDO::PARAM_STR);
     DB::getPDO()->exec("
     DB::getPDO()->exec("
@@ -482,10 +510,11 @@ class Core_AclBase {
     ");
     ");
   }
   }
 
 
-  public function createRefTable($tableName, $childTableName) {// TODO: $idTransaction
-    static $tables = array();
-    $refTable = "{$tableName}__#REF__{$childTableName}";
-    if (array_key_exists($refTable, $tables)) return $refTable;
+  public function createRefTable($childName) {// TODO: $idTransaction
+    static $cacheRefTables = array();
+    $objectName = $this->getName();
+    $refTable = "{$objectName}__#REF__{$childName}";
+    if (in_array($refTable, $cacheRefTables)) return $refTable;
     DB::getPDO()->exec("
     DB::getPDO()->exec("
       CREATE TABLE IF NOT EXISTS `{$refTable}` (
       CREATE TABLE IF NOT EXISTS `{$refTable}` (
         `PRIMARY_KEY` int(11) NOT NULL,
         `PRIMARY_KEY` int(11) NOT NULL,
@@ -495,7 +524,7 @@ class Core_AclBase {
         KEY `REMOTE_PRIMARY_KEY` (`REMOTE_PRIMARY_KEY`)
         KEY `REMOTE_PRIMARY_KEY` (`REMOTE_PRIMARY_KEY`)
       ) ENGINE=MyISAM DEFAULT CHARSET=latin2;
       ) ENGINE=MyISAM DEFAULT CHARSET=latin2;
     ");
     ");
-    $tables[$refTable] = true;
+    $cacheRefTables[] = $refTable;
     return $refTable;
     return $refTable;
   }
   }
 
 

+ 8 - 1
SE/se-lib/ParseOgcFilter.php

@@ -3,7 +3,14 @@
 Lib::loadClass('SqlQueryWhereBuilder');
 Lib::loadClass('SqlQueryWhereBuilder');
 Lib::loadClass('Api_WfsException');
 Lib::loadClass('Api_WfsException');
 
 
-/**
+/*
+ * TODO: parse xlink query
+	<ogc:PropertyIsEqualTo>
+		<ogc:PropertyName>File/@xlink:href</ogc:PropertyName>
+		<ogc:Literal>https://biuro.biall-net.pl/wfs/objects#File.45</ogc:Literal>
+	</ogc:PropertyIsEqualTo>
+ * TODO: in SqlQueryWhereBuilder split query for main database and join-ed db (right join in ref's)
+ *
  * @usage:
  * @usage:
 		$parser = new ParseOgcFilter();
 		$parser = new ParseOgcFilter();
 		$parser->loadOgcFilter($ogcFilter);
 		$parser->loadOgcFilter($ogcFilter);

+ 63 - 8
SE/se-lib/Route/ViewTableAjax.php

@@ -16,7 +16,7 @@ class Route_ViewTableAjax extends RouteBase {
 
 
 			$typeName = V::get('typeName', '', $_GET, 'word');
 			$typeName = V::get('typeName', '', $_GET, 'word');
 			if (!$typeName) throw new Exception("Wrong param typeName");
 			if (!$typeName) throw new Exception("Wrong param typeName");
-			$tblAcl = $this->getAclFromTypeName($typeName, $forceTblAclInit = ('1' == V::get('_force', '', $_GET)));
+			$acl = $this->getAclFromTypeName($typeName, $forceTblAclInit = ('1' == V::get('_force', '', $_GET)));
 
 
 			$forceFilterInit = array();
 			$forceFilterInit = array();
 			$filterInit = new stdClass();
 			$filterInit = new stdClass();
@@ -35,13 +35,68 @@ class Route_ViewTableAjax extends RouteBase {
 				}
 				}
 			}
 			}
 
 
-			$tbl = new TableAjax($tblAcl);
-			$tblLabel = array();
-			$zasobObj = ProcesHelper::getZasobTableInfo($tblAcl->getID());
-			if (!$zasobObj) throw new Exception("Zasob TABELA ID=" . $tblAcl->getID() . " nie istnieje");
-			if (!empty($zasobObj->DESC_PL)) $tblLabel []= $zasobObj->DESC_PL;
-			if (!empty($zasobObj->OPIS))    $tblLabel []= $zasobObj->OPIS;
-			$tblLabel = implode(" - ", $tblLabel);
+			$tbl = new TableAjax($acl);
+			$tblLabel = $typeName;
+			if ('p5_default_db:' == substr($typeName, 0, 14)) {
+				$tblLabel = array();
+				$zasobObj = ProcesHelper::getZasobTableInfo($acl->getID());
+				if (!$zasobObj) throw new Exception("Zasob TABELA ID=" . $acl->getID() . " nie istnieje");
+				if (!empty($zasobObj->DESC_PL)) $tblLabel []= $zasobObj->DESC_PL;
+				if (!empty($zasobObj->OPIS))    $tblLabel []= $zasobObj->OPIS;
+				$tblLabel = implode(" - ", $tblLabel);
+			}
+
+			if (DBG::isActive() && V::get('DBG_ACL', '', $_GET)) {// test load perms
+				Lib::loadClass('DebugExecutionTime');
+				$dbgExecTime = new DebugExecutionTime();
+				$dbgExecTime->activate();
+				$dbgExecTime->log('start');
+				UI::startContainer(['style'=>'border:1px solid red']);
+				UI::tag('p', null, "TEST - load perms from db");
+				$idTable = $acl->getID();
+				UI::tag('p', null, "DBG idTable({$idTable})");
+				$dbgExecTime->log('before sql');
+				$aclTableRows = DB::getPDO()->fetchAll("select * from `CRM_PROCES_idx_TABLE_TO_PROCES_PERMS_VIEW` where ID_TABLE = {$idTable}");
+				$dbgExecTime->log('after sql', ['sql']);
+				UI::table(['caption' => "from CRM_PROCES_idx_TABLE_TO_PROCES_PERMS_VIEW", 'rows' => $aclTableRows]);
+				$csvIdProces = array();
+				foreach ($aclTableRows as $row) {
+					if (!in_array($row['ID_PROCES'], $csvIdProces)) $csvIdProces[] = $row['ID_PROCES'];
+				}
+				$csvIdProces = implode(",", $csvIdProces);
+				UI::tag('p', null, "DBG csvIdProces({$csvIdProces})");
+				if (!empty($csvIdProces)) {
+					$userLogin = User::getLogin();
+					$dbgExecTime->log('before sql');
+					$rows = DB::getPDO()->fetchAll("select ID_PROCES from `CRM_PROCES_idx_USER_to_PROCES_VIEW` where ADM_ACCOUNT = '{$userLogin}' and ID_PROCES in({$csvIdProces}) group by ID_PROCES");
+					$dbgExecTime->log('after sql', ['sql']);
+					UI::table(['caption' => "from CRM_PROCES_idx_USER_to_PROCES_VIEW", 'rows' => $rows]);
+					$userIdProces = array(); foreach ($rows as $row) $userIdProces[] = $row['ID_PROCES'];
+					$userTablePerms = array();
+					foreach ($aclTableRows as $row) {
+						if (!in_array($row['ID_PROCES'], $userIdProces)) continue;
+						if (array_key_exists($row['CELL_NAME'], $userTablePerms)) {
+							$userTablePerms[ $row['CELL_NAME'] ][ 'PERM_R' ] += $row['PERM_R'];
+							$userTablePerms[ $row['CELL_NAME'] ][ 'PERM_W' ] += $row['PERM_W'];
+							$userTablePerms[ $row['CELL_NAME'] ][ 'PERM_X' ] += $row['PERM_X'];
+							$userTablePerms[ $row['CELL_NAME'] ][ 'PERM_C' ] += $row['PERM_C'];
+							$userTablePerms[ $row['CELL_NAME'] ][ 'PERM_S' ] += $row['PERM_S'];
+							$userTablePerms[ $row['CELL_NAME'] ][ 'PERM_O' ] += $row['PERM_O'];
+							$userTablePerms[ $row['CELL_NAME'] ][ 'PERM_V' ] += $row['PERM_V'];
+							$userTablePerms[ $row['CELL_NAME'] ][ 'PERM_E' ] += $row['PERM_E'];
+						} else {
+							$userTablePerms[ $row['CELL_NAME'] ] = $row;
+							unset($userTablePerms[ $row['CELL_NAME'] ][ 'TABLE_DESCRIPTION' ]);
+							unset($userTablePerms[ $row['CELL_NAME'] ][ 'ID_PROCES' ]);
+							unset($userTablePerms[ $row['CELL_NAME'] ][ 'FORM_TREAT' ]);
+						}
+					}
+					UI::table(['caption' => "\$userTablePerms", 'rows' => $userTablePerms]);
+				} else UI::alert('warning', "brak \$csvIdProces");
+				$dbgExecTime->printDebug();
+				UI::endContainer();
+			}
+
 			$tbl->setLabel($tblLabel);
 			$tbl->setLabel($tblLabel);
 			$tbl->setFilterInit($filterInit);
 			$tbl->setFilterInit($filterInit);
 			if (!empty($forceFilterInit)) $tbl->setForceFilterInit($forceFilterInit);
 			if (!empty($forceFilterInit)) $tbl->setForceFilterInit($forceFilterInit);

+ 74 - 0
SE/se-lib/Schema/AccessGroupStorageAcl.php

@@ -0,0 +1,74 @@
+<?php
+
+Lib::loadClass('Core_AclBase');
+Lib::loadClass('User');
+Lib::loadClass('UsersHelper');
+
+class Schema_AccessGroupStorageAcl extends Core_AclBase {// Read only class
+
+  public function getSourceName() { return 'objects'; }
+  public function init($force = false) {}
+  public function isInitialized() { return true; }
+  public function getName() { return 'AccessGroup'; }
+  public function getRootTableName() { return 'CRM_LISTA_ZASOBOW'; }
+  public function getRealFieldListByIdZasob($force = false) {
+    $cols[100000] = 'id';// CRM_LISTA_ZASOBOW.ID
+    $cols[100001] = 'name';// CRM_LISTA_ZASOBOW.DESC
+    $cols[100002] = 'uid';// Ldap.uid -> value stored in fields: A_ADM_COMPANY, A_CLASSIFIED
+    return $cols;
+  }
+  public function getFields() { return array_values($this->getRealFieldListByIdZasob()); }
+  public function getFieldType($fieldName) { return null; }
+
+  // TODO: replace legacy functions: isAllowed, hasFieldPerm, getFieldIdByName
+  public function canCreateField($fieldName) { return false; }
+  public function canReadField($fieldName) { return true; }
+  public function canReadObjectField($fieldName, $record) {return true; }
+  public function canWriteField($fieldName) { return false; }
+  public function canWriteObjectField($fieldName, $record) { return false; }
+
+  public function getItems($params = array()) {
+    $DBG = V::get('DBG_DS', 0, $_GET, 'int');
+    if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems \$params:";print_r($params);echo "\n";}
+    $items = array();
+    // TODO: fetch groups connectes with current user
+  {
+    $userLdapGroups = UsersHelper::getLDAPGroupByUserName(User::getLogin());
+    if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems \$userLdapGroups:";print_r($userLdapGroups);echo "\n";}
+    if (empty($userLdapGroups)) throw new Exception("User groups not found", 404);
+
+    foreach ($userLdapGroups as $vLdapGroup) {
+      $allowGroup = false;
+      if ('workgroup' == $vLdapGroup->cn) {
+        $items[1] = ['id'=>0, 'name'=>$vLdapGroup->cn, 'uid'=>$vLdapGroup->cn];
+      } else {
+        $cnTest = str_replace('-', '_', $vLdapGroup->cn);
+        $cnTest = explode('_', $cnTest);
+        $idZasob = $cnTest[0];
+        if (!is_numeric($idZasob)) {
+          if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems - skip cn - missing id zasob \$vLdapGroup->cn:";print_r($vLdapGroup->cn);echo "\n";}
+          continue;
+        }
+        $items[$idZasob] = ['id'=>$idZasob, 'name'=>$vLdapGroup->cn, 'uid'=>$vLdapGroup->cn];
+      }
+    }
+  }
+    if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems \$items:";print_r($items);echo "\n";}
+    return $items;
+  }
+  public function addItem($itemTodo) { throw new Exception("Insert not allowed"); }
+  public function updateItem($itemPatch) { throw new Exception("Update not allowed"); }
+  public function getGeomFieldType($fieldName) { return null; }
+  public function getPrimaryKeyField() { return 'id'; }
+  public function getID() { return 0; }
+  public function getAttributesFromZasoby() { return array(); }
+  public function isEnumerationField($fieldName) { return false; }
+  public function getEnumerations($fieldName) { return null; }
+  public function getXsdFieldType($fieldName) {
+    if ('id' == $fieldName) return 'xsd:string';
+    if ('name' == $fieldName) return 'xsd:string';
+    if ('uid' == $fieldName) return 'xsd:string';
+  }
+  public function isGeomField($fldName) { return false; }
+
+}

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

@@ -0,0 +1,55 @@
+<?php
+
+Lib::loadClass('Core_AclBase');
+
+class Schema_AccessOwnerStorageAcl extends Core_AclBase {
+
+  public function getSourceName() { return 'objects'; }
+  public function init($force = false) {}
+  public function isInitialized() { return true; }
+  public function getName() { return 'AccessOwner'; }
+  public function getRootTableName() { return 'ADMIN_USERS'; }// TODO: turn off - use getName for generating ref's
+  public function getRealFieldListByIdZasob($force = false) {
+    $cols[100000] = 'id';// ADMIN_USERS.ID
+    $cols[100001] = 'login';// ADMIN_USERS.ADM_ACCOUNT
+    $cols[100002] = 'name';// ADMIN_USERS.ADM_NAME
+    return $cols;
+  }
+  public function getFields() { return array_values($this->getRealFieldListByIdZasob()); }
+  public function getFieldType($fieldName) { return null; }
+
+  // TODO: replace legacy functions: isAllowed, hasFieldPerm, getFieldIdByName
+  public function canCreateField($fieldName) { return false; }
+  public function canReadField($fieldName) { return true; }
+  public function canReadObjectField($fieldName, $record) {return true; }
+  public function canWriteField($fieldName) { return false; }
+  public function canWriteObjectField($fieldName, $record) { return false; }
+
+  public function getItems($params = array()) {
+    $DBG = V::get('DBG_DS', 0, $_GET, 'int');
+    if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems \$params:";print_r($params);echo "\n";}
+    $items = DB::getPDO()->fetchAllByKey("
+      select u.ID as id, u.ADM_ACCOUNT as login, u.ADM_NAME as name
+      from ADMIN_USERS u
+      where u.A_STATUS = 'NORMAL'
+        and u.ADM_TECH_WORKER != 'NO'
+    ", $key = 'id');
+    if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems \$items:";print_r($items);echo "\n";}
+    return $items;
+  }
+  public function addItem($itemTodo) { throw new Exception("Insert not allowed"); }
+  public function updateItem($itemPatch) { throw new Exception("Update not allowed"); }
+  public function getGeomFieldType($fieldName) { return null; }
+  public function getPrimaryKeyField() { return 'id'; }
+  public function getID() { return 0; }
+  public function getAttributesFromZasoby() { return array(); }
+  public function isEnumerationField($fieldName) { return false; }
+  public function getEnumerations($fieldName) { return null; }
+  public function getXsdFieldType($fieldName) {
+    if ('id' == $fieldName) return 'xsd:string';
+    if ('name' == $fieldName) return 'xsd:string';
+    if ('uid' == $fieldName) return 'xsd:string';
+  }
+  public function isGeomField($fldName) { return false; }
+
+}

+ 25 - 5
SE/se-lib/Schema/FileStorageAcl.php

@@ -3,7 +3,7 @@
 Lib::loadClass('Core_AclBase');
 Lib::loadClass('Core_AclBase');
 Lib::loadClass('FileStorage');
 Lib::loadClass('FileStorage');
 
 
-class FileStorageAcl extends Core_AclBase {
+class Schema_FileStorageAcl extends Core_AclBase {
 
 
   public function __construct() {}
   public function __construct() {}
   public function getSourceName() { return 'objects'; }
   public function getSourceName() { return 'objects'; }
@@ -63,6 +63,30 @@ class FileStorageAcl extends Core_AclBase {
     if ('R' == $taskPerm && $idZasob > 0 && $idZasob < 7) return true;
     if ('R' == $taskPerm && $idZasob > 0 && $idZasob < 7) return true;
     return false;
     return false;
   }
   }
+
+  // TODO: replace legacy functions: isAllowed, hasFieldPerm, getFieldIdByName
+  public function canCreateField($fieldName) {
+    $fields = $this->getRealFieldListByIdZasob();
+    if (!in_array($fieldName, $fields)) return false;
+    return true;
+  }
+  public function canReadField($fieldName) {
+    $fields = $this->getRealFieldListByIdZasob();
+    if (!in_array($fieldName, $fields)) return false;
+    return true;
+  }
+  public function canReadObjectField($fieldName, $record) {
+    return $this->canReadField($fieldName);
+  }
+  public function canWriteField($fieldName) {
+    $fields = $this->getRealFieldListByIdZasob();
+    if (!in_array($fieldName, $fields)) return false;
+    return true;
+  }
+  public function canWriteObjectField($fieldName, $record) {
+    return $this->canWriteField($fieldName);
+  }
+
   public function getItems($params = array()) {
   public function getItems($params = array()) {
     $sqlLimit = V::get('limit', 10000, $params);
     $sqlLimit = V::get('limit', 10000, $params);
     $sqlOffset = V::get('limitstart', 0, $params);
     $sqlOffset = V::get('limitstart', 0, $params);
@@ -159,10 +183,6 @@ class FileStorageAcl extends Core_AclBase {
     // if (!$acl->hasFieldPerm($idZasob, 'R')) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_read", "false");
     // if (!$acl->hasFieldPerm($idZasob, 'R')) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_read", "false");
 		return $attributes;
 		return $attributes;
 	}
 	}
-  public function validateFieldAction($fieldName, $perms, $record = null) {
-    if ($this->getXsdFieldType($fieldName)) return true;
-    return false;
-	}
   public function getXsdFieldType($fieldName) {
   public function getXsdFieldType($fieldName) {
     switch ($fieldName) {
     switch ($fieldName) {
       case 'id': return 'xsd:integer';
       case 'id': return 'xsd:integer';

+ 25 - 17
SE/se-lib/Schema/KorespondencjaStorageAcl.php

@@ -3,7 +3,7 @@
 Lib::loadClass('Core_AclBase');
 Lib::loadClass('Core_AclBase');
 Lib::loadClass('FileStorage');
 Lib::loadClass('FileStorage');
 
 
-class KorespondencjaStorageAcl extends Core_AclBase {
+class Schema_KorespondencjaStorageAcl extends Core_AclBase {
 
 
   public function __construct() {
   public function __construct() {
     $this->parentAcl = User::getAcl()->getObjectAcl('default_db', 'IN7_DZIENNIK_KORESP');
     $this->parentAcl = User::getAcl()->getObjectAcl('default_db', 'IN7_DZIENNIK_KORESP');
@@ -54,6 +54,29 @@ class KorespondencjaStorageAcl extends Core_AclBase {
     }
     }
     return false;
     return false;
   }
   }
+
+  // TODO: replace legacy functions: isAllowed, hasFieldPerm, getFieldIdByName
+  public function canCreateField($fieldName) {
+    if ('File' == $fieldName) return true;
+    return $this->parentAcl->canCreateField($fieldName);
+  }
+  public function canReadField($fieldName) {
+    if ('File' == $fieldName) return true;
+    return $this->parentAcl->canReadField($fieldName);
+  }
+  public function canReadObjectField($fieldName, $record) {
+    if ('File' == $fieldName) return true;
+    return $this->parentAcl->canReadObjectField($fieldName, $record);
+  }
+  public function canWriteField($fieldName) {
+    if ('File' == $fieldName) return true;
+    return $this->parentAcl->canWriteField($fieldName);
+  }
+  public function canWriteObjectField($fieldName, $record) {
+    if ('File' == $fieldName) return true;
+    return $this->parentAcl->canWriteObjectField($fieldName, $record);
+  }
+
   public function getItems($params = array()) {
   public function getItems($params = array()) {
     $DBG = V::get('DBG_DS', 0, $_GET, 'int');
     $DBG = V::get('DBG_DS', 0, $_GET, 'int');
     if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems \$params:";print_r($params);echo "\n";}
     if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems \$params:";print_r($params);echo "\n";}
@@ -72,6 +95,7 @@ class KorespondencjaStorageAcl extends Core_AclBase {
     foreach ($this->getRealFieldListByIdZasob() as $id => $fieldName) {
     foreach ($this->getRealFieldListByIdZasob() as $id => $fieldName) {
       $fieldType = $this->getXsdFieldType($fieldName);
       $fieldType = $this->getXsdFieldType($fieldName);
       if ('ref:' == substr($fieldType, 0, 4)) $refs[$fieldName] = substr($fieldType, 4);
       if ('ref:' == substr($fieldType, 0, 4)) $refs[$fieldName] = substr($fieldType, 4);
+      else if ('alias_ref:' == substr($fieldType, 0, 10)) $refs[$fieldName] = substr($fieldType, 10);
     }
     }
     if (empty($refs)) return $items;
     if (empty($refs)) return $items;
     $fidList = array_keys($items);
     $fidList = array_keys($items);
@@ -113,13 +137,6 @@ class KorespondencjaStorageAcl extends Core_AclBase {
 		return $attributes;
 		return $attributes;
 	}
 	}
   public function isEnumerationField($fieldName) { return false; }
   public function isEnumerationField($fieldName) { return false; }
-  public function validateFieldAction($fieldName, $taskPerm, $record = null) {
-    if ('File' == $fieldName) {
-      // return 'ref:p5_objects:File';
-      return true;
-    }
-		return $this->parentAcl->isAllowed($fieldID = $this->parentAcl->getFieldIdByName($fieldName), $taskPerm, $record);
-	}
   public function getXsdFieldType($fieldName) {
   public function getXsdFieldType($fieldName) {
     if ('File' == $fieldName) return 'ref:p5_objects:File';
     if ('File' == $fieldName) return 'ref:p5_objects:File';
     return $this->parentAcl->getXsdFieldType($fieldName);
     return $this->parentAcl->getXsdFieldType($fieldName);
@@ -127,12 +144,3 @@ class KorespondencjaStorageAcl extends Core_AclBase {
   public function isGeomField($fldName) { return $this->parentAcl->isGeomField($fldName); }
   public function isGeomField($fldName) { return $this->parentAcl->isGeomField($fldName); }
 
 
 }
 }
-
-/*
-CREATE TABLE IF NOT EXISTS `IN7_DZIENNIK_KORESP__#REF__CRM_FILES` (
-  `PRIMARY_KEY` int(11) NOT NULL,
-  `REMOTE_PRIMARY_KEY` int(11) NOT NULL,
-  KEY `PRIMARY_KEY` (`PRIMARY_KEY`),
-  KEY `REMOTE_PRIMARY_KEY` (`REMOTE_PRIMARY_KEY`)
-) ENGINE=MyISAM DEFAULT CHARSET=latin2;
-*/

+ 76 - 42
SE/se-lib/Schema/TestPermsStorageAcl.php

@@ -3,7 +3,7 @@
 Lib::loadClass('Core_AclBase');
 Lib::loadClass('Core_AclBase');
 Lib::loadClass('FileStorage');
 Lib::loadClass('FileStorage');
 
 
-class TestPermsStorageAcl extends Core_AclBase {
+class Schema_TestPermsStorageAcl extends Core_AclBase {
 
 
   public function __construct() {
   public function __construct() {
     $this->parentAcl = User::getAcl()->getObjectAcl('default_db', 'TEST_PERMS');
     $this->parentAcl = User::getAcl()->getObjectAcl('default_db', 'TEST_PERMS');
@@ -17,30 +17,64 @@ class TestPermsStorageAcl extends Core_AclBase {
   public function getRealFieldListByIdZasob($force = false) {
   public function getRealFieldListByIdZasob($force = false) {
     $cols = $this->parentAcl->getRealFieldListByIdZasob();
     $cols = $this->parentAcl->getRealFieldListByIdZasob();
     $cols[100000] = 'File';
     $cols[100000] = 'File';
+    // $cols[100010] = 'File1';
+    // $cols[100011] = 'File2';
     // $cols[100001] = 'NestedObjectTest';
     // $cols[100001] = 'NestedObjectTest';
+    $cols[100002] = 'AccessGroupRead';
+    $cols[100003] = 'AccessGroupWrite';
+    $cols[100004] = 'AccessOwner';
     return $cols;
     return $cols;
   }
   }
-  public function getFieldIdByName($fieldName) {
-    $fields = $this->getRealFieldListByIdZasob();
-		if (empty($fieldName)) return null;
-		foreach ($fields as $idField => $vFieldName) {
-			if ($vFieldName == $fieldName) return $idField;
-		}
-		return null;
-	}
+  public function getFields() {// @returns array - $this->_fields
+    $fields = $this->parentAcl->getFields();
+    $fields[100000] = ['name'=>'File', 'perms'=>'RWXC', 'opis'=>'Plik', 'sort_prio'=>999, 'label'=>'Plik'];
+    // $fields[100001] = 'NestedObjectTest';
+    $fields[100002] = ['name'=>'AccessGroupRead', 'perms'=>'RWXC', 'opis'=>'Odczyt dla', 'sort_prio'=>999, 'label'=>'Odczyt dla'];
+    $fields[100003] = ['name'=>'AccessGroupWrite', 'perms'=>'RWXC', 'opis'=>'Zapis dla', 'sort_prio'=>999, 'label'=>'Zapis dla'];
+    $fields[100004] = ['name'=>'AccessOwner', 'perms'=>'RWXC', 'opis'=>'Osoba odpowiedzialna', 'sort_prio'=>999, 'label'=>'Osoba odp.'];
+    return $fields;
+  }
   public function getFieldType($colName) {
   public function getFieldType($colName) {
     return null;
     return null;
 	}
 	}
-  public function isAllowed($idZasob, $taskPerm, $record = null) {
-    if ('C' == $taskPerm && $idZasob > 1 && $idZasob < 7) return true;
-    if ('R' == $taskPerm && $idZasob > 0 && $idZasob < 7) return true;
-    return false;
+
+  // TODO: replace legacy functions: isAllowed, hasFieldPerm, getFieldIdByName
+  public function canCreateField($fieldName) {
+    if ('File' == $fieldName) return true;
+    if ('AccessGroupRead' == $fieldName) return true;
+    if ('AccessGroupWrite' == $fieldName) return true;
+    if ('AccessOwner' == $fieldName) return true;
+    return $this->parentAcl->canCreateField($fieldName);
   }
   }
-  public function hasFieldPerm($idZasob, $taskPerm) {
-    if ('C' == $taskPerm && $idZasob > 1 && $idZasob < 7) return true;
-    if ('R' == $taskPerm && $idZasob > 0 && $idZasob < 7) return true;
-    return false;
+  public function canReadField($fieldName) {
+    if ('File' == $fieldName) return true;
+    if ('AccessGroupRead' == $fieldName) return true;
+    if ('AccessGroupWrite' == $fieldName) return true;
+    if ('AccessOwner' == $fieldName) return true;
+    return $this->parentAcl->canReadField($fieldName);
+  }
+  public function canReadObjectField($fieldName, $record) {
+    if ('File' == $fieldName) return true;
+    if ('AccessGroupRead' == $fieldName) return true;
+    if ('AccessGroupWrite' == $fieldName) return true;
+    if ('AccessOwner' == $fieldName) return true;
+    return $this->parentAcl->canReadObjectField($fieldName, $record);
+  }
+  public function canWriteField($fieldName) {
+    if ('File' == $fieldName) return true;
+    if ('AccessGroupRead' == $fieldName) return true;
+    if ('AccessGroupWrite' == $fieldName) return true;
+    if ('AccessOwner' == $fieldName) return true;
+    return $this->parentAcl->canWriteField($fieldName);
   }
   }
+  public function canWriteObjectField($fieldName, $record) {
+    if ('File' == $fieldName) return true;
+    if ('AccessGroupRead' == $fieldName) return true;
+    if ('AccessGroupWrite' == $fieldName) return true;
+    if ('AccessOwner' == $fieldName) return true;
+    return $this->parentAcl->canWriteObjectField($fieldName, $record);
+  }
+
   public function getItems($params = array()) {
   public function getItems($params = array()) {
     $DBG = V::get('DBG_DS', 0, $_GET, 'int');
     $DBG = V::get('DBG_DS', 0, $_GET, 'int');
     if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems \$params:";print_r($params);echo "\n";}
     if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems \$params:";print_r($params);echo "\n";}
@@ -49,36 +83,45 @@ class TestPermsStorageAcl extends Core_AclBase {
     foreach ($rawItems as $pk => $item) $items[$pk] = (array)$item;
     foreach ($rawItems as $pk => $item) $items[$pk] = (array)$item;
     if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems \$items:";print_r($items);echo "\n";}
     if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems \$items:";print_r($items);echo "\n";}
     if (empty($items)) return $items;
     if (empty($items)) return $items;
-    $this->fetchItemRef($items);
+    $this->fetchItemRef($items);// TODO: only fields from request
     if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems after fetchItemRef \$items:";print_r($items);echo "\n";}
     if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems after fetchItemRef \$items:";print_r($items);echo "\n";}
     return $items;
     return $items;
   }
   }
   public function fetchItemRef(&$items) {
   public function fetchItemRef(&$items) {
     $DBG = V::get('DBG_DS', 0, $_GET, 'int');
     $DBG = V::get('DBG_DS', 0, $_GET, 'int');
     $refs = array();// fieldName => xsdType
     $refs = array();// fieldName => xsdType
+    $aliasRefs = array();// fieldName => aliasName
     foreach ($this->getRealFieldListByIdZasob() as $id => $fieldName) {
     foreach ($this->getRealFieldListByIdZasob() as $id => $fieldName) {
       $fieldType = $this->getXsdFieldType($fieldName);
       $fieldType = $this->getXsdFieldType($fieldName);
       if ('ref:' == substr($fieldType, 0, 4)) $refs[$fieldName] = substr($fieldType, 4);
       if ('ref:' == substr($fieldType, 0, 4)) $refs[$fieldName] = substr($fieldType, 4);
+      else if ('alias_ref:' == substr($fieldType, 0, 10)) {
+        $refs[$fieldName] = substr($fieldType, 10);
+        $aliasRefs[$fieldName] = $this->getName() . "__x3A__{$fieldName}";
+      }
     }
     }
     if (empty($refs)) return $items;
     if (empty($refs)) return $items;
-    $fidList = array_keys($items);
-    $sqlPk = array(); foreach ($fidList as $pk) { $sqlPk[] = "'{$pk}'"; } $sqlPk = implode(", ", $sqlPk);
-    $baseRefTableName = $this->getRootTableName() . "__#REF__";
+    $pkList = array_keys($items);
+    $sqlPk = array(); foreach ($pkList as $pk) { $sqlPk[] = DB::getPDO()->quote($pk, PDO::PARAM_STR); } $sqlPk = implode(", ", $sqlPk);
     $refRows = array();// $fieldName => [ pk, ... ]
     $refRows = array();// $fieldName => [ pk, ... ]
     foreach ($refs as $fieldName => $type) {
     foreach ($refs as $fieldName => $type) {
       $acl = $this->getAclFromTypeName($type);
       $acl = $this->getAclFromTypeName($type);
-      $refTableName = $this->getRootTableName() . "__#REF__" . $acl->getRootTableName();
+      // TODO: Core_AclBase->fetchRefs($fieldName, $pkList = array());// $refPk[$fieldName] = $this->fetchRefs($fieldName, $pkList);
+      $refTableName = $this->createRefTable($fieldName);
+      if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems loop(\$fieldName:{$fieldName}) \$refTableName:({$refTableName})";echo"\n";}
       $refRows[$fieldName] = DB::getPDO()->fetchAllByKey("
       $refRows[$fieldName] = DB::getPDO()->fetchAllByKey("
         select r.*
         select r.*
         from `{$refTableName}` r
         from `{$refTableName}` r
         where r.PRIMARY_KEY in({$sqlPk})
         where r.PRIMARY_KEY in({$sqlPk})
-        -- TODO and r.INSTANCE = '{$refInstanceName}' -- for multiple types based on the same root table
       ", $key = 'PRIMARY_KEY');
       ", $key = 'PRIMARY_KEY');
       if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems loop(\$fieldName:{$fieldName}) \$refTableName:({$refTableName}), \$refRows[$fieldName]";print_r($refRows[$fieldName]);echo"\n";}
       if($DBG>2){echo 'C.'.get_class($this).' L.' . __LINE__ . " getItems loop(\$fieldName:{$fieldName}) \$refTableName:({$refTableName}), \$refRows[$fieldName]";print_r($refRows[$fieldName]);echo"\n";}
     }
     }
     foreach ($refRows as $fieldName => $refList) {
     foreach ($refRows as $fieldName => $refList) {
       foreach ($refList as $pk => $ref) {
       foreach ($refList as $pk => $ref) {
-        $items[ $pk ][ $fieldName ][] = array('xlink' => "{$refs[$fieldName]}.{$ref['REMOTE_PRIMARY_KEY']}");
+        // if (array_key_exists($fieldName, $aliasRefs)) {
+        //   $items[ $pk ][ $aliasRefs[$fieldName] ][] = array('xlink' => "{$refs[$fieldName]}.{$ref['REMOTE_PRIMARY_KEY']}");
+        // } else {
+          $items[ $pk ][ $fieldName ][] = array('xlink' => "{$refs[$fieldName]}.{$ref['REMOTE_PRIMARY_KEY']}");
+        // }
       }
       }
     }
     }
   }
   }
@@ -92,13 +135,7 @@ class TestPermsStorageAcl extends Core_AclBase {
   public function getGeomFieldType($fieldName) { return null; }
   public function getGeomFieldType($fieldName) { return null; }
   public function getPrimaryKeyField() { return 'ID'; }
   public function getPrimaryKeyField() { return 'ID'; }
   public function getID() { return 0; }
   public function getID() { return 0; }
-  public function getAttributesFromZasoby() {
-		$attributes = array();// fldName => [ 'id_zasob' => int, 'label' => str, 'description' => str ]
-    // if ($acl->hasFieldPerm($idZasob, 'W')) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_write", "true");
-    // if ($acl->hasFieldPerm($idZasob, 'C')) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_create", "true");
-    // if (!$acl->hasFieldPerm($idZasob, 'R')) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_read", "false");
-		return $attributes;
-	}
+  public function getAttributesFromZasoby() { return array(); }
   public function isEnumerationField($fieldName) {
   public function isEnumerationField($fieldName) {
     if ('A_STATUS' == $fieldName) return true;
     if ('A_STATUS' == $fieldName) return true;
     return false;
     return false;
@@ -107,24 +144,21 @@ class TestPermsStorageAcl extends Core_AclBase {
     if ('A_STATUS' == $fieldName) return $this->parentAcl->getEnumerations($fieldName);
     if ('A_STATUS' == $fieldName) return $this->parentAcl->getEnumerations($fieldName);
     return null;
     return null;
   }
   }
-  public function validateFieldAction($fieldName, $taskPerm, $record = null) {
-    if ('File' == $fieldName) {
-      // return 'ref:p5_objects:File';
-      return true;
-    }
-    // if ('NestedObjectTest' == $fieldName) {
-    //   // return 'ref:p5_objects:NestedObjectTest';
-    //   return true;
-    // }
-		return $this->parentAcl->isAllowed($fieldID = $this->parentAcl->getFieldIdByName($fieldName), $taskPerm, $record);
-	}
   public function getXsdFieldType($fieldName) {
   public function getXsdFieldType($fieldName) {
     if ('File' == $fieldName) return 'ref:p5_objects:File';
     if ('File' == $fieldName) return 'ref:p5_objects:File';
+    // if ('File1' == $fieldName) return 'alias_ref:p5_objects:File';
+    // if ('File2' == $fieldName) return 'alias_ref:p5_objects:File';
     // if ('NestedObjectTest' == $fieldName) return 'local_ref:p5_objects:NestedObjectTest';
     // if ('NestedObjectTest' == $fieldName) return 'local_ref:p5_objects:NestedObjectTest';
+    if ('AccessGroupRead' == $fieldName) return 'alias_ref:p5_objects:AccessGroup';
+    if ('AccessGroupWrite' == $fieldName) return 'alias_ref:p5_objects:AccessGroup';
+    if ('AccessOwner' == $fieldName) return 'ref:p5_objects:AccessOwner';
     return $this->parentAcl->getXsdFieldType($fieldName);
     return $this->parentAcl->getXsdFieldType($fieldName);
   }
   }
   public function isGeomField($fldName) {
   public function isGeomField($fldName) {
     if ('File' == $fieldName) return false;
     if ('File' == $fieldName) return false;
+    if ('AccessGroupRead' == $fieldName) return false;
+    if ('AccessGroupWrite' == $fieldName) return false;
+    if ('AccessOwner' == $fieldName) return false;
     // if ('NestedObjectTest' == $fieldName) return false;
     // if ('NestedObjectTest' == $fieldName) return false;
     return $this->parentAcl->isGeomField($fldName);
     return $this->parentAcl->isGeomField($fldName);
   }
   }

+ 43 - 5
SE/se-lib/TableAcl.php

@@ -168,7 +168,7 @@ class TableAcl extends Core_AclBase {
 		return '';
 		return '';
 	}
 	}
 
 
-	public function hasFieldPerm($fieldID, $perm) {
+	public function hasFieldPerm($fieldID, $perm) {// TODO: legacy
 		if (array_key_exists($fieldID, $this->_fields)) {
 		if (array_key_exists($fieldID, $this->_fields)) {
 			if (false !== strpos($this->_fields[$fieldID]['perms'], $perm)) {
 			if (false !== strpos($this->_fields[$fieldID]['perms'], $perm)) {
 				return true;
 				return true;
@@ -287,10 +287,7 @@ class TableAcl extends Core_AclBase {
 	/**
 	/**
 	 * @param $taskPerm - 'C', 'W', 'R'
 	 * @param $taskPerm - 'C', 'W', 'R'
 	 */
 	 */
-	public function validateFieldAction($fieldName, $perms, $record = null) {
-		return $this->isAllowed($fieldID = $this->getFieldIdByName($fieldName), $perms, $record);
-	}
-	public function isAllowed($fieldID, $taskPerm, $record = null) {
+	public function isAllowed($fieldID, $taskPerm, $record = null) {// TODO: legacy - replace with canWriteField, canReadField, canWriteObjectField, canReadObjectField, canCreateField
 		if (!in_array($taskPerm, array('C', 'W', 'R'))) {
 		if (!in_array($taskPerm, array('C', 'W', 'R'))) {
 			return false;
 			return false;
 		}
 		}
@@ -351,6 +348,47 @@ class TableAcl extends Core_AclBase {
 		return true;
 		return true;
 	}
 	}
 
 
+  public function canCreateField($fieldName) {
+		$idZasob = $this->getFieldIdByName($fieldName);
+		return ($idZasob && $this->hasFieldPerm($idZasob, $taskPerm = 'C'));
+	}
+	public function canReadField($fieldName) {
+		$idZasob = $this->getFieldIdByName($fieldName);
+		if (!$idZasob) return false;
+		if ('ID' == $fieldName) return true;
+		if ('A_RECORD_CREATE_DATE' == $fieldName) return true;
+		if ('A_RECORD_CREATE_AUTHOR' == $fieldName) return true;
+		if ('A_RECORD_UPDATE_DATE' == $fieldName) return true;
+		if ('A_RECORD_UPDATE_AUTHOR' == $fieldName) return true;
+		if (!$this->hasFieldPerm($idZasob, $taskPerm = 'R')) {
+			if ($this->hasFieldPerm($idZasob, 'V')) return true;
+		}
+		return true;
+	}
+  public function canReadObjectField($fieldName, $record) {
+		if (!$this->canReadField($fieldName)) return false;
+		if (!$record) return false;
+		$idZasob = $this->getFieldIdByName($fieldName);
+		if (!$idZasob) return false;
+		if (!$this->hasFieldPerm($idZasob, $taskPerm = 'R')) {
+			if ($this->hasFieldPerm($idZasob, 'V')) return true;
+			return ($this->hasFieldPerm($idZasob, 'O') && ($this->canReadRecord($record) || $this->canWriteRecord($record)));// 'WO' or 'CO'
+		}
+		return ($this->canReadRecord($record) || $this->hasFieldPerm($idZasob, 'V'));// 'R' require
+	}
+	public function canWriteField($fieldName) {
+		$idZasob = $this->getFieldIdByName($fieldName);
+		if (!$idZasob) return false;
+		return $this->hasFieldPerm($idZasob, $taskPerm = 'W');
+	}
+	public function canWriteObjectField($fieldName, $record) {
+		if (!$this->canWriteField($fieldName)) return false;
+		$idZasob = $this->getFieldIdByName($fieldName);
+		if (!$idZasob) return false;
+		if(V::get('DBG_ACL', '', $_REQUEST) > 1){echo '(Field: "'.$fieldName.'" ['.$idZasob.'], canWriteRecord: ' . $this->canWriteRecord($record) . ' || (hasFieldPerm(S): ' . $this->hasFieldPerm($idZasob, 'S') . ' && hasFieldPerm(W): ' . $this->hasFieldPerm($idZasob, 'W') . '))';}
+		return ($this->canWriteRecord($record) || $this->hasFieldPerm($idZasob, 'S'));
+	}
+
 	/**
 	/**
 	 * @param $taskPerm - 'C', 'W'
 	 * @param $taskPerm - 'C', 'W'
 	 */
 	 */

+ 4 - 11
SE/se-lib/UserAcl.php

@@ -162,17 +162,10 @@ class UserAcl {
 			if ($this->hasTableAcl($zasobTblInfo->ID)) {
 			if ($this->hasTableAcl($zasobTblInfo->ID)) {
 				return $this->getTableAcl($zasobTblInfo->ID);
 				return $this->getTableAcl($zasobTblInfo->ID);
 			}
 			}
-		} else if ('objects' == $sourceName && 'File' == $objName) {
-			Lib::loadClass('FileStorageAcl');
-			return new FileStorageAcl();
-		} else if ('objects' == $sourceName && 'TestPerms' == $objName) {
-			// TODO: ObjectAcl::getAcl($objName);
-			Lib::loadClass('TestPermsStorageAcl');
-			return new TestPermsStorageAcl();
-		} else if ('objects' == $sourceName && 'Korespondencja' == $objName) {
-			// TODO: ObjectAcl::getAcl($objName);
-			Lib::loadClass('KorespondencjaStorageAcl');
-			return new KorespondencjaStorageAcl();
+		} else if ('objects' == $sourceName && !empty($objName)) {
+			$objClassName = "Schema_{$objName}StorageAcl";
+			if (!Lib::tryLoadClass($objClassName)) throw new HttpException("Not implemented", 501);
+			return new $objClassName();
 		} else throw new HttpException("Not Implemented", 501);
 		} else throw new HttpException("Not Implemented", 501);
 		return false;
 		return false;
 	}
 	}

+ 0 - 43
atom-open-by-url.php

@@ -1,43 +0,0 @@
-#!/usr/bin/env php
-<?php
-
-$scriptName = basename(__FILE__);
-if ($_SERVER['argc'] < 2) die("Usage: {$scriptName} url\n");
-if (empty($_SERVER['argv'][1])) die("Usage: {$scriptName} url\n");
-
-$url = $_SERVER['argv'][1];
-echo">>> DBG L." . __LINE__ . ": url: '{$url}'\n";
-// UrlAction_ProjektyProNetMediaZamZlec
-// https://biuro.pro-netmedia.pl/dev-pl-se/index.php?_route=UrlAction_ProjektyProNetMediaZamZlec&ID_PROJECT=50
-
-if (false === strpos($url, 'index.php')) die("Unrecognized url - no index.php\n");
-
-$query = parse_url($url, PHP_URL_QUERY);// only query string
-echo">>> query:"; print_r($query);echo"\n";
-$args = array(); parse_str($query, $args);
-echo">>> args:"; print_r($args);echo"\n";
-
-if (!empty($args['_route'])) {
-  $route = $args['_route'];
-  echo">>> DBG L." . __LINE__ . ": found route '{$route}'\n";
-
-  $pathProject = dirname(__FILE__);
-	$path = $pathProject . '/SE/se-lib/Route/' . implode('/', explode('_', $route)) . '.php';
-  echo">>> DBG L." . __LINE__ . ": path '{$path}'\n";
-	if (file_exists($path)) {
-    echo">>> DBG L." . __LINE__ . ": found file '{$path}' for route '{$route}'\n";
-		exec("cd {$pathProject}; atom {$path}");
-    return;
-	} else {
-		$path = "{$pathProject}/SE/se-lib/Route/{$route}.php";
-		if (file_exists($path)) {
-      echo">>> DBG L." . __LINE__ . ": found file '{$path}' for route '{$route}'\n";
-      exec("cd {$pathProject}; atom {$path}");
-      return;
-		}
-	}
-  die("Unrecognized url - cannot find class file for route '{$route}'\n");
-} else die("Unrecognized url - missing _route\n");
-
-exit;
-?>