Piotr Labudda 8 лет назад
Родитель
Сommit
6ec8f9c947
3 измененных файлов с 83 добавлено и 5 удалено
  1. 17 2
      SE/se-lib/AclQueryFeatures.php
  2. 41 2
      SE/se-lib/Api/Wfs/GetFeature.php
  3. 25 1
      SE/static/p5WFS/GetFeature.js

+ 17 - 2
SE/se-lib/AclQueryFeatures.php

@@ -493,8 +493,10 @@ class AclQueryFeatures {
 		foreach ($this->getSelectRemote() as $fieldName => $cols) {
 			DBG::log($cols, 'array', "add select remote '{$fieldName}' \$cols");
 
+			$refLimit = 10; // TODO: get from $this->_params and pass to nested buildQuery
+			$refLimitPlus1 = $refLimit + 1;
 			$xsdType = $this->_acl->getXsdFieldType($fieldName);
-			if ('ref:' === substr($xsdType, 0, 4) && empty($cols)) { // only xlink's
+			if ('ref:' === substr($xsdType, 0, 4) && empty($cols)) {
 				DBG::log("add remote xlink's '{$fieldName}' \$items[{$primaryKey}] ...");
 				$refTable = ACL::getRefTable($this->_acl->getNamespace(), $fieldName);
 				if (!$refTable) DBG::log("BUG: Missing refTable in add remote xlink's '{$fieldName}' \$items[{$primaryKey}]");
@@ -503,6 +505,7 @@ class AclQueryFeatures {
 						select r.REMOTE_PRIMARY_KEY
 						from `{$refTable}` r
 						where r.PRIMARY_KEY = '{$primaryKey}'
+						limit {$refLimitPlus1}
 					");
 					DBG::log($xlinks, 'array', "add remote xlink's for '{$fieldName}' \$items[{$primaryKey}]");
 					$row[$fieldName] = array_map(function ($refInfo) use ($fieldName) {
@@ -512,9 +515,19 @@ class AclQueryFeatures {
 							'xlink' => "{$ns['url']}#{$ns['name']}.{$refInfo['REMOTE_PRIMARY_KEY']}",
 						];
 					}, $xlinks);
+					if (count($xlinks) > $refLimit) DBG::log('TODO: xlink FETCH MORE DATA...');
+					if (count($xlinks) > $refLimit) $row[$fieldName][] = [ 'p5:links' => [
+						'p5:next' => [
+							'@typeName' => $fieldName,
+							'@backRefNS' => $this->_acl->getNamespace(),
+							'@backRefPK' => $primaryKey,
+							'@startIndex' => $refLimit,
+							'value' => Request::getScriptUri() . "?SERVICE=WFS&VERSION=1.0.0&TYPENAME={$fieldName}&REQUEST=GetFeature&backRefNS=".$this->_acl->getNamespace()."&backRefPK={$primaryKey}&backRefField={$fieldName}&startIndex={$refLimit}",
+						],
+					] ];
 					DBG::log($row[$fieldName], 'array', "remote xlinks for \$items[{$primaryKey}][{$fieldName}]");
 				}
-			} else if ('ref:' === substr($xsdType, 0, 4)) { // cols
+			} else if ('ref:' === substr($xsdType, 0, 4) && !empty($cols)) {
 				$items = ACL::getAclByTypeName($fieldName)->buildQuery([
 					'cols' => $cols,
 					'__backRef' => [
@@ -522,7 +535,9 @@ class AclQueryFeatures {
 						'primaryKey' => $primaryKey,
 						'fieldName' => $fieldName,
 					]
+					// TODO: add $refLimit + 1
 				])->getItems();
+				// TODO: if (count($items) > $refLimit) // TODO: add item for GUI - has more data + wfs link to fetch more (offset)
 				DBG::log($items, 'array', "add remote items '{$fieldName}' \$items");
 				$row[$fieldName] = $items;
 			} else { // TODO: field is not ref

+ 41 - 2
SE/se-lib/Api/Wfs/GetFeature.php

@@ -33,6 +33,10 @@ class Api_Wfs_GetFeature {
 		$args['resolve'] = V::get('resolve', '', $rawArgs);
 		$args['resolveDepth'] = V::get('resolveDepth', 0, $rawArgs, 'int'); // TODO: if ('*' === resolveDepth) - recurse resolve
 
+		$args['backRefPK'] = V::get('backRefPK', '', $rawArgs);
+		$args['backRefNS'] = V::get('backRefNS', '', $rawArgs);
+		$args['backRefField'] = V::get('backRefField', '', $rawArgs);
+
 		$lowerArgs = array(); foreach ($rawArgs as $name => $value) $lowerArgs[ strtolower($name) ] = trim($value);
 
 		$args['xsd:type'] = V::get('typename', '', $lowerArgs);
@@ -346,6 +350,41 @@ class Api_Wfs_GetFeature {
 			$xmlWriter->endElement();// {$itemPrefix}:{$fldName}
 			return;
 		}
+		if (1 === count($item) && !empty($item['p5:links'])) {
+			DBG::log($item, 'array', "TODO: p5:links");
+			// array (
+			//   'p5:links' =>
+			//   array (
+			//     'p5:next' =>
+			//     array (
+			//       '@typeName' => 'default_db__x3A__CRM_WSKAZNIK:CRM_WSKAZNIK',
+			//       '@backRefPK' => '6125',
+			//     ),
+			//   ),
+			// )
+			$xmlWriter->startElement('p5:links');
+			foreach ($item['p5:links'] as $type => $link) {
+				if ('p5:next' === $type) {
+					$xmlWriter->startElement('p5:next');
+					if (empty($link['@typeName'])) throw new Exception("Missing 'p5:links/p5:next/@typeName'");
+					if (empty($link['@backRefNS'])) throw new Exception("Missing 'p5:links/p5:next/@backRefNS'");
+					if (empty($link['@backRefPK'])) throw new Exception("Missing 'p5:links/p5:next/@backRefPK'");
+					if (empty($link['@startIndex'])) throw new Exception("Missing 'p5:links/p5:next/@startIndex'");
+					if (empty($link['value'])) throw new Exception("Missing 'p5:links/p5:next'");
+					$xmlWriter->writeAttribute("p5:typeName", $link['@typeName']);
+					$xmlWriter->writeAttribute("p5:backRefNS", $link['@backRefNS']);
+					$xmlWriter->writeAttribute("p5:backRefPK", $link['@backRefPK']);
+					$xmlWriter->writeAttribute("p5:startIndex", $link['@startIndex']);
+					$xmlWriter->text($link['value']); // str_replace('&', '&', $link['value'])
+					$xmlWriter->endElement(); // 'p5:next'
+				} else {
+					DBG::log("TODO: Not Implemented p5:links chldren '{$type}'");
+					$xmlWriter->writeComment("TODO: Not implemented p5:links chldren '{$type}'");
+				}
+			}
+			$xmlWriter->endElement(); // 'p5:links'
+			return;
+		}
 
 		$xmlWriter->startElement($tagName);
 		foreach ($attrs as $name => $value) {
@@ -403,8 +442,8 @@ class Api_Wfs_GetFeature {
 					if (!array_key_exists($fieldNs, $schemaCache)) {
 						// maybe only xlinks - acl not needed
 						$firstItem = reset($item[$fldName]);
-						if (1 === count($firstItem) && !empty($firstItem['xlink'])) { // TODO: $schemaCache[$fieldNs] must exists for xlinks - xlmns is required
-							foreach ($item[$fldName] as $childItem) {
+						if (1 === count($firstItem) && !empty($firstItem['xlink'])) {
+							foreach ($item[$fldName] as $childItem) { // xlink or p5:links
 								self::printXmlFeatureRecurse($xmlWriter, $childAcl = null, $childItem, [
 									'fields' => [],
 									'tagName' => $fldName,

+ 25 - 1
SE/static/p5WFS/GetFeature.js

@@ -16,7 +16,31 @@ function p5WFS_ParseFeatureFieldRecurse(tagNode) { // @returns object from xml e
 	var i = 0
 	for (i = 0; i < tagNode.children.length; i++) {
 		var fieldNode = tagNode.children[i]
-		if (!fieldNode.children.length) {
+		if ('p5:links' === fieldNode.tagName) {
+			// <p5:links>
+			//    ​<p5:next p5:typeName=​"default_db__x3A__BI_audit_KW_requested_person:​BI_audit_KW_requested_person"
+			//             p5:backRefNS=​"default_db/​BI_audit_ENERGA_RUM_KONTRAHENCI_POWIAZANIA/​BI_audit_ENERGA_RUM_KONTRAHENCI_POWIAZANIA"
+			//             p5:backRefPK=​"20"
+			//             p5:startIndex=​"10">
+			// ​"https://.../wfs-data.php/default_db/?SERVICE=WFS&amp;VERSION=1.0.0&amp;TYPENAME=default_db__x3A__BI_audit_KW_requested_person:BI_audit_KW_requested_person&amp;REQUEST=GetFeature&amp;backRefNS=default_db/BI_audit_ENERGA_RUM_KONTRAHENCI_POWIAZANIA/BI_audit_ENERGA_RUM_KONTRAHENCI_POWIAZANIA&amp;backRefPK=20&amp;backRefField=default_db__x3A__BI_audit_KW_requested_person:BI_audit_KW_requested_person&amp;startIndex=10"
+			// </p5:next>​</p5:links>​
+			for (var j = 0; j < fieldNode.children.length; j++) {
+				var p5LinkNode = fieldNode.children[j]
+				if ('p5:next') {
+					var typeName = p5LinkNode.getAttribute('p5:typeName')
+					item[ typeName ].push( {
+						'@backRefNS': p5LinkNode.getAttribute('p5:backRefNS'),
+						'@backRefPK': p5LinkNode.getAttribute('p5:backRefPK'),
+						'@typeName': p5LinkNode.getAttribute('p5:typeName'),
+						'@startIndex': p5LinkNode.getAttribute('p5:startIndex'),
+						'value': p5LinkNode.textContent
+					} )
+				} else {
+					// Not implemented
+				}
+			}
+		}
+		else if (!fieldNode.children.length) {
 			if (fieldNode.textContent) item[ fieldNode.localName ] = fieldNode.textContent
 			else {
 				var xlink = fieldNode.getAttribute('xlink:href')