From 666b74d44252916c4b73e761c574e6f7770e841a Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Sat, 28 Sep 2024 14:21:28 +0300 Subject: [PATCH] fix deep nested navigation tab id calculation --- app/src/Lib/Util/TableUtilities.php | 105 ++++++++++++++++++ app/src/View/Helper/TabHelper.php | 61 ++++++++++ .../element/subnavigation/tabList.php | 6 +- 3 files changed, 167 insertions(+), 5 deletions(-) diff --git a/app/src/Lib/Util/TableUtilities.php b/app/src/Lib/Util/TableUtilities.php index b0753967a..add83efe1 100644 --- a/app/src/Lib/Util/TableUtilities.php +++ b/app/src/Lib/Util/TableUtilities.php @@ -31,6 +31,8 @@ use Cake\ORM\Table; use Cake\ORM\TableRegistry; +use Cake\Datasource\ConnectionManager; +use Cake\Utility\Inflector; class TableUtilities { /** @@ -58,4 +60,107 @@ public static function getTableFromRegistry(string $alias, array $options): Tabl return $Locator->get($alias, $options); } } + + /** + * We calculate the model name from the primary link, the primary link value is the id + * of the record. We use these to traverse backwards to all the records associations + * Then we return a list where the keys are the model names and the values are the ids + * + * @param string $primaryLinkKey + * @param int $primaryLinkValue + * @param array $results + * + * @return void + * @since COmanage Registry v5.0.0 + */ + public static function treeTraversalFromPrimaryLink( + string $primaryLinkKey, + int $primaryLinkValue, + array &$results, + string $primaryLinkClassName = null + ): void + { + $db = ConnectionManager::get('default'); + // Create a schema collection. + $collection = $db->getSchemaCollection(); + $listOfTables = $collection->listTables(); + + $primaryLinkModelName = StringUtilities::foreignKeyToClassName(($primaryLinkKey)); + // Check if the table exists. + // We can not handle + + // We need to save the id by its alias not the containing class + $results[$primaryLinkModelName] = $primaryLinkValue; + + if ($primaryLinkClassName !== null) { + $primaryLinkModelName = $primaryLinkClassName; + $results[$primaryLinkModelName] = $primaryLinkValue; + } + + // Get a table reference + $ModelTable = TableRegistry::getTableLocator()->get($primaryLinkModelName); + // Get the Record from the database + $resp = $ModelTable->find() + ->where(['id' => $primaryLinkValue]) + ->first() + ->toArray(); + + // Find all the foreign keys and fetch the rest of the tree + foreach($resp as $col => $val) { + if ( + $val !== null + && $col !== $primaryLinkKey + && str_ends_with($col, '_id') + ) { + $fkModel = StringUtilities::foreignKeyToClassName(($col)); + $fk_table = Inflector::underscore($fkModel); + if (\in_array($fk_table, $listOfTables, true)) { + self::treeTraversalFromPrimaryLink($col, $val, $results); + } + } + } + } + + /** + * With a model name and the id know we return a list where the + * keys are the model names and the values are the ids + * + * @param string $modelName + * @param int $id + * @param array $results + * + * @return void + * @since COmanage Registry v5.0.0 + */ + public static function treeTraversalFromId(string $modelName, int $id, array &$results): void + { + $db = ConnectionManager::get('default'); + // Create a schema collection. + $collection = $db->getSchemaCollection(); + $listOfTables = $collection->listTables(); + + $results[$modelName] = $id; + // Get a table reference + $ModelTable = TableRegistry::getTableLocator()->get($modelName); + // Get the Record from the database + $resp = $ModelTable->find() + ->where(['id' => $id]) + ->first() + ->toArray(); + + // Find all the foreign keys and fetch the rest of the tree + foreach($resp as $col => $val) { + if ( + $val !== null + && $col !== $modelName + && str_ends_with($col, '_id') + ) { + $fkModel = StringUtilities::foreignKeyToClassName(($col)); + $fk_table = Inflector::underscore($fkModel); + if (\in_array($fk_table, $listOfTables, true)) { + self::treeTraversalFromPrimaryLink($col, $val, $results); + } + } + } + } } \ No newline at end of file diff --git a/app/src/View/Helper/TabHelper.php b/app/src/View/Helper/TabHelper.php index 22227dc11..04b10b56c 100644 --- a/app/src/View/Helper/TabHelper.php +++ b/app/src/View/Helper/TabHelper.php @@ -175,6 +175,67 @@ public function tabBelongsToModelPath(string $tab, string $modelFullName, int &$ return false; } + /** + * Calculate the ID for the tab link + * + * @param string|null $tabName + * @param bool $isNested + * + * @return int + */ + public function getCurrentId(string $tabName = null, bool $isNested = false): int + { + $vv_person_id = $this->getView()->get('vv_person_id'); + $vv_obj = $this->getView()->get('vv_obj'); + $vv_primary_link = $this->getView()->get('vv_primary_link'); + $vv_bc_title_links = $this->getView()->get('vv_bc_title_links'); + $request = $this->getView()->getRequest(); + $curController = $request->getParam('controller'); + $curAction = $request->getParam('action'); + $plugin = $this->getView()->getPlugin(); + $vv_sub_nav_attributes = $this->getView()->get('vv_sub_nav_attributes'); + $tab_actions = !$isNested ? $vv_sub_nav_attributes['action'] : $vv_sub_nav_attributes['nested']['action']; + $tabs = !$isNested ? $vv_sub_nav_attributes['tabs'] : $vv_sub_nav_attributes['nested']['tabs']; + + $tid = $vv_person_id + ?? $request->getQuery($vv_primary_link) + ?? $vv_obj->id + ?? end($vv_bc_title_links[0]['target']); + + // Get the ids of all the associated Model records + $results = []; + if ($request->getQuery($vv_primary_link) !== null) { + TableUtilities::treeTraversalFromPrimaryLink($vv_primary_link, (int)$tid, $results, ); + } else { + TableUtilities::treeTraversalFromId($curController, (int)$tid, $results); + } + + $tabAction = !empty($tab_actions[$tabName][0]) ? $tab_actions[$tabName][0] : null; + + if ( + $tabAction === null + && str_contains($tabName, '@action') + ) { + return (int)$results[ $tabs[0] ]; + } else if( + !$isNested + && ($tabAction === 'index' || $curController !== $tabName) + && \in_array($tabName, $tabs, true) + ) { + return (int)$results[ $tabs[0] ]; + } else if ( + !$isNested + && ($tabAction !== 'index' || $curController === $tabName) + && \in_array($tabName, $tabs, true) + ) { + return (int)$tid; + } + + return (int)$tid; + } + + + /** * Check the belongsTo tree hierarchy * diff --git a/app/templates/element/subnavigation/tabList.php b/app/templates/element/subnavigation/tabList.php index b2eb6d65e..73bd0ffc3 100644 --- a/app/templates/element/subnavigation/tabList.php +++ b/app/templates/element/subnavigation/tabList.php @@ -33,16 +33,12 @@ extract($vv_sub_nav_attributes, EXTR_PREFIX_ALL, 'vv_subnavigation'); -$curId = $vv_person_id - ?? $this->request->getQuery($vv_primary_link) - ?? $vv_obj->id - ?? end($vv_bc_title_links[0]['target']); - ?>