Bugfix Issue 979 TcView Foreach On Null KeywordSet - sebiboga/testlink-upgraded GitHub Wiki
Bugfix — Issue #979: tcView E_WARNING foreach() on null keyword set (testcase.class.php:9347)
Problem
Rendering a test case that has no keywords — neither own nor inherited
from an ancestor testsuite — fired PHP warnings that landed in the Event
Viewer / events table:
E_WARNING foreach() argument must be of type array|object, null given
- in lib/functions/testcase.class.php - Line 9347
Plus, for every keywordless test case, a set of str_replace() parameter
deprecations at testcase.class.php:9358 (Passing null to parameter #1/#2).
The symptoms only appear on PHP 8.x (E_WARNING / E_DEPRECATED). Keywordless TCs are the common case on a fresh database.
Root Cause
renderSpecialTSuiteKeywords() (lib/functions/testcase.class.php:9313)
builds a static cache:
$skwSet[$tcase_id] = $this->getPathLayered($tcase_id,$optSKW);
getPathLayered() (testcase.class.php:5578) initialises $xtree = null
and only fills it for nodes whose node_table == 'testsuites' (line 5602).
Two failure modes:
- Test case attached directly under the project root —
get_path()returns[testproject, testcase]with no testsuite node, so$xtreestaysnullandgetPathLayered()returnsnull.$skwSetbecomes the array[tcase_id => null], which is notnull, so the guardif( is_null($skwSet) ) return;(old line 9330) never triggers. The doubleforeachat line 9346-9347 then iterates the null element →E_WARNING foreach() ... null givenat 9347. This is the primary reported symptom. - No
@#special keyword anywhere in the chain — the cache holds testsuite entries whosedata_managementisnull, so nothing ever gets appended to$searchSet/$replaceSet, which staynull→str_replace(null,null,...)raises deprecations at 9358 for all keywordless TCs (including suite children).
Fix
File: lib/functions/testcase.class.php — 3 changes in
renderSpecialTSuiteKeywords():
-
Default a
nullgetPathLayered()result to an empty array when filling the cache (fixes theforeach()E_WARNING):$skwSet[$tcase_id] = $this->getPathLayered($tcase_id,$optSKW); if( is_null($skwSet[$tcase_id]) ) { $skwSet[$tcase_id] = array(); } -
Harden the early-return guard from
is_null($skwSet)toempty($skwSet)(the array is nevernullonce an element is stored). -
Initialise the search/replace sets to
array()instead ofnull(fixes thestr_replace()deprecations for keywordless TCs):$searchSet = array(); $replaceSet = array();
Behaviour is unchanged when special keywords DO exist — str_replace() on an
empty array of replacements simply leaves summary/preconditions untouched.
No i18n impact, no user-facing strings changed.
Files Changed
| File | Change |
|---|---|
lib/functions/testcase.class.php |
renderSpecialTSuiteKeywords() — null→array() cache default, empty() guard, array() search/replace init (7+ / 4-) |
docs/screenshots/issue-979-tcview-no-warning-postfix.png |
post-fix TC view render (new) |
docs/screenshots/issue-979-event-viewer-postfix.png |
Event Viewer after post-fix renders (new) |
Commit bed7f8561 on branch fix/issue-979.
Testing / Evidence
- Primary symptom (before): harness calling
renderSpecialTSuiteKeywords()for a root-attached keywordless TC capturedtestcase.class.php:9347 foreach() argument must be of type array|object, null givenplus 4str_replace()deprecations; the browser produced the same line-9347 event (event id 24,10:02:00). - Primary symptom (after): same harness → 0 warnings from
testcase.class.php; browser re-render ofarchiveData.php?edit=testcase&id=50→ clean TC view, no new9347/9358event in the Event Viewer. - Keywordless suite child (TC30): 4
str_replace()deprecations → 0. - Positive control: keyword
@#DYNon the ancestor suite → summarymy @#DYN summaryrenders asmy DYN:Suite summary, still 0 warnings → replacement logic intact. - Syntax gate:
php -l→No syntax errors detected. - Blast radius:
renderSpecialTSuiteKeywordsis referenced only insidetestcase.class.php(3 occurrences: 1 def + 2 calls at lines 2944 / 4324); neither signature nor output contract changed. - Code review subagent: PASS (see review notes).
- Event Viewer: no new Error/Warning from this fix. Unrelated pre-existing
template warnings (label keys,
testcase.class.php:7490) remain tracked separately.
Screenshots


Regression Test Case
Suite Regression — Issue #979 (7/7 PASS) appended to tmp/TLU_Test_Cases.md:
root-attached keywordless TC harness, suite-child keywordless harness, positive
@# keyword control, browser render of the affected view, Event Viewer
accounting, php -l gate, and diff-scope check.