浏览代码

updated test ant schema for instance and backRef

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

+ 87 - 0
SE/schema/ant-object/default_db.TEST_PERMS/TestPermsAnt/TestPermsAnt.xsd

@@ -0,0 +1,87 @@
+<xsd:schema
+    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+    xmlns:gml="http://www.opengis.net/gml"
+    xmlns:p5="https://biuro.biall-net.pl/wfs"
+    xmlns:default_db="https://biuro.biall-net.pl/wfs/default_db"
+    xmlns:default_objects="https://biuro.biall-net.pl/wfs/default_objects"
+    elementFormDefault="qualified"
+    targetNamespace="https://biuro.biall-net.pl/wfs/default_objects"
+    version="1.0.0">
+    <xsd:import namespace="http://www.opengis.net/gml" schemaLocation="https://biuro.biall-net.pl/dev-pl/se-master/schema/gml/2.1.2/feature.xsd"/>
+    <xsd:complexType name="TEST_PERMSType">
+        <xsd:complexContent>
+            <xsd:extension base="gml:AbstractFeatureType">
+                <xsd:sequence>
+                    <xsd:element minOccurs="1" maxOccurs="1" name="ID" type="xsd:integer" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="L_APPOITMENT_USER" type="xsd:string" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="KATALOG_LINK" type="p5:www_link" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="WWW" type="p5:www_link" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="ADM_ADMIN_LEVEL" type="xsd:string" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="ADM_PASSWD" type="xsd:string" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="A_STATUS" type="xsd:string" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="EMAIL" type="xsd:string" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="ADM_NAME" type="xsd:string" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="PARENT_ID" type="xsd:integer" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="OPIS" type="xsd:string" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="the_geom" type="gml:PolygonPropertyType" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="A_ADM_COMPANY" type="xsd:string" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="A_CLASSIFIED" type="xsd:string" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="A_RECORD_CREATE_AUTHOR" type="xsd:string" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="A_RECORD_CREATE_DATE" type="xsd:string" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="A_RECORD_UPDATE_AUTHOR" type="xsd:string" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="A_RECORD_UPDATE_DATE" type="xsd:string" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="test_date" type="xsd:date" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="test_datetime" type="xsd:dateTime" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="test_price" type="p5:price" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="test_time" type="xsd:string" nillable="true"/>
+                    <xsd:element minOccurs="0" maxOccurs="unbounded" name="__instance">
+                        <xsd:complexType>
+                            <xsd:sequence>
+                                <xsd:element name="instance_name" type="default_objects:TestPerms__instanceType"/>
+                                <xsd:element name="instance_type" type="xsd:string"/>
+                                <!-- 'instance', 'waiting', 'derived', 'matching' -->
+                                <xsd:element name="create_author" type="xsd:string"/>
+                                <xsd:element name="create_date" type="xsd:dateTime"/>
+                                <xsd:element name="update_author" type="xsd:string"/>
+                                <xsd:element name="updage_date" type="xsd:dateTime"/>
+                                <xsd:element name="verified" type="xsd:integer"/>
+                            </xsd:sequence>
+                        </xsd:complexType>
+                    </xsd:element>
+                    <xsd:element minOccurs="0" maxOccurs="1" name="__backRef">
+                        <xsd:complexType>
+                            <xsd:sequence>
+                                <xsd:element name="default_db__x3A__CRM_PROCES" type="default_objects:TestPerms__backRefType"/>
+                                <xsd:element name="default_db__x3A__CRM_WSKAZNIK" type="default_objects:TestPerms__backRefType"/>
+                                <xsd:element name="default_db__x3A__BUILDINGS" type="default_objects:TestPerms__backRefType"/>
+                            </xsd:sequence>
+                        </xsd:complexType>
+                    </xsd:element>
+                </xsd:sequence>
+                <xsd:attribute name="instance" type="default_objects:instanceType"/>
+            </xsd:extension>
+        </xsd:complexContent>
+    </xsd:complexType>
+    <xsd:element name="TEST_PERMS" type="default_objects:TEST_PERMSType" substitutionGroup="gml:_Feature"/>
+
+    <xsd:simpleType name="TestPerms__instanceType">
+        <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="TestPerms"/>
+            <xsd:enumeration value="TestPermsDoUzgodnienia"/>
+            <xsd:enumeration value="TestPermsUzgodniony"/>
+            <xsd:enumeration value="TestPermsOdrzucony"/>
+            <xsd:enumeration value="TestPermsAktywny"/>
+        </xsd:restriction>
+    </xsd:simpleType>
+
+    <xsd:complexType name="TestPerms__backRefType">
+        <xsd:sequence>
+            <xsd:element name="primaryKey" type="xsd:string"/>
+            <xsd:element name="create_author" type="xsd:string"/>
+            <xsd:element name="create_date" type="xsd:dateTime"/>
+            <xsd:element name="update_author" type="xsd:string"/>
+            <xsd:element name="updage_date" type="xsd:dateTime"/>
+        </xsd:sequence>
+    </xsd:complexType>
+
+</xsd:schema>

