Skip to content

Commit

Permalink
fix deep nested navigation tab id calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
Ioannis committed Dec 15, 2024
1 parent 65ba066 commit 64c39ed
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 5 deletions.
105 changes: 105 additions & 0 deletions app/src/Lib/Util/TableUtilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

use Cake\ORM\Table;
use Cake\ORM\TableRegistry;
use Cake\Datasource\ConnectionManager;
use Cake\Utility\Inflector;

class TableUtilities {
/**
Expand Down Expand Up @@ -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);
}
}
}
}
}
61 changes: 61 additions & 0 deletions app/src/View/Helper/TabHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down
6 changes: 1 addition & 5 deletions app/templates/element/subnavigation/tabList.php
Original file line number Diff line number Diff line change
Expand Up @@ -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']);

?>

<?php foreach($vv_subnavigation_tabs as $tab): ?>
<li class="nav-item">
<?php
$curId = $this->Tab->getCurrentId($tab, $isNested);
// Calculate Tab Title
$title = $this->element('subnavigation/tabTitle', compact('tab', 'curId'));
// Construct Target URL
Expand Down

0 comments on commit 64c39ed

Please sign in to comment.