From 3cde7d402620769d0ff74fe9451abcb10d44fd29 Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Wed, 26 Feb 2025 03:17:55 +1100 Subject: [PATCH 01/29] fix issue #640 --- apps/Core/Views/Default/html/modules/queue/analyse.html | 2 +- system/Base/Installer/Components/Setup.php | 2 +- system/Base/Installer/View/setup.phtml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/Core/Views/Default/html/modules/queue/analyse.html b/apps/Core/Views/Default/html/modules/queue/analyse.html index 1546467df..d82d44a83 100644 --- a/apps/Core/Views/Default/html/modules/queue/analyse.html +++ b/apps/Core/Views/Default/html/modules/queue/analyse.html @@ -250,7 +250,7 @@ dataCollectionSectionForm['vars']['queue'] = JSON.parse('{{queue}}'); dataCollectionSectionForm['funcs'] = { }; dataCollectionSectionForm['funcs']['init'] = function() { - BazProgress.buildProgressBar($('#installer-progress'), false, true, true); + BazProgress.buildProgressBar($('#installer-progress'), false, true, true, false); if ($.fn.DataTable && !$.fn.DataTable.isDataTable('#{{componentId}}-{{sectionId}}-queue-table')) { $('#{{componentId}}-{{sectionId}}-queue-table').DataTable({ diff --git a/system/Base/Installer/Components/Setup.php b/system/Base/Installer/Components/Setup.php index 240b4f416..9d8ff6309 100644 --- a/system/Base/Installer/Components/Setup.php +++ b/system/Base/Installer/Components/Setup.php @@ -179,7 +179,7 @@ function () { $this->helper = $this->container->getShared('helper'); if ($onlyUpdateDb === false) { - $this->progress = $this->basepackages->progress->init($this->container); + $this->progress = $this->basepackages->progress->init($this->container, 'setup'); } $this->config = $configsObj->toArray(); diff --git a/system/Base/Installer/View/setup.phtml b/system/Base/Installer/View/setup.phtml index fedf2965c..ea591e8ca 100644 --- a/system/Base/Installer/View/setup.phtml +++ b/system/Base/Installer/View/setup.phtml @@ -392,10 +392,10 @@ + \ No newline at end of file From a464189c91d8b592e3de1b3360389694643bdd1c Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Sat, 1 Mar 2025 04:24:58 +1100 Subject: [PATCH 14/29] minor bug fix for #640 --- .../BasepackagesServiceProvider/Packages/Progress.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php index 7771bbdef..0705fb173 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php @@ -175,7 +175,8 @@ public function updateProgress($method, $callResult = null, $deleteFile = true, $progressFile = $this->readProgressFile(); if (isset($progressFile['processes']) && count($progressFile['processes']) > 0) { - if ($progressFile['allProcesses'][0]['method'] === $method && + if (isset($progressFile['allProcesses'][0]) && + $progressFile['allProcesses'][0]['method'] === $method && !$callResult && !$child && !$counters && From 8927fecacb5c4df13314b78bef76f8f14ccb5c27 Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Sat, 1 Mar 2025 04:26:55 +1100 Subject: [PATCH 15/29] fix issue #648 --- .../Providers/DatabaseServiceProvider/Ff.php | 3 +-- .../Ff/Classes/DocumentFinder.php | 24 +++++++++++++++---- .../Ff/Classes/IndexHandler.php | 12 ++++++++++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/system/Base/Providers/DatabaseServiceProvider/Ff.php b/system/Base/Providers/DatabaseServiceProvider/Ff.php index 1266ee7ff..d15d563f8 100644 --- a/system/Base/Providers/DatabaseServiceProvider/Ff.php +++ b/system/Base/Providers/DatabaseServiceProvider/Ff.php @@ -364,7 +364,6 @@ public function generateConfig($tableName, $tableClass, $tableModel, $configArr foreach ($tableClass->columns()['columns'] as $column) { $columns[$column->getName()] = $column; } - foreach ($tableClass->indexes() as $index) { if ($index->getType() === 'UNIQUE' && $index->getColumns() && count($index->getColumns()) > 0) { if (isset($config['uniqueFields']) && count($config['uniqueFields']) > 0) { @@ -378,7 +377,7 @@ public function generateConfig($tableName, $tableClass, $tableModel, $configArr foreach ($index->getColumns() as $indexColumn) { if (isset($columns[$indexColumn])) { if (in_array($columns[$indexColumn]->getType(), $columnsTypeToIndex)) { - $config['indexes'] = array_merge($config['indexes'], $index->getColumns()); + array_push($config['indexes'], $indexColumn); } } } diff --git a/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php b/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php index 1d9f44b42..345d63d3c 100644 --- a/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php +++ b/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php @@ -86,10 +86,18 @@ public function findDocuments(bool $getOneDocument, bool $reduceAndJoinPossible) if (count($indexJson) > 0) { if (isset($indexJson[strtolower($keyword)])) { if (count($indexJson[strtolower($keyword)]) === 1) { - $found[] = $this->store->findById($indexJson[strtolower($keyword)][0]); + $indexIdData = $this->store->findById($indexJson[strtolower($keyword)][0]); + + if ($indexIdData) { + $found[] = $indexIdData; + } } else { foreach ($indexJson[strtolower($keyword)] as $id) { - $found[] = $this->store->findById($id); + $indexIdData = $this->store->findById($id); + + if ($indexIdData) { + $found[] = $indexIdData; + } } } } else { @@ -99,7 +107,11 @@ public function findDocuments(bool $getOneDocument, bool $reduceAndJoinPossible) if (strtolower($condition[0][1]) === 'like') { if (str_starts_with($key, strtolower($keyword))) { foreach ($ids as $id) { - $found[] = $this->store->findById($id); + $indexIdData = $this->store->findById($id); + + if ($indexIdData) { + $found[] = $indexIdData; + } } } } else if ($condition[0][1] === '=' || @@ -107,7 +119,11 @@ public function findDocuments(bool $getOneDocument, bool $reduceAndJoinPossible) ) { if ($key === strtolower($keyword)) { foreach ($ids as $id) { - $found[] = $this->store->findById($id); + $indexIdData = $this->store->findById($id); + + if ($indexIdData) { + $found[] = $indexIdData; + } } } } diff --git a/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/IndexHandler.php b/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/IndexHandler.php index 26f912974..5f2fb5364 100644 --- a/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/IndexHandler.php +++ b/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/IndexHandler.php @@ -82,11 +82,19 @@ public function setIndex($content, $remove = false) $indexChars = strtolower(mb_substr($content, 0, $this->minIndexChars, 'UTF-8')); + if (str_contains($indexChars, '/')) {//this will result in subdirectories + continue; + } + $this->writeIndex($indexPointer, $index, $indexChars, $content, $remove); } } else { $indexChars = strtolower(mb_substr($content[$index], 0, $this->minIndexChars, 'UTF-8')); + if (str_contains($indexChars, '/')) {//this will result in subdirectories + continue; + } + $this->writeIndex($indexPointer, $index, $indexChars, $content[$index], $remove); } } else { @@ -96,6 +104,10 @@ public function setIndex($content, $remove = false) if (is_string($content[$index])) { $indexChars = strtolower(mb_substr($content[$index], 0, $this->minIndexChars, 'UTF-8')); + if (str_contains($indexChars, '/')) {//this will result in subdirectories + continue; + } + $this->writeIndex($indexPointer, $index, $indexChars, $content[$index], $remove); } else { $this->writeIndex($indexPointer, $index, $content[$index], $content[$index], $remove); From dd5998a615437514dfc8664c530232062c7fdb9f Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Sat, 1 Mar 2025 14:23:50 +1100 Subject: [PATCH 16/29] fix issue #649 --- .../Packages/Progress.php | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php index 0705fb173..24ecc397b 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php @@ -18,6 +18,8 @@ class Progress extends BasePackage protected $countersTimer; + protected $errors = []; + public function init($container = null, $fileName = null) { if ($container) { @@ -329,6 +331,12 @@ protected function sendNotification($callResult, $counters = null) $progressFile = $this->readProgressFile(); if ($progressFile) { + $errors = false; + + if (is_array($this->errors) && count($this->errors) > 0) { + $errors = $this->helper->encode($this->errors); + } + $this->wss->send( [ 'type' => 'progress', @@ -346,7 +354,8 @@ protected function sendNotification($callResult, $counters = null) 'totalPercentComplete' => $this->getPercentComplete($progressFile, false), 'percentComplete' => $this->getPercentComplete($progressFile), 'runners' => $progressFile['runners'] ?? false, - 'callResult' => $callResult + 'callResult' => $callResult, + 'errors' => $errors ] ] ] @@ -416,6 +425,16 @@ public function resetProgress($reRegisterMethods = true) return true; } + public function setErrors(array $errors) + { + $this->errors = $errors; + } + + public function getErrors() + { + return $this->errors; + } + protected function checkProgressPath() { if (!is_dir(base_path('var/progress/'))) { @@ -595,6 +614,8 @@ protected function writeProgressFile( $file['pid'] = getmypid(); } + $file['errors'] = $this->errors; + if ($this->opCache) { if ($progressFile) { $this->opCache->resetCache($this->progressFileName, $file, 'progress'); From b4a6e56100ed94a2be797df91bb1f0ce0e97af4d Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Sat, 1 Mar 2025 15:57:17 +1100 Subject: [PATCH 17/29] update issue #649 --- .../default/js/footer/core/Baz/BazProgress.js | 55 ++++++++++++++++--- public/core/default/js/footer/jsFooterCore.js | 55 ++++++++++++++++--- .../Packages/Progress.php | 6 +- 3 files changed, 99 insertions(+), 17 deletions(-) diff --git a/public/core/default/js/footer/core/Baz/BazProgress.js b/public/core/default/js/footer/core/Baz/BazProgress.js index 550debdab..d0224237a 100644 --- a/public/core/default/js/footer/core/Baz/BazProgress.js +++ b/public/core/default/js/footer/core/Baz/BazProgress.js @@ -18,7 +18,7 @@ var BazProgress = function() { var initialized = false; var progressCounter = 0; var online = false; - var element, manualShowHide, hasChild, hasSubProcess, hasCancelButton; + var element, manualShowHide, hasChild, hasSubProcess, hasCancelButton, hasDetails; var callableFunc = null; var url var postData = { }; @@ -68,12 +68,13 @@ var BazProgress = function() { console.log('Progress service offline'); } - function buildProgressBar(el, mSH = false, hC = false, hSP = false, hCB = true) { + function buildProgressBar(el, mSH = false, hC = false, hSP = false, hCB = true, hD = true) { element = el; manualShowHide = mSH; hasChild = hC; hasSubProcess = hSP; hasCancelButton = hCB; + hasDetails = hD; $(element).html( '
' + @@ -179,6 +180,19 @@ var BazProgress = function() { } }); } + + if (hasDetails) { + $(element).append( + '' + ); + } } function getProgress(options) { @@ -187,6 +201,7 @@ var BazProgress = function() { if (callableFunc && callableFunc['beforeStart']) { if (callableFunc['beforeStart']() === false) { resetProgressCounter(); + return; } } @@ -219,6 +234,7 @@ var BazProgress = function() { if (callableFunc && callableFunc['beforeProcess']) { if (callableFunc['beforeProcess'](response) === false) { resetProgressCounter(); + return; } } @@ -244,9 +260,28 @@ var BazProgress = function() { } if (responseData['preCheckComplete'] == false || - (responseData['callResult'] && responseData['callResult'] === 'reset') + (responseData['callResult'] && responseData['callResult'] === 'reset') || + (responseData['callResult'] && responseData['callResult'] === 'pid_running') ) { - resetProgressCounter(); + if (responseData['errors']) { + $('#details-div').attr('hidden', false); + $('#details-data').val(responseData['errors']); + $('#details-data').scrollTop($('#details-data')[0].scrollHeight); + } + + if (responseData['callResult'] === 'pid_running') { + $('#' + $(element)[0].id).attr('hidden', false); + $('#' + $(element)[0].id + '-cancel').attr('hidden', false); + $('#' + $(element)[0].id + '-cancel-button').text('Cancel Process: ' + responseData['pid']); + } + + if (responseData['callResult'] && responseData['callResult'] === 'reset') { + if (responseData['errors']) { + resetProgressCounter(false); + } else { + resetProgressCounter(); + } + } return false; } @@ -486,7 +521,7 @@ var BazProgress = function() { return text; } - function resetProgressCounter() { + function resetProgressCounter(hideDiv = true) { if (progressCounter !== 60) { progressCounter ++; @@ -498,10 +533,14 @@ var BazProgress = function() { } } - $('#' + $(element)[0].id).attr('hidden', true); + if (hideDiv) { + $('#' + $(element)[0].id).attr('hidden', true); + $('#details-div').attr('hidden', true); + } $('.' + $(element)[0].id + '-bar').css('width', '0%'); $('.' + $(element)[0].id + '-bar').attr('aria-valuenow', 0); switchProgressBarColor('.' + $(element)[0].id + '-bar', 'info'); + $('#' + $(element)[0].id + '-cancel-button').text('Cancel'); downloadTotal = 0; downloadedBytes = 0; uploadTotal = 0; @@ -551,8 +590,8 @@ var BazProgress = function() { getProgress(options); } } - BazProgress.buildProgressBar = function(el, mSH = false, child = false, hasSubProcess = false, hasCancelButton = true) { - buildProgressBar(el, mSH, child, hasSubProcess, hasCancelButton); + BazProgress.buildProgressBar = function(el, mSH = false, child = false, hasSubProcess = false, hasCancelButton = true, hasDetails = true) { + buildProgressBar(el, mSH, child, hasSubProcess, hasCancelButton, hasDetails); } BazProgress.switchProgressBarColor = function(el, color) { switchProgressBarColor(el, color); diff --git a/public/core/default/js/footer/jsFooterCore.js b/public/core/default/js/footer/jsFooterCore.js index e32dbe8cc..d941e3364 100644 --- a/public/core/default/js/footer/jsFooterCore.js +++ b/public/core/default/js/footer/jsFooterCore.js @@ -11845,7 +11845,7 @@ var BazProgress = function() { var initialized = false; var progressCounter = 0; var online = false; - var element, manualShowHide, hasChild, hasSubProcess, hasCancelButton; + var element, manualShowHide, hasChild, hasSubProcess, hasCancelButton, hasDetails; var callableFunc = null; var url var postData = { }; @@ -11895,12 +11895,13 @@ var BazProgress = function() { console.log('Progress service offline'); } - function buildProgressBar(el, mSH = false, hC = false, hSP = false, hCB = true) { + function buildProgressBar(el, mSH = false, hC = false, hSP = false, hCB = true, hD = true) { element = el; manualShowHide = mSH; hasChild = hC; hasSubProcess = hSP; hasCancelButton = hCB; + hasDetails = hD; $(element).html( '
' + @@ -12006,6 +12007,19 @@ var BazProgress = function() { } }); } + + if (hasDetails) { + $(element).append( + '' + ); + } } function getProgress(options) { @@ -12014,6 +12028,7 @@ var BazProgress = function() { if (callableFunc && callableFunc['beforeStart']) { if (callableFunc['beforeStart']() === false) { resetProgressCounter(); + return; } } @@ -12046,6 +12061,7 @@ var BazProgress = function() { if (callableFunc && callableFunc['beforeProcess']) { if (callableFunc['beforeProcess'](response) === false) { resetProgressCounter(); + return; } } @@ -12071,9 +12087,28 @@ var BazProgress = function() { } if (responseData['preCheckComplete'] == false || - (responseData['callResult'] && responseData['callResult'] === 'reset') + (responseData['callResult'] && responseData['callResult'] === 'reset') || + (responseData['callResult'] && responseData['callResult'] === 'pid_running') ) { - resetProgressCounter(); + if (responseData['errors']) { + $('#details-div').attr('hidden', false); + $('#details-data').val(responseData['errors']); + $('#details-data').scrollTop($('#details-data')[0].scrollHeight); + } + + if (responseData['callResult'] === 'pid_running') { + $('#' + $(element)[0].id).attr('hidden', false); + $('#' + $(element)[0].id + '-cancel').attr('hidden', false); + $('#' + $(element)[0].id + '-cancel-button').text('Cancel Process: ' + responseData['pid']); + } + + if (responseData['callResult'] && responseData['callResult'] === 'reset') { + if (responseData['errors']) { + resetProgressCounter(false); + } else { + resetProgressCounter(); + } + } return false; } @@ -12313,7 +12348,7 @@ var BazProgress = function() { return text; } - function resetProgressCounter() { + function resetProgressCounter(hideDiv = true) { if (progressCounter !== 60) { progressCounter ++; @@ -12325,10 +12360,14 @@ var BazProgress = function() { } } - $('#' + $(element)[0].id).attr('hidden', true); + if (hideDiv) { + $('#' + $(element)[0].id).attr('hidden', true); + $('#details-div').attr('hidden', true); + } $('.' + $(element)[0].id + '-bar').css('width', '0%'); $('.' + $(element)[0].id + '-bar').attr('aria-valuenow', 0); switchProgressBarColor('.' + $(element)[0].id + '-bar', 'info'); + $('#' + $(element)[0].id + '-cancel-button').text('Cancel'); downloadTotal = 0; downloadedBytes = 0; uploadTotal = 0; @@ -12378,8 +12417,8 @@ var BazProgress = function() { getProgress(options); } } - BazProgress.buildProgressBar = function(el, mSH = false, child = false, hasSubProcess = false, hasCancelButton = true) { - buildProgressBar(el, mSH, child, hasSubProcess, hasCancelButton); + BazProgress.buildProgressBar = function(el, mSH = false, child = false, hasSubProcess = false, hasCancelButton = true, hasDetails = true) { + buildProgressBar(el, mSH, child, hasSubProcess, hasCancelButton, hasDetails); } BazProgress.switchProgressBarColor = function(el, color) { switchProgressBarColor(el, color); diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php index 24ecc397b..11d2c0048 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php @@ -288,7 +288,11 @@ public function checkProcessIsRunning($progressFile = null) count($output) > 0 ) { if (str_contains($output[0], 'php')) { - throw new DuplicateProgressException('Process is already running with process ID: ' . $progressFile['pid']); + $this->errors = ['PID running' => 'Progress is already running with process ID: ' . $progressFile['pid']]; + + $this->sendNotification('pid_running'); + + throw new DuplicateProgressException('Progress is already running with process ID: ' . $progressFile['pid']); } } } From 19d21b98c0b0a73d13c01be4d4c9f6e471b11080 Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Sat, 1 Mar 2025 20:34:01 +1100 Subject: [PATCH 18/29] update issue #649. Added details of each process to be sent to the client. --- .../default/js/footer/core/Baz/BazHelpers.js | 32 ++++- .../default/js/footer/core/Baz/BazProgress.js | 88 +++++++++++-- public/core/default/js/footer/jsFooterCore.js | 120 +++++++++++++++--- .../Packages/Progress.php | 69 ++++++++-- 4 files changed, 270 insertions(+), 39 deletions(-) diff --git a/public/core/default/js/footer/core/Baz/BazHelpers.js b/public/core/default/js/footer/core/Baz/BazHelpers.js index 5174effa9..0622f37e1 100644 --- a/public/core/default/js/footer/core/Baz/BazHelpers.js +++ b/public/core/default/js/footer/core/Baz/BazHelpers.js @@ -108,7 +108,37 @@ var BazHelpers = function() { output += bazCreateHtmlList(obj[k]); output += ''; } else { - output += '
  • ' + k + ' : ' + obj[k] + '
  • '; + if (typeof obj[k] === 'string') { + if (obj[k].startsWith('{')) { + var regex = /{.*}/g; + + var found = obj[k].match(regex); + + if (found) { + //eslint-disable-next-line + var data = found[0].replaceAll('\"', '"'); + //eslint-disable-next-line + data = data.replaceAll('\\', '\\\\\\\\'); + //eslint-disable-next-line + data = data.replaceAll('\\\\\\u0022', '"'); + var objObject = JSON.parse(data); + + if (objObject) { + output += '
  • ' + k + ' : '; + output += bazCreateHtmlList(objObject); + output += '
  • '; + } else { + output += '
  • ' + k + ' : ' + obj[k] + '
  • '; + } + } else { + output += '
  • ' + k + ' : ' + obj[k] + '
  • '; + } + } else { + output += '
  • ' + k + ' : ' + obj[k] + '
  • '; + } + } else { + output += '
  • ' + k + ' : ' + obj[k] + '
  • '; + } } }); output += ''; diff --git a/public/core/default/js/footer/core/Baz/BazProgress.js b/public/core/default/js/footer/core/Baz/BazProgress.js index d0224237a..646a13da1 100644 --- a/public/core/default/js/footer/core/Baz/BazProgress.js +++ b/public/core/default/js/footer/core/Baz/BazProgress.js @@ -116,17 +116,37 @@ var BazProgress = function() { ); } + var buttons = '
    '; + if (hasCancelButton) { - $(element).append( - '' - ); + buttons += + '
    ' + + '' + + '
    '; + } + + if (hasDetails) { + buttons += + '
    ' + + '
    ' + + '' + + '
    ' + + '
    '; + } + + buttons += '
    '; - $('#' + $(element)[0].id + '-cancel').off(); - $('#' + $(element)[0].id + '-cancel').click(function() { + $(element).append(buttons); + + if (hasCancelButton) { + $('#' + $(element)[0].id + '-cancel-button').off(); + $('#' + $(element)[0].id + '-cancel-button').click(function() { if (pid > 0) { Swal.fire({ title : ' Cancel current process?', @@ -182,12 +202,25 @@ var BazProgress = function() { } if (hasDetails) { + $('#' + $(element)[0].id + '-details-button').off(); + $('#' + $(element)[0].id + '-details-button').click(function() { + var text = $('#' + $(element)[0].id + '-details-button').text().toLowerCase(); + + if (text === 'show details') { + $('#' + $(element)[0].id + '-details-button').text('Hide details'); + $('#details-div').attr('hidden', false); + } else if (text === 'hide details') { + $('#' + $(element)[0].id + '-details-button').text('Show details'); + $('#details-div').attr('hidden', true); + } + }); + $(element).append( '' @@ -253,6 +286,8 @@ var BazProgress = function() { if (responseData['pid']) { $('#' + $(element)[0].id + '-cancel').attr('hidden', false); pid = responseData['pid']; + + $('#details-data').html('PID running : Progress is running with process ID: ' + pid + '
    '); } if (responseData['progressFile']) { @@ -265,7 +300,29 @@ var BazProgress = function() { ) { if (responseData['errors']) { $('#details-div').attr('hidden', false); - $('#details-data').val(responseData['errors']); + var html = responseData['errors']; + var regex = /{.*}/g; + var found = html.match(regex); + + if (found) { + //eslint-disable-next-line + var data = found[0].replaceAll('\"', '"'); + //eslint-disable-next-line + data = data.replaceAll('\\', '\\\\\\\\'); + //eslint-disable-next-line + data = data.replaceAll('\\\\\\u0022', '"'); + var obj = JSON.parse(data); + + if (obj) { + $('#details-data').html( + '
    ' + + BazHelpers.createHtmlList({'obj': obj})); + '
    ' + } + } else { + $('#details-data').html(html); + } + $('#details-data').scrollTop($('#details-data')[0].scrollHeight); } @@ -276,9 +333,7 @@ var BazProgress = function() { } if (responseData['callResult'] && responseData['callResult'] === 'reset') { - if (responseData['errors']) { - resetProgressCounter(false); - } else { + if (!responseData['errors']) { resetProgressCounter(); } } @@ -286,6 +341,11 @@ var BazProgress = function() { return false; } + if (responseData['details']) { + var pidHtml = $('#details-data').html(); + $('#details-data').html(pidHtml + BazHelpers.createHtmlList({'obj': responseData['details']})); + } + if (responseData['total'] !== 'undefined' && responseData['completed'] !== 'undefined') { if (responseData['total'] !== responseData['completed']) { if (responseData['runners'] && responseData['runners']['running'] !== false) { diff --git a/public/core/default/js/footer/jsFooterCore.js b/public/core/default/js/footer/jsFooterCore.js index d941e3364..277daf822 100644 --- a/public/core/default/js/footer/jsFooterCore.js +++ b/public/core/default/js/footer/jsFooterCore.js @@ -3072,7 +3072,37 @@ var BazHelpers = function() { output += bazCreateHtmlList(obj[k]); output += ''; } else { - output += '
  • ' + k + ' : ' + obj[k] + '
  • '; + if (typeof obj[k] === 'string') { + if (obj[k].startsWith('{')) { + var regex = /{.*}/g; + + var found = obj[k].match(regex); + + if (found) { + //eslint-disable-next-line + var data = found[0].replaceAll('\"', '"'); + //eslint-disable-next-line + data = data.replaceAll('\\', '\\\\\\\\'); + //eslint-disable-next-line + data = data.replaceAll('\\\\\\u0022', '"'); + var objObject = JSON.parse(data); + + if (objObject) { + output += '
  • ' + k + ' : '; + output += bazCreateHtmlList(objObject); + output += '
  • '; + } else { + output += '
  • ' + k + ' : ' + obj[k] + '
  • '; + } + } else { + output += '
  • ' + k + ' : ' + obj[k] + '
  • '; + } + } else { + output += '
  • ' + k + ' : ' + obj[k] + '
  • '; + } + } else { + output += '
  • ' + k + ' : ' + obj[k] + '
  • '; + } } }); output += ''; @@ -11943,17 +11973,37 @@ var BazProgress = function() { ); } + var buttons = '
    '; + if (hasCancelButton) { - $(element).append( - '' - ); + buttons += + '
    ' + + '' + + '
    '; + } - $('#' + $(element)[0].id + '-cancel').off(); - $('#' + $(element)[0].id + '-cancel').click(function() { + if (hasDetails) { + buttons += + '
    ' + + '
    ' + + '' + + '
    ' + + '
    '; + } + + buttons += '
    '; + + $(element).append(buttons); + + if (hasCancelButton) { + $('#' + $(element)[0].id + '-cancel-button').off(); + $('#' + $(element)[0].id + '-cancel-button').click(function() { if (pid > 0) { Swal.fire({ title : ' Cancel current process?', @@ -12009,12 +12059,25 @@ var BazProgress = function() { } if (hasDetails) { + $('#' + $(element)[0].id + '-details-button').off(); + $('#' + $(element)[0].id + '-details-button').click(function() { + var text = $('#' + $(element)[0].id + '-details-button').text().toLowerCase(); + + if (text === 'show details') { + $('#' + $(element)[0].id + '-details-button').text('Hide details'); + $('#details-div').attr('hidden', false); + } else if (text === 'hide details') { + $('#' + $(element)[0].id + '-details-button').text('Show details'); + $('#details-div').attr('hidden', true); + } + }); + $(element).append( '' @@ -12080,6 +12143,8 @@ var BazProgress = function() { if (responseData['pid']) { $('#' + $(element)[0].id + '-cancel').attr('hidden', false); pid = responseData['pid']; + + $('#details-data').html('PID running : Progress is running with process ID: ' + pid + '
    '); } if (responseData['progressFile']) { @@ -12092,7 +12157,29 @@ var BazProgress = function() { ) { if (responseData['errors']) { $('#details-div').attr('hidden', false); - $('#details-data').val(responseData['errors']); + var html = responseData['errors']; + var regex = /{.*}/g; + var found = html.match(regex); + + if (found) { + //eslint-disable-next-line + var data = found[0].replaceAll('\"', '"'); + //eslint-disable-next-line + data = data.replaceAll('\\', '\\\\\\\\'); + //eslint-disable-next-line + data = data.replaceAll('\\\\\\u0022', '"'); + var obj = JSON.parse(data); + + if (obj) { + $('#details-data').html( + '
    ' + + BazHelpers.createHtmlList({'obj': obj})); + '
    ' + } + } else { + $('#details-data').html(html); + } + $('#details-data').scrollTop($('#details-data')[0].scrollHeight); } @@ -12103,9 +12190,7 @@ var BazProgress = function() { } if (responseData['callResult'] && responseData['callResult'] === 'reset') { - if (responseData['errors']) { - resetProgressCounter(false); - } else { + if (!responseData['errors']) { resetProgressCounter(); } } @@ -12113,6 +12198,11 @@ var BazProgress = function() { return false; } + if (responseData['details']) { + var pidHtml = $('#details-data').html(); + $('#details-data').html(pidHtml + BazHelpers.createHtmlList({'obj': responseData['details']})); + } + if (responseData['total'] !== 'undefined' && responseData['completed'] !== 'undefined') { if (responseData['total'] !== responseData['completed']) { if (responseData['runners'] && responseData['runners']['running'] !== false) { diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php index 11d2c0048..0d1423857 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php @@ -20,6 +20,8 @@ class Progress extends BasePackage protected $errors = []; + protected $details = []; + public function init($container = null, $fileName = null) { if ($container) { @@ -111,10 +113,18 @@ public function unregisterMethods(array $methods, $using = 'method', array $chil foreach ($progressFile['processes'][$progressFileKey]['childs'] as $childKey => $child) { if (in_array($child[$using], $childs)) { unset($progressFile['processes'][$progressFileKey]['childs'][$childKey]); + + if (isset($progressFile['registeredMethods'][$progressFileKey]['childs'][$childKey])) { + unset($progressFile['registeredMethods'][$progressFileKey]['childs'][$childKey]); + } } } } else { unset($progressFile['processes'][$progressFileKey]); + + if (isset($progressFile['registeredMethods'][$progressFileKey])) { + unset($progressFile['registeredMethods'][$progressFileKey]); + } } } } @@ -136,16 +146,25 @@ public function getProgress($session = null, $returnArray = false) return false; } + $errors = false; + + if (is_array($this->errors) && count($this->errors) > 0) { + $errors = $this->helper->encode($this->errors); + } + $progress = [ + 'progressFile' => $this->progressFileName, + 'pid' => $progressFile['pid'] ?? false, 'total' => $progressFile['total'], 'completed' => $progressFile['completed'], 'preCheckComplete' => $progressFile['preCheckComplete'], 'totalPercentComplete' => $this->getPercentComplete($progressFile, false), 'percentComplete' => $this->getPercentComplete($progressFile), - 'runners' => $progressFile['runners'] ?? false + 'runners' => $progressFile['runners'] ?? false, + 'callResult' => $callResult, + 'errors' => $errors ]; - if ($returnArray) { return $progress; } @@ -274,7 +293,7 @@ public function checkProcessIsRunning($progressFile = null) $progressFile = $this->checkProgressFile(); } - //Check if process is already running + //Check if process is running //If a user tries to reinitiate same process from start, we should return an error. if ($progressFile && array_key_exists('runners', $progressFile) && @@ -288,11 +307,11 @@ public function checkProcessIsRunning($progressFile = null) count($output) > 0 ) { if (str_contains($output[0], 'php')) { - $this->errors = ['PID running' => 'Progress is already running with process ID: ' . $progressFile['pid']]; + $this->errors = ['PID running' => 'Progress is running with process ID: ' . $progressFile['pid']]; $this->sendNotification('pid_running'); - throw new DuplicateProgressException('Progress is already running with process ID: ' . $progressFile['pid']); + throw new DuplicateProgressException('Progress is running with process ID: ' . $progressFile['pid']); } } } @@ -341,6 +360,35 @@ protected function sendNotification($callResult, $counters = null) $errors = $this->helper->encode($this->errors); } + $details = false; + if (isset($progressFile['allProcesses']) && is_array($progressFile['allProcesses'])) { + $details = []; + + foreach ($progressFile['allProcesses'] as $processKey => $process) { + if (!array_key_exists('callResult', $process)) { + continue; + } + + $processCallResult = 'Running...'; + if ($progressFile['runners']['running']['method'] !== $process['method']) { + if ($process['callResult'] === true) { + $processCallResult = 'Done'; + } else if ($process['callResult'] === false) { + $processCallResult = 'Error'; + } + if (count($this->errors) > 0) { + $processCallResult = 'Error'; + } + } + + $details[$process['text']] = $processCallResult; + } + + if (count($details) === 0) { + $details = false; + } + } + $this->wss->send( [ 'type' => 'progress', @@ -359,7 +407,8 @@ protected function sendNotification($callResult, $counters = null) 'percentComplete' => $this->getPercentComplete($progressFile), 'runners' => $progressFile['runners'] ?? false, 'callResult' => $callResult, - 'errors' => $errors + 'errors' => $errors, + 'details' => $details ] ] ] @@ -420,7 +469,7 @@ public function resetProgress($reRegisterMethods = true) $this->deleteProgressFile(true); if ($reRegisterMethods) { - $this->registerMethods($progressFile['allProcesses']); + $this->registerMethods($progressFile['registeredMethods']); } } @@ -536,10 +585,10 @@ protected function writeProgressFile( $file['runners']['running'] = current($methods); $file['runners']['next'] = next($methods); if ($register) { - $file['allProcesses'] = $methods; + $file['allProcesses'] = $file['registeredMethods'] = $methods; } else if ($unregister) { $progressFile = $this->readProgressFile(); - $file['allProcesses'] = $progressFile['allProcesses']; + $file['allProcesses'] = $progressFile['registeredMethods']; } } @@ -603,6 +652,8 @@ protected function writeProgressFile( if ($runners) { $file['runners'] = $runners; } + + $file['registeredMethods'] = $progressFile['registeredMethods']; } $file['processes'] = $methods; From 5bf28957ed1846977f4b2dfece205ff2b39885ed Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Sat, 1 Mar 2025 21:18:10 +1100 Subject: [PATCH 19/29] fix minor bug #649 --- .../BasepackagesServiceProvider/Packages/Progress.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php index 0d1423857..cfc9fae98 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php @@ -370,7 +370,8 @@ protected function sendNotification($callResult, $counters = null) } $processCallResult = 'Running...'; - if ($progressFile['runners']['running']['method'] !== $process['method']) { + if (isset($progressFile['runners']['running']) && + $progressFile['runners']['running']['method'] !== $process['method']) { if ($process['callResult'] === true) { $processCallResult = 'Done'; } else if ($process['callResult'] === false) { From 818e37c33a6a9b2d1bdeb9888657eef6d4689a1e Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Sat, 1 Mar 2025 21:20:30 +1100 Subject: [PATCH 20/29] fix minor bug #649 --- .../Providers/BasepackagesServiceProvider/Packages/Progress.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php index cfc9fae98..39567a329 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php @@ -370,7 +370,7 @@ protected function sendNotification($callResult, $counters = null) } $processCallResult = 'Running...'; - if (isset($progressFile['runners']['running']) && + if (isset($progressFile['runners']['running']['method']) && $progressFile['runners']['running']['method'] !== $process['method']) { if ($process['callResult'] === true) { $processCallResult = 'Done'; From f5fcc550fa4251f6572899275ecf645f513e2c5a Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Sun, 2 Mar 2025 14:59:11 +1100 Subject: [PATCH 21/29] update issue #649 --- .../Packages/Progress.php | 73 +++++++++++-------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php index 39567a329..bb6733793 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php @@ -152,6 +152,8 @@ public function getProgress($session = null, $returnArray = false) $errors = $this->helper->encode($this->errors); } + $details = $this->getProgressDetails($progressFile); + $progress = [ 'progressFile' => $this->progressFileName, @@ -163,7 +165,8 @@ public function getProgress($session = null, $returnArray = false) 'percentComplete' => $this->getPercentComplete($progressFile), 'runners' => $progressFile['runners'] ?? false, 'callResult' => $callResult, - 'errors' => $errors + 'errors' => $errors, + 'details' => $details ]; if ($returnArray) { return $progress; @@ -360,35 +363,7 @@ protected function sendNotification($callResult, $counters = null) $errors = $this->helper->encode($this->errors); } - $details = false; - if (isset($progressFile['allProcesses']) && is_array($progressFile['allProcesses'])) { - $details = []; - - foreach ($progressFile['allProcesses'] as $processKey => $process) { - if (!array_key_exists('callResult', $process)) { - continue; - } - - $processCallResult = 'Running...'; - if (isset($progressFile['runners']['running']['method']) && - $progressFile['runners']['running']['method'] !== $process['method']) { - if ($process['callResult'] === true) { - $processCallResult = 'Done'; - } else if ($process['callResult'] === false) { - $processCallResult = 'Error'; - } - if (count($this->errors) > 0) { - $processCallResult = 'Error'; - } - } - - $details[$process['text']] = $processCallResult; - } - - if (count($details) === 0) { - $details = false; - } - } + $details = $this->getProgressDetails($progressFile); $this->wss->send( [ @@ -418,6 +393,44 @@ protected function sendNotification($callResult, $counters = null) } } + protected function getProgressDetails($progressFile) + { + $details = false; + + if (isset($progressFile['allProcesses']) && is_array($progressFile['allProcesses'])) { + $details = []; + + foreach ($progressFile['allProcesses'] as $process) { + if (!array_key_exists('callResult', $process)) { + continue; + } + + $processCallResult = 'Running...'; + if (isset($progressFile['runners']['running']['method']) && + $progressFile['runners']['running']['method'] !== $process['method']) { + if ($process['callResult'] === true) { + $processCallResult = 'Done'; + } else if ($process['callResult'] === false) { + $processCallResult = 'Error'; + } + if (count($this->errors) > 0) { + $processCallResult = 'Error'; + } + } else if ($progressFile['completed'] === $progressFile['total']) { + $processCallResult = 'Done'; + } + + $details[$process['text']] = $processCallResult; + } + + if (count($details) === 0) { + $details = false; + } + } + + return $details; + } + protected function getPercentComplete($progressFile, $counters = true) { $percentComplete = (float) number_format(($progressFile['completed'] * 100) / $progressFile['total']); From b47ee0785da3a604738bf17a7321d6590e871665 Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Tue, 4 Mar 2025 03:30:57 +1100 Subject: [PATCH 22/29] Initial commit issue #650 --- .../Ff/Classes/DocumentFinder.php | 116 +++++++++--------- 1 file changed, 56 insertions(+), 60 deletions(-) diff --git a/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php b/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php index 345d63d3c..4ca1e0f4d 100644 --- a/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php +++ b/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php @@ -55,7 +55,6 @@ public function findDocuments(bool $getOneDocument, bool $reduceAndJoinPossible) $skip = $queryBuilderProperties["skip"]; $limit = $queryBuilderProperties["limit"]; $fieldsToExclude = $queryBuilderProperties["fieldsToExclude"]; - unset($queryBuilderProperties); if ($this->storeConfiguration['indexing']) { @@ -139,87 +138,84 @@ public function findDocuments(bool $getOneDocument, bool $reduceAndJoinPossible) } if (count($found) === 0) { - if ($handle = opendir($dataPath)) { - while (false !== ($entry = readdir($handle))) { - if ($entry === "." || $entry === "..") { - continue; - } + $scanDir = scandir($dataPath); + $files = []; + array_walk($scanDir, function($file) use (&$files) { + if ($file !== '..' && $file !== '.') { + array_push($files, (int) str_replace('.json', '', $file)); + } + }); + sort($files); + if ($limit && count($conditions) === 0 && count($files) > 0) { + self::skip($files, $skip); + self::limit($files, $limit); + } - $documentPath = $dataPath . $entry; + foreach ($files as $entry) { + $documentPath = $dataPath . $entry . '.json'; - try { - $data = IoHelper::getFileContent($documentPath); - } catch (Exception $exception) { - continue; - } + try { + $data = IoHelper::getFileContent($documentPath); + } catch (Exception $exception) { + continue; + } - $data = @json_decode($data, true); + $data = @json_decode($data, true); - if (!is_array($data)) { - continue; - } + if (!is_array($data)) { + continue; + } - $storePassed = true; + $storePassed = true; - if (!empty($conditions)) { - $storePassed = ConditionsHandler::handleWhereConditions($conditions, $data); - } + if (!empty($conditions)) { + $storePassed = ConditionsHandler::handleWhereConditions($conditions, $data); + } - if ($storePassed === true && count($distinctFields) > 0) { - $storePassed = ConditionsHandler::handleDistinct($found, $data, $distinctFields); - } + if ($storePassed === true && count($distinctFields) > 0) { + $storePassed = ConditionsHandler::handleDistinct($found, $data, $distinctFields); + } - if ($storePassed === true) { - $found[] = $data; + if ($storePassed === true) { + $found[] = $data; - if ($getOneDocument === true) { - break; - } + if ($getOneDocument === true) { + break; } } - - closedir($handle); } } - if ($reduceAndJoinPossible === true) { - DocumentReducer::joinData($found, $listOfJoins); - } - if (count($found) > 0) { + if ($reduceAndJoinPossible === true) { + DocumentReducer::joinData($found, $listOfJoins); + } + self::performSearch($found, $search, $searchOptions); - } - if ($reduceAndJoinPossible === true && !empty($groupBy) && count($found) > 0) { - DocumentReducer::handleGroupBy( - $found, - $groupBy, - $fieldsToSelect - ); - } + if ($reduceAndJoinPossible === true && !empty($groupBy) && count($found) > 0) { + DocumentReducer::handleGroupBy( + $found, + $groupBy, + $fieldsToSelect + ); + } - if ($reduceAndJoinPossible === true && empty($groupBy) && count($found) > 0) { - DocumentReducer::selectFields($found, $primaryKey, $fieldsToSelect); - } + if ($reduceAndJoinPossible === true && empty($groupBy) && count($found) > 0) { + DocumentReducer::selectFields($found, $primaryKey, $fieldsToSelect); + } - if (count($found) > 0) { self::handleHaving($found, $havingConditions); - } - - if ($reduceAndJoinPossible === true && count($found) > 0) { - DocumentReducer::excludeFields($found, $fieldsToExclude); - } - if (count($found) > 0) { - self::sort($found, $orderBy); - } - - if (count($found) > 0) { - self::skip($found, $skip); - } + if ($reduceAndJoinPossible === true && count($found) > 0) { + DocumentReducer::excludeFields($found, $fieldsToExclude); + } - if (count($found) > 0) { - self::limit($found, $limit); + if (count($conditions) > 0) { + self::sort($found, $orderBy); + self::skip($found, $skip); + self::limit($found, $limit); + } } return $found; From bbac370a10857327870643be2ea62ffcf69de3f6 Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Tue, 4 Mar 2025 04:21:34 +1100 Subject: [PATCH 23/29] update issue #649 --- system/Base/BasePackage.php | 12 ++++++++++++ .../Packages/Progress.php | 8 ++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/system/Base/BasePackage.php b/system/Base/BasePackage.php index 350c49883..7bc21be64 100644 --- a/system/Base/BasePackage.php +++ b/system/Base/BasePackage.php @@ -2271,6 +2271,18 @@ protected function addToLog($code, $message, $debug = true) //Only if debug is enabled. } + public function getDbCount($recount = false) + { + if ($this->config->databasetype === 'db') { + return $this->modelToUse::count(); + } else { + if (!$this->ffStore) { + $this->ffStore = $this->ff->store($this->ffStoreToUse); + } + + return $this->ffStore->count($recount); + } + } // protected function addRefId($data) // { // if (!isset($data['ref_id'])) { diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php index bb6733793..93f0f8b9d 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php @@ -201,9 +201,9 @@ public function updateProgress($method, $callResult = null, $deleteFile = true, if (isset($progressFile['processes']) && count($progressFile['processes']) > 0) { if (isset($progressFile['allProcesses'][0]) && $progressFile['allProcesses'][0]['method'] === $method && - !$callResult && - !$child && - !$counters && + is_null($callResult) && + is_null($child) && + is_null($counters) && $progressFile['completed'] === 0 && $progressFile['pid'] > 0 ) { @@ -700,7 +700,7 @@ protected function writeProgressFile( } } - public function deleteProgressFile($reset = false) + public function deleteProgressFile(bool $reset = false) { if (!$reset) { $this->checkProcessIsRunning(); From 72abae6e8febd0ec9de3ffaba7bdc5212cf3af11 Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Tue, 4 Mar 2025 13:46:56 +1100 Subject: [PATCH 24/29] fix issue #651 --- .../Providers/DatabaseServiceProvider/Ff/Store.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php b/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php index 8a02c3425..75144f553 100644 --- a/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php +++ b/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php @@ -1199,8 +1199,10 @@ protected function setConfigurationAndSchema(array $configuration = [], array $s $cacheLifetime = $configuration['cache_lifetime']; } - $configuration = IoHelper::getFileContent($this->storePath . 'config.json'); - $configuration = json_decode($configuration, true); + $oldConfiguration = IoHelper::getFileContent($this->storePath . 'config.json'); + $oldConfiguration = json_decode($oldConfiguration, true); + + $configuration = array_replace($oldConfiguration, $configuration); if (isset($autoCache)) { $configuration['auto_cache'] = $autoCache; @@ -1213,8 +1215,10 @@ protected function setConfigurationAndSchema(array $configuration = [], array $s if (count($schema) === 0) { if (file_exists($this->storePath . 'schema.json')) { - $schema = IoHelper::getFileContent($this->storePath . 'schema.json'); - $schema = json_decode($schema, true); + $oldSchema = IoHelper::getFileContent($this->storePath . 'schema.json'); + $oldSchema = json_decode($oldSchema, true); + + $schema = array_replace($oldSchema, $schema); } if (count($schema) > 0) { From 37f52fa3d2f4936c9f323b76db6b3ad81530e820 Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Wed, 5 Mar 2025 00:21:05 +1100 Subject: [PATCH 25/29] fix issue #652. Changed method to include .fileHashes file for views directory. Fixed incorrect updated_version being populated if the versions are same. --- .../Devtools/Modules/DevtoolsModules.php | 166 +++++++++--------- .../ModulesServiceProvider/Manager.php | 28 ++- 2 files changed, 105 insertions(+), 89 deletions(-) diff --git a/apps/Core/Packages/Devtools/Modules/DevtoolsModules.php b/apps/Core/Packages/Devtools/Modules/DevtoolsModules.php index 8cbc5dfd8..f71fc4d5e 100644 --- a/apps/Core/Packages/Devtools/Modules/DevtoolsModules.php +++ b/apps/Core/Packages/Devtools/Modules/DevtoolsModules.php @@ -558,48 +558,55 @@ public function reCalculateFilesHash($module, $remove = false, $viaGenerateRelea $filesHash['module_id'] = $module['id']; } - $moduleLocation = $this->getModuleFilesLocation($module); + $moduleLocationFiles['files'] = []; - $moduleLocationFiles = $this->basepackages->utils->scanDir($moduleLocation, true, ['.git/', '.fileHashes']); - - //In case you have .gitignore file, it can get complicated to sort which files to hash. - //So, the files you want to hash, just add them in .fileHashes in the same folder as .gitignore - //The file should have a list of all files to hash (1 filename per line) - //Example: - //.gitignore - // README.md - // view.html - // view.json - $filesToHash = []; - if ($this->localContent->fileExists($moduleLocation . '.fileHashes')) { - $filesToHash = $this->localContent->read($moduleLocation . '.fileHashes'); - - if ($filesToHash && $filesToHash !== '') { - $filesToHash = str_replace("'", '', $filesToHash); - $filesToHash = explode(PHP_EOL, $filesToHash); - } + if ($module['module_type'] === 'views' && $module['is_subview'] == false) { + $moduleLocations = [$this->getModuleFilesLocation($module), $this->getModuleFilesLocation($module, true)]; + } else { + $moduleLocations = [$this->getModuleFilesLocation($module)]; } - if ($module['module_type'] === 'views' && $module['is_subview'] == false) { - $moduleLocation = $this->getModuleFilesLocation($module, true); + foreach ($moduleLocations as $moduleLocation) { + if ($this->localContent->fileExists($moduleLocation . '.fileHashes')) { + $filesToHash = $this->localContent->read($moduleLocation . '.fileHashes'); - $viewFiles = $this->basepackages->utils->scanDir($moduleLocation, true, ['.git/', '.fileHashes']); + if ($filesToHash && $filesToHash !== '') { + $filesToHash = str_replace("'", '', $filesToHash); + $filesToHash = explode(PHP_EOL, $filesToHash); - if ($viewFiles && count($viewFiles['files']) > 0) { - $moduleLocationFiles['files'] = array_merge($moduleLocationFiles['files'], $viewFiles['files']); - } + if (count($filesToHash) > 0) { + $hashFiles = []; - if ($this->localContent->fileExists($moduleLocation . '.fileHashes')) { - $viewFilesToHash = $this->localContent->read($moduleLocation . '.fileHashes'); + foreach ($filesToHash as $fileToHash) { + if (str_ends_with($fileToHash, '/')) { + $fileToHashDirList = $this->basepackages->utils->scanDir($moduleLocation . $fileToHash, true); - if ($viewFilesToHash && $viewFilesToHash !== '') { - $viewFilesToHash = str_replace("'", '', $viewFilesToHash); - $viewFilesToHash = explode(PHP_EOL, $viewFilesToHash); + if ($fileToHashDirList && count($fileToHashDirList['files']) > 0) { + $hashFiles = array_merge($hashFiles, $fileToHashDirList['files']); + } + } else { + array_push($hashFiles, $moduleLocation . $fileToHash); + } + } - if (count($viewFilesToHash) > 0) { - $filesToHash = array_merge($filesToHash, $viewFilesToHash); + if (count($hashFiles) > 0) { + $moduleLocationFiles['files'] = array_merge($moduleLocationFiles['files'], $hashFiles); + } } } + } else { + $files = $this->basepackages->utils->scanDir( + $moduleLocation, + true, + [ + '.git/', + 'linter-backup/' + ] + ); + + if ($files && count($files['files']) > 0) { + $moduleLocationFiles['files'] = array_merge($moduleLocationFiles['files'], $files['files']); + } } } @@ -611,12 +618,6 @@ public function reCalculateFilesHash($module, $remove = false, $viaGenerateRelea $file = str_replace($moduleLocation, '', $file); - if (count($filesToHash) > 0) { - if (!in_array($file, $filesToHash)) { - continue; - } - } - $hash = hash_file('md5', base_path($filePath)); $filesHash['files_hash'][$file] = $hash; @@ -641,15 +642,17 @@ public function validateFilesHash($module) $module['repoExists'] = false; $module['latestRelease'] = false; if ($this->localContent->directoryExists($moduleLocation . '.git')) { - if (!isset($module['repo_details']) || - !isset($module['repo_details']['latestRelease']) + if ((!isset($module['repo_details']) || + !isset($module['repo_details']['latestRelease'])) || + (isset($module['repo_details']['latestRelease']['name']) && + $module['repo_details']['latestRelease']['name'] !== $module['version']) ) { $module = $this->modules->manager->getModuleInfo( [ 'module_type' => $module['module_type'], 'module_id' => $module['id'], 'sync' => true, - 'getLatestRelease' => (!isset($module['repo_details']['latestRelease'])) ? true : false + 'getLatestRelease' => true ] ); } @@ -672,61 +675,64 @@ public function validateFilesHash($module) return $module; } - $moduleFiles = $this->basepackages->utils->scanDir($moduleLocation, true, ['.git/', '.fileHashes']); - - //In case you have .gitignore file, it can get complicated to sort which files to hash. - //So, the files you want to hash, just add them in .fileHashes in the same folder as .gitignore - //The file should have a list of all files to hash (1 filename per line) - //Example: - //.gitignore - // README.md - // view.html - // view.json - $filesToHash = []; - if ($this->localContent->fileExists($moduleLocation . '.fileHashes')) { - $filesToHash = $this->localContent->read($moduleLocation . '.fileHashes'); + $moduleLocationFiles['files'] = []; - if ($filesToHash && $filesToHash !== '') { - $filesToHash = str_replace("'", '', $filesToHash); - $filesToHash = explode(PHP_EOL, $filesToHash); - } + if ($module['module_type'] === 'views' && $module['is_subview'] == false) { + $moduleLocations = [$this->getModuleFilesLocation($module), $this->getModuleFilesLocation($module, true)]; + } else { + $moduleLocations = [$this->getModuleFilesLocation($module)]; } - if ($module['module_type'] === 'views' && $module['is_subview'] == false) { - $moduleLocation = $this->getModuleFilesLocation($module, true); + foreach ($moduleLocations as $moduleLocation) { + if ($this->localContent->fileExists($moduleLocation . '.fileHashes')) { + $filesToHash = $this->localContent->read($moduleLocation . '.fileHashes'); - $viewFiles = $this->basepackages->utils->scanDir($moduleLocation, true, ['.git/', '.fileHashes']); + if ($filesToHash && $filesToHash !== '') { + $filesToHash = str_replace("'", '', $filesToHash); + $filesToHash = explode(PHP_EOL, $filesToHash); - if ($viewFiles && count($viewFiles['files']) > 0) { - $moduleFiles['files'] = array_merge($moduleFiles['files'], $viewFiles['files']); - } + if (count($filesToHash) > 0) { + $hashFiles = []; - if ($this->localContent->fileExists($moduleLocation . '.fileHashes')) { - $viewFilesToHash = $this->localContent->read($moduleLocation . '.fileHashes'); + foreach ($filesToHash as $fileToHash) { + if (str_ends_with($fileToHash, '/')) { + $fileToHashDirList = $this->basepackages->utils->scanDir($moduleLocation . $fileToHash, true); - if ($viewFilesToHash && $viewFilesToHash !== '') { - $viewFilesToHash = str_replace("'", '', $viewFilesToHash); - $viewFilesToHash = explode(PHP_EOL, $viewFilesToHash); + if ($fileToHashDirList && count($fileToHashDirList['files']) > 0) { + $hashFiles = array_merge($hashFiles, $fileToHashDirList['files']); + } + } else { + array_push($hashFiles, $moduleLocation . $fileToHash); + } + } - if (count($viewFilesToHash) > 0) { - $filesToHash = array_merge($filesToHash, $viewFilesToHash); + if (count($hashFiles) > 0) { + $moduleLocationFiles['files'] = array_merge($moduleLocationFiles['files'], $hashFiles); + } } } + } else { + $files = $this->basepackages->utils->scanDir( + $moduleLocation, + true, + [ + '.git/', + 'linter-backup/' + ] + ); + + if ($files && count($files['files']) > 0) { + $moduleLocationFiles['files'] = array_merge($moduleLocationFiles['files'], $files['files']); + } } } - if ($moduleFiles && count($moduleFiles['files']) > 0) { - foreach ($moduleFiles['files'] as $file) { + if ($moduleLocationFiles && count($moduleLocationFiles['files']) > 0) { + foreach ($moduleLocationFiles['files'] as $file) { $filePath = $file; $file = str_replace($moduleLocation, '', $file); - if (count($filesToHash) > 0) { - if (!in_array($file, $filesToHash)) { - continue; - } - } - $hash = hash_file('md5', base_path($filePath)); if (!isset($filesHash['files_hash'][$file]) || @@ -735,7 +741,7 @@ public function validateFilesHash($module) ) { $module['isModified'] = true; - return $module; + break; } } } diff --git a/system/Base/Providers/ModulesServiceProvider/Manager.php b/system/Base/Providers/ModulesServiceProvider/Manager.php index 20681120a..d9683f708 100644 --- a/system/Base/Providers/ModulesServiceProvider/Manager.php +++ b/system/Base/Providers/ModulesServiceProvider/Manager.php @@ -255,11 +255,16 @@ public function updateModuleRepoDetails($module, $data = null) } else { $module['dependencies'] = $module['repo_details']['latestRelease']['moduleJson']['dependencies']; if ($module['installed'] == '1') { - $module['update_available'] = '1'; - $module['update_version'] = $module['repo_details']['latestRelease']['name']; + if ($module['repo_details']['latestRelease']['name'] !== $module['version']) { + $module['update_available'] = '1'; + $module['update_version'] = $module['repo_details']['latestRelease']['name']; + } else { + $module['update_available'] = null; + $module['update_version'] = null; + } } else { $module['version'] = $module['repo_details']['latestRelease']['name']; - $module['update_available'] = '0'; + $module['update_available'] = null; $module['update_version'] = null; } } @@ -299,16 +304,21 @@ public function updateModuleRepoDetails($module, $data = null) if ($latestRelease) { $module['repo_details']['latestRelease'] = $latestRelease; if ($module['installed'] == '1') { - $module['update_available'] = '1'; - $module['update_version'] = $module['repo_details']['latestRelease']['name']; + if ($module['repo_details']['latestRelease']['name'] !== $module['version']) { + $module['update_available'] = '1'; + $module['update_version'] = $module['repo_details']['latestRelease']['name']; + } else { + $module['update_available'] = null; + $module['update_version'] = null; + } } else { - $module['update_available'] = '0'; + $module['update_available'] = null; + $module['update_version'] = null; $module['version'] = $module['repo_details']['latestRelease']['name']; - $module['update_version'] = '-'; } } else { - $module['update_available'] = '0'; - $module['update_version'] = '-'; + $module['update_available'] = null; + $module['update_version'] = null; } } else { $module['repo_details'] = false; From fb8f36da6fce12fa4b5998cbc66cbd6b73a87b4d Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Wed, 5 Mar 2025 00:22:43 +1100 Subject: [PATCH 26/29] fix issue #653 --- .../js/footer/core/Baz/BazContentSectionWithListing.js | 9 +++++---- public/core/default/js/footer/jsFooterCore.js | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/public/core/default/js/footer/core/Baz/BazContentSectionWithListing.js b/public/core/default/js/footer/core/Baz/BazContentSectionWithListing.js index 2ede05e53..bead534ca 100644 --- a/public/core/default/js/footer/core/Baz/BazContentSectionWithListing.js +++ b/public/core/default/js/footer/core/Baz/BazContentSectionWithListing.js @@ -1266,10 +1266,11 @@ // Control Column if (datatableOptions.rowControls) { listColumns[thisOptions.listOptions.tableName].push({ - data : '__control', - title : 'ACTIONS', - orderable : false, - className : classes + data : '__control', + title : 'ACTIONS', + orderable : false, + className : classes, + responsivePriority : -1 }); } diff --git a/public/core/default/js/footer/jsFooterCore.js b/public/core/default/js/footer/jsFooterCore.js index 277daf822..67a732a4b 100644 --- a/public/core/default/js/footer/jsFooterCore.js +++ b/public/core/default/js/footer/jsFooterCore.js @@ -6851,10 +6851,11 @@ Object.defineProperty(exports, '__esModule', { value: true }); // Control Column if (datatableOptions.rowControls) { listColumns[thisOptions.listOptions.tableName].push({ - data : '__control', - title : 'ACTIONS', - orderable : false, - className : classes + data : '__control', + title : 'ACTIONS', + orderable : false, + className : classes, + responsivePriority : -1 }); } From 452fe9551ca94b0eec7d189b8201e3f4b8bf14d2 Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Thu, 6 Mar 2025 14:23:36 +1100 Subject: [PATCH 27/29] update issue #650. Rewrite the FF method to get relation data increasing the performance 3x. --- system/Base/BasePackage.php | 13 +- .../Model/ServiceProviderApiScopes.php | 2 +- .../Model/Users/BasepackagesUsersAccounts.php | 11 +- .../Packages/Users/Accounts.php | 7 +- .../Providers/DatabaseServiceProvider/Ff.php | 10 +- .../DatabaseServiceProvider/Ff/Store.php | 289 ++++++++++-------- .../ModulesServiceProvider/DbInstaller.php | 5 + 7 files changed, 200 insertions(+), 137 deletions(-) diff --git a/system/Base/BasePackage.php b/system/Base/BasePackage.php index 7bc21be64..9b276cba3 100644 --- a/system/Base/BasePackage.php +++ b/system/Base/BasePackage.php @@ -383,6 +383,10 @@ public function getByParams(array $params, bool $resetCache = false, bool $enabl } } + if (count($relationColumns) > 0) { + $this->ffRelations = true; + } + $order = null; $limit = null; $offset = null; @@ -408,13 +412,16 @@ public function getByParams(array $params, bool $resetCache = false, bool $enabl $offset = $params['offset']; } if (isset($params['conditions']) && is_array($params['conditions']) && count($params['conditions']) > 0) { - $this->ffData = $this->ffStore->findBy($params['conditions'], $order, $limit, $offset); + $this->ffData = + $this->ffStore->findBy( + $params['conditions'], $order, $limit, $offset, $this->ffRelations, $this->ffRelationsConditions + ); } else if (isset($params['conditions']) && ((is_array($params['conditions']) && count($params['conditions']) === 0) || $params['conditions'] === '' ) ) { - $this->ffData = $this->ffStore->findAll($order, $limit, $offset); + $this->ffData = $this->ffStore->findAll($order, $limit, $offset, $this->ffRelations, $this->ffRelationsConditions); } else { throw new \Exception('getByParams needs parameter conditions (array) to be set.'); } @@ -461,7 +468,7 @@ protected function getRelationColumnsData($relationColumns, $data) $relationRowData = $model->{$alias}->toArray(); } } else { - $relationRowData = $this->ffStore->findById($row['id'], true); + $relationRowData = $row; } foreach ($relationColumns as $relationColumnKey => $relationColumn) { diff --git a/system/Base/Providers/ApiServiceProvider/Model/ServiceProviderApiScopes.php b/system/Base/Providers/ApiServiceProvider/Model/ServiceProviderApiScopes.php index 4b500b195..53e3922f1 100644 --- a/system/Base/Providers/ApiServiceProvider/Model/ServiceProviderApiScopes.php +++ b/system/Base/Providers/ApiServiceProvider/Model/ServiceProviderApiScopes.php @@ -27,7 +27,7 @@ public function getIdentifier() public function initialize() { - $this->modelRelations['api']['relationObj'] = $this->hasMany( + $this->modelRelations['api']['relationObj'] = $this->belongsTo( 'id', ServiceProviderApi::class, 'scope_id', diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Users/BasepackagesUsersAccounts.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Users/BasepackagesUsersAccounts.php index 377acabdd..f44e20fac 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Users/BasepackagesUsersAccounts.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Users/BasepackagesUsersAccounts.php @@ -70,7 +70,13 @@ public function initialize() BasepackagesUsersAccountsIdentifiers::class, ['account_id', 'session_id'], [ - 'alias' => 'identifier' + 'alias' => 'identifier', + 'params' => [ + 'conditions' => 'session_id = :session_id:', + 'bind' => [ + 'session_id' => $this->getDi()->getShared('session')->getId() + ] + ] ] ); @@ -124,9 +130,8 @@ public function initialize() [ 'alias' => 'api_clients', 'params' => [ - 'conditions' => 'account_id = :account_id: AND revoked = :revoked:', + 'conditions' => 'revoked = :revoked:', 'bind' => [ - 'account_id' => $account_id, 'revoked' => '0' ] ] diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Users/Accounts.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Users/Accounts.php index db6d36cd3..915c9c48f 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Users/Accounts.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Users/Accounts.php @@ -26,7 +26,12 @@ public function getAccountById(int $id) { $this->setFFRelations(true); - $this->setFFRelationsConditions(['api_clients' => [['account_id', '=', $id], ['revoked', '=', false]]]); + $this->setFFRelationsConditions( + [ + 'api_clients' => [['revoked', '=', false]], + 'identifier' => [['session_id', '=', $this->session->getId()]] + ] + ); $this->getFirst('id', $id); diff --git a/system/Base/Providers/DatabaseServiceProvider/Ff.php b/system/Base/Providers/DatabaseServiceProvider/Ff.php index d15d563f8..b459a09ec 100644 --- a/system/Base/Providers/DatabaseServiceProvider/Ff.php +++ b/system/Base/Providers/DatabaseServiceProvider/Ff.php @@ -146,6 +146,7 @@ public function generateSchema($tableName, $tableClass, $tableModel) $schema['type'] = 'object'; $schema['properties'] = []; $schema['required'] = []; + $schema['relations'] = []; foreach ($tableClass->columns()['columns'] as $column) { $schema['properties'][$column->getName()] = []; @@ -216,11 +217,14 @@ public function generateSchema($tableName, $tableClass, $tableModel) if ($relation['relationObj']->getReferencedModel() && is_string($relation['relationObj']->getReferencedModel()) ) { + $references[$relationKey]['alias'] = $relationKey; if (isset($relation['relationObj']->getOptions()['alias'])) { $references[$relationKey]['alias'] = $relation['relationObj']->getOptions()['alias']; } - switch ($relation['relationObj']->getType()) { + case '0': + $references[$relationKey]['type'] = 'belongsTo'; + break; case '1': $references[$relationKey]['type'] = 'hasOne'; break; @@ -274,7 +278,7 @@ public function generateSchema($tableName, $tableClass, $tableModel) } if (isset($relation['relationObj']->getOptions()['params'])) { - $references[$relationKey]['params'] = 'hasParams'; + $references[$relationKey]['hasParams'] = true; } } } @@ -282,6 +286,8 @@ public function generateSchema($tableName, $tableClass, $tableModel) } if (isset($references) && is_array($references)) { + $schema['relations'] = $references; + foreach ($references as $key => $reference) { if (isset($reference['alias'])) { $schema['properties'][$reference['alias']] = []; diff --git a/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php b/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php index 75144f553..c589c0648 100644 --- a/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php +++ b/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php @@ -53,6 +53,8 @@ class Store protected $storeSchema = []; + protected $relationStores = []; + public $data; protected $ff; @@ -83,12 +85,14 @@ public function __construct(string $storeName, string $databasePath, $ff, array $this->indexesPath = $this->databasePath . $this->storeName . 'indexes/'; - $this->setConfigurationAndSchema($configuration, $schema); - $this->createDatabasePath(); if (count($schema) > 0) { + $this->setConfigurationAndSchema($configuration, $schema, true); + $this->createStore($configuration, $schema); + } else { + $this->setConfigurationAndSchema($configuration, $schema); } } @@ -289,7 +293,7 @@ public function getStoreName(): string return $this->storeName; } - public function findAll(array $orderBy = null, int $limit = null, int $offset = null): array + public function findAll(array $orderBy = null, int $limit = null, int $offset = null, $getRelations = false, $relationsConditions = false): array { try { $qb = $this->createQueryBuilder(); @@ -305,8 +309,17 @@ public function findAll(array $orderBy = null, int $limit = null, int $offset = if (!is_null($offset)) { $qb->skip($offset); } + $dataArr = $qb->getQuery()->fetch(); + + if ($dataArr && count($dataArr) > 0) { + if ($getRelations) { + foreach ($dataArr as &$data) { + $data = $this->getRelations($data, $relationsConditions); + } + } + } - $this->data = $qb->getQuery()->fetch(); + $this->data = $dataArr; } catch (\Exception $e) { throw $e; } @@ -335,7 +348,7 @@ public function findById($id, $getRelations = false, $relationsConditions = fals return $data; } - public function findBy(array $criteria, array $orderBy = null, int $limit = null, int $offset = null): array + public function findBy(array $criteria, array $orderBy = null, int $limit = null, int $offset = null, $getRelations = false, $relationsConditions = false): array { try { $qb = $this->createQueryBuilder(); @@ -352,7 +365,17 @@ public function findBy(array $criteria, array $orderBy = null, int $limit = null $qb->skip($offset); } - $this->data = $qb->getQuery()->fetch(); + $dataArr = $qb->getQuery()->fetch(); + + if ($dataArr && count($dataArr) > 0) { + if ($getRelations) { + foreach ($dataArr as &$data) { + $data = $this->getRelations($data, $relationsConditions); + } + } + } + + $this->data = $dataArr; } catch (\Exception $e) { throw $e; } @@ -979,137 +1002,132 @@ public function getRelations($data, $relationsConditions = false) $schema = json_decode($this->storeSchema, true); } - if (isset($schema['properties']) && count($schema['properties']) > 0) { - foreach ($schema['properties'] as $propertyKey => $property) { - if (!is_array($property['type'])) { - continue; - } + if (!isset($schema['relations']) || + isset($schema['relations']) && count($schema['relations']) === 0 + ) { + return true; + } - if (in_array('array', $property['type']) && isset($property['relation'])) { - $relation = explode('|', $property['relation']); + foreach ($schema['relations'] as $relationKey => $relation) { + if ($relation['type'] === 'belongsTo') {//We dont want to get relations if it belongs to. This will cause infinite loop! + continue; + } - if (count($relation) > 0) { - if ($relation[1] === 'hasOne' || $relation[1] === 'hasMany') { + if ((isset($relation['hasParams']) && + $relationsConditions && + count($relationsConditions) === 0 + ) || + (isset($relation['hasParams']) && + $relationsConditions && + count($relationsConditions) > 0 && + !isset($relationsConditions[$relation['alias']]) + ) + ) { + throw new InvalidArgumentException('Model has params(conditions) set for ' . $relation['type'] . '. Please set ffRelationsConditions. Please refer to model file.'); + } - if ((in_array('hasParams', $relation) && $relationsConditions && count($relationsConditions) === 0) || - (in_array('hasParams', $relation) && $relationsConditions && count($relationsConditions) > 0 && !isset($relationsConditions[$relation[0]])) - ) { - throw new InvalidArgumentException('Model has params(conditions) set for ' . $relation[0] . '. Please set ffRelationsConditions. Please refer to model file.'); - } + if ($relation['type'] === 'hasOne' || $relation['type'] === 'hasMany') { + if (isset($relation['fields']) && + count($relation['fields']) > 0 && + count($relation['fields']) % 2 == 0 + ) { + $fieldsArr = $this->ff->helper->chunk($relation['fields'], 2); - if (isset($relation[4])) { - if (isset($relationsConditions[$relation[0]])) { - try { - $store = new Store($relation[2], $this->databasePath, $this->ff); + $criteria = []; - $storeData = $store->findBy($relationsConditions[$relation[0]]); + if (count($fieldsArr) === 1) { + foreach ($fieldsArr as $fieldArr) { + array_push($criteria, [$fieldArr[1], '=', $data[$fieldArr[0]]]); + } + } else { + foreach ($fieldsArr as $fieldArrKey => $fieldArr) { + array_push($criteria, [$fieldArr[$fieldArrKey], '=', $data[$fieldArr[$fieldArrKey]]]); + } + } - if ($storeData && count($storeData) > 0) { - if ($relation[1] === 'hasOne') { - $data[$relation[0]] = $storeData[0]; - } else if ($relation[1] === 'hasMany') { - $data[$relation[0]] = $storeData; - } - } else { - $data[$relation[0]] = null; - } - } catch (\Exception $e) { - continue; - } - } else { - $fields = explode(':', $relation[4]); + if (isset($relationsConditions[$relation['alias']])) {//Relation with condition + $criteria = array_merge($criteria, $relationsConditions[$relation['alias']]); + } - if (count($fields) > 0 && count($fields) % 2 == 0) { - $fieldsArr = $this->ff->helper->chunk($fields, 2); - $criteria = []; + try { + $directRelationStoreData = $this->relationStores[$relation['table']]->findBy($criteria); - foreach ($fieldsArr as $fieldArr) { - array_push($criteria, [$fieldArr[1], '=', $data[$fieldArr[0]]]); - } + if ($directRelationStoreData && count($directRelationStoreData) > 0) { + if ($relation['type'] === 'hasOne') { + $data[$relation['alias']] = $directRelationStoreData[0]; + } else if ($relation['type'] === 'hasMany') { + $data[$relation['alias']] = $directRelationStoreData; + } + } else { + $data[$relation['alias']] = null; + } + } catch (\Exception $e) { + continue; + } + } + } else if ($relation['type'] === 'hasOneThrough' || $relation['type'] === 'hasManyThrough') { + if (isset($relation[0]['fields']) && + count($relation[0]['fields']) > 0 && + count($relation[0]['fields']) % 2 == 0 + ) { + $fieldsArr = $this->ff->helper->chunk($relation[0]['fields'], 2); - try { - $store = new Store($relation[2], $this->databasePath, $this->ff); + $criteria = []; - $storeData = $store->findBy($criteria); + if (count($fieldsArr) === 1) { + foreach ($fieldsArr as $fieldArr) { + array_push($criteria, [$fieldArr[1], '=', $data[$fieldArr[0]]]); + } + } else { + foreach ($fieldsArr as $fieldArrKey => $fieldArr) { + array_push($criteria, [$fieldArr[$fieldArrKey], '=', $data[$fieldArr[$fieldArrKey]]]); + } + } - if ($storeData && count($storeData) > 0) { - if ($relation[1] === 'hasOne') { - $data[$relation[0]] = $storeData[0]; - } else if ($relation[1] === 'hasMany') { - $data[$relation[0]] = $storeData; - } - } else { - $data[$relation[0]] = null; - } - } catch (\Exception $e) { - continue; - } - } - } - } - } else if ($relation[1] === 'hasOneThrough' || $relation[1] === 'hasManyThrough') { - if (isset($relation[2]) && isset($relation[3])) { - $relation[2] = explode('+', $relation[2]); - $relation[3] = explode('+', $relation[3]); - } + if (isset($relationsConditions[$relation['alias']])) {//Relation with condition + $criteria = array_merge($criteria, $relationsConditions[$relation['alias']]); + } - if (isset($relation[2][2]) && isset($relation[3][2])) { - $intermediateFields = explode(':', $relation[2][2]); - $fields = explode(':', $relation[3][2]); - } + try { + $intermediateStoreDataArr = $this->relationStores[$relation[0]['table']]->findBy($criteria); + } catch (\Exception $e) { + continue; + } - if ((count($intermediateFields) > 0 && count($intermediateFields) % 2 == 0) && - (count($fields) > 0 && count($fields) % 2 == 0) + if (!$intermediateStoreDataArr) { + continue; + } + + if (count($intermediateStoreDataArr) > 0) { + foreach ($intermediateStoreDataArr as $intermediateStoreData) { + if (isset($relation[1]['fields']) && + count($relation[1]['fields']) > 0 && + count($relation[1]['fields']) % 2 == 0 ) { - $fieldsArr = $this->ff->helper->chunk($intermediateFields, 2); - $criteria = []; + $fieldsArr = $this->ff->helper->chunk($relation[1]['fields'], 2); + $criteria = []; if (count($fieldsArr) === 1) { foreach ($fieldsArr as $fieldArr) { - array_push($criteria, [$fieldArr[1], '=', $data[$fieldArr[0]]]); + array_push($criteria, [$fieldArr[1], '=', $intermediateStoreData[$fieldArr[0]]]); } } else { foreach ($fieldsArr as $fieldArrKey => $fieldArr) { - array_push($criteria, [$fieldArr[$fieldArrKey], '=', $data[$fieldArr[$fieldArrKey]]]); + array_push($criteria, [$fieldArr[$fieldArrKey], '=', $intermediateStoreData[$fieldArr[$fieldArrKey]]]); } } try { - $store = new Store($relation[2][0], $this->databasePath, $this->ff); - - $storeData = $store->findOneBy($criteria); - - $fieldsArr = $this->ff->helper->chunk($fields, 2); - $criteria = []; + $finalRelationStoreData = $this->relationStores[$relation[1]['table']]->findBy($criteria); - if ($storeData && count($storeData) > 0) { - if (count($fieldsArr) === 1) { - foreach ($fieldsArr as $fieldArr) { - array_push($criteria, [$fieldArr[1], '=', $storeData[$fieldArr[0]]]); - } - } else { - foreach ($fieldsArr as $fieldArrKey => $fieldArr) { - array_push($criteria, [$fieldArr[$fieldArrKey], '=', $storeData[$fieldArr[$fieldArrKey]]]); - } - } - } - - if (count($criteria) > 0) { - $store = new Store($relation[3][0], $this->databasePath, $this->ff); - - $storeData = $store->findBy($criteria); - - if ($storeData && count($storeData) > 0) { - if ($relation[1] === 'hasOneThrough') { - $data[$relation[0]] = $storeData[0]; - } else if ($relation[1] === 'hasManyThrough') { - $data[$relation[0]] = $storeData; - } - } else { - $data[$relation[0]] = null; + if ($finalRelationStoreData && count($finalRelationStoreData) > 0) { + if ($relation['type'] === 'hasOneThrough') { + $data[$relation['alias']] = $finalRelationStoreData[0]; + } else if ($relation['type'] === 'hasManyThrough') { + $data[$relation['alias']] = $finalRelationStoreData; } } else { - $data[$relation[0]] = null; + $data[$relation['alias']] = null; } } catch (\Exception $e) { continue; @@ -1188,8 +1206,9 @@ protected function createDatabasePath() IoHelper::createFolder($this->databasePath, $this->folderPermissions); } - protected function setConfigurationAndSchema(array $configuration = [], array $schema = []) + protected function setConfigurationAndSchema(array $configuration = [], array $schema = [], $createStore = false) { + //Configuration if (count($configuration) === 0 || !array_key_exists('primary_key', $configuration)) { if (file_exists($this->storePath . 'config.json')) { if (isset($configuration['auto_cache'])) { @@ -1213,21 +1232,6 @@ protected function setConfigurationAndSchema(array $configuration = [], array $s } } - if (count($schema) === 0) { - if (file_exists($this->storePath . 'schema.json')) { - $oldSchema = IoHelper::getFileContent($this->storePath . 'schema.json'); - $oldSchema = json_decode($oldSchema, true); - - $schema = array_replace($oldSchema, $schema); - } - - if (count($schema) > 0) { - $this->storeSchema = json_encode($schema); - } - } else { - $this->storeSchema = json_encode($schema); - } - if (array_key_exists("min_index_chars", $configuration)) { if (!is_int($configuration["min_index_chars"])) { throw new InvalidConfigurationException("min_index_chars has to be an integer"); @@ -1256,7 +1260,6 @@ protected function setConfigurationAndSchema(array $configuration = [], array $s $this->minMultiWordsChars = $configuration["minMultiWordsChars"]; } - if (array_key_exists("indexes", $configuration)) { if (!is_array($configuration["indexes"])) { throw new InvalidConfigurationException("indexes has to be an array"); @@ -1364,6 +1367,38 @@ protected function setConfigurationAndSchema(array $configuration = [], array $s } $this->storeConfiguration(); + + //Schema + if (count($schema) === 0) { + if (file_exists($this->storePath . 'schema.json')) { + $oldSchema = IoHelper::getFileContent($this->storePath . 'schema.json'); + $oldSchema = json_decode($oldSchema, true); + $schema = array_replace($oldSchema, $schema); + } + } + + if (!$createStore && + isset($schema['relations']) && count($schema['relations']) > 0 + ) { + foreach ($schema['relations'] as $relation) { + if ($relation['type'] === 'belongsTo') { + continue; + } + + if (isset($relation['table'])) { + $this->relationStores[$relation['table']] = new Store($relation['table'], $this->databasePath, $this->ff); + } else if (isset($relation[0]) && isset($relation[1])) { + if (!isset($this->relationStores[$relation[0]['table']])) { + $this->relationStores[$relation[0]['table']] = new Store($relation[0]['table'], $this->databasePath, $this->ff); + } + if (!isset($this->relationStores[$relation[1]['table']])) { + $this->relationStores[$relation[1]['table']] = new Store($relation[1]['table'], $this->databasePath, $this->ff); + } + } + } + } + + $this->storeSchema = json_encode($schema); } protected function storeConfiguration() diff --git a/system/Base/Providers/ModulesServiceProvider/DbInstaller.php b/system/Base/Providers/ModulesServiceProvider/DbInstaller.php index 80b9ae7cf..1e71c31d4 100644 --- a/system/Base/Providers/ModulesServiceProvider/DbInstaller.php +++ b/system/Base/Providers/ModulesServiceProvider/DbInstaller.php @@ -131,6 +131,11 @@ public function installDb($databases) } if (count($storesToIndex) > 0) { + //Increase Exectimeout to 1 hour as this process takes time to index + if ((int) ini_get('max_execution_time') < 3600) { + set_time_limit(3600); + } + foreach ($storesToIndex as $storeToIndex) { ($this->ff->store($storeToIndex))->reIndexStore(); } From 705c98dd3c0361aaae0e366fd4d50f6edcdefa8b Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Thu, 6 Mar 2025 15:32:10 +1100 Subject: [PATCH 28/29] update issue #650. If index is searched, we do not need to search again. Also, added limit to index searches. --- .../Ff/Classes/DocumentFinder.php | 19 +++++++++++++++++-- .../DatabaseServiceProvider/Ff/Store.php | 12 ++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php b/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php index 4ca1e0f4d..f61d8b518 100644 --- a/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php +++ b/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php @@ -57,6 +57,8 @@ public function findDocuments(bool $getOneDocument, bool $reduceAndJoinPossible) $fieldsToExclude = $queryBuilderProperties["fieldsToExclude"]; unset($queryBuilderProperties); + $indexSearched = false; + if ($this->storeConfiguration['indexing']) { // This has to be rewritten to include multiple keywords using spaces // Example: If we want to search for wes aus, it should search for all entries with Wes keyword and that also includes Aus keyword. @@ -65,6 +67,8 @@ public function findDocuments(bool $getOneDocument, bool $reduceAndJoinPossible) if (isset($condition[0]) && in_array($condition[0][0], $this->storeConfiguration['indexes']) ) { + $indexSearched = true; + $keyword = trim($condition[0][2], '%');//This needs to extend if (strlen($keyword) < $this->storeConfiguration['min_index_chars']) { @@ -83,6 +87,11 @@ public function findDocuments(bool $getOneDocument, bool $reduceAndJoinPossible) $indexJson = json_decode($indexFile, true); if (count($indexJson) > 0) { + if ($limit && count($indexJson) > 0) { + self::skip($indexJson, $skip); + self::limit($indexJson, $limit); + } + if (isset($indexJson[strtolower($keyword)])) { if (count($indexJson[strtolower($keyword)]) === 1) { $indexIdData = $this->store->findById($indexJson[strtolower($keyword)][0]); @@ -101,6 +110,12 @@ public function findDocuments(bool $getOneDocument, bool $reduceAndJoinPossible) } } else { foreach ($indexJson as $key => $ids) { + if ($limit && count($ids) > $limit) { + + self::skip($ids, $skip); + self::limit($ids, $limit); + } + $key = strtolower($key); if (strtolower($condition[0][1]) === 'like') { @@ -137,7 +152,7 @@ public function findDocuments(bool $getOneDocument, bool $reduceAndJoinPossible) } } - if (count($found) === 0) { + if (!$indexSearched && count($found) === 0) { $scanDir = scandir($dataPath); $files = []; array_walk($scanDir, function($file) use (&$files) { @@ -211,7 +226,7 @@ public function findDocuments(bool $getOneDocument, bool $reduceAndJoinPossible) DocumentReducer::excludeFields($found, $fieldsToExclude); } - if (count($conditions) > 0) { + if (!$indexSearched && count($conditions) > 0) { self::sort($found, $orderBy); self::skip($found, $skip); self::limit($found, $limit); diff --git a/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php b/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php index c589c0648..9fcfe38a9 100644 --- a/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php +++ b/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php @@ -1804,4 +1804,16 @@ public function reIndexStore() return $this; } + + public function getIndexing() + { + return $this->indexing; + } + + public function setIndexing($indexing = true) + { + $this->indexing = $indexing; + + return $this->getIndexing(); + } } \ No newline at end of file From 2c63fb73375730309a0ef2ee260c602d46b2bd10 Mon Sep 17 00:00:00 2001 From: "Gurdeep Singh (Guru)" Date: Thu, 6 Mar 2025 15:36:46 +1100 Subject: [PATCH 29/29] update issue #650. removed writing of relationship information to fields. --- .../Providers/DatabaseServiceProvider/Ff.php | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/system/Base/Providers/DatabaseServiceProvider/Ff.php b/system/Base/Providers/DatabaseServiceProvider/Ff.php index b459a09ec..2de3aaf2f 100644 --- a/system/Base/Providers/DatabaseServiceProvider/Ff.php +++ b/system/Base/Providers/DatabaseServiceProvider/Ff.php @@ -287,32 +287,6 @@ public function generateSchema($tableName, $tableClass, $tableModel) if (isset($references) && is_array($references)) { $schema['relations'] = $references; - - foreach ($references as $key => $reference) { - if (isset($reference['alias'])) { - $schema['properties'][$reference['alias']] = []; - $schema['properties'][$reference['alias']]['type'] = ['null','array']; - - if (isset($reference[0]) && isset($reference[1])) { - if (isset($reference[0]['fields']) && count($reference[0]['fields']) > 0) { - $reference[0]['fields'] = join(':', $reference[0]['fields']); - } - if (isset($reference[1]['fields']) && count($reference[1]['fields']) > 0) { - $reference[1]['fields'] = join(':', $reference[1]['fields']); - } - - $reference[0] = join('+', $reference[0]); - $reference[1] = join('+', $reference[1]); - $schema['properties'][$reference['alias']]['relation'] = join('|', $reference); - } else { - if (isset($reference['fields']) && count($reference['fields']) > 0) { - $reference['fields'] = join(':', $reference['fields']); - } - - $schema['properties'][$reference['alias']]['relation'] = join('|', $reference); - } - } - } } }