+ 42 - 3
SE/schema/ant-object/default_db.TEST_PERMS/TestPermsAnt/build.xml

@@ -23,7 +23,7 @@
                 xmlns:default_objects="https://biuro.biall-net.pl/wfs/default_objects"
                 xmlns:p5_objects="https://biuro.biall-net.pl/wfs/objects"
                 elementFormDefault="qualified"
-                targetNamespace="https://biuro.biall-net.pl/wfs/default_db"
+                targetNamespace="https://biuro.biall-net.pl/wfs/default_objects"
                 version="1.0.0">
                 <xsd:import namespace="http://www.opengis.net/gml" schemaLocation="https://biuro.biall-net.pl/dev-pl/se-master/schema/gml/2.1.2/feature.xsd"/>
                 <!--typeName 'p5_default_db:TEST_PERMS'-->
@@ -53,12 +53,51 @@
                                 <xsd:element minOccurs="0" maxOccurs="1" name="test_datetime" type="xsd:dateTime" nillable="true"/>
                                 <xsd:element minOccurs="0" maxOccurs="1" name="test_price" type="p5:price" nillable="true"/>
                                 <xsd:element minOccurs="0" maxOccurs="1" name="test_time" type="xsd:string" nillable="true"/>
+                                <xsd:element minOccurs="0" maxOccurs="unbounded" name="__instance">
+                                  <xsd:sequence>
+                                      <xsd:element name="instance_name" type="default_objects:TestPerms__instanceType"/>
+                                      <xsd:element name="instance_type" type="xsd:string"/><!-- 'instance', 'waiting', 'derived', 'matching' -->
+                                      <xsd:element name="create_author" type="xsd:string"/>
+                                      <xsd:element name="create_date" type="xsd:dateTime"/>
+                                      <xsd:element name="update_author" type="xsd:string"/>
+                                      <xsd:element name="updage_date" type="xsd:dateTime"/>
+                                      <xsd:element name="verified" type="xsd:integer"/>
+                                  </xs:sequence>
+                                </xsd:element>
+                                <xsd:element minOccurs="0" maxOccurs="1" name="__backRef">
+                                  <xsd:sequence>
+                                      <xsd:element name="default_db__x3A__CRM_PROCES" type="default_objects:TestPerms__backRefType"/>
+                                      <xsd:element name="default_db__x3A__CRM_WSKAZNIK" type="default_objects:TestPerms__backRefType"/>
+                                      <xsd:element name="default_db__x3A__BUILDINGS" type="default_objects:TestPerms__backRefType"/>
+                                  </xsd:sequence>
+                                </xsd:element>
                             </xsd:sequence>
-                            <xsd:attribute name="instance" type="default_db:instanceType"/>
+                            <xsd:attribute name="instance" type="default_objects:instanceType"/>
                         </xsd:extension>
                     </xsd:complexContent>
                 </xsd:complexType>
