|
|
@@ -219,6 +219,8 @@ class ACL {
|
|
|
|
|
|
public static function getRefTable($rootObjectNamespace, $childName) { // CRM_REF_CONFIG
|
|
|
static $cacheRefTables = array();
|
|
|
+ if ($recurseCounter > 1) throw new Exception("BUG loop in ref config (SOURCE = 'backRef') for ns({$rootObjectNamespace}) child({$childName})");
|
|
|
+
|
|
|
DBG::log("DBG get ref table ({$rootObjectNamespace}, {$childName}) ...");
|
|
|
$rootObjectNamespace = ACL::getBaseNamespace($rootObjectNamespace);
|
|
|
$cacheKey = "{$rootObjectNamespace}/{$childName}";
|
|
|
@@ -238,7 +240,9 @@ class ACL {
|
|
|
|
|
|
if ('view' === $refInfo['SOURCE']) {
|
|
|
$refTableName = "CRM__#REF_TABLE__{$refInfo['ID']}_VIEW"; // view created by ACL::generateRefSelectSqlByFlatRelationCache
|
|
|
- } else {
|
|
|
+ } else if ('backRef' === $refInfo['SOURCE']) {
|
|
|
+ $refTableName = "CRM__#REF_TABLE__{$refInfo['ID']}_VIEW"; // view created by ACL::generateRefSelectSqlByFlatRelationCache
|
|
|
+ } else if ('table' === $refInfo['SOURCE']) {
|
|
|
$refTableName = "CRM__#REF_TABLE__{$refInfo['ID']}";
|
|
|
if ('WAITING' == $refInfo['A_STATUS']) {
|
|
|
DB::getPDO()->execSql("
|
|
|
@@ -260,6 +264,8 @@ class ACL {
|
|
|
'VERSION' => $refInfo['VERSION']
|
|
|
]);
|
|
|
}
|
|
|
+ } else {
|
|
|
+ throw new Exception("Not Implemented ref SOURCE = '{$refInfo['SOURCE']}'");
|
|
|
}
|
|
|
|
|
|
if ($refInfo['VERSION'] < self::$REF_TABLE_VERSION) throw new Exception("TODO: ref table {$refInfo['ID']} require upgrade - field '{$childName}' in object '{$rootObjectNamespace}'");
|
|
|
@@ -272,6 +278,45 @@ class ACL {
|
|
|
$refInfo = self::getRefConfig($rootObjectNamespace, $childName);
|
|
|
return V::get('SOURCE', 'table', $refInfo);
|
|
|
}
|
|
|
+ public static function decodeAppInfoJson($appInfoJsonString) {
|
|
|
+ $appInfo = @json_decode($appInfoJsonString, $assoc = true);
|
|
|
+ if (null == $appInfo && 0 !== json_last_error()) throw new Exception("Parsing Json failed: " . json_last_error());
|
|
|
+ return $appInfo;
|
|
|
+ }
|
|
|
+ public static function generateRefSelectSqlByBackRef($rootObjectNamespace, $childName) { // TODO: mv to generateRefSelectSqlByFlatRelationCache
|
|
|
+ // TODO: generate view which is select from {replaced(pk, remote pk) on ref table from backRef}
|
|
|
+ // {
|
|
|
+ // DBG::nicePrint($refInfo, "\$refInfo");
|
|
|
+ // DBG::nicePrint($rootObjectNamespace, "\$rootObjectNamespace");
|
|
|
+ // DBG::nicePrint($childName, "\$childName");
|
|
|
+ // DBG::nicePrint($childNamespace, "\$childNamespace");
|
|
|
+ // $replacedObjNs = Api_WfsNs::namespaceFromTypeName($childName);
|
|
|
+ // $replacedChildName = Api_WfsNs::typeName($rootObjectNamespace);
|
|
|
+ // DBG::nicePrint($replacedObjNs, "\$replacedObjNs");
|
|
|
+ // DBG::nicePrint($replacedChildName, "\$replacedChildName");
|
|
|
+ // return ACL::getRefTable($replacedObjNs, $replacedChildName, 1);
|
|
|
+ // throw new Exception("Not Implemented ref SOURCE = '{$refInfo['SOURCE']}'");
|
|
|
+ // }
|
|
|
+ $childNs = Api_WfsNs::namespaceFromTypeName($childName);
|
|
|
+ $rootTypeName = Api_WfsNs::typeName($rootObjectNamespace);
|
|
|
+ $backRefTable = ACL::getRefTable($childNs, $rootTypeName);
|
|
|
+ DBG::nicePrint($backRefTable, "ACL::getRefTable({$childNs}, {$rootTypeName})");
|
|
|
+
|
|
|
+ // TODO: check if ref_config is not backRef to avoid loop // $refInfo = self::getRefConfig($fieldNs, $item['typeName'], $item['typeName']);
|
|
|
+
|
|
|
+ $lastActionDateField = "NULL"; // , IF(l.A_RECORD_UPDATE_DATE > r.A_RECORD_UPDATE_DATE, l.A_RECORD_UPDATE_DATE, r.A_RECORD_UPDATE_DATE) as A_LAST_ACTION_DATE
|
|
|
+ $sql = "
|
|
|
+ select backRef.REMOTE_PRIMARY_KEY as PRIMARY_KEY
|
|
|
+ , backRef.PRIMARY_KEY as REMOTE_PRIMARY_KEY
|
|
|
+ , backRef.REMOTE_TYPENAME as REMOTE_TYPENAME
|
|
|
+ , backRef.A_STATUS as A_STATUS
|
|
|
+ , 0 as TRANSACTION_ID
|
|
|
+ , {$lastActionDateField} as A_LAST_ACTION_DATE
|
|
|
+ from `{$backRefTable}` backRef
|
|
|
+ ";
|
|
|
+ DBG::log($sql, 'sql', "generateRefSelectSqlByBackRef");
|
|
|
+ return $sql;
|
|
|
+ }
|
|
|
public static function generateRefSelectSqlByFlatRelationCache($rootObjectNamespace, $childName) { // CRM_REF_CONFIG
|
|
|
$appInfo = DB::getPDO()->fetchValue("
|
|
|
select f.appInfo
|
|
|
@@ -280,7 +325,7 @@ class ACL {
|
|
|
and f.fieldNamespace = '{$childName}'
|
|
|
");
|
|
|
if (!$appInfo) throw new Exception("Missing app:info for field '{$rootObjectNamespace}/{$childName}'");
|
|
|
- $appInfo = @json_decode($appInfo, $assoc = true);
|
|
|
+ $appInfo = ACL::decodeAppInfoJson($appInfo);
|
|
|
if (empty($appInfo)) throw new Exception("Empty app:info for field '{$rootObjectNamespace}/{$childName}'");
|
|
|
|
|
|
DBG::log(['$appInfo'=>$appInfo, '$rootObjectNamespace'=>$rootObjectNamespace, '$childName'=>$childName], 'array', "\$appInfo");
|
|
|
@@ -409,14 +454,18 @@ class ACL {
|
|
|
return $sql;
|
|
|
}
|
|
|
public static function setRefSource($rootObjectNamespace, $childName, $source, $viewSelectSql = null) { // CRM_REF_CONFIG
|
|
|
- if (!in_array($source, ['view', 'table'])) throw new Exception("Wrong param source - expected 'table' or 'view'");
|
|
|
+ if (!in_array($source, ['view', 'table', 'backRef'])) throw new Exception("Wrong param source - expected 'table', 'view' or 'backRef'");
|
|
|
if ('view' === $source && !$viewSelectSql) throw new Exception("Missing create view sql");
|
|
|
$refInfo = self::getRefConfig($rootObjectNamespace, $childName);
|
|
|
- if ($source != $refInfo['SOURCE']) {
|
|
|
+ if (true) { // if ($source != $refInfo['SOURCE']) {
|
|
|
if ('view' === $source) {
|
|
|
$refTableName = "CRM__#REF_TABLE__{$refInfo['ID']}_VIEW";
|
|
|
DB::getPDO()->execSql(" CREATE OR REPLACE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `{$refTableName}` AS {$viewSelectSql} ");
|
|
|
}
|
|
|
+ if ('backRef' === $source) {
|
|
|
+ $refTableName = "CRM__#REF_TABLE__{$refInfo['ID']}_VIEW";
|
|
|
+ DB::getPDO()->execSql(" CREATE OR REPLACE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `{$refTableName}` AS {$viewSelectSql} ");
|
|
|
+ }
|
|
|
$affected = DB::getPDO()->update("CRM_REF_CONFIG", 'ID', $refInfo['ID'], [
|
|
|
'SOURCE' => $source,
|
|
|
]);
|
|
|
@@ -466,6 +515,11 @@ class ACL {
|
|
|
DBG::log($e);
|
|
|
}
|
|
|
}
|
|
|
+ try {
|
|
|
+ DB::getPDO()->execSql(" ALTER TABLE `CRM_REF_CONFIG` CHANGE `SOURCE` `SOURCE` enum('table', 'view', 'backRef') not null default 'table' ");
|
|
|
+ } catch (Exception $e) {
|
|
|
+ DBG::log($e);
|
|
|
+ }
|
|
|
if (empty($refInfo)) {
|
|
|
$refInfo = [ 'ID' => 0, 'A_STATUS' => 'WAITING', 'VERSION' => 0, 'SOURCE' => 'table' ];
|
|
|
$refInfo['ID'] = DB::getPDO()->insert("CRM_REF_CONFIG", [
|
|
|
@@ -515,13 +569,21 @@ class ACL {
|
|
|
select c.CHILD_NAME as namespace
|
|
|
, c.A_STATUS
|
|
|
, c.ID
|
|
|
+ , c.SOURCE
|
|
|
from CRM_REF_CONFIG c
|
|
|
where c.ROOT_OBJECT_NS = :namespace
|
|
|
- and c.A_STATUS = 'NORMAL'
|
|
|
+ -- and c.A_STATUS = 'NORMAL'
|
|
|
", [
|
|
|
':namespace' => $namespace,
|
|
|
]);
|
|
|
}
|
|
|
+ public static function updateChildRefSource($id, $source) {
|
|
|
+ if (!$id) throw new Exception("Missing id");
|
|
|
+ if (!in_array($source, ['view', 'table', 'backRef'])) throw new Exception("Wrong source");
|
|
|
+ return DB::getPDO()->update('CRM_REF_CONFIG', 'ID', $id, [
|
|
|
+ 'SOURCE' => $source
|
|
|
+ ]);
|
|
|
+ }
|
|
|
|
|
|
public static function fetchRefs($namespace, $childNamespace, $primaryKey, $params = []) { // TODO: $params: limit, total
|
|
|
if (!$namespace) throw new Exception("Missing namespace");
|