Przeglądaj źródła

added p5_objects:File in WFS - read only

Piotr Labudda 9 lat temu
rodzic
commit
efc963a5d3

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

@@ -113,6 +113,7 @@ class Api_WfsDataServer extends Api_WfsServerBase {
 	public function getFeatures($nsPrefix, $type, $maxFeatures, $srsname, $ogcFilter = '', $sortBy = '', $startIndex = 0, $propertyName = '', $simple = true) {
 		$DBG = (V::get('DBG_GEO', '', $_GET) > 0);// TODO: Profiler
 		$typeName = "{$nsPrefix}:{$type}";
+		if($DBG){echo "typeName($typeName})\n";}
 		$acl = $this->getAclFromTypeName($typeName);
 		$fldList = $this->_getFieldListFromAcl($acl);
 
@@ -120,7 +121,7 @@ class Api_WfsDataServer extends Api_WfsServerBase {
 		$rootWfsNs = 'p5';
 		$rootWfsNsUri = "{$baseNsUri}";
 		//$wfsNs = 'p5_default_db_' . $type;//$nsPrefix;
-		$wfsNs = 'p5_default_db';//$nsPrefix;
+		$wfsNs = $nsPrefix;//'p5_default_db';
 		$wfsNsUri = "{$baseNsUri}/" . substr($nsPrefix, 3);
 		$featureTypeUri = $this->getBaseUri() . "?SERVICE=WFS&VERSION=1.0.0&TYPENAME={$typeName}&REQUEST=DescribeFeatureType";
 
@@ -191,7 +192,7 @@ if($DBG){echo '(geomFld: '.$geomFld.'):';print_r($acl->getFieldType($geomFld));e
 		}
 		foreach ($items as $itemKey => $item) {
 
-if($DBG){echo 'item['.$itemKey.'] ('.$geomFld.')isEmpty('.empty($item->{$geomFld}).'):';print_r($item->{$geomFld});echo "\n";}
+if($DBG && !empty($geomFld)){echo 'item['.$itemKey.'] ('.$geomFld.')isEmpty('.empty($item->{$geomFld}).'):';print_r($item->{$geomFld});echo "\n";}
 
 			$featureMemberNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:featureMember');
 			$rootNode->appendChild($featureMemberNode);
@@ -239,9 +240,7 @@ if($DBG){echo 'item['.$itemKey.'] ('.$geomFld.')isEmpty('.empty($item->{$geomFld
 			//throw new HttpException("Wrong param TYPENAME", 400);
 		}
 		$typeEx = explode(':', $type);
-		if (count($typeEx) != 2) {
-			throw new HttpException("Wrong param TYPENAME", 400);
-		}
+		if (count($typeEx) != 2) throw new HttpException("Wrong param TYPENAME", 400);
 		return $this->_getDescribeFeatureType($typeEx[0], $typeEx[1]);
 	}
 
@@ -257,9 +256,7 @@ if($DBG){echo 'item['.$itemKey.'] ('.$geomFld.')isEmpty('.empty($item->{$geomFld
 			//throw new HttpException("Wrong param TYPENAME", 400);
 		}
 		$typeEx = explode(':', $type);
-		if (count($typeEx) != 2) {
-			throw new HttpException("Wrong param TYPENAME", 400);
-		}
+		if (count($typeEx) != 2) throw new HttpException("Wrong param TYPENAME", 400);
 		return $this->_getDescribeFeatureType($typeEx[0], $typeEx[1], $simple = false);
 	}
 

+ 8 - 2
SE/se-lib/Api/WfsServerBase.php

@@ -56,6 +56,8 @@ class Api_WfsServerBase {
 			if ($acl) {
 				return true;
 			}
+		} else if ('p5_objects' == $nsPrefix && 'File' == $type) {
+			return true;
 		}
 		return false;
 	}
@@ -375,7 +377,7 @@ class Api_WfsServerBase {
 		$baseNsUri = $this->getBaseNamespaceUri();
 		$listNs = array();
 		$listNs[] = 'xmlns:p5_default_db="' . $baseNsUri . '/default_db"';
-		// $listNs[] = 'xmlns:p5_objects="' . $baseNsUri . '/objects"';
+		$listNs[] = 'xmlns:p5_objects="' . $baseNsUri . '/objects"';
 		return implode("\n", $listNs);
 	}
 
@@ -543,7 +545,7 @@ class Api_WfsServerBase {
 			$featureTypes[$tblName] = $featureType;
 		}
 
-		if(0){// add p5_objects:File
+		{// add p5_objects:File
 			Lib::loadClass('FileStorage');
 			$featureType = array();
 			$featureType['ns'] = "p5_objects";
@@ -1395,6 +1397,7 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 			$tblName = $tblAcl->getName();
 			$typeNames[] = array("p5_{$dataSourceName}", $tblName);
 		}
+		$typeNames[] = array("p5_objects", 'File');
 		return $this->_getDescribeFeatureTypes($typeNames, $simple);
 	}
 
@@ -1506,6 +1509,9 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 				else if ($acl->isEnumerationField($fldName)) {
 					$fldType = ($simple)? 'xsd:string' : "{$nsPrefix}:{$fldName}Type";
 				}
+				else if ($acl->isBinaryField($fldName)) {
+					$fldType = 'xsd:base64Binary';
+				}
 				$elNode->setAttribute('type', $fldType);
 
 				if (!$simple) {

+ 59 - 9
SE/se-lib/FileStorage.php

@@ -20,7 +20,8 @@ Lib::loadClass('Http');
 - [x] use streams for upload - better memory usage
 - [ ] use streams for upload progress in form - http://www.webiny.com/blog/2012/05/07/webiny-file-upload-with-html5-and-ajax-using-php-streams/
 - [x] add IP to table struct
-- [ ] WebDav - use only files from this table
+- [ ] WebDav - use only files from this table @see WebDav on Mac OS X https://www.qnap.com/pl-pl/tutorial/con_show.php?op=showone&cid=75
+- [ ] Update file - add {tblName}__#VERSIONS table (work like _HIST, but only on update file content)
 */
 class FileStorage {
 
@@ -39,7 +40,7 @@ class FileStorage {
 		return (self::isProduction()) ? 'CRM_FILES' : 'CRM_FILES__#DEV';
 	}
 
-	public static function getFileById($idFile) {
+	public static function getFileById($idFile, $forceVersion = null) {
 		$fileObject = array();// @returns array
 		$fileObject['_raw'] = null;// raw object from database
 		$fileObject['id'] = (int)$idFile;
@@ -49,11 +50,13 @@ class FileStorage {
 		$fileObject['exists'] = null;
 		$fileObject['size'] = 0;
 		$fileObject['mimeType'] = null;
-		$rowFile = self::_getRowFile($idFile);
+		$fileObject['version'] = 0;
+		$rowFile = self::_getRowFile($idFile, $forceVersion);
 		$fileObject['_raw'] = $rowFile;
 		// TODO: check perms
 		$fileObject['name'] = V::get('FILE_LABEL', $id, $rowFile);
-		$fileObject['relativePath'] = self::generateFilePathHashFromId($rowFile['ID']);
+		$fileObject['version'] = ($forceVersion) ? $forceVersion : V::get('FILE_VERSION', 0, $rowFile);
+		$fileObject['relativePath'] = self::generateFilePathHashFromId($rowFile['ID'], $version);
 		$fileObject['absolutePath'] = self::getRootStoragePath() . "/" . $fileObject['relativePath'];
 		$fileObject['exists'] = file_exists($fileObject['absolutePath']);
 		if ($fileObject['exists']) {
@@ -118,6 +121,18 @@ class FileStorage {
 		return $idFile;
 	}
 
+	public static function updateFileStream($idFile, $inputHandler, $name = '') {
+		throw new Exception("TODO: insert into `\{\$tblName\}__#VERSIONS` for file `{$idFile}`");
+		$fileObject = self::getFileById($idFile);
+		if (!$fileObject['exists']) throw new Exception("Oryginalny plik nie istnieje");
+		// TODO: check perms
+		$fileVersion = self::_createUpdateRowFile($idFile, $name);// insert into `{$tblName}__#VERSIONS` ( `FILE_VERSION` = 1 + (select MAX(`FILE_VERSION`) from #VER) )
+		{// upload by stream
+
+		}
+		self::_updateRowFileFromVersion($fileVersion);// update `{$tblName}` values from `{$tblName}__#VERSIONS`
+	}
+
 	public static function _createRowFile($name = '') {
 		$sqlLogin = User::getLogin();
 		$sqlLabel = DB::getPDO()->quote($name, PDO::PARAM_STR);
@@ -132,7 +147,7 @@ class FileStorage {
 		return DB::getPDO()->lastInsertId();
 	}
 
-	public static function _getRowFile($idFile) {
+	public static function _getRowFile($idFile, $version = null) {
 		$idFile = intval($idFile);
 		if ($idFile <= 0) throw new HttpException("#L" . __LINE__ . ": Wrong file id", 500);
 		$sqlId = DB::getPDO()->quote($idFile, PDO::PARAM_INT);
@@ -144,7 +159,9 @@ class FileStorage {
 		");
 		DBG::_('DBG', '>2', "rows", $rows, __CLASS__, __FUNCTION__, __LINE__);
 		if (empty($rows)) throw new HttpException("Plik nie istnieje w bazie", 404);
-		return $rows[0];
+		$rowFile = $rows[0];
+		// TODO: fetch info by $version
+		return $rowFile;
 	}
 
 	public static function _uploadUpdateMimeType($idFile, $absPath) {
@@ -198,7 +215,7 @@ class FileStorage {
 		");
 	}
 
-	public static function generateFilePathHashFromId($intId) {
+	public static function generateFilePathHashFromId($intId, $version = null) {
 		// $base36Id = base_convert($intId, 10, 10 + 26);// 0-9 + A-Z
 		$base36Id = base_convert($intId, 10, 10 + 6);// 0-9 + A-F
 		$base36Str = str_pad($base36Id, 10, "0", STR_PAD_LEFT);
@@ -209,6 +226,7 @@ class FileStorage {
 		$pathParts[] = substr($base36Str, 4);
 		$hashPath = implode("/", $pathParts);
 		// echo "ID($intId) converted to ({$base36Id})\t to ({$base36Str})\t to path ({$hashPath})\n";
+		// TODO: add $version to file name: .= "-v{$version}"
 		return $hashPath;
 	}
 
@@ -233,7 +251,7 @@ CREATE TABLE IF NOT EXISTS `CRM_FILES` (
 	`A_CLASSIFIED` varchar(100) NOT NULL DEFAULT '',
 	`A_USER_IP` bigint NOT NULL DEFAULT '0',
 	PRIMARY KEY (`ID`),
-	KEY `FILE_TYPE` (`FILE_MIME_TYPE`)
+	KEY `FILE_TYPE` (`FILE_TYPE`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=latin2;
 			");
 			DB::getPDO()->exec("
@@ -255,7 +273,39 @@ CREATE TABLE IF NOT EXISTS `CRM_FILES__#DEV` (
 	`A_CLASSIFIED` varchar(100) NOT NULL DEFAULT '',
 	`A_USER_IP` bigint NOT NULL DEFAULT '0',
 	PRIMARY KEY (`ID`),
-	KEY `FILE_TYPE` (`FILE_MIME_TYPE`)
+	KEY `FILE_TYPE` (`FILE_TYPE`)
+) ENGINE=MyISAM  DEFAULT CHARSET=latin2;
+			");
+			DB::getPDO()->exec("
+CREATE TABLE IF NOT EXISTS `CRM_FILES__#VERSIONS` (
+	`ID_FILE` int(11) NOT NULL,
+	`FILE_HASH` varchar(255) NOT NULL, -- generated from ID by hash function - only for cache
+  `FILE_LABEL` varchar(255) NOT NULL, -- original file name or system name
+  `FILE_TYPE` varchar(32) NOT NULL DEFAULT '', -- $TRG_FILE -> config/.cnf--folders...
+	`FILE_MIME_TYPE` varchar(64) NOT NULL DEFAULT '',
+	`FILE_MTIME` datetime NOT NULL,
+	`FILE_SIZE` bigint NOT NULL DEFAULT 0,
+	`FILE_VERSION` int(11) NOT NULL DEFAULT 0, -- used for update
+	`A_RECORD_CREATE_DATE` datetime DEFAULT NULL,
+	`A_RECORD_CREATE_AUTHOR` varchar(20) NOT NULL DEFAULT '',
+	`A_USER_IP` bigint NOT NULL DEFAULT '0',
+	KEY `ID_FILE` (`ID_FILE`)
+) ENGINE=MyISAM  DEFAULT CHARSET=latin2;
+			");
+			DB::getPDO()->exec("
+CREATE TABLE IF NOT EXISTS `CRM_FILES__#DEV__#VERSIONS` (
+	`ID_FILE` int(11) NOT NULL,
+	`FILE_HASH` varchar(255) NOT NULL, -- generated from ID by hash function - only for cache
+  `FILE_LABEL` varchar(255) NOT NULL, -- original file name or system name
+  `FILE_TYPE` varchar(32) NOT NULL DEFAULT '', -- $TRG_FILE -> config/.cnf--folders...
+	`FILE_MIME_TYPE` varchar(64) NOT NULL DEFAULT '',
+	`FILE_MTIME` datetime NOT NULL,
+	`FILE_SIZE` bigint NOT NULL DEFAULT 0,
+	`FILE_VERSION` int(11) NOT NULL DEFAULT 0, -- used for update
+	`A_RECORD_CREATE_DATE` datetime DEFAULT NULL,
+	`A_RECORD_CREATE_AUTHOR` varchar(20) NOT NULL DEFAULT '',
+	`A_USER_IP` bigint NOT NULL DEFAULT '0',
+	KEY `ID_FILE` (`ID_FILE`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=latin2;
 			");
 

+ 125 - 0
SE/se-lib/FileStorageAcl.php

@@ -0,0 +1,125 @@
+<?php
+
+Lib::loadClass('FileStorage');
+
+class FileStorageAcl {
+
+  public function __construct() {
+
+  }
+
+
+  public function init($force = false) {}
+  public function isInitialized() { return true; }
+  public function getRealFieldListByIdZasob($force = false) {
+    $cols = array();// FileStorage::getFileById()
+    $cols[1] = 'id';
+    $cols[2] = 'name';
+    $cols[3] = 'size';
+    $cols[4] = 'mimeType';
+    $cols[5] = 'version';
+    $cols[6] = 'content';
+    // $cols[] = 'relativePath';
+    // $cols[] = 'absolutePath';
+    // $cols[] = 'exists';
+    return $cols;
+  }
+  public function isIntegerField($fieldName) {
+    if ('id' == $fieldName) return true;
+    if ('size' == $fieldName) return true;
+    if ('version' == $fieldName) return true;
+    return false;
+  }
+  public function isDecimalField($fieldName) { return false; }
+	public function isGeomField($fldName) { return false; }
+	public function isDateField($fldName) { return false; }
+	public function isDateTimeField($fldName) { return false; }
+	public function isStringField($fieldName) {
+    if ('name' == $fieldName) return true;
+    if ('mimeType' == $fieldName) return true;
+    return false;
+  }
+	public function isTextField($fldName) { return false; }
+  public function isBinaryField($fieldName) {
+    if ('content' == $fieldName) return true;
+    return false;
+  }
+	public function isEnumerationField($fldName) { return false; }
+  public function getFieldType($colName) {
+    switch ($colName) {
+      case 'id': return array(); break;
+    }
+    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;
+  }
+  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 getItems($params = array()) {
+    $sqlLimit = V::get('limit', 10000, $params);
+    $sqlOffset = V::get('limitstart', 0, $params);
+    // TODO: parse params:
+    //   [sortBy] => ID D,test_date A
+    //   [cols] => Array( [0] => ID
+    //                    [1] => test_date
+    //                    [2] => A_STATUS )
+    $sqlTblName = FileStorage::getTableName();
+    $sqlUserLogin = User::getLogin();
+    $rows = array_map(function($row) {
+      $wfsItem = array();
+      $wfsItem['id'] = $row['ID'];
+      $wfsItem['name'] = V::get('FILE_LABEL', $row['ID'], $row);
+      $wfsItem['size'] = $row['FILE_SIZE'];
+      $wfsItem['mimeType'] = $row['FILE_MIME_TYPE'];
+      $wfsItem['version'] = $row['FILE_VERSION'];
+      {// fetch file content
+        $objectFile = FileStorage::getFileById($row['ID']);// TODO: avoid sql in FileStorage::convertFromDBRow($row)
+        $wfsItem['content'] = ($objectFile['exists']) ? base64_encode(file_get_contents($objectFile['absolutePath'])) : null;
+      }
+    	return $wfsItem;
+    }, DB::getPDO()->fetchAll("
+    	select t.ID
+    		, t.FILE_HASH
+    		, t.FILE_LABEL
+    		, t.FILE_TYPE
+    		, t.FILE_MIME_TYPE
+    		, t.FILE_MTIME
+    		, t.FILE_SIZE
+    		, t.FILE_VERSION
+    		, t.A_STATUS
+    		, t.A_RECORD_CREATE_DATE
+    		, t.A_RECORD_CREATE_AUTHOR
+    		, t.A_RECORD_UPDATE_DATE
+    		, t.A_RECORD_UPDATE_AUTHOR
+    		, t.A_ADM_COMPANY
+    		, t.A_CLASSIFIED
+    		, INET_NTOA(t.A_USER_IP) as IP
+    	from `{$sqlTblName}` t
+      where t.`A_RECORD_CREATE_AUTHOR` = '{$sqlUserLogin}'
+    	order by ID DESC
+    	limit {$sqlLimit} offset {$sqlOffset}
+    "));
+    $items = array();
+    foreach ($rows as $row) {
+      $items[$row['id']] = (object)$row;
+    }
+    return $items;
+  }
+
+  public function getPrimaryKeyField() { return 'id'; }
+  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;
+	}
+
+}

+ 14 - 0
SE/se-lib/TableAcl.php

@@ -1648,6 +1648,20 @@ class TableAcl {
 		return false;
 	}
 
+	public function isBinaryField($fldName) {
+		$type = $this->getFieldType($fldName);
+		if (!$type) return false;
+
+		if (substr($type['type'], 0, 4) == 'blob'
+				|| substr($type['type'], 0, 8) == 'tinyblob'
+				|| substr($type['type'], 0, 10) == 'mediumblob'
+				|| substr($type['type'], 0, 8) == 'longblob'
+		) {
+			return true;
+		}
+		return false;
+	}
+
 	public function isEnumerationField($fldName) {
 		$type = $this->getFieldType($fldName);
 		if (!$type) return false;

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

@@ -87,9 +87,9 @@ class UserAcl {
 					and p.IF_TRUE_GOTO>0
 					and p.IF_TRUE_GOTO_FLAG='GOTO_AND_RETURN'
 		";
-		//	union select '83','122'		  union select p.`ID` as ID, p.`IF_TRUE_GOTO` as PARENT_ID from `CRM_PROCES` as p where p.`A_STATUS` in('WAITING','NORMAL') and p.IF_TRUE_GOTO>0 
-		//union select '83','122'	
-		//union select '83','2025'	
+		//	union select '83','122'		  union select p.`ID` as ID, p.`IF_TRUE_GOTO` as PARENT_ID from `CRM_PROCES` as p where p.`A_STATUS` in('WAITING','NORMAL') and p.IF_TRUE_GOTO>0
+		//union select '83','122'
+		//union select '83','2025'
 		$res = $db->query($sql);
 		while ($r = $db->fetch($res)) {
 			$this->_proces_tree_flat[$r->PARENT_ID][] = $r->ID;
@@ -158,15 +158,14 @@ class UserAcl {
 	public function getObjectAcl($sourceName, $objName) {
 		if ('default_db' == $sourceName) {
 			$zasobTblInfo = ProcesHelper::getZasobTableInfoByUri("{$sourceName}/{$objName}");
-			if ($zasobTblInfo) {
-				if ($this->hasTableAcl($zasobTblInfo->ID)) {
-					return $this->getTableAcl($zasobTblInfo->ID);
-				}
+			if (!$zasobTblInfo) throw new HttpException("Object not Found", 404);
+			if ($this->hasTableAcl($zasobTblInfo->ID)) {
+				return $this->getTableAcl($zasobTblInfo->ID);
 			}
-		}
-		else {
-			throw new HttpException("Not Implemented", 501);
-		}
+		} else if ('objects' == $sourceName && 'File' == $objName) {
+			Lib::loadClass('FileStorageAcl');
+			return new FileStorageAcl();
+		} else throw new HttpException("Not Implemented", 501);
 		return false;
 	}