-                <xsd:element name="TEST_PERMS" type="default_db:TEST_PERMSType" substitutionGroup="gml:_Feature"/>
+                <xsd:element name="TEST_PERMS" type="default_objects:TEST_PERMSType" substitutionGroup="gml:_Feature"/>
+
+                <xsd:simpleType name="TestPerms__instanceType">
+                    <xsd:restriction base="xsd:string">
+                        <xsd:enumeration value="TestPerms"/>
+                        <xsd:enumeration value="TestPermsDoUzgodnienia"/>
+                        <xsd:enumeration value="TestPermsUzgodniony"/>
+                        <xsd:enumeration value="TestPermsOdrzucony"/>
+                        <xsd:enumeration value="TestPermsAktywny"/>
+                    </xsd:restriction>
+                </xsd:simpleType>
+
+                <xsd:complexType name="TestPerms__backRefType">
+                    <xsd:sequence>
+                        <xsd:element name="primaryKey" type="xsd:string"/>
+                        <xsd:element name="create_author" type="xsd:string"/>
+                        <xsd:element name="create_date" type="xsd:dateTime"/>
+                        <xsd:element name="update_author" type="xsd:string"/>
+                        <xsd:element name="updage_date" type="xsd:dateTime"/>
+                    </xsd:sequence>
+                </xsd:complexType>
+
             </xsd:schema>
         </echoxml>
         <echo message="OUTPUT__END"/>

+ 113 - 62
SE/se-lib/Route/Storage.php

