소스 검색

added childRef

Piotr Labudda 8 년 전
부모
커밋
8792ee5bf4
4개의 변경된 파일113개의 추가작업 그리고 3개의 파일을 삭제
  1. 37 0
      SE/se-lib/ACL.php
  2. 23 0
      SE/se-lib/AclQueryFeatures.php
  3. 34 0
      SE/se-lib/Core/AclHelper.php
  4. 19 3
      SE/se-lib/Route/ViewTableAjax.php

+ 37 - 0
SE/se-lib/ACL.php

@@ -461,6 +461,43 @@ class ACL {
 		if (!$refInfo['ID']) throw new Exception("Ref table not found in ref config table for field '{$childName}' in object '{$rootObjectNamespace}'");
 		return $refInfo;
 	}
+	public static function getBackRefList($namespace) {
+		if (!$namespace) throw new Exception("Missing namespace");
+		$nsParts = explode('/', $namespace);
+		$typeName = array_pop($nsParts);
+		$typeName = implode("__x3A__", $nsParts) . ":{$typeName}";
+		return DB::getPDO()->fetchAll("
+			select c.ROOT_OBJECT_NS as namespace
+				, i.id as idInstance
+			from CRM_REF_CONFIG c
+				join CRM_INSTANCE_CONFIG i on ( i.namespace = c.ROOT_OBJECT_NS )
+			where ( c.CHILD_NAME = :type_name or c.CHILD_NAME = :namespace )
+				and c.A_STATUS = 'NORMAL'
+		", [
+			':type_name' => $typeName,
+			':namespace' => $namespace,
+		]);
+	}
+
+	public static function fetchRefs($namespace, $childNamespace, $primaryKey, $params = []) { // TODO: $params: limit, total
+		if (!$namespace) throw new Exception("Missing namespace");
+		if (!$childNamespace) throw new Exception("Missing child namespace");
+		if (!$primaryKey) throw new Exception("Missing primary key");
+		throw new Exception("TODO: fetch refs from '{$namespace}' where primaryKey = '{$primaryKey}'");
+	}
+
+	public static function fetchBackRefs($namespace, $primaryKey, $parentNamespace, $params = []) { // TODO: $params: limit, total
+		if (!$namespace) throw new Exception("Missing namespace");
+		if (!$parentNamespace) throw new Exception("Missing parent namespace");
+		if (!$primaryKey) throw new Exception("Missing primary key");
+
+		$typeName = Api_WfsNs::typeName($namespace);
+		$refTable = ACL::getRefTable($parentNamespace, $typeName);
+		if (V::get('total', false, $params)) {
+			return DB::getPDO()->fetchValue(" select count(*) as cnt from `{$refTable}` where REMOTE_PRIMARY_KEY = :primary_key and A_STATUS not in ('DELETED') ", [ ':primary_key' => $primaryKey ]);
+		}
+		throw new Exception("TODO: fetch back refs from '{$namespace}' where primaryKey({$primaryKey}) by refTable({$refTable})");
+	}
 
 	public static function generateIsInstanceFunctionBody($namespace, $item = null) {
 		if (!$item) $item = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ]);

+ 23 - 0
SE/se-lib/AclQueryFeatures.php

@@ -302,6 +302,7 @@ class AclQueryFeatures {
 				DBG::log([ $fieldName, $comparisonSign, $value, $fieldType ], 'array', "parseQueryValue");
 				$this->_query->where([$fieldName, $comparisonSign, $value]);
 			} else if ('__backRef' === $k) { // skip - parse below
+			} else if ('__childRef' === $k) { // skip - parse below
 			} else if ('limit' === $k) {
 			} else if ('limitstart' === $k) {
 			} else if ('order_by' === $k) {
@@ -337,6 +338,28 @@ class AclQueryFeatures {
 			");
 		}
 
+		if (array_key_exists('__childRef', $this->_params)) {
+			$childRef = $this->_params['__childRef'];
+			if (!is_array($childRef)) throw new Exception("Wrong child ref structure - expected array");
+			if (empty($childRef['namespace'])) throw new Exception("Wrong child ref structure - missing namespace");
+			if (empty($childRef['primaryKey'])) throw new Exception("Wrong child ref structure - missing primaryKey");
+			$refAcl = ACL::getAclByNamespace($childRef['namespace']);
+			if ($refAcl->getSourceName() !== $this->_acl->getSourceName()) throw new Exception("Not implemented join with different source");
+			$refTypeName = Api_WfsNs::typeName($childRef['namespace']);
+			DBG::log("\$refTypeName({$refTypeName})");
+			$refTable = ACL::getRefTable($this->_acl->getNamespace(), $refTypeName);
+			// TODO: 'in' operator? // $this->_query->where($pkField, 'in', "");
+			$sqlPk = $this->getAclSqlPrimaryKeyField();
+			$sqlChildRefPk = DB::getPDO()->quote($childRef['primaryKey']);
+			$this->_query->where("
+				t.{$sqlPk} in (
+					select refTable.PRIMARY_KEY
+					from `{$refTable}` refTable
+					where refTable.REMOTE_PRIMARY_KEY = {$sqlChildRefPk}
+				)
+			");
+		}
+
 		return clone($this->_query);
 	}
 

+ 34 - 0
SE/se-lib/Core/AclHelper.php

@@ -227,6 +227,40 @@ class Core_AclHelper {// Helper class for Acl
 			];
 		}
 		DBG::log(['msg'=>"\$rowFunList", '$rowFunList'=>$rowFunList]);
