Skip to content

Commit

Permalink
Improve Tab link and names/titles construction
Browse files Browse the repository at this point in the history
  • Loading branch information
Ioannis committed Apr 19, 2026
1 parent 128449e commit da2f194
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 17 deletions.
3 changes: 2 additions & 1 deletion app/src/Controller/Component/RegistryAuthComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,8 @@ protected function calculatePermissions(?int $id=null): array {
->applyOptions(['archived' => true]);

// QueryModificationTrait
$getActionMethod = "get{$reqAction}Contains";
$reqActionCapitlize = ucfirst($reqAction) ;
$getActionMethod = "get{$reqActionCapitlize}Contains";
if(method_exists($table, $getActionMethod) && $table->$getActionMethod()) {
$query = $query->contain($table->$getActionMethod());
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/View/Helper/FieldHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ public function formField(string $fieldName,
string $fieldType = null,
array $fieldSelectOptions = null,
string $fieldNameAlias = null,
bool $labelIsTextOnly = null): string
bool $labelIsTextOnly = null): string
{
$fieldArgs = $fieldOptions ?? [];
$fieldArgs['label'] = $fieldOptions['label'] ?? false;
Expand Down
42 changes: 34 additions & 8 deletions app/src/View/Helper/TabHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ public function constructLinkUrl(string $tab, string|int $curId, bool $isNested
if(str_ends_with($tab, '.Plugin')) {
// This is always the second tab of the plugin and it is configuration
$controller = $curController;
$controllerQualifiedName = StringUtilities::modelNameToQualifiedModelName($controller);
$plugin = StringUtilities::pluginPlugin($controllerQualifiedName);
$plugin = !empty($plugin) ? $plugin : null;
$action = 'configure';
} else if (str_ends_with($tab, '.Hierarchy')) {
$modelName = $this->retrievePluginName($tab, (int)$curId);
Expand Down Expand Up @@ -236,7 +239,7 @@ public function getLinkClass(string $tab, bool $isNested = false, array $nesting
// Always mark active the parent Tab
!$isNested && $parentModelForNested !== null && $tab === $parentModelForNested && in_array($fullModelName, $nestings),
// Match Configuration and Hierarchy tabs
isset($plugin) && str_contains($tab, '.Plugin') && $curAction === 'edit',
isset($plugin) && str_contains($tab, '.Plugin') && $curAction === 'configure',
isset($plugin) && str_contains($tab, '.Hierarchy') && $curAction === 'index',
// Matches the action tab links, e.g. FileSource/search
$tab === "{$curController}@action.{$curAction}" => 'nav-link active',
Expand Down Expand Up @@ -547,14 +550,37 @@ public function retrievePluginName(string $tab, int $curId): string
{
// Get the name of the Core Model
$coreModel = substr($tab, 0, strrpos($tab, '.'));
$ModelTable = TableRegistry::getTableLocator()->get($coreModel);
$response = $ModelTable
->find()
->select(['plugin'])
->where(['id' => $curId])
->first();

return $response?->plugin;
// Ensure we resolve plugin tables correctly
$qualifiedCoreModel = StringUtilities::modelNameToQualifiedModelName($coreModel);
$ModelTable = TableRegistry::getTableLocator()->get($qualifiedCoreModel);

// If this table actually has a "plugin" column, fetch the plugin model path from the record.
// Example (pluggable wrapper tables):
// ProvisioningTargets.plugin = "LdapConnector.LdapProvisioners"
if ($ModelTable->getSchema()->hasColumn('plugin')) {
$response = $ModelTable
->find()
->select(['plugin'])
->where(['id' => $curId])
->first();

return (string)($response?->plugin ?? '');
}

// Otherwise, this isn't a pluggable wrapper record (no plugin column).
// Fall back to the table's registry alias, which is already in Plugin.Model form
// for plugin tables.
//
// Example:
// Table registry alias: "LdapConnector.PersonSchemas"
// This avoids querying a non-existent "plugin" column (eg person_schemas.plugin).
if (method_exists($ModelTable, 'getRegistryAlias')) {
return (string)$ModelTable->getRegistryAlias();
}

// Last resort: return the qualified name we used to locate the table.
return (string)$qualifiedCoreModel;
}

/**
Expand Down
14 changes: 10 additions & 4 deletions app/templates/element/form/listItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,24 @@
// - add a prefix and create a namespace
// - wrap them in an array.
// We choose the latter.
use App\Lib\Util\StringUtilities;

$this->set('fieldName', $arguments['fieldName']);
$fieldName = $arguments['fieldName'];
$this->set('vv_field_arguments', $arguments);

$qualifiedModelName = StringUtilities::entityToPluginClassName($this->Field->getEntity());
$plugin = StringUtilities::pluginPlugin($qualifiedModelName);
$controller = StringUtilities::pluginModel($qualifiedModelName);

// If an attribute is frozen, inject a special link to unfreeze it, since
// the attribute is read-only and the admin can't simply uncheck the setting
if($fieldName == 'frozen' && $this->Field->getEntity()->frozen) {
$url = [
'label' => __d('operation', 'unfreeze'),
'url' => [
'plugin' => null,
'controller' => \App\Lib\Util\StringUtilities::entityToClassname($this->Field->getEntity()),
'plugin' => !empty($plugin) ? $plugin : null,
'controller' => $controller,
'action' => 'unfreeze',
$this->Field->getEntity()->id
]
Expand All @@ -63,8 +69,8 @@
$url = [
'label' => __d('operation', 'configure.plugin'),
'url' => [
'plugin' => null,
'controller' => \App\Lib\Util\StringUtilities::entityToClassname($this->Field->getEntity()),
'plugin' => !empty($plugin) ? $plugin : null,
'controller' => $controller,
'action' => 'configure',
$this->Field->getEntity()->id
]
Expand Down
4 changes: 2 additions & 2 deletions app/templates/element/subnavigation/supertitle.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
if (
(!empty($vv_obj) || !empty($$objectName))
&& !empty($this->getPlugin())
&& $vv_subnavigation_tabs[0] !== StringUtilities::entityToClassName($vv_bc_parent_obj)
&& $vv_subnavigation_tabs[0] !== $vv_bc_parent_obj->getSource()
) {
$object = $vv_obj ?? $$objectName?->items()?->first();
if ($object === null) {
Expand All @@ -73,7 +73,7 @@
// 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);
TableUtilities::treeTraversalFromId($object->getSource(), (int)$object->id, $results);
$superTitleModelReference = $this->Tab->getModelTableReference($vv_subnavigation_tabs[0]);
$superTitleModelDisplayField = $superTitleModelReference->getDisplayField();
$superTitleModelId = $results[$vv_subnavigation_tabs[0]];
Expand Down
6 changes: 5 additions & 1 deletion app/templates/element/subnavigation/tabTitle.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@
$tabToTableName = Inflector::tableize(Inflector::singularize($tab));

// Plugin Configuration Tab
if (str_contains($tab, '.') && in_array('edit', $navigation_action[$tab], true)) {
if (
str_contains($tab, '.')
&& in_array('edit', $navigation_action[$tab], true)
&& array_search($tab, $vv_subnavigation_tabs, true) !== 0
) {
$title = __d('operation','configure.plugin');
} else if (str_contains($tab, '@action.')) { // Top Links/Actions
[$modelName, ] = explode('@', $tab);
Expand Down

0 comments on commit da2f194

Please sign in to comment.