Issue 421 BuildView Fatal Class And Null Buildset Fix - sebiboga/testlink-upgraded GitHub Wiki
Issue #421 β buildView.php Fatal build_mgr + Empty-Plan E_WARNING Fix
Issue: #421 β buildView.php instantiates non-existent class build_mgr β Builds/Releases page is a fatal error
Area: Test Plan β Builds / Releases (legacy lib/plan/buildView.php + lib/plan/buildEdit.php)
Symptoms
-
Fatal error (original report): opening Test Plan β Builds / Releases died before rendering anything:
Fatal error: Uncaught Error: Class "build_mgr" not found in lib/plan/buildView.php:41 -
Residual E_WARNING (found while verifying the fix): with a test plan that has zero builds, every view logged
E_WARNING foreach() argument must be of type array|object, null given - lib/plan/buildView.php - Line 90into the
eventstable. Once at least one build existed, no warning fired.
Root Cause
1. Non-existent class build_mgr (already fixed by 4c73d651e)
buildView.php:41 executed new build_mgr($dbHandler), but the only class in
the tree is build (declared lib/functions/build.class.php:26;
build_mgr survives solely as a closing comment, build.class.php:658).
Commit 4c73d651e ("Fix missing template file and class references for test
plan functionality", 2026-08-17) corrected line 41 to
new build($dbHandler) but the issue was never verified/closed.
2. Unguarded loop over a NULL build set (fixed by this run β 6ac0e88c6)
Chain of two broken contracts:
lib/plan/buildView.php:53β$gui->buildSet = $tplan_mgr->get_builds($gui->tplan_id);lib/functions/testplan.class.php:2250βget_builds()ends withreturn $this->db->fetchRowsIntoMap($sql,$accessField);β NULL when the plan has zero rows inbuilds.lib/plan/buildView.php:90βforeach($gui->buildSet as $elemBuild)had no null guard β PHP 8.x E_WARNING (captured by TL logging as event id=12).
The null case was already a known contract inside the same function β line 58
wraps the custom-field bootstrap in if (!is_null($gui->buildSet)). The main
loop simply missed it, and the template renders its own
"No builds are defined within this Test Plan!" message anyway.
The Fix
One line, lib/plan/buildView.php:90 (commit 6ac0e88c6):
- foreach($gui->buildSet as $elemBuild) {
+ foreach(($gui->buildSet ?? []) as $elemBuild) {
Non-empty plans behave identically; empty plans now yield an empty array so the loop is skipped and the template's empty-state message stands alone.
Alternatives rejected:
- Wrapping the ~25-line loop body in an added
if (!is_null(...))block β bigger diff for identical behaviour. - Changing
get_builds()to always return an array β touches a widely used API (grepshows many call sites); violates minimal-fix rule.
Verification (regression matrix, all PASS)
Run 2026-08-23, headless Chrome against http://localhost:8082, fresh DB, fixtures created via UI (project "Bug421 Project", plans id=2 with one build / id=3 zero builds), SQL event-table diffs around each step:
| # | Case | Result |
|---|---|---|
| R1 | Zero-build plan β buildView.php?tplan_id=3 |
Renders "No builds are definedβ¦"; ZERO events from buildView.php (pre-fix produced event id=12) |
| R2 | Create build via Create button | Build 1.0 persisted + audit event |
| R3 | Populated view lists build | Table row rendered, no warnings |
| R4 | Edit link | buildEdit.php?do_action=edit&build_id=1 opens prefilled |
| R5 | Event Viewer after whole pass | No new Error/Warning attributable to Builds screens |
Full suite: Suite 60 in tmp/TLU_Test_Cases.md (8/8 PASS).
Screenshots
Empty plan after fix (no fatal, no warning):

Populated view after fix (build listed):

Out-of-scope findings
While verifying, repeated E_WARNINGs were observed on the Test Plan
Management screens (planView.tpl lines 213/217/279, planEdit.tpl lines
62β63) β filed separately as #622,
not touched by this fix.