Selaa lähdekoodia

updated ACL instance, AntAclBase, TableAjax - use UserTableFilter

Piotr Labudda 9 vuotta sitten
vanhempi
commit
ca254ff7f4

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

@@ -179,7 +179,7 @@ SQL;
 		return Core_AclHelper::parseNamespaceUrl($namespace);
 	}
 
-	public static function getRefTable($rootObjectNamespace, $childName) {
+	public static function getRefTable($rootObjectNamespace, $childName) { // CRM_REF_CONFIG
 		static $cacheRefTables = array();
 		$cacheKey = "{$rootObjectNamespace}/{$childName}";
 		if (array_key_exists($cacheKey, $cacheRefTables)) return $cacheRefTables[$cacheKey];
@@ -254,4 +254,89 @@ SQL;
 		return $refTableName;
 	}
 
+	public static function getInstanceId($namespace) { // CRM_INSTANCE_CONFIG
+		$conf = self::getInstanceConfig($namespace);
+		return $conf['id'];
+	}
+	public static function getInstanceConfig($namespace) { // CRM_INSTANCE_CONFIG
+		try {
+			$conf = self::fetchInstanceConfig($namespace);
+		} catch (Exception $e) {
+			DB::getPDO()->execSql("
+	      create table if not exists `CRM_INSTANCE_CONFIG` (
+	        `id` int(11) not null AUTO_INCREMENT,
+	        `namespace` varchar(255) NOT NULL DEFAULT '',
+	        `rootNamespace` varchar(255) NOT NULL DEFAULT '',
+	        `tableName` varchar(255) NOT NULL DEFAULT '',
+					`_createdAt` datetime NOT NULL,
+	        UNIQUE KEY `namespace` (`namespace`),
+	        KEY `rootNamespace` (`rootNamespace`),
+					PRIMARY KEY (`id`)
+	      ) ENGINE=MyISAM  DEFAULT CHARSET=latin2
+	    ");
+			// TODO:?: `_tableInstalled` tinyint(1) not null default 0,
+			$conf = self::fetchInstanceConfig($namespace);
+		}
+		if (!$conf) {
+			$id = DB::getPDO()->insert("CRM_INSTANCE_CONFIG", [
+				'namespace' => $namespace,
+				'rootNamespace' => self::getRootNamespace($namespace),
+				'_createdAt' => 'NOW()',
+			]);
+			$conf = self::fetchInstanceConfig($namespace);
+		}
+		if (!$conf) throw new Exception("Instance not found in config table '{$namespace}'");
+		return $conf;
+	}
+	public static function fetchInstanceConfig($namespace) {
+		return DB::getPDO()->fetchFirst("
+			select c.*
+			from `CRM_INSTANCE_CONFIG` c
+			where c.namespace = '{$namespace}'
+		");
+	}
+	public static function getRootNamespace($namespace) { // TODO: works only for relative urls! - mv to Acl->getRootNamespace
+		Lib::loadClass('SchemaFactory');
+		try {
+			$objectItem = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace);
+		} catch (Exception $e) {
+			throw new Exception("Object not installed '{$namespace}'");
+		}
+		if (!$objectItem['isStructInstalled']) throw new Exception("Object structure not installed '{$namespace}'");
+
+		if ($objectItem['idDatabase'] != DB::getPDO()->getZasobId()) throw new Exception("Only default_db supported"); // TODO: support more Sources
+
+		return "default_db/{$objectItem['_rootTableName']}";
+	}
+	public static function getInstanceTable($namespace) {
+		$conf = self::getInstanceConfig($namespace);
+		if (!empty($conf['tableName'])) return $conf['tableName'];
+
+		$rootNs = $conf['rootNamespace'];
+		$rootConf = self::getInstanceConfig($rootNs);
+		$instanceTableName = "CRM__#INSTANCE_TABLE__{$rootConf['id']}";
+		if (!empty($rootConf['tableName'])) {
+			$affected = DB::getPDO()->update("CRM_INSTANCE_CONFIG", 'rootNamespace', $rootNs, [
+				'tableName' => $instanceTableName
+			]);
+			return $rootConf['tableName'];
+		}
+
+		// TODO: fetch primaryKeyType - TODO: store primaryKey and primaryKeyType in SystemObject item
+		$pkType = 'int';
+		DB::getPDO()->exec("
+			CREATE TABLE IF NOT EXISTS `{$instanceTableName}` (
+				`pk` int(11) NOT NULL COMMENT 'primary key'
+				, `idInstance` int(11) NOT NULL
+				, `_createdAt` datetime NOT NULL
+				, KEY `pk` (`pk`)
+				, KEY `idInstance` (`idInstance`)
+			) ENGINE=MyISAM DEFAULT CHARSET=latin2 COMMENT='{$rootNs} #INSTANCE';
+		");
+		$affected = DB::getPDO()->update("CRM_INSTANCE_CONFIG", 'rootNamespace', $rootNs, [
+			'tableName' => $instanceTableName
+		]);
+		return $instanceTableName;
+	}
+
 }

+ 30 - 2
SE/se-lib/AntAclBase.php

@@ -1,5 +1,7 @@
 <?php
 
+Lib::loadClass('ACL');
+
 /**
 * SE/schema/ant-object/default_db.{rootTableName}/{name}/build.xml
 */
@@ -18,6 +20,9 @@ class AntAclBase extends Core_AclBase {
   public function getSourceName() { return 'default_db'; } // TODO: ?
   public function getRootTableName() { $this->_rootTableName; }
   public function getPrimaryKeyField() { $this->_primaryKey; }
+  public function getFieldListByIdZasob() { return $this->getRealFieldListByIdZasob(); }
+  public function getVirtualFieldListByIdZasob() { return []; }
+  public function getVisibleFieldListByIdZasob() { return $this->getRealFieldListByIdZasob(); } // TODO: get visible fields
   public function getRealFieldListByIdZasob() {
     $cols = array();
     $fakeZasobId = 1000000;
@@ -27,7 +32,7 @@ class AntAclBase extends Core_AclBase {
     }
     return $cols;
   }
-  // public function getFieldType($fieldName) {
+  public function getFieldType($fieldName) { return null; }
   //   try {
   //     throw new Exception("TODO: AntAclBase::getFieldType({$fieldName})");
   //   } catch (Exception $e) {
@@ -68,6 +73,9 @@ class AntAclBase extends Core_AclBase {
   public function canReadField($fieldName) {
     return true; // TODO: return $this->getPerms($fieldName)->canRead()
   }
+  public function canReadObjectField($fieldName, $object) {
+    return true; // TODO: return $this->getPerms($fieldName, $object)->canRead()
+  }
 
   public function getFields() {
     if (empty($this->_fields)) {
@@ -87,9 +95,29 @@ class AntAclBase extends Core_AclBase {
     throw new Exception("Field not found '{$this->_namespace}/{$fieldName}'");
   }
 
+  public function getSqlPrimaryKeyField() { return 'ID'; } // TODO: read from root object schema (_rootTableName)
+
+  public function getTotal($params = []) {
+    DBG::log($params, 'array', "AntAclBase::getTotal params");
+    $idInstance = ACL::getInstanceId($this->_namespace);
+    $instanceTable = ACL::getInstanceTable($this->_namespace);
+    $sqlPrimaryKey = $this->getSqlPrimaryKeyField();
+    return DB::getPDO()->fetchValue(" -- getTotal({$this->_namespace})
+      select count(1)
+      from `{$this->_rootTableName}` t
+        join `{$instanceTable}` i on(i.pk = t.{$sqlPrimaryKey} and i.idInstance = {$idInstance})
+    ");
+  }
   public function getItems($params = []) {
     DBG::log($params, 'array', "AntAclBase::getItems params");
-    return [];
+    $idInstance = ACL::getInstanceId($this->_namespace);
+    $instanceTable = ACL::getInstanceTable($this->_namespace);
+    $sqlPrimaryKey = $this->getSqlPrimaryKeyField();
+    return DB::getPDO()->fetchAll(" -- getItems({$this->_namespace})
+      select t.*
+      from `{$this->_rootTableName}` t
+        join `{$instanceTable}` i on(i.pk = t.{$sqlPrimaryKey} and i.idInstance = {$idInstance})
+    ");
   }
 
   public static function buildInstance($idZasob, $conf = []) {

+ 1 - 1
SE/se-lib/Core/XmlWriter.php

@@ -17,7 +17,7 @@ class Core_XmlWriter extends XMLWriter {
    * @example h('tag', ['id' => 'ID'], ['tag2', null]) => <tag id="ID"><tag2/></tag>
    */
   public function h($arg1, $arg2 = false, $arg3 = false) {
-    DBG::log(['arg1'=>$arg1, 'arg2'=>$arg2, 'arg3'=>$arg3], '', "XMLWriter::h(...)");
+    // DBG::log(['arg1'=>$arg1, 'arg2'=>$arg2, 'arg3'=>$arg3], '', "XMLWriter::h(...)");
     $tag = null;
     $attrs = [];
     $childrens = [];// [] or null or ''

+ 2 - 1
SE/se-lib/P5.php

@@ -43,7 +43,8 @@ class P5 {
 
   public static function buildAclFromSystemObject($objItem, $idUser) {
     if ('AntAcl' == $objItem['_type']) {
-      throw new Exception("TODO: buildAclFromSystemObject - type = '{$objItem['_type']}'");
+      Lib::loadClass('AntAclBase');
+      return AntAclBase::buildInstance($objItem['idZasob'], $objItem);
     }
     if ('TableAcl' == $objItem['_type']) {
       // $this->_db = $arr['db'];

+ 10 - 0
SE/se-lib/Route/Storage.php

@@ -1799,6 +1799,16 @@ jQuery(document).on('p5UIBtnAjax:Storage:checkObjectInstallAjax:ajaxLoaded', fun
 			$objFieldAcl = new Schema_SystemObjectFieldStorageAcl();
 			$objFieldAcl->updateCache($namespace);
 
+			{
+				DBG::nicePrint([
+					'idInstance' => ACL::getInstanceId($namespace),
+					'rootInstance' => ACL::getRootNamespace($namespace),
+					'conf' => ACL::fetchInstanceConfig($namespace),
+					'table' => ACL::getInstanceTable($namespace),
+				], "dbg");
+				throw new Exception("TODO...");
+			}
+
 		} catch (Exception $e) {
 			UI::alert('danger', "Error #" . $e->getCode() .  "|" . $e->getLine() .  ": " . $e->getMessage());
 			DBG::log($e);

+ 18 - 3
SE/se-lib/Route/ViewObject.php

@@ -20,13 +20,28 @@ class Route_ViewObject extends Route_ViewTableAjax {
 	public function getTableAjaxWidget($acl) {
 		$syncUrl = Request::getPathUri() . 'index.php?_route=ViewObject&namespace=' . $acl->getNamespace();
 		$tbl = new TableAjax($acl);
+		$tbl->showProcesInit(false); // TODO: activate when ready
 		$tblLabel = $acl->getNamespace();
 		if ('default_db' == $acl->getSourceName()) {
 			$tblLabel = array();
+			DBG::nicePrint($acl->getID(), '$acl->getID()');
 			$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;
+			DBG::nicePrint($zasobObj, '$zasobObj');
+			$sqlId = $acl->getID();
+			if (!$sqlId) throw new Exception("Missing zasob id!");
+			$zasobItem = DB::getPDO()->fetchFirst("
+				select z.ID, z.`DESC`, z.DESC_PL, z.OPIS
+				from CRM_LISTA_ZASOBOW z
+				where z.ID = {$sqlId}
+					and z.`TYPE` = 'TABELA'
+			");
+			DBG::nicePrint($zasobItem, '$zasobItem');
+			// 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;
+			if (!$zasobItem) throw new Exception("Zasob TABELA ID=" . $acl->getID() . " nie istnieje");
+			if (!empty($zasobItem['DESC_PL'])) $tblLabel []= $zasobItem['DESC_PL'];
+			if (!empty($zasobItem['OPIS']))    $tblLabel []= $zasobItem['OPIS'];
 			$tblLabel = implode(" - ", $tblLabel);
 		}
 		$tbl->setSyncUrl($syncUrl);

+ 1 - 0
SE/se-lib/Route/ViewTableAjax.php

@@ -28,6 +28,7 @@ class Route_ViewTableAjax extends RouteBase {
 			$tblLabel = implode(" - ", $tblLabel);
 		}
 		$tbl->setSyncUrl($syncUrl);
+		$tbl->showUserTableFilter($this->getLink("getUserTableFilterAjax"));
 		$tbl->setLabel($tblLabel);
 		$tbl->addRowFunction('edit');
 		$tbl->addRowFunction('hist');

+ 1 - 0
SE/se-lib/SchemaHelper.php

@@ -15,6 +15,7 @@ class SchemaHelper {
   public static function convertMysqlTypeToSchemaXsd($mysqlSchema, $fieldName = '') {
     $restrictions = [];
     switch ($mysqlSchema['DATA_TYPE']) {
+      case 'text':
       case 'char':
       case 'varchar': {
         if (!empty($mysqlSchema['CHARACTER_MAXIMUM_LENGTH'])) $restrictions['maxLength'] = $mysqlSchema['CHARACTER_MAXIMUM_LENGTH'];

+ 38 - 30
SE/se-lib/TableAjax.php

@@ -24,6 +24,7 @@ class TableAjax extends ViewAjax {
 	private $_filterInit = null;
 	private $_forceFilterInit = null;
 	private $_showProcesInit = true;
+	private $_useUserTableFilter = false;
 	public $syncUrl = null;
 
 	public function __construct($tblAcl) {
@@ -58,6 +59,10 @@ class TableAjax extends ViewAjax {
 		$this->_showProcesInit = $bool;
 	}
 
+	public function showUserTableFilter($url = null) {
+		$this->_useUserTableFilter = $url;
+	}
+
 	private function _hasStateFilterInit() {
 		return array_key_exists($this->_htmlID, $_SESSION['TableAjax_Cache']) && array_key_exists('_filterInit', $_SESSION['TableAjax_Cache'][$this->_htmlID]);
 	}
@@ -2877,36 +2882,38 @@ var p5UI_TableAjax_generateFunctionNode = function(funObj, rowPK, props) {
 				};
 				_state._modelColFilter.saveBtn.on('click', priv.modelColFilter_saveBtnClicked)
 
-				fetch('<?= Request::getPathUri() . "index.php?_route=ViewTableAjax&_task=getUserTableFilterAjax" ?>', {
-					method: 'POST',
-					headers: {
-						'Content-Type': 'application/json'
-					},
-					credentials: 'same-origin',// add cookies
-					body: JSON.stringify({
-						namespace: '<?= $acl->getNamespace(); ?>',
-					})
-				}).then(function (response) {
-					return response.json()
-				}).then(function (result) {
-					if ('success' == result.type) {
-						// p5UI__notifyAjaxCallback(result)
-						_state._modelColFilter.filters = _state._modelColFilter.filters.filter(function (filter) {
-							return ('all' === filter.name || 'most_used' == filter.name)
-						}).concat(Object.keys(result.data).map(function (fltr) {
-							return {
-								name: fltr,
-								label: fltr,
-								visibleCols: result.data[fltr].split(',')
-							}
-						}))
-						jQuery(_uiNodeCont).trigger('TableAjax:render', ['foot__columnPicker']);
-					} else {
-						p5UI__notifyAjaxCallback(result)
-					}
-				}).catch(function (e) {
-					// TODO: show error ("ajax response error: " + e)
-				});
+				if (priv.options.userTableFilterUrl) {
+					fetch(priv.options.userTableFilterUrl, {
+						method: 'POST',
+						headers: {
+							'Content-Type': 'application/json'
+						},
+						credentials: 'same-origin',// add cookies
+						body: JSON.stringify({
+							namespace: '<?= $acl->getNamespace(); ?>',
+						})
+					}).then(function (response) {
+						return response.json()
+					}).then(function (result) {
+						if ('success' == result.type) {
+							// p5UI__notifyAjaxCallback(result)
+							_state._modelColFilter.filters = _state._modelColFilter.filters.filter(function (filter) {
+								return ('all' === filter.name || 'most_used' == filter.name)
+							}).concat(Object.keys(result.data).map(function (fltr) {
+								return {
+									name: fltr,
+									label: fltr,
+									visibleCols: result.data[fltr].split(',')
+								}
+							}))
+							jQuery(_uiNodeCont).trigger('TableAjax:render', ['foot__columnPicker']);
+						} else {
+							p5UI__notifyAjaxCallback(result)
+						}
+					}).catch(function (e) {
+						// TODO: show error ("ajax response error: " + e)
+					});
+				}
 			}
 		};
 		priv.modelColFilter_onClickRemoveFilter = function (e) {
@@ -3696,6 +3703,7 @@ function TableAjax__HIST_Route(args) {
 jQuery(document).ready(function(){
 	jQuery('#<?php echo $this->_htmlID; ?>').TableAjax({
 		url: '<?= $this->syncUrl; ?>&_hash=<?= $this->_htmlID; ?>&_task=loadDataAjax',// priv.options.url
+		userTableFilterUrl: '<?= ($this->_useUserTableFilter) ? $this->_useUserTableFilter : ''; ?>',
 		columnPicker: true,
 		filter: true,
 		filterInit: <?php echo json_encode($filterInit); ?>,