From a9cfa0c95e2d545fca1fffe18937d6c635f9f9cf Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Tue, 4 Feb 2025 20:30:33 +0200 Subject: [PATCH] Fix miscalculated tab link process --- app/src/View/Helper/TabHelper.php | 54 +++++++++++++++++++ .../element/subnavigation/supertitle.php | 24 +++++---- 2 files changed, 69 insertions(+), 9 deletions(-) diff --git a/app/src/View/Helper/TabHelper.php b/app/src/View/Helper/TabHelper.php index 9bc78da51..71f314295 100644 --- a/app/src/View/Helper/TabHelper.php +++ b/app/src/View/Helper/TabHelper.php @@ -63,6 +63,8 @@ class TabHelper extends Helper public function constructLinkUrl(string $tab, string|int $curId, bool $isNested = false): array { $curController = $this->getView()->getRequest()->getParam('controller'); + $vv_associated_ids = $this->getView()->get('vv_associated_ids'); + $modelName = $tab; $controller = $modelName; $plugin = null; @@ -100,7 +102,15 @@ public function constructLinkUrl(string $tab, string|int $curId, bool $isNested ]; if ($action === 'index') { + $deepId = $this->getDeepNestedId($linkFilter); + If($deepId !== null) { + $linkFilterForeignKey = array_key_first($linkFilter); + $linkFilter[$linkFilterForeignKey] = $deepId; + } $url['?'] = $linkFilter; + } else if ($action === 'edit') { + // I will get the id from the associated ids table + $url[] = $vv_associated_ids[$controller]; } else { $url[] = $curId; } @@ -108,6 +118,49 @@ public function constructLinkUrl(string $tab, string|int $curId, bool $isNested return $url; } + + /** + * Retrieve the ID for a deeply nested association. + * + * @param array $linkFilter The link filter containing foreign key details. + * + * @return int|null The ID of the deeply nested associated model or null if not found. + * @since COmanage Registry v5.1.0 + */ + public function getDeepNestedId(array $linkFilter): ?int + { + $vv_associated_ids = $this->getView()->get('vv_associated_ids'); + + // Get the foreign from the linkFilter + $linkFilterForeignKey = array_key_first($linkFilter); + // Generate the ModelName and instantiate the linked Table + $modelName = StringUtilities::foreignKeyToClassName($linkFilterForeignKey); + $table = TableRegistry::getTableLocator()->get($modelName); + $linkFilterId = $vv_associated_ids[Inflector::pluralize($modelName)] ?? null; + if($linkFilterId !== null) { + return (int)$linkFilterId; + } + $foreignKeyId = -1; + $foreignKey = null; + // This means that we are working on deep nested associations and we need + // to fetch more data + $linkFilterSchema = $table->getSchema(); + foreach($linkFilterSchema->columns() as $column) { + // Check the foreign keys + if(str_ends_with($column, '_id')) { + $foreignKeytToTableName = Inflector::pluralize(StringUtilities::foreignKeyToClassName($column)); + if(isset($vv_associated_ids[$foreignKeytToTableName])) { + $foreignKeyId = $vv_associated_ids[$foreignKeytToTableName]; + $foreignKey = $column; + break; + } + } + } + $id = $table->find()->where([$foreignKey => $foreignKeyId])->first()->id; + + return(int)$id; + } + /** * Calculate the link Class * @@ -205,6 +258,7 @@ public function getCurrentId(string $tabName = null, bool $isNested = false): in TableUtilities::treeTraversalFromId($curController, (int)$tid, $results); } + $this->getView()->set('vv_associated_ids', $results); $tabAction = $this->getTabAction($tabName, $isNested); if( diff --git a/app/templates/element/subnavigation/supertitle.php b/app/templates/element/subnavigation/supertitle.php index b5f238df3..840d09547 100644 --- a/app/templates/element/subnavigation/supertitle.php +++ b/app/templates/element/subnavigation/supertitle.php @@ -65,16 +65,22 @@ && $vv_subnavigation_tabs[0] !== StringUtilities::entityToClassName($vv_bc_parent_obj) ) { $object = $vv_obj ?? $$objectName?->first(); - // If we get here, it means that neither the request object nor its parent can give us a supertitle. - // We need to fetch all the ids and get the supertitle from the root tab/node - $results = []; - TableUtilities::treeTraversalFromId(StringUtilities::entityToClassName($object), (int)$object->id, $results); - $superTitleModelReference = $this->Tab->getModelTableReference($vv_subnavigation_tabs[0]); - $superTitleModelDisplayField = $superTitleModelReference->getDisplayField(); - $superTitleModelId = $results[$vv_subnavigation_tabs[0]]; + if ($object === null) { + // This is a deep nested association that has not been initialized yet. The controller name + // will become the supertitle + $vv_subnavigation_tabsSupertitle = Inflector::humanize($vv_controller); + } else { + // If we get here, it means that neither the request object nor its parent can give us a supertitle. + // We need to fetch all the ids and get the supertitle from the root tab/node + $results = []; + TableUtilities::treeTraversalFromId(StringUtilities::entityToClassName($object), (int)$object->id, $results); + $superTitleModelReference = $this->Tab->getModelTableReference($vv_subnavigation_tabs[0]); + $superTitleModelDisplayField = $superTitleModelReference->getDisplayField(); + $superTitleModelId = $results[$vv_subnavigation_tabs[0]]; - $root_obj = $superTitleModelReference->get($superTitleModelId); - $vv_subnavigation_tabsSupertitle = $root_obj->$superTitleModelDisplayField; + $root_obj = $superTitleModelReference->get($superTitleModelId); + $vv_subnavigation_tabsSupertitle = $root_obj->$superTitleModelDisplayField; + } } $supertitle = match (true) {