Bugfix Issue 488 ZeroProject Umbrella Fixed GrantBuilder Handler Cleanup - sebiboga/testlink-upgraded GitHub Wiki

Issue 488 โ€” Zero-test-project warnings: umbrella verified fixed + grant-builder handler cleanup

Issue: #488 Branch: fix/issue-488 ยท Commits: 1357fc21e (fix), 35b563844 (regression suite), docs (this page) Status: FIXED & VERIFIED (2026-08-24)

Symptom (as reported, 2026-08-18)

286 PHP 8 warnings in the Event Viewer when no test projects exist, grouped in five sites: missing platform grants in getAccess() (common.php:2003/2004), aside.tpl missing showMenu keys (search, project_inventory_*, countPlans, plugin_management), projectEdit.tpl create-case properties (actions, itemID, tplan_id, tproject_id, mgt_view_events), mainPage.php null access (testprojectOptions, inventoryEnabled) and tlRole.class.php:264 array-offset-on-null.

Investigation outcome โ€” symptom already eliminated piecemeal

Reproduction against current HEAD (fresh DB, zero testprojects, admin login + full authenticated sweep of every zero-project-reachable screen) produced 0 WARNING/ERROR events while the logging pipeline was proven live (AUDIT/INFO rows written during the same window). Each original group is now hardened by fixes that landed under later refs:

Original group Current guard
getAccess() platform grants property_exists() checks โ€” common.php:2142-2155; full grant shape incl. platform_management/platform_view โ€” common.php:2053-2092
aside.tpl showMenu keys 'search' => false default โ€” common.php:2248; countPlans = 0 init โ€” common.php:1663; hardened $menuGrants from TLSmarty::addMenuContext() โ€” lib/functions/tlsmarty.inc.php:568-612
projectEdit create case initializeGui() sets actions/itemID/tplan_id/tproject_id/mgt_view_events โ€” lib/project/projectEdit.php:723-745
mainPage.php null access guarded reads โ€” lib/general/mainPage.php:187-189 and live-options read at :533-541
tlRole.class.php:264 site no longer exists after refactors; no array-offset access remains

The refs responsible include #483 (zero-project aside), #487, the #609 session-hardening series, #537 and #674. Issue #488 itself stayed open as a stale umbrella.

Remaining live defect found inside group 1's own function

getGrantSetWithExit(&$dbHandler,...) dereferenced undefined locals on its normal path:

// common.php:2131/2133 (pre-fix)
$argsObj->user->hasRight($dbH,"testproject_user_role_assignment", ...)
$argsObj->user->hasRight($db,"user_role_assignment",null,-1)

Neither $dbH nor $db exists in function scope (the parameter is $dbHandler; no global). It worked silently because tlUser::hasRight(&$db,...) takes the handler by reference (PHP auto-vivifies the undefined variable to null with no warning) and never dereferences it when $getAccess=false (tlUser.class.php:794-882). Any future call path that passes $getAccess=true would fatal with "call to a member function on null". This exact latent fragility was pre-flagged in the issue #674 wiki page "Notes for future work" section. Blast radius: both lines run on every authenticated page load (grant builder serves the normal, blind-folded and zero-project paths).

Approach โ€” pass the real handler

Minimal fix: replace $dbH/$db with the function's parameter $dbHandler (+ explanatory comment). No behavior change for existing callers (verified by the regression matrix below); removes reliance on by-ref autovivification and makes the code correct for any future handler-using call. Rejected alternatives: global $db; (wrong layering โ€” the handler is already an argument) and leave-as-is (latent fatal).

Files changed

File Change
lib/functions/common.php getGrantSetWithExit(): undefined $dbH/$db โ†’ $dbHandler (+ comment)
tmp/TLU_Test_Cases.md Suite 488 regression entry (6-case matrix)

Verification (Suite 488 โ€” 6/6 PASS)

Case Result
Original symptom absent (browser login, zero projects โ†’ shell renders) PASS โ€” 0 WARNING/ERROR events
Authenticated sweep of all zero-project screens (13 URLs) PASS โ€” full content everywhere, events delta 0
Logging health canary PASS โ€” AUDIT/INFO rows present โ‡’ zero-warning result meaningful
Grant builder fix live (both changed lines run per page load) PASS โ€” no fatal, grants unchanged
Non-zero-project branch regression (create project via UI โ†’ full menus โ†’ delete) PASS
Syntax gate (php -l) PASS

zero-project shell renders clean

Method note recorded on the issue: cURL logins must use field names tl_login/tl_password/tl_login_btn โ€” a first sweep with wrong names silently re-rendered the login form and was discarded.