+
+		$ns = $acl->getNamespace();
+		$partsNs = explode('/', $ns);
+		$typeName = Api_WfsNs::typeName($acl->getNamespace());
+		// DBG::log([
+		// 	'Api_WfsNs::typeName' => Api_WfsNs::typeName($acl->getNamespace()),
+		// 	'self::parseNamespaceUrl' => self::parseNamespaceUrl($acl->getNamespace()),
+		// ], 'array', "DBG typeName");
+		if (count($partsNs) > 2) { // is AntAcl
+			$backRefList = ACL::getBackRefList($ns);
+			DBG::log($backRefList, 'array', "\$backRefList");
+			foreach ($backRefList as $backRef) { // [ namespace, idInstance ]
+				$backRefLabel = $backRef['namespace']; // TODO: get DESC from Zasoby
+				$backRefShort = explode("/", $backRefLabel);
+				$backRefShort = array_pop($backRefShort);
+				$backRefShort = (strlen($backRefShort) > 20) ? substr($backRefShort, 0, 20) . "..." : $backRefShort;
+
+				// 'namespace' => 'default_db/BI_audit_KRS/BI_audit_KRS',
+				// 'idInstance' => '24'
+				$totalBackRefs = ACL::fetchBackRefs($acl->getNamespace(), $id, $backRef['namespace'], [ 'total' => true ]);
+				DBG::log($backRefs, 'array', "\$backRefs {$backRef['namespace']} pk({$id})");
+
+				$rowFunList[] = [
+					'ico' => 'glyphicon glyphicon-random',
+					'href' => Router::getRoute('ViewTableAjax')->getLink('', [
+						'namespace' => $backRef['namespace'],
+						'childRefNS' => $acl->getNamespace(),
+						'childRefPK' => $id,
+					]),
+					'title' => "Wyszukaj powiązania z '{$backRefLabel}'",
+					'label' => "Wyszukaj powiązania z '{$backRefShort}' <span class=\"badge\">{$totalBackRefs}</span>",
+				];
+			}
+		}
 		return $rowFunList;
 	}
 

+ 19 - 3
SE/se-lib/Route/ViewTableAjax.php

@@ -15,7 +15,7 @@ Lib::loadClass('UserProfile');
 
 class Route_ViewTableAjax extends RouteBase {
 
-	public function getTableAjaxWidget($acl, $backRefFilter = []) {
+	public function getTableAjaxWidget($acl, $backRefFilter = [], $childRefFilter = []) {
 		$syncUrl = $this->getLink('', [ 'namespace' => $acl->getNamespace() ]);
 		$tbl = new TableAjax($acl);
 		$tbl->setRootUrl($syncUrl);
@@ -28,6 +28,14 @@ class Route_ViewTableAjax extends RouteBase {
 				'backRefField' => $backRefFilter['fieldName'],
 			]);
 		}
+		if (!empty($childRefFilter['namespace']) && !empty($childRefFilter['primaryKey'])) {
+			$tbl->setChildRefFilter($childRefFilter);
+			$syncUrl = $this->getLink('', [
+				'namespace' => $acl->getNamespace(),
+				'childRefNS' => $childRefFilter['namespace'],
+				'childRefPK' => $childRefFilter['primaryKey'],
+			]);
+		}
 		$tblLabel = $acl->getNamespace();
 		if ('default_db' == $acl->getSourceName()) {
 			$tblLabel = array();
@@ -84,7 +92,11 @@ class Route_ViewTableAjax extends RouteBase {
 				'primaryKey' => V::get('backRefPK', '', $_GET),
 				'fieldName' => V::get('backRefField', '', $_GET),
 			];
-			$tbl = $this->getTableAjaxWidget($acl, $backRefFilter);
+			$childRefFilter = [
+				'namespace' => V::get('childRefNS', '', $_GET),
+				'primaryKey' => V::get('childRefPK', '', $_GET),
+			];
+			$tbl = $this->getTableAjaxWidget($acl, $backRefFilter, $childRefFilter);
 			$tbl->setFilterInit($filterInit);
 			if (!empty($forceFilterInit)) $tbl->setForceFilterInit($forceFilterInit);
 			echo $tbl->render();
@@ -743,7 +755,11 @@ class Route_ViewTableAjax extends RouteBase {
 			'primaryKey' => V::get('backRefPK', '', $_REQUEST),
 			'fieldName' => V::get('backRefField', '', $_REQUEST),
 		];
-		$tbl = $this->getTableAjaxWidget($acl, $backRefFilter);
+		$childRefFilter = [
+			'namespace' => V::get('childRefNS', '', $_GET),
+			'primaryKey' => V::get('childRefPK', '', $_GET),
+		];
+		$tbl = $this->getTableAjaxWidget($acl, $backRefFilter, $childRefFilter);
 		Response::sendTryCatchJson(array($tbl, 'ajaxData'), $args = $_GET);
 	}