@@ -582,14 +582,18 @@ jQuery(document).on('p5UIBtnAjax:Storage:checkObjectInstallAjax:ajaxLoaded', fun
 						// 'opis' => $item['description'],
 						'active?' => ($item['isActive']) ? '<span class="label label-success">TAK</span>' : '<span class="text text-muted">nie</span>',
 						'struktura' => UI::h('a', [ 'href' => $this->getLink('tableStruct', [ 'idStorage' => $idStorage, 'table' => $item['name'] ]) ], "struktura"),
+						'struktura OBJ' => UI::h('a', [ 'href' => $this->getLink('objectStruct', [ 'idStorage' => $idStorage, 'namespace' => $item['namespace'] ]) ], "obj struct"),
 						'raw info' => UI::h('a', [ 'href' => $this->getLink('rawInfo', [ 'idStorage' => $idStorage, 'table' => $item['name'] ]) ], "raw info"),
+						'reinstall' => UI::h('a', [ 'href' => $item['reinstallLink'] ], "reinstall"),
 						// 'xsd' => UI::h('a', [ 'href' => $this->getLink('xsd', [ 'idStorage' => $idStorage ]) ], "xsd"),
 					];
 				}, $objectStorage->getItems([
 					'#refFrom' => [
 						'namespace' => 'default_objects/SystemSource',
 						'primaryKey' => $sourceItem['idZasob']
-					]
+					],
+					'order_by' => 'namespace',
+					'order_dir' => 'asc'
 				]))
 			]);
 			echo UI::h('script', [], "
@@ -637,13 +641,46 @@ jQuery(document).on('p5UIBtnAjax:Storage:checkObjectInstallAjax:ajaxLoaded', fun
 		UI::menu();
 		$this->navView();
 		try {
-
+			$namespace = V::get('namespace', '', $_GET);
+			if (empty($namespace)) throw new Exception("Missing param namespace");
+			$item = $this->getObjectAclRow($namespace);
+			DBG::nicePrint($item, '$item');
+			// DBG::log($item, 'array', '$item');
+			switch ($item['_type']) {
+				case 'TableAcl': $this->structTableAclView($item); break;
+				default: throw new Exception("Not implemented struct view for '{$namespace}'");
+			}
 		} catch (Exception $e) {
 			UI::alert('danger', "Error #" . $e->getCode() .  "|" . $e->getLine() .  ": " . $e->getMessage());
 			DBG::log($e);
 		}
 		UI::dol();
 	}
+	public function structTableAclView($item) {
+		UI::table([
+			'caption' => UI::h('h3', [], "Struktura obiektu '{$item['namespace']}'"),
+			'rows' => array_map(function ($field) {
+				return $field;
+			}, $this->getObjectFields($item))
+		]);
+	}
+	public function getObjectFields($namespace) {
+		Lib::loadClass('Schema_SystemObjectFieldStorageAcl');
+		$acl = new Schema_SystemObjectFieldStorageAcl();
+		$items = $acl->getItems([
+			'#refFrom' => [
+				'namespace' => 'default_objects/SystemObject',
+				'primaryKey' => $namespace
+			],
+			'order_by' => 'namespace',
+			'order_dir' => 'asc'
+		]);
+		if (empty($items)) throw new Exception("SystemObject '{$namespace}' not found");
+		$item = reset($items);
+		if (empty($item)) throw new Exception("SystemObject '{$namespace}' not found");
+		return $item;
+	}
+
 	public function tableStructAction() {
 		UI::gora();
 		UI::menu();
@@ -1276,18 +1313,18 @@ jQuery(document).on('p5UIBtnAjax:Storage:checkObjectInstallAjax:ajaxLoaded', fun
 							$sTypeResMinInclusive->setAttribute('value', $restrictionValue);
 						}
 						/* TODO: xsd restrictions:
-	enumeration	Defines a list of acceptable values
-	fractionDigits	Specifies the maximum number of decimal places allowed. Must be equal to or greater than zero
-	length	Specifies the exact number of characters or list items allowed. Must be equal to or greater than zero
-	maxExclusive	Specifies the upper bounds for numeric values (the value must be less than this value)
-	maxInclusive	Specifies the upper bounds for numeric values (the value must be less than or equal to this value)
-	maxLength	Specifies the maximum number of characters or list items allowed. Must be equal to or greater than zero
-	minExclusive	Specifies the lower bounds for numeric values (the value must be greater than this value)
-	minInclusive	Specifies the lower bounds for numeric values (the value must be greater than or equal to this value)
-	minLength	Specifies the minimum number of characters or list items allowed. Must be equal to or greater than zero
-	pattern	Defines the exact sequence of characters that are acceptable
-	totalDigits	Specifies the exact number of digits allowed. Must be greater than zero
-	whiteSpace	Specifies how white space (line feeds, tabs, spaces, and carriage returns) is handled
+							enumeration	Defines a list of acceptable values
+							fractionDigits	Specifies the maximum number of decimal places allowed. Must be equal to or greater than zero
+							length	Specifies the exact number of characters or list items allowed. Must be equal to or greater than zero
+							maxExclusive	Specifies the upper bounds for numeric values (the value must be less than this value)
+							maxInclusive	Specifies the upper bounds for numeric values (the value must be less than or equal to this value)
+							maxLength	Specifies the maximum number of characters or list items allowed. Must be equal to or greater than zero
+							minExclusive	Specifies the lower bounds for numeric values (the value must be greater than this value)
+							minInclusive	Specifies the lower bounds for numeric values (the value must be greater than or equal to this value)
+							minLength	Specifies the minimum number of characters or list items allowed. Must be equal to or greater than zero
+							pattern	Defines the exact sequence of characters that are acceptable
+							totalDigits	Specifies the exact number of digits allowed. Must be greater than zero
+							whiteSpace	Specifies how white space (line feeds, tabs, spaces, and carriage returns) is handled
 						*/
 					}
 				} else {
@@ -1353,6 +1390,7 @@ jQuery(document).on('p5UIBtnAjax:Storage:checkObjectInstallAjax:ajaxLoaded', fun
 				case 'viewList':  $currentLabel = "Widoki [{$idStorage}]"; break;
 				case 'rawInfo':   $currentLabel = "Raw info [{$idStorage}]"; break;
 				case 'tableStruct': $currentLabel = "Struktura tabeli '{$tblName}'"; break;
+				case 'objectStruct': $currentLabel = "Obiekt '{$namespace}'"; break;
 				case 'coreObjectList': $currentLabel = "Obiekty podstawowe"; break;
 				case 'coreObjectStruct': $currentLabel = "Obiekt '{$objName}'"; break;
 				case 'objectList': $currentLabel = "Obiekty z aktualnej domeny"; break;// TODO: domain from $_GET
@@ -1570,22 +1608,22 @@ jQuery(document).on('p5UIBtnAjax:Storage:checkObjectInstallAjax:ajaxLoaded', fun
 		$this->navView();
 		try {
 			throw new Exception("TODO: F." . __FUNCTION__ . ' L.' . __LINE__);
-	// 		$coreObjlist = OBJXSD::getSystemObjectsStruct();
-	// 		$objectList = array();
-	// 		foreach ($coreObjlist as $objName) {
-	// 			$objItem = array();
-	// 			$objItem['name'] = $objName;
-	// 			$objItem['struktura'] = '<a href="index.php?_route=Storage&_task=systemObjectsStruct&object=' . $objName . '">' . "struct" . '</a>';
-	// 			// $objItem['label'] = "";// TODO: read from json
-	// 			$objectList[] = $objItem;
-	// 		}
-	// 		usort($objectList, function($rowA, $rowB) {
-	// 			$a = $rowA['nazwa']; $b = $rowB['nazwa'];
-	// 			if ($a == $b) return 0;
-	// 			return ($a < $b) ? -1 : 1;
-	// 		});
-	//
-	// 		DBG::table("objectList", $objectList, __CLASS__, __FUNCTION__, __LINE__);
+			// $coreObjlist = OBJXSD::getSystemObjectsStruct();
+			// $objectList = array();
+			// foreach ($coreObjlist as $objName) {
+			// 	$objItem = array();
+			// 	$objItem['name'] = $objName;
+			// 	$objItem['struktura'] = '<a href="index.php?_route=Storage&_task=systemObjectsStruct&object=' . $objName . '">' . "struct" . '</a>';
+			// 	// $objItem['label'] = "";// TODO: read from json
+			// 	$objectList[] = $objItem;
+			// }
+			// usort($objectList, function($rowA, $rowB) {
+			// 	$a = $rowA['nazwa']; $b = $rowB['nazwa'];
+			// 	if ($a == $b) return 0;
+			// 	return ($a < $b) ? -1 : 1;
+			// });
+			//
+			// DBG::table("objectList", $objectList, __CLASS__, __FUNCTION__, __LINE__);
 		} catch (Exception $e) {
 			UI::alert('danger', "Error #" . $e->getCode() .  "|" . $e->getLine() .  ": " . $e->getMessage());
 		}
@@ -1624,20 +1662,25 @@ jQuery(document).on('p5UIBtnAjax:Storage:checkObjectInstallAjax:ajaxLoaded', fun
 		UI::dol();
 	}
 
+	public function getObjectAclRow($namespace) {
+		Lib::loadClass('Schema_SystemObjectStorageAcl');
+		$acl = new Schema_SystemObjectStorageAcl();
+		$items = $acl->getItems([
+			'f_namespace' => "={$namespace}",
+		]);
+		if (empty($items)) throw new Exception("SystemObject '{$namespace}' not found");
+		$item = reset($items);
+		if (empty($item)) throw new Exception("SystemObject '{$namespace}' not found");
+		return $item;
+	}
+
 	public function objectReinstallAction() {
 		UI::gora();
 		UI::startContainer();
 		try {
 			$namespace = V::get('namespace', '', $_GET);
 			if (empty($namespace)) throw new Exception("Missing param namespace");
-			Lib::loadClass('Schema_SystemObjectStorageAcl');
-			$acl = new Schema_SystemObjectStorageAcl();
-			$items = $acl->getItems([
-				'f_namespace' => "={$namespace}",
-			]);
-			if (empty($items)) throw new Exception("SystemObject '{$namespace}' not found");
-			$item = reset($items);
-			if (empty($item)) throw new Exception("SystemObject '{$namespace}' not found");
+			$item = $this->getObjectAclRow($namespace);
 			DBG::log($item, 'array', '$item');
 
 			switch ($item['_type']) {
@@ -1656,38 +1699,46 @@ jQuery(document).on('p5UIBtnAjax:Storage:checkObjectInstallAjax:ajaxLoaded', fun
 		Lib::loadClass('AntAclBase');
 		$antAclPath = APP_PATH_SCHEMA . DS . 'ant-object' . DS . str_replace(['__x3A__', ':'], ['.', '/'], $item['typeName']);
 		if (!file_exists("{$antAclPath}/build.xml")) throw new Exception("Ant build file not exists");
-		DBG::log($antAclPath, 'string', '$antAclPath');
-		$antBin = APP_PATH_WWW . DS . 'stuff' . DS . 'dita-ot-2.3.3' . DS . 'bin' . DS . 'ant';
-		$cmd = "cd {$antAclPath} && {$antBin} DescribeFeatureType 2>&1";
-		V::exec($cmd, $out, $ret);
-		DBG::log($out, 'array', "DescribeFeatureType ret({$ret})");
-		$outputType = 'XML';
-		$html = []; $startRead = false;
-		foreach ($out as $line) {
-			// $line = "     [echo] OUTPUT__TYPE__XML"
-			if ('[echo]' == substr(trim($line), 0, 6)) {
-				$line = trim(substr(trim($line), 7));
-			}
 
-			if (!$startRead) {
-				if ('OUTPUT__TYPE__XML' == $line) $outputType = 'XML';
-				if ('OUTPUT__TYPE__HTML' == $line) $outputType = 'HTML';
-				if ('OUTPUT__START' == $line) {
-					$startRead = true;
-					continue;
+		if (file_exists("{$antAclPath}/{$item['name']}.xsd")) {
+			DBG::log("{$antAclPath}/{$item['name']}.xsd", 'string', 'xsd file exists');
+			$outputType = 'XML';
+			$html = file_get_contents("{$antAclPath}/{$item['name']}.xsd");
+		} else {
+			DBG::log($antAclPath, 'string', '$antAclPath');
+			$antBin = APP_PATH_WWW . DS . 'stuff' . DS . 'dita-ot-2.3.3' . DS . 'bin' . DS . 'ant';
+			$cmd = "cd {$antAclPath} && {$antBin} DescribeFeatureType 2>&1";
+			V::exec($cmd, $out, $ret);
+			DBG::log($out, 'array', "DescribeFeatureType ret({$ret})");
+			$outputType = 'XML';
+			$html = []; $startRead = false;
+			foreach ($out as $line) {
+				// $line = "     [echo] OUTPUT__TYPE__XML"
+				if ('[echo]' == substr(trim($line), 0, 6)) {
+					$line = trim(substr(trim($line), 7));
 				}
-			} else {
-				if ('<!DOCTYPE' == substr($line, 0, strlen('<!DOCTYPE'))) continue;
-				if ('OUTPUT__END' == $line) {
-					break;
+
+				if (!$startRead) {
+					if ('OUTPUT__TYPE__XML' == $line) $outputType = 'XML';
+					if ('OUTPUT__TYPE__HTML' == $line) $outputType = 'HTML';
+					if ('OUTPUT__START' == $line) {
+						$startRead = true;
+						continue;
+					}
+				} else {
+					if ('<!DOCTYPE' == substr($line, 0, strlen('<!DOCTYPE'))) continue;
+					if ('OUTPUT__END' == $line) {
+						break;
+					}
+					$html[]= $line;
 				}
-				$html[]= $line;
 			}
+			if (!empty($html)) $html = implode("\n", $html);
 		}
 		if (empty($html)) UI::alert('danger', "Empty output!");
 		else {
 			if ('XML' == $outputType) {
-				echo UI::h('pre', [], htmlspecialchars(implode("\n", $html)));
+				echo UI::h('pre', [], htmlspecialchars($html));
 			} else if ('HTML' == $outputType) {
 				echo UI::h('div', ['class'=>"container", 'style'=>"padding:12px; border:1px solid #ddd"], $html);
 			}

+ 129 - 0
SE/se-lib/Schema/SystemObjectFieldStorageAcl.php

@@ -0,0 +1,129 @@
+<?php
+
+Lib::loadClass('Core_AclSimpleSchemaBase');
+Lib::loadClass('ParseOgcFilter');
+Lib::loadClass('Router');
+
+class Schema_SystemObjectStorageAcl extends Core_AclSimpleSchemaBase {
+
+  public $_simpleSchema = [
+    'root' => [
+      '@namespace' => 'default_objects/SystemObject',
+      '@primaryKey' => 'idZasob',
+      'idZasob' => [ '@type' => 'xsd:integer' ],
+      'idDatabase' => [ '@type' => 'xsd:integer' ],
+      'namespace' => [ '@type' => 'xsd:string' ],
+      '_rootTableName' => [ '@type' => 'xsd:string' ],
+      '_type' => [ '@type' => 'xsd:string' ],
+      'isActive' => [ '@type' => 'xsd:integer' ], // installed
+      'description' => [ '@type' => 'xsd:string' ],
+      'name' => [ '@type' => 'p5:string' ],
+      'typeName' => [ '@type' => 'p5:string' ],
+      'reinstallLink' => [ '@type' => 'p5:www_link' ],
+      // 'A_RECORD_CREATE_AUTHOR' => [ '@type' => 'xsd:string' , '@label' => 'autor' ],
+      // 'A_RECORD_CREATE_DATE' => [ '@type' => 'xsd:date' , '@label' => 'utworzono' ],
+      // 'A_RECORD_UPDATE_AUTHOR' => [ '@type' => 'xsd:string' , '@label' => 'zaktualizował' ],
+      // 'A_RECORD_UPDATE_DATE' => [ '@type' => 'xsd:date', '@label' => 'zaktualizowano' ],
+      '@key' => 'namespace'
+    ]
+  ];
+  // public $_rootTableName = 'CRM_LISTA_ZASOBOW';
+  public $_rootTableName = 'CRM_#CACHE_ACL_OBJECT_FIELD';
+  public $_version = '1';
+
+  public function _parseWhere($params = []) {
+    $sqlWhere = [];
+    DBG::log($params, 'array', "SystemObject::_parseWhere");
+    if (!empty($params['#refFrom'])) {
+      // '#refFrom' => [
+      //   'namespace' => 'default_objects/SystemSource',
+      //   'primaryKey' => $sourceItem['idZasob']
+      // ]
+      if (empty($params['#refFrom']['namespace'])) throw new Exception("Missing refFrom/namespace");
+      if (empty($params['#refFrom']['primaryKey'])) throw new Exception("Missing refFrom/primaryKey");
+
+      if ('default_objects/SystemSource' != $params['#refFrom']['namespace']) throw new Exception("Unsupported refFrom/namespace '{$params['#refFrom']['namespace']}'");
+      $sqlWhere[] = "t.idDatabase = " . DB::getPDO()->quote($params['#refFrom']['primaryKey'], PDO::PARAM_INT);
+    }
+    {
+      $filterParams = [];
+      $xsdFields = $this->getXsdTypes();
+      foreach ($params as $k => $v) {
+        if ('f_' != substr($k, 0, 2)) continue;
+        $fieldName = substr($k, 2);
+        if (!array_key_exists($fieldName, $xsdFields)) {
+          // TODO: check query by xpath or use different param prefix
+          throw new Exception("Field '{$fieldName}' not found in '{$this->_namespace}'");
+        }
+        if ('p5:' == substr($xsdFields[$fieldName], 0, 3)) {
+          continue;
+        }
+        $filterParams[$fieldName] = $v;
+      }
+    }
+    if (!empty($filterParams)) {
+      DBG::log($filterParams, 'array', "SystemObject::_parseWhere TODO \$filterParams");
+      foreach ($filterParams as $fieldName => $value) {
+        if (is_array($value)) {
+          DBG::log($value, 'array', "TODO SystemObject::_parseWhere array value for \$filterParams[{$fieldName}]");
+        } else if (is_scalar($value)) {
+          if ('=' == substr($value, 0, 1)) {
+            $sqlWhere[] = "t.{$fieldName} = " . DB::getPDO()->quote(substr($value, 1), PDO::PARAM_STR);
+          } else {
+            $sqlWhere[] = "t.{$fieldName} like " . DB::getPDO()->quote("%{$value}%", PDO::PARAM_STR);
+          }
+        } else {
+          DBG::log($value, 'array', "BUG SystemObject::_parseWhere unknown type for \$filterParams[{$fieldName}]");
+        }
+      }
+    }
+    return (!empty($sqlWhere)) ? "where " . implode(" and ", $sqlWhere) : '';
+  }
+
+  public function getTotal($params = []) {
+    $sqlWhere = $this->_parseWhere($params);
+    return DB::getPDO()->fetchValue("
+      select count(1) as cnt
+      from `{$this->_rootTableName}` t
+      {$sqlWhere}
+    ");
+  }
+
+  public function getItems($params = []) {
+    $sqlWhere = $this->_parseWhere($params);
+
+    $currSortCol = V::get('order_by', 'idZasob', $params);
+    $currSortFlip = strtolower(V::get('order_dir', 'desc', $params));
+    // TODO: validate $currSortCol is in field list
+    // TODO: validate $currSortFlip ('asc' or 'desc')
+    $xsdFields = $this->getXsdTypes();
+    if (!array_key_exists($currSortCol, $xsdFields)) throw new Exception("Field '{$currSortCol}' not found in '{$this->_namespace}'");
+    if (!in_array($currSortFlip, ['asc', 'desc'])) throw new Exception("Sort dir not allowed");
+    $sqlOrderBy = "order by t.`{$currSortCol}` {$currSortFlip}";
+
+    $limit = V::get('limit', 0, $params, 'int');
+    $limit = ($limit < 0) ? 0 : $limit;
+    $offset = V::get('limitstart', 0, $params, 'int');
+    $offset = ($offset < 0) ? 0 : $offset;
+    $sqlLimit = ($limit > 0)
+      ? "limit {$limit} offset {$offset}"
+      : '';
+
+    return array_map(array($this, 'buildFeatureFromSqlRow'), DB::getPDO()->fetchAll("
+      select t.*
+      from `{$this->_rootTableName}` t
+      {$sqlWhere}
+      {$sqlOrderBy}
+      {$sqlLimit}
+    "));
+  }
+
+  public function buildFeatureFromSqlRow($item) {
+    $exNs = explode('/', $item['namespace']);
+    $item['name'] = array_pop($exNs);
+    $item['typeName'] = implode('__x3A__', $exNs) . ':' . $item['name'];
+    $item['reinstallLink'] = Router::getRoute('Storage')->getLink('objectReinstall', [ 'namespace' => $item['namespace'] ]);
+    return $item;
+  }
+
+}

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

@@ -24,22 +24,8 @@ class Schema_SystemObjectStorageAcl extends Core_AclSimpleSchemaBase {
       // 'A_RECORD_CREATE_DATE' => [ '@type' => 'xsd:date' , '@label' => 'utworzono' ],
       // 'A_RECORD_UPDATE_AUTHOR' => [ '@type' => 'xsd:string' , '@label' => 'zaktualizował' ],
       // 'A_RECORD_UPDATE_DATE' => [ '@type' => 'xsd:date', '@label' => 'zaktualizowano' ],
+      'field' => [ '@ref' => 'default_objects/SystemObjectField', '@maxOccurs' => 'unbounded' ]
     ]
-    // 'root' => [
-    //   '@namespace' => 'default_objects/SystemObject',
-    //   '@primaryKey' => 'ID',
-    //   'ID' => [ '@type' => 'xsd:integer' ],
-    //   'namespace' => [ '@type' => 'xsd:string' ],
-    //   'typeName' => [ '@type' => 'xsd:string' ],
-    //   'tabela' => [ '@type' => 'xsd:string', '@alias' => 'DESC' ],
-    //   'nazwa' => [ '@type' => 'xsd:string', '@alias' => 'DESC' ],
-    //   'opis' => [ '@type' => 'xsd:string', '@alias' => 'OPIS' ],
-    //   'id_zasob' => [ '@type' => 'xsd:integer' ],
-    //   'autor' => [ '@type' => 'xsd:string' , '@alias' => 'A_RECORD_CREATE_AUTHOR' ],
-    //   'utworzono' => [ '@type' => 'xsd:date' , '@alias' => 'A_RECORD_CREATE_DATE' ],
-    //   'zaktualizował' => [ '@type' => 'xsd:string' , '@alias' => 'A_RECORD_UPDATE_AUTHOR' ],
-    //   'zaktualizowano' => [ '@type' => 'xsd:date', '@alias' => 'A_RECORD_UPDATE_DATE' ]
-    // ]
   ];
   // public $_rootTableName = 'CRM_LISTA_ZASOBOW';
   public $_rootTableName = 'CRM_#CACHE_ACL_OBJECT';